Sep 03, 2005
IEでXMLHttpRequestを使えるようにする
IEで「new XMLHttpRequest」と書けるようにするラッパを書いてみた。
XMLHttpRequest for IE
http://la.ma.la/misc/js/ie_xmlhttp.html
結構前にIE7(JavaScriptの方)の人が似たようなのを作ってたのですが、
http://dean.edwards.name/weblog/2004/11/ie7-xml-extras/
ふつうに使う分にはこれでも問題はないです。
if(typeof ActiveXObject == "function" && typeof XMLHttpRequest == "undefined"){
XMLHttpRequest = function(){
return new ActiveXObject("Microsoft.XMLHTTP")
}
}
IEでXMLHttpRequestが未定義だったら、XMLHTTPオブジェクトを返すコンストラクタを定義してやる。
これだけでいい。ただ、これだとXMLHttpRequest.prototypeをいじったりすることができない。
IEのActiveXObjectっていうのはちょっと特殊で、メソッドなんかがJavaScriptのfunctionではない。
var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
alert(typeof xmlhttp.open); // unknown
こうなる。xmlhttp.openはfunctionではなくて謎オブジェクト。
FirefoxやOperaのXMLHttpRequest#openは、ちゃんとfunctionになっているのだが、
IEの場合は関数ではないので、関数型言語としてのJavaScriptの機能が使えない。
----
XMLHttpRequest for IEは何なのかというと、
IEでもXMLHttpRequestのメソッドをfunctionオブジェクトとして扱うことができるようになるラッパです。
あとついでにonloadイベントハンドラを定義してあるので記述が楽になります。
functionalでアスペクト指向なコードを書く際に、役に立ちますが、
functionalでアスペクト指向なコードを書かない場合は書き方が共通になって嬉しい程度で、
その辺はすでにprototype.jsとかあるので大してメリットはないと思われる。
ものすごくシンプルな例はこんな感じ。
var XP = XMLHttpRequest.prototype;
XP.open_old = XP.open;
XP.open = function(){
alert("open called!");
return this.open_old.apply(this,arguments)
}
XMLHttpRequest.prototypeを書き換えてやることで、通信をトレースできるようにしたり、機能を拡張したり制限を加えたりすることができるようになる。もちろんクロスブラウザで動く(safariは知らないけど)。
例えば、通信するときには必ず前回のリクエストから1秒のウェイトを入れるようにする、とか、
デバッグ用に通信状態をステータスバーに流すとか、
他ドメインのURLを開こうとした場合はプロキシCGI経由のリクエストにするとか、
UserAgentを強制的に書き換えるとか、キャッシュが利かないようにユニークなURLにするとか。
全般にわたる振る舞いを効率的に記述することができるようになる。
----
工夫したのはこのあたり。
var methods = "open,abort,send,setRequestHeader,getResponseHeader,getAllResponseHeaders".split(",");
var make_method = function(name){
XMLHttpRequest.prototype[name] = function(){
var params = new Array(arguments.length);
for(var i=0;i<params.length;i++) params[i] = "_"+i;
return Function(
params.join(","),
["return this.__request__.",name,"(",params.join(","),")"].join("")
).apply(this,arguments);
}
};
for(var i=0;i<methods.length;i++) make_method(methods[i]);本来のXMLHTTPオブジェクトをthis.__request__に保存していて、
引数の数に応じて関数を動的に生成して、本来のXMLHTTPオブジェクトに処理を丸投げする。
this.open("GET",url)
→(function(_1,_2){this.__request__.open(_1,_2)}).apply(this,arguments)
this.open("GET",url,async)
→(function(_1,_2,_3){this.__request__.open(_1,_2,_3)}).apply(this,arguments)
this.open("GET",url,async,user,pass)
→(function(_1,_2,_3,_4,_5){this.__request__.open(_1,_2,_3,_4,_5)}).apply(this,arguments)
こんな具合に変換される。
ふつうにラッパーを書くときは、
function wrapper(){
return original.apply(this,arguments)
}
こんな具合にやるんだけど、オリジナルのxmlhttp.openは上記のとおり、そもそも関数ではないのでxmlhttp.open.applyが存在しない。
eval使わないと無理かな、とも思ったんだけどFunctionコンストラクタ使うときれいに書けた。
Functionコンストラクタは文字列から関数を生成する。
add = new Function("a","b","return a+b");そして、こう書いてもOK。
add = new Function("a,b","return a+b");これはJavaScriptの方言ではなくてちゃんとECMA準拠。
http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/15-3_Function_Objects.html#section-15.3.2.1
まあ、あんまり使わないと思うんだけど。
配布ライセンスについて
いつも参考にさせていただいています。
今回の物もなるほどと言う感じです。
ところで、このie_xmlhttp.jsのライセンスなのですが、LGPLやBSDライセンスにしたりしませんか?
というのは、PHPなどで動的にie_xmlhttp.jsを使うJavaScriptコードを吐いている物があった場合、PHPコードにもGPLを適用しないといけない可能性があるかもしれないからです(GPLライセンスについてはまだ理解不足であるので、そうならないかもしれないのですが)。
商用のプログラムを作っている場合、セキュリティー確保などの関係でPHPコードを公開できないことがあり、その場合ie_xmlhttp.jsがつかえなくなり、せっかくの素晴らしい成果物が利用できないのはすごく残念なのですが。
よろしかったらですが、ライセンスの変更の方を検討していただけると助かります。
XMLHttpRequest
【Ajax】prototype.jsのXMLHttpRequest Opera 9's XMLHttpRequest #2 d.aql - XMLHttpRequestとリクエストヘッダ 【仕様】W3C 草案UPDATE The XMLHttpRequest Object Opera 9's XMLHttpRequest ふぁっきん not well-formed, XMLHttpRequest とかで MTでAjax!!〜XML
Is very interesting craps roulette [url=http://xoomer.alice.it/casq/craps-roulette/]craps roulette[/url] http://xoomer.alice.it/casq/craps-roulette/
Hi, nice site! aladdin resort and casino [url=http://xoomer.alice.it/burka/aladdin-resort-and-casino/]aladdin resort and casino[/url] http://xoomer.alice.it/burka/aladdin-resort-and-casino/
Interesting site seneca casino [url=http://xoomer.alice.it/burka/seneca-casino/]seneca casino[/url] http://xoomer.alice.it/burka/seneca-casino/
Very nice site shreveport casino [url=http://xoomer.alice.it/burka/shreveport-casino/]shreveport casino[/url] http://xoomer.alice.it/burka/shreveport-casino/
Exciting website. casino party [url=http://xoomer.alice.it/burka/casino-party/]casino party[/url] http://xoomer.alice.it/burka/casino-party/
Exciting website. foreclosure
http://accountingmontreal.com
Exciting website. foreclosure
http://accountingmontreal.com
Good Luck! http://megamozg.com/online-trading/map.html
Great work on website. http://megamozg.com/travel-insurance/map.html
Hi, nice site! http://megamozg.com/homeowners-insurance/map.html
VERY GOOD I THINK http://megamozg.com/need-money/map.html
Thanks for taking http://megamozg.com/bachelor-degree/map.html
Is very interesting http://wwwwtahoo.com/canon-inkjet-printer-cartridge/
Very useful http://wwwwtahoo.com/caribbean-stud-poker-game/
Your hard work paid off http://wwwwtahoo.com/horse-racing-wager/
annuncio lavoro
Blog Records:tireur isol辿 de 50 caloriesComments...
annuncio lavoro
Blog Records:tireur isol辿 de 50 caloriesComments...
Good site
wallmart
lemon detox diet
kohls department store
coach handbag outlet
royal caribean cruises
atkins diet negative
dj cammy
al4a
diana death crash photo
skimpy bikini
艢鞐瘤鴈蒂獺驟鱶 蓁鱚齏纈
Good site
wallmart
lemon detox diet
kohls department store
coach handbag outlet
royal caribean cruises
atkins diet negative
dj cammy
al4a
diana death crash photo
skimpy bikini
艢鞐瘤鴈蒂獺驟鱶 蓁鱚齏纈
Good site
wallmart
lemon detox diet
kohls department store
coach handbag outlet
royal caribean cruises
atkins diet negative
dj cammy
al4a
diana death crash photo
skimpy bikini
艢鞐瘤鴈蒂獺驟鱶 蓁鱚齏纈
writeback message: Ready to post a comment.

