2010年8月29日

ほしい物リストを作る 4

前回からのつづき。今回は具体的なサンプルを作ってみました。関数名、id名は任意でどうぞ。
XMLHttpRequestで送受信する部分は、いろいろなページで解説がされています。中身は、それらとほとんど変わりません。ただ、配列を使うバージョンはなかったように思いますので、その分だけ若干複雑になっています。

1.商品詳細ページの任意の場所に設置
<a href="#" onClick="JavaScript:set_wish_cookie(1);return false">ほしい物リストに追加する</a>

2.JavaScript-wish.js
//XMLHttpRequestオブジェクト生成
function createHttpRequest(num) {
  if(window.XMLHttpRequest) {
    //IE7 IE8 Firefox Opera Safari
    httpObj[num] = new XMLHttpRequest();
  }
  else if(window.ActiveXObject) {
    try {
        //MSXML2以降所
        httpObj[num] = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
      try {
          //旧MSXML
          httpObj[num] = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e2) {
          httpObj[num] = null;
      }
    }
  }
  else {
    httpObj[num] = null;
  }
}
//タイムアウト処理
function timeout(n) {
  httpObj[n].abort();
  document.getElementById("wish"+n).innerHTML = strPid[n] + " (Timeout)";
}
//ファイルにアクセスし受信内容を確認
function wish_requestFile(num,method,async,pid) {
  createHttpRequest(num);
  if(httpObj[num]) {
    timerID[num] = setTimeout('timeout("' + num + '")',30000);//タイムアウト30秒
    fileName[num] = "http://www.hogehoge.com/?pid="+pid;
    httpObj[num].open(method,fileName[num],async); 
    httpObj[num].onreadystatechange = function() {
      if(httpObj[num].readyState==4) {//受信完了後の処理
        clearTimeout(timerID[num]);//タイムアウト解除
        if(httpObj[num].status == 200) {//正常
          strRes[num] = httpObj[num].responseText;         
          //ほしい物リスト表示
          if(strRes[num].match(/現在、この商品は扱っておりません。/igm) == null) {
            //在庫ありの場合の処理
           document.getElementById("wish"+num).innerHTML ='' + '<a href="#" onClick="JavaScript:del_wish_cookie(' + pid + ');location.reload();return false">リストから削除</a>';
          }
          else {
            //在庫なしの場合の処理
            document.getElementById("wish"+num).innerHTML ="現在、商品ID "+ pid +" は扱っておりません。次回表示時にリストから自動的に削除されます。";
            del_wish_cookie(pid);
          }
        }
        else if(httpObj[num].status == 404) {//404エラー処理
          document.getElementById("wish"+num).style.display = "none";
        }
        else {//それ以外
          document.getElementById("wish"+num).innerHTML = "server status " + httpObj[num].status;
        }
      }
    }
    httpObj[num].send(null);
  }
}


//Cookie部分削除
function del_wish_cookie(strNum) {
  strCookie=$.cookie('wish');
  strNum="!"+strNum+"!";
  re = new RegExp(strNum);
  if(strCookie.search(re)!=-1) {
    if(strCookie.indexOf(strNum)==0) {
      strCookie=strCookie.slice(strNum.length);
    }
    else {
      strCookie=strCookie.slice(0,strCookie.indexOf(strNum)) +       strCookie.slice(strCookie.indexOf(strNum)+strNum.length);
    }
    $.cookie('wish', strCookie ,{expires:365});
  }
}

//Cookieセット
function set_wish_cookie(i) {
  if(i==1) {//追加
    strURL=location.href;
    strCookie=$.cookie('wish');
    if(strCookie==null) {
      strCookie="";
    }
    else {
      loop=strCookie.match(/!/g)
      if(loop!=null && loop.length/2 >= 20) {
        window.alert("これ以上追加することはできません(最大20点まで)");
        return;
      }
    }
    if(strURL.indexOf("?pid=")!=-1) {
      strURL=strURL.slice(strURL.indexOf("?pid=")+5);
      strURL="!"+strURL+"!";
      re = new RegExp(strURL);
      if(strCookie==null || strCookie=="") {
        strCookie=strURL;
        $.cookie('wish', strCookie,{expires:365});
        window.alert("ほしい物リストに追加しました");
      }
      else if(strCookie.search(re)==-1) {
        strCookie=strCookie+strURL;
        $.cookie('wish', strCookie,{expires:365});
        window.alert("ほしい物リストに追加しました");
      }
      else {
        window.alert("この商品はすでに追加されています");
      }
    }
  }
  else {//削除
    $.cookie('wish','',{expires:-1});
  }
}


//ほしい物リスト表示
function load_wishlist() {
  //Cookie読み込み
  httpObj = new Array();
  strRes = new Array();
  timerID = new Array();
  fileName = new Array();
  strPid = new Array();

  strCookie=$.cookie('wish');
  if(strCookie==null)  {
    strCookie="";
  }
  loop=strCookie.match(/!/g);
  if(loop!=null) {
    if(loop.length/2>20) {//最大20点まで
      N=20;
    }
   else {
      N=loop.length/2;
    }
  }
  else {
    N=0;
  }
  for(i=1;i<=N;i++) {    strPid[i]=strCookie.substring(strCookie.indexOf("!")+1,strCookie.indexOf("!",strCookie.indexOf("!")+1));
    wish_requestFile(N+1-i,'GET',true,strPid[i]);
    strCookie=strCookie.slice(strCookie.indexOf("!",strCookie.indexOf("!")+1)+1);
  }
}

3.フリーページ
<div id="wish1"></div>
<div id="wish2"></div>
<div id="wish3"></div>
<div id="wish4"></div>
<div id="wish5"></div>
<div id="wish6"></div>
<div id="wish7"></div>
<div id="wish8"></div>
<div id="wish9"></div>
<div id="wish10"></div>
<div id="wish11"></div>
<div id="wish12"></div>
<div id="wish13"></div>
<div id="wish14"></div>
<div id="wish15"></div>
<div id="wish16"></div>
<div id="wish17"></div>
<div id="wish18"></div>
<div id="wish19"></div>
<div id="wish20"></div>
<script type="text/javascript">
<!--
  load_wishlist();
//-->
</script>
補足
・strRes[]に商品詳細ページまるまる格納されています。
・切り出す部分と表示は各自で作成してください(根気のいる作業です)。
・「現在、この商品は扱っておりません。」はテンプレートによっては異なるかもしれません。在庫の有無によって、処理・表示を分岐させます。在庫表示管理の設定や商材の種類によって、内容を見直す必要があります。
・~部分に表示させる情報を。その上の行に、切り出す処理を追加してください。
・最大登録数を20点にしています。サーバーへの負荷がかかりますので、無茶しない数で。
・Cookieに書き込む商品IDは、!で囲む形式にしています。!は区切り文字として使用。ex. !12345678!

XMLHttpRequestを使用せずに、もっと楽にシンプルに作れるとよいのですが。
使用時はサーバーに過度の負担をかけない程度に。

これに追加して、「カートに入れるボタンを商品詳細ページ以外に設置する」 を使えば、ほしい物リストページにカートに入れるボタンを設置することも可能(多分)。試したあとで、ご紹介したいと思います。


【関連記事】
カラーミーにできること、できないこと