Chrome拡張に買い物かごボタンを追加した

いやもう、タイトルの通りでございます。いつものAmazon to Rakutenに買い物かごをしれっと追加しました。まあ、つけた方が個人的に便利やし。そこで工夫した点など。

必要な情報

まず、実際の楽天ブックスの商品ページの買い物かごボタンを見て、どんなデータをPOSTしてやればいいのかを調べます。

<form method="post" action="https://books.step.rakuten.co.jp/rms/mall/book/bs/Cart">
	<div>
		<span class="unit">個数&nbsp; </span>
		<input value="1" type="text" size="4" name="units" id="units">
		<input value="買い物かごに入れる" type="submit">
		<input type="hidden" value="213310" name="shop_bid">
		<input type="hidden" value="14034556" name="item_id" id="ScItemGet">
		<input type="hidden" value="1" name="inventory_flag">
	</div>
</form>

見た感じ、いじる必要がありそうなとこは、

1.「個数」をhiddenで1個に固定
2."item_id"を商品に合わせて変更

の2点。楽天ブックスは楽天市場の1店舗なので、"shop_bid"は全部一緒のはず。"inventory_flag"は、まあようわからんけどこのままでいいっしょ。

実装

ということで、実質コードを書く必要があるのは"item_id"だけ。ところが厄介なことに、"item_id"はなんとAPIに入っていないので、もっかいXMLHttpRequestを叩いて無理矢理取ってくることに。http通信2回分なんて待ってられないので、一回目のAPI通信で取得したデータはすぐ表示しつつ、続けてitem_idが取得出来次第ボタンを表示っていう仕様にしました。

chrome.extension.onConnect.addListener(function(port) {
  console.assert(port.name == "AtoR");
  port.onMessage.addListener(function(msg) {
		if(msg.status == "start"){
			//ページアクションのアイコンを表示
			chrome.pageAction.show(port.sender.tab.id);
			
			//楽天APIから商品を検索
			query = "http://api.rakuten.co.jp/rws/3.0/json?" +
					"developerId=" + devId +
					"&affiliateId=" + afiId +
					"&operation=" + opr +
					"&version=" + ver+
					"&keyword=" + encodeURI(msg.title);
					
			api.open("GET",query,true);
			api.onreadystatechange = sourceGet(port);
			api.send(null);
		}
		else if(msg.status == "null"){
			content = "このページでは使用できません。";
		}
		else{
			sourceGet(port);
		}
  });
});


//タブが変更された時の処理
chrome.tabs.onSelectionChanged.addListener(function(tabid){
	chrome.tabs.getSelected(null, function(tab) {
		・・・
	});
});


function sourceGet(port){
	if (api.readyState == 4 && api.status == 200){
		response = eval('[' + api.responseText + ']')[0];
		
		if(response['Header']['Status'] == 'Success'){
			items = response['Body']['BooksTotalSearch']['Items']['Item'];
			
			//商品データを1つずつhtmlに出力
			content = '<table width="300">';
			for(i=0;i<items.length;i++){			
				content = content+'<tr><td><a href="'+items[i]['affiliateUrl']+'"><img src="'+items[i]['mediumImageUrl']+'" /></a></td><td style="width:200px;vertical-align:top;">タイトル:<a href="'+items[i]['affiliateUrl']+'" target="_blank">'+items[i]['title']+'</a><br />著者:'+items[i]['author']+'<br />価格(税込):'+setComma(items[i]['itemPrice'])+'円<br />ポイント:'+Math.floor(items[i]['itemPrice']/1.05/100)+'ポイント<br /><img src="img/star_';
				if(items[i]['reviewAverage'] == 0) content = content + '0';
				else if(items[i]['reviewAverage'] > 0 && items[i]['reviewAverage'] < 1) content = content + '0.5';
				else if(items[i]['reviewAverage'] == 1) content = content + '1';
				else if(items[i]['reviewAverage'] > 1 && items[i]['reviewAverage'] < 2) content = content + '1.5';
				else if(items[i]['reviewAverage'] == 2) content = content + '2';
				else if(items[i]['reviewAverage'] > 2 && items[i]['reviewAverage'] < 3) content = content + '2.5';
				else if(items[i]['reviewAverage'] == 3) content = content + '3';
				else if(items[i]['reviewAverage'] > 3 && items[i]['reviewAverage'] < 4) content = content + '3.5';
				else if(items[i]['reviewAverage'] == 4) content = content + '4';
				else if(items[i]['reviewAverage'] > 4 && items[i]['reviewAverage'] < 5) content = content + '4.5';
				else if(items[i]['reviewAverage'] == 5) content = content + '5';
				content = content + '.png" />('+items[i]['reviewCount']+')<br />買い物かごに入れる</td></tr>';
				
				rakuten.open("GET",items[i]["itemUrl"],true);
				rakuten.onreadystatechange = function(){
					if (rakuten.readyState == 4 && rakuten.status == 200){
						rr = rakuten.responseText;
						rr.match(/value="([^"]*)"[^>]*id="ScItemGet"/);
						rr = RegExp.$1;
						
						//買い物かご
						cart = '<form method="post" action="https://books.step.rakuten.co.jp/rms/mall/book/bs/Cart" target="_blank">';
						cart = cart + '<div>';
						cart = cart + '<input value="1" type="hidden" name="units" id="units">';
						cart = cart + '<input value="買い物かごに入れる" type="submit">';
						cart = cart + '<input type="hidden" value="213310" name="shop_bid">';
						cart = cart + '<input type="hidden" value="'+rr+'" name="item_id" id="ScItemGet">';
						cart = cart + '<input type="hidden" value="1" name="inventory_flag">'
						cart = cart + '</div>'
						cart = cart + '</form>'
						
						content = content.replace("買い物かごに入れる", cart);
						viewContent();
					}
				};
				rakuten.send(null);
			}
			content = content+'</table>';
			viewContent();
		}
		・・・
	}
	・・・
}

61行目で、まずベタ文字で「買い物かごに入れる」って表示しつつ、63行目以下で2度目の通信を行ってます。item_idは67行目の正規表現で強引にゲット。正規表現が一発で決まると気持ちいい。
無事にitem_idが取れたらベタ文字をformタグで置換。めでたしめでたし。

You can leave a response, or trackback from your own site.

Leave a Reply

Subscribe to RSS Feed Follow me on Twitter!