JSでブラウザを判別してみよう2010年11月25日 05時07分32秒

油断してたらまた4ヶ月も更新してなかったのだが、なんとなくJSでブラウザ判別を行うという、わりとありがちな事に挑戦してみる。

ライブラリとしてまとめようと思ってたんだけど、そろそろ眠いので、今日のところは断片的な記述にしておこう。

何を判別する?

メジャーどころだったらたいていはレンダリングエンジン≒ブラウザが成立しそうなもんなんだけど、WebKitの場合はSafariとChromeの両方がなかなか普及してるので、「レンダリングエンジンが何であるか」と「ブラウザが何であるか」の2種類を判別することにする。で、Safari/Chromeの場合はモバイル版かどうかも見ないとね。

ということで、レンダリングエンジンは

  • Trident
  • Gecko
  • Presto
  • WebKit
、ブラウザは
  • IE
  • Firefox
  • Opera
  • Safari
  • Chrome
を判別してみる。

まずは、Presto = Opera。

めちゃくちゃ手抜きなんだけど、window.operaがundefinedじゃなければPrestoっつーことで。しかもPrestoだったら何も考えずにOperaっつーことで。

<button type="button" onclick="alert(!! window.opera)">レンダリングエンジンははPresto?</button>

<button type="button" onclick="alert(!! window.opera)">ブラウザはOpera?</button>

次はGecko = Firefox。

まぁ、GeckoをみんなFirefoxとみなすのは乱暴なのはわかってるんだけども、こちらも手抜き。

昔、MooToolsの1.2.2のブラウザ判定部分のソース見たときは、window.document.getBoxObjectForがundefinedでなければGeckoてな判断してたみたいなんだけど、Firefox 3.6の環境で試したらこれが成立しなくなってたのでwindowのプロパティを総当りで調べたところ、window.mozInnerScreenXあたりが使えそうなので組み合わせで判別してみる。

<button type="button" onclick="alert(window.document.getBoxObjectFor != undefined || window.mozInnerScreenX != undefined);">レンダリングエンジンはGecko?</button>

<button type="button" onclick="alert(window.document.getBoxObjectFor != undefined || window.mozInnerScreenX != undefined);">ブラウザはFirefox?</button>

IEかどうか、までは簡単。

IEかどうかを判別するのは、window.ActiveXObjectをチェックするのが定番なんだけども、念のためMSDNを見てみたら、なんかIE9で廃止になっちゃいそうな記述が。

びっくりしてIE9ベータで確認したらnullは返してこなかったんだけど、ちょっと怖いのでもうひとつの定番「window.document.all」を使うことに。でもこれ、Operaも実装してるんだったよな、確か。 っつーことで、こんな感じに。

<button type="button" onclick="alert(!!((window.ActiveXObject || window.document.all) && !window.opera))">レンダリングエンジンはTrident?</button>

IEのバージョンは細かく見てみたい。

で、IEの場合は他のブラウザよりもバージョンの違いをなるべく厳密に判別したくなるので、

  • IE6よりも前
  • IE6
  • IE7
  • IE8
  • IE9
をなんとか判別してみようかといろいろ探してみたところ、これまたMSDNにDetecting Internet Explorer More Effectivelyなんてぴったりの記事が見つかった。冒頭のほうではユーザエージェントで判別する方法を記載してるんだけど、これじゃ心もとないのでもう少し読み進めてみたら、「Another IE version detector snippet」と題するコメントが
Another IE version detector snippet
function getIEVersion(odoc){
if (odoc.body.style.scrollbar3dLightColor!=undefined)
{
if (odoc.body.style.opacity!=undefined) {return 'IE9';}
else if (odoc.body.style.msBlockProgression!=undefined) {return 'IE8';}
else if (odoc.body.style.msInterpolationMode!=undefined) {return 'IE7';}
else if (odoc.body.style.textOverflow!=undefined) {return 'IE6'}
else {return 'IE5.5 or lower';}
}
}
なるほど、styleプロパティでチェックするのね。ただこのサンプルどおりbody.styleをチェックする方法だとページロードが完了しないと判定できないので不便なので、head要素でチェックをしてみることに。あ、あとIE9かどうかの判別はwindow.msPerformanceでチェックしたほうがよさげ。

で、こんなコードを実行して、

<script type="text/javascript">
window.detected_ie_name = (function() {
    if(window.ActiveXObject == undefined && window.document.all == undefined) return "IEじゃない";
    if(window.msPerformance != undefined) return "IE9";
    var h = document.getElementsByTagName("head")[0];
    if(h.style.msBlockProgression != undefined) return "IE8";
    if(h.style.msInterpolationMode != undefined) return "IE7";
    if(h.style.textOverflow != undefined) return "IE6";
    return "IE5.5かそれ以前";
})();
</script>

こんな感じのボタンを貼ってみる。
<button type="button" onclick="alert(window.detected_ie_name)">IEのバージョンは?</button>

WebKitか否か。

MooTools 1.2.2では、navigator.taintEnabledのチェックでもって判別してた。これなんぞ?と思ったら、よい解説が見つかった。

navigator.taintEnabled() というのは、「ユーザーに非通知でデータ送信が可能かどうか(データテイント機能の使用有無)を返すメソッド」です。「何それ?」て思われた方、ご安心ください。Netscape Navigator 3.x の時代の、古い古ーい仕様で、データテイント機能は現在使われておりません。多くのブラウザは、ただfalseを返すだけです。
ただしSafari(WebKit)では、このメソッドそのものを定義していません。
だそうで、まんま使わせてもらおう。

<button type="button" onclick="try { alert(window.navigator.taintEnabled == undefined) } catch(e) { alert(false); }">レンダリングエンジンはWebKit?</button>

って、IETester使ってるせいか、デフォルトIE以外だとwindow.navigator.taintEnabledにアクセスしただけで例外吐くのでtry catchで囲まなきゃ。

Safariか、Chromeか。

これはあんまりいい方法が見つからなかったので、両方でSafari5とChrome7の両方でwindowのプロパティを洗いざらい列挙してめぼしいところをいくつか試してみたところ、window.TouchListの有無がよさそうだった。

と思って今試したら、Safariでもwindow.TouchListがundefined返してきた。あれぇ?会社で試したときと違うなあ。

ということで、ちょっと別の方法探さなきゃ。ちなみにモバイル版かの判別は今のところwindow.orientationがNaNじゃなければモバイルってな判定でよさげ。