MSIEのドキュメントモードとやら

MSIEの独自プロパティdocumentModeについてのメモ

先日、text-shadow for MSIEのスクリプトに関して、IE9でエラーが出るという主旨の呟きをツイッターで見つけた。 ご本人に再現するサンプルなどはないか問い合わせたところ、ご自身でDOCTYPE宣言の有無によるものだったと原因をつきとめ、再現サンプルも挙げてくださった。深謝。

エラーのもととなっている関数は、IEのバージョンをみてcurrentStyleかgetComputedStyleかを返すというものだが、ソースから該当箇所を抜き出すとこんな感じ。

var isMSIE = /*@cc_on!@*/false;
var ieVersion = (function(reg) { return isMSIE && navigator.userAgent.match(reg) ? RegExp.$1 * 1 : null; })(/MSIE\s([0-9]+[\.0-9]*)/);
function getCompStyle(elm, pseudo) {
    return isMSIE && ieVersion < 9 ? elm.currentStyle : pseudo != null ? document.defaultView.getComputedStyle(elm, pseudo) : document.defaultView.getComputedStyle(elm, '');
}

で、DOCTYPE宣言の有無でエラーが出たり出なかったりするということは、IE9がQuirksモードになっている時に、スクリプトはIE9なのねとgetComputedStyleを返そうとして、でもそんなものは知らんとIEがエラーを吐き出していた、というわけ。

てっきりQuirksモードのときはcurrentStyleが返っているものと思い込んでいたが、調べてみたら、実はQuirksモードのときもUserAgentでは"MSIE 9"を名乗っていたのであった。 つまり、UAの文字列からの判別だけでは不十分。
ではどうやって判別すればいいのか、というと、マイクロソフトがIE8から導入したdocumentModeという独自プロパティを使えということらしい。 ドキュメント互換性の定義(MSDNライブラリ)

で、そのdocumentModeを参照するとどんな値が返ってくるのかというと

5

Internet Explorer 5 mode (also known as "quirks mode").

7

Internet Explorer 7 Standards mode.

8

Internet Explorer 8 Standards mode.

9

Internet Explorer 9 Standards mode.

10

Internet Explorer 10 Standards mode.

…もうね自己都合的なプロパティを勝手に作られても知らんよと小一時間(ry

というわけで、以下のようにスクリプトを修正。

var isMSIE = /*@cc_on!@*/false;
var ieVersion = (function(reg) { return isMSIE && navigator.userAgent.match(reg) ? RegExp.$1 * 1 : null; })(/MSIE\s([0-9]+[\.0-9]*)/);
function getCompStyle(elm, pseudo) {
    return (isMSIE && (ieVersion < 9 || document.documentMode < 9)) ? elm.currentStyle : pseudo != null ? document.defaultView.getComputedStyle(elm, pseudo) : document.defaultView.getComputedStyle(elm, '');
}

ちなみに、わざわざIEであることやバージョンを調べずとも、本来は

function getCompStyle(elm, pseudo) {
    return document.defaultView.getComputedStyle ? document.defaultView.getComputedStyle(elm, pseudo) : elm.currentStyle;
}

とかで良さそうなものだが、これだとやっぱりIE8以下でエラーを吐いてくるのであったorz

追記

ieVersionであらかじめ判別した方がなにかと効率がいいので、現在はこうしている。

/* MSIE判別 */
var isMSIE = /*@cc_on!@*/false;
var ieVersion = (function(_doc, reg) { return _doc.documentMode ? _doc.documentMode : isMSIE && _nav.userAgent.match(reg) ? RegExp.$1 * 1 : null; })(document, /MSIE\s([0-9]+[\.0-9]*)/);
/* getCompStyle() getComputedStyle互換 */
function getCompStyle(elm, pseudo) {
    return isMSIE && ieVersion < 9 ? elm.currentStyle : pseudo ? document.defaultView.getComputedStyle(elm, pseudo) : document.defaultView.getComputedStyle(elm, '');
}

"MSIEのドキュメントモードとやら"へのTwitter上でのコメントやRT

1件のツイートがあります。

ツイート 1