Introduction

ブログ内検索

  • このサイトの記事を検索 by Google

おすすめの一冊!

無料ブログはココログ

« Ruby はじめました | トップページ | Firefox の button の点線囲い »

2010-05-01

ぐりもんのクロスドメイン JSONP

GW の初日は、ぐりもん (UserScript) のコーディングを満喫しました♪

ふぁぼったーの censored をかいくぐるスクリプト「uncensored_favotter」で
懸案だったクロスブラウザ対応をついに実現しました!

    ⇒ ダウンロードはこちら

いままでは GreaseMonkey 独自関数 GM_XMLHttpRequest() を使っていたので
Firefox でしか動かなかったのですが、今日、うまい方法を思いついて、
Chrome/Opera でも動くようになったというわけです。

    ⇒ Opera での UserScript の使い方は Opera wiki を参照





思いついたアイディアは、スクリプト全体を function で wrap して、
それを丸ごと toString() して script タグに流し込む、というものです。

実際のコードで示すと、次の2行でスクリプト全体を囲むことになります。

(function(e){e.text='(function(){var f='+(function(){
}).toString()+';with(f){f()}})()';document.body.appendChild(e)})(document.createElement('script'));
こうすると、スクリプト全体が通常の window (unsafeWindow) のコンテキストで 動くようになるため、JSONP のコールバック関数から直接処理を戻すことが可能になります。 JSONP なら GM 独自関数を使う必要が無いので、Chrome/Opera でも動くようになります。 逆に言うと、GM_* 系の独自関数は使えなくなってしまいますが・・・。 (HTML5 の WebStorage を使えば独自関数はなくても大丈夫なことが多いかも?) まぁ、ざっくり言えば、クロスドメイン通信をする UserScript を作りたいとき、 サーバ側が JSONP に対応しているなら今回の方法を使う(Chrome/Opera でも動く)、 そうでないなら GM 独自関数でやる、というのがいいと思います。 今日わかったノウハウは以下の通り: ・JSONP のコールバック関数はグローバルに可視でなければならないが、  window オブジェクトのプロパティにしてあげれば OK。
function loadUrl(url, callback) {
	var fname = (function(s){do{var x=Math.floor(Math.random()*0x1fffffffffffff)}while(window[s+x]);return s+x})('hogehoge_callback');

	window[fname] = function(json){delete window[fname];callback(json)};

	if (url.indexOf('?') == -1) {
		url += '?';
	}
	if (url.indexOf('=') != -1) {
		url += '&';
	}
	url += 'callback=' + fname;

	var elem = document.createElement('script');
	elem.setAttribute('type', 'text/javascript');
	elem.setAttribute('src', url);
	document.body.appendChild(elem);
}
・script タグを動的に生成して文字列としてスクリプトを流し込むときは、  innerHTML 属性じゃなくて text 属性に代入する。innerHTML に代入すると  Opera が不等号記号に反応してしまって動作しないことがある。  これは UserScript に限らず、通常の JavaScript でも同様。 ・Opera で innerHTML を読むとタグ名が大文字になってるので注意。 今日のアイディアをひらめいたときは、思わず自分が天才じゃないかと 錯覚してしまいました。クロスブラウザ対応をこんなシンプルな方法で (ブラウザごとの分岐コード無しに)実現できて、すごくうれしいです♪ Chrome/Opera ユーザの皆さん、ぜひご利用ください!

« Ruby はじめました | トップページ | Firefox の button の点線囲い »