Archive of obsolete content

クロスブラウザ/クロスプラットフォームのページ作成

クロスブラウザ、クロスプラットフォームを実践して DHTML 開発を行うにあたって重要な慣習は、ページを表示しているブラウザの機能を動作時に判別できるようにすることです。Web ページの作者としては当然のことながら、スクリプトエラーやページレイアウトの問題を回避する必要がありますし、できる限り幅広い訪問者のもとでスクリプトが機能するようにしたいことでしょう。そのような目的を達成するために知られる手段が 2 つあります。: ブラウザを識別する方法(ユーザエージェントを表す文字列を判別する方法としても知られており、しばしば "ブラウザ判別" とも呼ばれます)と、オブジェクや機能のサポートを判別する方法です。 ブラウザを識別する方法は、現在、複雑で、信頼できず、かつ、維持が難しいものとして知られています。

ブラウザを識別する方法(別名 "ブラウザ判別"):最適ではない、信頼できない方法

今でも一般的に使われているこの方法は、ブラウザを識別しようとするもので、設計時にブラウザの能力に応じてスクリプトの動きを Web ページ作成者が決めるのですが、これには問題の困難が伴います。Web ページ作成者はページを訪問するかもしれないすべての現行ブラウザの能力についての知識があり、コードがそれ対して適切であることが求められます。また、将来のブラウザで何が起こるかについて仮定するか、安全だが限定したサービスを提供することで手を打つこととなるので、初めに Web ページ作成者がブラウザとそれらのバージョンを正しく識別できることが求められます。これは信頼性の面からもとても適切とは言えず、決して簡単な作業でもありません。

ブラウザを識別する方法は、ブラウザのタイプを表す文字列、及び、ブラウザのバージョンを表す文字列の値をチェックし、 navigator.userAgent プロパティの文字列から一定の文字または部分文字列を検索する関数に依存します。一度 "判別すると、" Web ページ作成者は、異なる関数を用いたり(いわゆる、コードブランチ)、ユーザに異なるページ(いわゆる、サイトブランチ)や Web コンテンツ に誘導することになります。サイトブランチは、特に危険性を伴う可能性があります。なぜなら、ユーザが、"誤った" ブラウザを用いて、リンク、ブックマーク、検索エンジン、あるいは、キャッシュを通してページを訪問するかもしれないからです。

この方法の基本的な例を示します。

// BAD EXAMPLE
if (navigator.appVersion.charAt(0) = "8") {
  if (navigator.appName = "Netscape") {
    isNS8 = true;
    alert("NS8");
  };
} else if (navigator.appVersion.indexOf("MSIE")!= -1) {
  isIE = true;
  alert("IE");
};

上のコードにあるようなこの種のチェックは甘い可能性があり、賢明な読者なら、IE 8 がリリースされたときや、Opera 8.x ユーザがページを訪れたとき、あるいは appVersion 文字列が「8」で始まっている Netscape 以外のブラウザのユーザがページを訪れたときに何が起きるか首をかしげるかもしれません。新しいブラウザがリリースされるたび、ブラウザやそれらのバージョンを特定するためのこのようなコードを更新し、適切な切り換えを作ることが必要になります。

このアプローチにおけるもう一つの大きな問題は、ブラウザの自称名が偽装可能であるということです。最近の多くのブラウザでは navigator.appVersionnavigator.userAgent 文字列プロパティはユーザ設定可能な文字列だからです。例えば...

  • Firefox 1.x やすべての Mozilla ベースのブラウザでは、「general.useragent.*」文字列プロパティはどのような値にも設定できます。
  • Opera 6 以降では、ブラウザの自称名をメニューから設定できます。
  • MSIE は Windows レジストリを使用します。
  • Safari や Icab は、ブラウザの自称名を隠して Internet Explorer や Netscape で代用しています。

ユーザやブラウザのディストリビュータは navigator.userAgent に好きな文字列を置くことができます。これにより、あなたのコードがだまされて想定外のコードが実行されるかもしれません。それのみならず、厳密に認識されたブラウザでさえ、それと評価されたとおりに働かないケースが多々あります。

では、数あるブラウザに対して「嗅ぎ分け」が当てにならなかったり難しかったりするのであれば、様々なブラウザやバージョンに対して、あなたのコードをどうするのが安全でしょう?

オブジェクトや機能のサポートを判別する: 最適な、最も信頼性の高い方法

オブジェクト・機能サポートの判別を用いる場合、クライアントがサポートすることを最初にテストした機能だけを実装します。この方法にはブラウザがあなたのコードの特定の機能をサポートしているかどうかの確認以外のテストを必要としないという利点があります。

オブジェクト検出は次の例が分かりやすいでしょう。

function hideElement(id_attribute_value) {
  if (document.getElementById &&
      document.getElementById(id_attribute_value) &&
      document.getElementById(id_attribute_value).style
  ) {
    document.getElementById(id_attribute_value).style.visibility = "hidden";
  };
}

// 例:
// <button type="button" onclick="hideElement('d1');">div を隠す</button>
// <div id="d1">テキスト</div>

これらの document.getElementById の反復呼び出しは、そのブラウザの DOM 実装において特定のオブジェクトや機能が存在するかを調べる最善の方法ではありませんが、オブジェクトサポートの判別がどのように機能するかを分かりやすく説明するために載せています。

最上階層の if 文はドキュメントオブジェクトに getElementById とよばれるオブジェクトがあるかどうかを見ています。これはブラウザにおいて DOM のためのサポートのもっとも基本的なレベルです。もしあれば、コードは document.getElementById(id_attribute_value) が要素を返すかどうかを見ます。これは style オブジェクトのためのチェックです。もし、 style オブジェクトが要素にあれば、そのオブジェクトの visibility プロパティをセットします。もし、未定義のプロパティがあっても、ブラウザはエラーを出しません。ですので、 visibility プロパティ自身の有無はチェックする必要はありません。

つまり、どのブラウザのどのバージョンが特定の DOM メソッド (あるいは DOM の属性や機能) をサポートしているか知る必要はなく、訪問者のブラウザで特定のメソッドがサポートされているかどうかを確認できます。この方法を使えば、今後リリースされる、 未知の userAgent 文字列を持つブラウザも含め、どのブラウザでも、コードが動作し続けることを保証できます。

オブジェクトや機能をサポートを判別する方法についてのさらなる情報:

ドキュメントのタグと貢献者

 このページの貢献者: chrisdavidmills, ethertank, Potappo, kohei.yoshino
 最終更新者: chrisdavidmills,