この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
IE9とjQueryの相性が悪い
今日はこれに悩まされました。ある特殊な状況で発生する発見しづらいバグです。以前もお伝えしましたが、重要なので繰り返しますと、IE 6,7はCORSに対応していません。IE 8,9は特殊対応しています。IE 10から正式対応する予定です。ここでいう、特殊対応とは、IE独自のオブジェクトを使ってクロスドメイン通信をします。XDomainRequestオブジェクトです。そして、こいつがやらかしましたw。常に動かないならまだしも、動いたり動かなかったり微妙な感じなのです。。。
jQueryでは空を表すためにjQuery.noopを使う
これはjQueryでイベントハンドラを書くときによく使う書き方で、ハンドラの中身に何も処理が無いのであれば、何も無いを明示するためにjQuery.noopを使っています。これは、function(){}と同じ事なのですが、XDomainRequestくんは違うものと認識してCORSを中断してしまいます。Nullと空文字みたいな感じかな。
IE 8,9でCORSをするためにxdr.jsを使ってjQueryを拡張する
xdr.jsは、jQueryの記述をほとんど変更することなく、IE 8,9に対してCORS命令を書く事ができる優れものの拡張表現です。
jQueryのロード後に宣言することで有効になります。基本的にはコレでOKです。
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script src="xdr.js" type="text/javascript"></script>
jQuery.noop処理でCORS通信中断を回避
現在公開されているxdr.jsは、jQuery.noopによるバグ対策が施されていません。そこで、xdr.jsにパッチを充てました。
以下は修正したコードです。
if ( window.XDomainRequest ) {
jQuery.ajaxTransport(function( s ) {
if ( s.crossDomain && s.async ) {
if ( s.timeout ) {
s.xdrTimeout = s.timeout;
delete s.timeout;
}
var xdr;
return {
send: function( _, complete ) {
function callback( status, statusText, responses, responseHeaders ) {
xdr.onload = xdr.onerror = xdr.ontimeout = function() { };
xdr = undefined;
complete( status, statusText, responses, responseHeaders );
}
xdr = new XDomainRequest();
xdr.onload = function() {
callback( 200, "OK", { text: xdr.responseText }, "Content-Type: " + xdr.contentType );
};
xdr.onerror = function() {
callback( 404, "Not Found" );
};
xdr.onprogress = function() { };
xdr.ontimeout = function() {
callback( 0, "timeout" );
};
xdr.timeout = s.xdrTimeout || Number.MAX_VALUE;
xdr.open( s.type, s.url );
xdr.send( ( s.hasContent && s.data ) || null );
},
abort: function() {
if ( xdr ) {
xdr.onerror = function() { };
xdr.abort();
}
}
};
}
});
}
まとめ
エンジニアの肩書きがあるならソーシャルコーディングして片っ端から問題解決しようよぜー!