読者です 読者をやめる 読者になる 読者になる

jQueryのloadメソッドのこと

jQuery[v1.4.2]のloadメソッドで2度もはまったのでメモ。
これ。$(selector).load(url,data,callback)
このurlの書式がセレクタ有り無しの場合でレスポンスの挙動が変わる。

結論から

セレクタ有りでloadすると、レスポンス内のscriptが抜かれる。

サンプル

以下サンプルはdataとcallbackは使用しないパターンとして省略。
この場合、windowの読み込みが完了したときに"/foo/bar #hoge"を非同期でリクエストして
結果を#resに流しこむ。

■アクセスする側の部分的コード

<div id="res">
</div>

<script>
$(window).bind('load',function(){
  var url='/foo/bar #hoge';  //#hogeの内容を取ってきて
  $('#res').load(url);
});
</script>

アクセス先にセレクタ指定があるときは、レスポンス内容のscriptが抜かれる。(2回目)

jQuery[v1.4.2]のload辺りを見てみる

var sb = J(), tb = /<script(.|\s)*?\/script>/gi, ub = /select|textarea/i, vb = /color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i, N = /=\?(&|$)/, ka = /\?/, wb = /(\?|&)_=.*?(&|$)/, xb = /^(\w+:)?\/\/([^\/?#]+)/, yb = /%20/g, zb = c.fn.load;
c.fn.extend({load: function(a, b, d) {
        if (typeof a !== 
        "string")
            return zb.call(this, a);
        else if (!this.length)
            return this;
        var f = a.indexOf(" ");
        if (f >= 0) {
            var e = a.slice(f, a.length);
            a = a.slice(0, f)
        }
        f = "GET";
        if (b)
            if (c.isFunction(b)) {
                d = b;
                b = null
            } else if (typeof b === "object") {
                b = c.param(b, c.ajaxSettings.traditional);
                f = "POST"
            }
        var j = this;
        c.ajax({url: a,type: f,dataType: "html",data: b,complete: function(i, o) {
                if (o === "success" || o === "notmodified")
                    j.html(e ? c("<div />").append(i.responseText.replace(tb, "")).find(e) : i.responseText);
                d && j.each(d, [i.responseText, o, i])
            }});
        return this
    },
周辺のことはともかく、まず注目する部分。
j.html(e ? c("<div />").append(i.responseText.replace(tb, "")).find(e) : i.responseText);

レスポンスを返す時に、eをチェックしている。

eは何?
var f = a.indexOf(" ");
if (f >= 0) {
    var e = a.slice(f, a.length);
    a = a.slice(0, f)
}

アクセス先のURLに半角スペースがあれば、eにセレクタ相応部分の文字列を格納している。

立ち戻る。
j.html(e ? c("<div />").append(i.responseText.replace(tb, "")).find(e) : i.responseText);

eが存在する(true)とき、responseText内のtbを空文字列に置換した上で、
新しい空divに、セレクタ要素を流しこむ。

tbは最初に宣言してあったね。

tb = /<script(.|\s)*?\/script>/gi,

というわけでscript抜かれる。

まとめ

loadメソッドではセレクタ無しではscript抜かれず、セレクタ有りではscriptが抜かれる。

※ちなみにv1.8.2での当該ソース部分でのコメント

// inject the contents of the document in, removing the scripts
// to avoid any 'Permission Denied' errors in IE

なんで抜かれるん!って思ったけどちょっと分かった。
要するに、もしセレクタ内のscriptを取得してしまうと、
セレクタ範囲外におけるscriptとの依存関係が不明で、
動作保証できないし危険だということだと思う。