IE6, 7で iframeを含むページで:textを走らせるとエラー
あ、これか Issue #66: :text selector throws an error in IE7 when there is a cross domain iframe on the page · jquery/sizzle github.com/jquery/sizzle/…
— あほむ@世界樹の迷宮たのしみ (@ahomu) March 16, 2012
なんぞこれー、と思って検証してたらissueでてた。察しが付いてきた時点で、先に見ればよかった。||| orz
検証コード
以下のコードをレガシーIEで実行すると、:textだけエラーが出てundefinedを返しfailedになります。iframe要素まではいいけど、src属性がクロスドメインな時点でアウト。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xml:lang="ja" lang="ja" dir="ltr" xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Test</title> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script> <script type="text/javascript"> $(function() { var results = document.getElementById('results'), exprCollection = [ ':text', ':input', ':password', ':radio', 'checkbox', ':submit',':image', ':reset', ':button', ':file' ], i = 0, expr; function test(expr) { if ($(expr) === void 0) { throw Error(expr); } } function succeed(expr) { results.innerHTML += '<dt>'+expr+'</dt><dd>succeed</dd>'; } function failed(expr) { results.innerHTML += '<dt>'+expr+'</dt><dd>failed</dd>'; } while(expr = exprCollection[i++]) { try { test(expr); } catch(e) { failed(expr); continue; } succeed(expr); } }); </script> </head> <body> <h1>(´Д`)</h1> <dl id="results"> </dl> <iframe width="640" height="360" src="http://www.youtube.com/embed/HiRgU78_g9o" frameborder="0" allowfullscreen></iframe> </body> </html>
Sizzleさん
- Sizzle JavaScript Selector Library
- jQueryのCSSセレクタAPIを高速に扱う方法 | tech.kayac.com - KAYAC engineers' blog
SizzleというjQueryが内包しているセレクタエンジン(querySelectorの代替品+α)のバグですね。jQueryのセレクタAPI周りは2つめのURLの情報がよろしいです。
バグじゃ〜ん
内容的には、iframeでクロスドメインを引き込んでいると、getAttribute("type")
をレガシーIE的に使えないのが理由らしい。判明してから半年以上経ってるし、プライオリティが低いからとりあえずこの場を凌ぐ。
対策
jQuery.expr.filters.text
をスクリプトの冒頭で上書きします。さきほどのGitHubのページに対策コードも掲載されていたので、とりあえずそれを丸々拝借します。
// @see https://github.com/jquery/sizzle/issues/66 jQuery.expr.filters.text = function( elem ) { var attr, type; return elem.nodeName.toLowerCase() === "input" && (type = elem.type, attr = elem.getAttribute("type"), "text" === type) && ( attr === type || attr === null ); };
これで対策できました。副作用があるようだったら、この中身を改造していけばよいかな〜、と思いながらこれでやり過ごします。assigned bugってことは、そのうち直るのよ...ね?
参考
- Issue #66: :text selector throws an error in IE7 when there is a cross domain iframe on the page · jquery/sizzle
- #10570 (:text selector throws an error in IE7 when there is a cross domain iframe on the page) – jQuery Core - Bug Tracker