その1

実際動いているサイトはこちら

序章

 sirmiles.comでは、「手抜きなショッピング・モール」というサイトを公開していました。Amazon楽天ビッダーズ、ストアミックスから、商品を一括検索するというページです。
 ただし、このページは面白味がなく、アフィリエイトとしても殆ど役に立たなかったため、「もうちょっとこのページで遊べないか」と考えるようになりました。
 月日は過ぎ、Google Mapを目にし、これがJavaScriptを基幹とした技術で作られているとは思いもしませんでした。
 さらに月日は過ぎ、ふと「Ajax」という言葉を目にし、衝撃を受けました。これだ!(?)と直感した私は、本屋で羽田野太巳氏の著作「AJAX Webアプリケーションアイデアブック」をすぐに買って帰り、色々とサンプルスクリプトを作っては遊んでみました。
 そして、Ajaxのクセを一通り頭に入れ、「手抜きなショッピング・モール」を「インタラクティヴ・プラザ」に改変すべく、作業を開始しました。

ソリューション

 Ajaxはクライアントサイドとサーバーサイドの連携によって、ブラウザがサイト間を移動することなく、ユーザーアクションなどに応じてコンテンツを動的に変更する方法論です。
 私は、1-man.netでサーバーレンタルしており、このサーバではPHP4が使える為、サーバーサイドはPHP4で構築します。
 クライアントサイドのスクリプトは、羽田野太巳氏の著作を最大限に活用させていただきました。多謝。ブラウザは、Ajaxで使用する特定のオブジェクトが、JavaScriptにおいて使用できるものに一応限定します。
 ただし、クローラー対策(リンク先になった場合に中身を拾ってもらう=アフィリエイトに有利になるようにする)として、メインページがGETパラメータを受け付けるようにし、通常のクエリ送信検索も可能とします。これにより、動作保障外ブラウザでも、一応検索ができるはずです。

 流れとしては…。
 ページの検索ワードに文字を入力すると、そのイベントを感知したJavaScriptイベントハンドラが、XMLHttpRequestオブジェクトを使用してサーバーサイドのPHPスクリプトにリクエストを投げます。
 サーバーサイドのPHPスクリプトは、各ショッピングモールのWebサービスにアクセスし、なるべく簡単なXMLドキュメントを生成してクライアントへレスポンスを返します。
 レスポンスを受け取ったクライアントは、XMLを解析し、ページ内の適切なdivタグに対して、商品を羅列するHTMLを追加していきます。
 こうして、検索ワードに応じた結果が、入力するたび(実際は負荷軽減のため、インターバルを取っていますが)に変化します。

index.php

 まずは、実際のページです。「index.php」となっていますが、PHPスクリプトを説明すると、AJAXにたどり着かないので、ブラウザに帰ってきた基本的なHTMLで説明します。基幹的な部分以外は省略しています。文字セットはUTF-8とします。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" lang="ja">
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<title>インタラクティヴ・プラザ βver. Presented by SirMiles</title>
<script type="text/javascript" src="ajax.js"></script>
<script type="text/javascript" src="plaza.js"></script>
</head>
<body>

<h1 id="top">Ajaxを利用して、Amazon・楽天・ビッダーズ・ストアミックスから、インタラクティヴに商品を検索します。</h1>

<div id="msg" style="font-weight : bold; background-color : #CCFFFF; border : solid 1px #00CCCC; height : 1.5em;"></div> 

<form id="searchbox" action="index.php" method="get" target="_top" accept-charset="utf-8">
<p>検索ワード:<input id="Keywords" name="Keywords" type="text" size="50" value="" /><input id="submitbutton" type="submit" value="検索" /></p>

<script type="text/javascript">
<!--
if(objValid()) {
    document.getElementById("submitbutton").disabled = true;
}
else {
    document.write('<p><strong>インタラクティヴ検索はご利用になれません。検索ボタンをご利用ください。</strong></p>');
}
//-->
</script>

<noscript>
<p><strong>インタラクティヴ検索はご利用になれません。検索ボタンをご利用ください。</strong></p>
</noscript>

<p><input type="radio" name="Sort" value="Bestselling" id="SortBestselling" checked="checked" /><label for="SortBestselling">指定なし</label>
&nbsp;<input type="radio" name="Sort" value="Newest" id="SortNewest"  /><label for="SortNewest">新着順</label>
&nbsp;<input type="radio" name="Sort" value="LowPrice" id="SortLowPrice"  /><label for="SortLowPrice">安い順</label>
&nbsp;<input type="radio" name="Sort" value="HighPrice" id="SortHighPrice"  /><label for="SortHighPrice">高い順</label></p>

<p class="indent">※ アマゾンの場合、カテゴリー指定がないと、新着順や価格順が無効になります。</p>
<p class="indent">※ ストアミックスの場合、カテゴリーや並び順はすべて無効になります。</p>

<hr/>

<table summary="CATEGORY" border="0" cellspacing="0" cellpadding="0">
  <tbody>
    <tr>
      <td>
      <p><input id="Amazon" name="Amazon" type="checkbox" checked="checked" value="true"/>アマゾン:</p>
      </td>
      <td>
      <p>
      <select id="SearchIndex" name="SearchIndex" style="width : 20em;">
        <option value="Blended" selected="selected">カテゴリー指定なし</option>
        <option value="Books" >本</option>
        <option value="ForeignBooks" >洋書</option>
        <option value="Electronics" >エレクトロニクス</option>
        <option value="Kitchen" >キッチン</option>
        <option value="Music" >音楽</option>
        <option value="Classical" >クラシック</option>
        <option value="MusicTracks" >音楽トラック</option>
        <option value="DVD" >DVD</option>
        <option value="Video" >ビデオ</option>
        <option value="VHS" >VHS</option>
        <option value="Software" >ソフトウェア</option>
        <option value="VideoGames" >ゲーム</option>
        <option value="Toys" >トイ</option>
      </select>
      </p>
      </td>
      <td>
      <p>&nbsp;</p>
      </td>
    </tr>
    <tr>
      <td>
      <p><input id="Rakuten" name="Rakuten" type="checkbox" checked="checked" value="true"/>楽天:</p>
      </td>
      <td>
      <p>
      <select id="Genre" name="Genre" style="width : 20em;">
        <option value="" selected="selected">カテゴリー指定なし</option>
        <option value="100371" >ファッション</option>
        <option value="100227" >グルメ(食品)</option>
        <option value="100316" >グルメ(ドリンク)</option>
        <option value="100553" >生活・インテリア</option>
        <option value="100026" >パソコン・家電・AV</option>
        <option value="100938" >ダイエット・健康</option>
        <option value="101070" >スポーツ・アウトドア</option>
        <option value="100939" >美容・コスメ・香水</option>
        <option value="101164" >おもちゃ・ホビー・ゲーム</option>
        <option value="101240" >CD・DVD・楽器</option>
        <option value="100005" >フラワー・ガーデン</option>
        <option value="101213" >ペット・ペットグッズ</option>
        <option value="101114" >車・バイク</option>
        <option value="100533" >キッズ・ベビー・マタニティ</option>
        <option value="200162" >本・雑誌・コミック</option>
        <option value="101381" >旅行・出張・チケット</option>
        <option value="200163" >不動産・住まい</option>
        <option value="101438" >サービス</option>
      </select>
      </p>
      </td>
      <td>
      <p>&nbsp;</p>
      </td>
    </tr>
    <tr>
      <td>
      <p><input id="Bidders" name="Bidders" type="checkbox" checked="checked" value="true"/>ビッダーズ:</p>
      </td>
      <td>
      <p>
      <select id="Categ" name="Categ" style="width : 20em;">
        <option value="" selected="selected">カテゴリー指定なし</option>
        <option value="7" >コンピュータ</option>
        <option value="8" >家電・AV・カメラ</option>
        <option value="4" >ブランド</option>
        <option value="3" >ファッション</option>
        <option value="931" >ペット・いきもの</option>
        <option value="909" >グルメ・ドリンク</option>
        <option value="211" >チケット・金券</option>
        <option value="10" >キッズ・ベビー</option>
        <option value="921" >ヘルス・ビューティー</option>
        <option value="27" >アクセサリー・時計</option>
        <option value="6" >アンティーク・コレクション</option>
        <option value="28" >ホビー・カルチャー</option>
        <option value="5" >レジャー・スポーツ</option>
        <option value="508" >自転車・バイク</option>
        <option value="9" >住まい・インテリア・花</option>
        <option value="2" >音楽・映画・DVD</option>
        <option value="1019" >おもちゃ・ゲーム</option>
        <option value="1" >タレント・キャラクターグッズ</option>
        <option value="212" >本・雑誌・コミック</option>
        <option value="11" >ビジネス・事務・店舗用品・文房具</option>
      </select>
      </p>
      </td>
      <td>
      <p>&nbsp;</p>
      </td>
    </tr>
    <tr>
      <td>
      <p><input id="Storemix" name="Storemix" type="checkbox" checked="checked" value="true"/>ストアミックス:</p>
      </td>
      <td>
      <p>
      <select id="SCateg" name="SCateg" style="width : 20em;" disabled="disabled">
        <option value="" selected="selected">カテゴリー指定なし</option>
      </select>
      </p>
      </td>
    </tr>
  </tbody>
</table>
</form>
<hr />

<div id="amazonbookmarks"></div>
<div id="rakutenbookmarks"></div>
<div id="biddersbookmarks"></div>
<div id="storemixbookmarks"></div>

<div id="amazoninfo"></div>
<div id="amazonresults"></div>
<div id="amazonerror"></div>

<div id="rakuteninfo"></div>
<div id="rakutenresults"></div>
<div id="rakutenerror"></div>

<div id="biddersinfo"></div>
<div id="biddersresults"></div>
<div id="bidderserror"></div>

<div id="storemixinfo"></div>
<div id="storemixresults"></div>
<div id="storemixerror"></div>

</body>
</html>

 このHTMLの解説は次回。