1. ホーム
  2. jquery

[解決済み] Firefoxで開発したJavascriptがIEで失敗する典型的な理由は何ですか?[クローズド]

2022-10-29 09:33:45

質問

私は、最近の Firefox と Safari でうまく動作する、いくつかの javascript で強化されたページを開発しました。私は Internet Explorer で確認するのを忘れ、そして今、私は IE 6 と 7 (今のところ) でページが動作しないことを発見しました。スクリプトはなぜか実行されず、いくつかのjavascriptは実行されるものの、ページはjavascriptが存在しないかのように表示されます。YUI 2からYUI-LoaderとXML-http-Requestを使用し、1つのページでJQueryに依存する"psupload"を使用して、ドム操作の独自のライブラリを使用しています。

Office XPからMicrosoft Script Editorをインストールし、これからデバッグを行います。また、私は今、特定のテストを書きます。

IEの代表的な不具合箇所はどこでしょうか?どのような方向に目をつむればいいのか。

こんなページがありました。 癖のあるモード

あなたの経験から、最初に見るべき典型的なものを挙げていただけますか?

私はまた、後で特定のタスクのためにここでより多くの質問をするでしょうが、今のところ、私はなぜ IE が Firefox でうまく実行されるスクリプトで通常失敗するのか、あなたの経験に興味があります。

編集します。 たくさんの素晴らしい回答をありがとうございました

その間に、私はInternet Explorerでも動作するようにコード全体を適応させました。私は jQuery を統合し、その上に独自のクラスを構築しました。これは私の基本的なミスで、最初からすべてのものを jQuery 上で構築しませんでした。今はそうしています。

また、JSLintも私を大いに助けてくれました。

そして、異なる回答からの多くのシングルイシューが役に立ちました。

どのように解決したのですか?

エラー/省略などがあれば、このリストを更新してください。

注意してください。 IE9では以下の問題の多くが修正されているため、この多くはIE8以下と、ある程度癖のあるモードのIE9にしか当てはまりません。たとえば、IE9 は SVG をサポートしています。 <canvas> , <audio><video> はネイティブですが 標準準拠モードを有効にする を有効にする必要があります。


##一般的なこと

  • 部分的に読み込まれたドキュメントに関する問題。 JavaScript を window.onload などのイベントにJavaScriptを追加するのが良いでしょう。IEは部分的にロードされたドキュメントでの多くの操作をサポートしていません。

  • 異なる属性 : CSSでは elm.style.styleFloat であるのに対し、IEでは elm.style.cssFloat を Firefox で使用した場合。で <label> タグは for 属性にアクセスするには elm.htmlFor でアクセスするのに対して、IE では elm.for は Firefox のものです。なお for は IE で予約されているので elm['for'] はIEが例外を発生させないようにするためのより良いアイデアでしょう。


##ベースとなるJavaScriptの言語です。

  • 文字列中の文字にアクセスする : 'string'[0] は、本来のJavaScriptの仕様にないため、IEではサポートされていません。使用する 'string'.charAt(0) または 'string'.split('')[0] を使用するよりも、配列内のアイテムへのアクセスが大幅に高速化されることに注意してください。 charAt を使うよりもはるかに高速です (ただし、IE で split が最初に呼び出されたときに、若干のオーバーヘッドが発生します)。

  • オブジェクトの末尾にカンマを入れる。 {'foo': 'bar',} はIEでは使用できません。


##要素固有の問題

  • を取得する document IFrameの :

    • FirefoxとIE8+。 IFrame.contentDocument (IEはこれをサポートし始めました はバージョン8から .)
    • IEです。 IFrame.contentWindow.document
    • ( IFrame.contentWindowwindow を両ブラウザで表示します)。

  • キャンバスです。 IE9 より前のバージョンの IE は <canvas> 要素をサポートしていません。IE は VML をサポートしていますが、これは類似の技術であり エクスプローラキャンバス のインプレースラッパーを提供することができます。 <canvas> 要素のインプレースラッパーを提供できます。標準準拠モードの IE8 は、VML を使用する場合、癖のあるモードのときよりも何倍も遅く、多くの不具合があることに注意してください。

  • SVGです。 IE9 は SVG をネイティブでサポートしています。IE6-8 は SVG をサポートしますが、その場合は 外部プラグイン が必要で、そのうちのいくつかは JavaScript 操作をサポートしています。

  • <audio> そして <video> : はIE9でのみサポートされています。

  • ラジオボタンを動的に作成する。 IE <8 にはバグがあり、ラジオボタンを document.createElement で作成されたラジオボタンがチェックできなくなるバグがあります。また Javascriptで、すべてのブラウザで動作するラジオボタンを動的に作成する方法は? を参照してください。

  • でのJavaScriptの埋め込み <a href> タグと onbeforeunload の競合が IE で発生します。 にJavaScriptが埋め込まれている場合 href の部分に a タグの一部(例えば <a href="javascript: doStuff()"> と記述すると、IE は常に onbeforeunload から返されたメッセージを表示します。 onbeforeunload ハンドラが事前に削除されていなければなりません。また タブを閉じるときに確認を求める .

  • <script> タグのイベント差分です。 onsuccessonerror は IE ではサポートされていないため、IE 固有の onreadystatechange に置き換えられ、ダウンロードが成功したか失敗したかに関係なく実行されます。また JavaScript の狂気 を参照してください。


##要素のサイズ/位置/スクロールとマウスの位置。

  • 要素のサイズ/位置の取得 要素の幅や高さは、時々 elm.style.pixelHeight/Width でなく、IE では elm.offsetHeight/Width の方が良いのですが、IE ではどちらも信頼できず、特に癖のあるモードでは、どちらかが他よりも良い結果を出すことがあります。

elm.offsetTop そして elm.offsetLeft はしばしば正しく報告されないため、要素の位置が正しくなくなり、ポップアップ要素などが多くの場合、数ピクセルずれているのはそのためです。

また、要素 (または要素の親) に displaynone の場合、IE は size/position 属性にアクセスすると例外を発生させ、代わりに 0 を返すのではなく、Firefox のように例外を発生させます。

  • 画面サイズを取得する (画面の表示可能な領域を取得する)。

    • Firefox。 window.innerWidth/innerHeight
    • IE標準モードです。 document.documentElement.clientWidth/clientHeight
    • IE の癖のあるモード。 document.body.clientWidth/clientHeight

  • ドキュメントのスクロール位置/マウス位置 : これは実はw3cで定義されていないため、Firefoxでも非標準となっています。を見つけるには scrollLeft / scrollTopdocument :

    • FirefoxとIEの癖のあるモード。 document.body.scrollLeft/scrollTop

    • IE を標準モードで表示します。 document.documentElement.scrollLeft/scrollTop

    • NOTE 他のいくつかのブラウザでは pageXOffset / pageYOffset も同様です。

        function getDocScrollPos() {
         var x = document.body.scrollLeft ||
                 document.documentElement.scrollLeft ||
                 window.pageXOffset || 0,
             y = document.body.scrollTop ||
                 document.documentElement.scrollTop ||
                 window.pageYOffset || 0;
         return [x, y];
        };
      
      

    マウスカーソルの位置を取得するために evt.clientXevt.clientYmousemove イベントは、ドキュメントからの相対的な位置を与えます。 にスクロール位置を追加することなく ということで、前の関数を組み込む必要があります。

     var mousepos = [0, 0];
     document.onmousemove = function(evt) {
      evt = evt || window.event;
      if (typeof evt.pageX != 'undefined') {
       // Firefox support
       mousepos = [evt.pageX, evt.pageY];
      } else {
       // IE support
       var scrollpos = getDocScrollPos();
       mousepos = [evt.clientX+scrollpos[0], evt.clientY+scrollpos[1]];
      };
     };
    
    

##セレクション/レンジ


##IDで要素を取得する。

  • document.getElementById を参照することもできます。 name 属性を参照することもできます (どちらが先に定義されているかはドキュメントに依存します)。 nameid . これは id が w3c 標準でなかった頃にさかのぼります。 document.all ( は、IE 固有のプロパティである ) よりも大幅に高速です。 document.getElementById を常に優先してしまうという問題があります。 name よりも先に id . 私は個人的にこのコードを使っていますが、念のため追加のチェックでフォールバックしています。

     function getById(id) {
      var e;
      if (document.all) {
       e = document.all[id];
       if (e && e.tagName && e.id === id) {
        return e;
       };
      };
      e = document.getElementById(id);
      if (e && e.id === id) {
       return e;
      } else if (!e) {
       return null;
      } else {
       throw 'Element found by "name" instead of "id": ' + id;
      };
     };
    
    

##読み取り専用のinnerHTMLの問題点。

  • IE は をサポートしない の innerHTML を設定することができません。 col , colGroup , frameSet , html , head , style , table , tBody , tFoot , tHead , title そして tr といった要素があります。ここでは、テーブル関連要素のためにそれを回避する関数を紹介します。

     function setHTML(elm, html) {
      // Try innerHTML first
      try {
       elm.innerHTML = html;
      } catch (exc) {
       function getElm(html) {
        // Create a new element and return the first child
        var e = document.createElement('div');
        e.innerHTML = html;
        return e.firstChild;
       };
       function replace(elms) {
        // Remove the old elements from 'elm'
        while (elm.children.length) {
         elm.removeChild(elm.firstChild);
        }
        // Add the new elements from 'elms' to 'elm'
        for (var x=0; x<elms.children.length; x++) {
         elm.appendChild(elms.children[x]);
        };
       };
       // IE 6-8 don't support setting innerHTML for
       // TABLE, TBODY, TFOOT, THEAD, and TR directly
       var tn = elm.tagName.toLowerCase();
       if (tn === 'table') {
        replace(getElm('<table>' + html + '</table>'));
       } else if (['tbody', 'tfoot', 'thead'].indexOf(tn) != -1) {
        replace(getElm('<table><tbody>' + html + '</tbody></table>').firstChild);
       } else if (tn === 'tr') {
        replace(getElm('<table><tbody><tr>' + html + '</tr></tbody></table>').firstChild.firstChild);
       } else {
        throw exc;
       };
      };
     };
    
    

    また、IE では <tbody><table> を追加する前に <tr> を追加し、その <tbody> 要素で作成した場合 document.createElement を使って作成する場合、例えば

     var table = document.createElement('table');
     var tbody = document.createElement('tbody');
     var tr = document.createElement('tr');
     var td = document.createElement('td');
     table.appendChild(tbody);
     tbody.appendChild(tr);
     tr.appendChild(td);
     // and so on
    
    

##イベントの違い

  • を取得する event 変数を取得します。 DOM イベントは IE では関数に渡されず、アクセスできるのは window.event . イベントを取得する一般的な方法として、例えば

    elm.onmouseover = function(evt) {evt = evt||window.event}

    で、デフォルトは window.event もし evt が未定義である場合。

  • 主なイベントコードの違い。 キーイベント・コードは実にさまざまです。 奇数モード または JavaScript マッドネス のように、IEに特化したものではありませんし、SafariやOperaはまた別物です。

  • マウスイベントの違い。 その button 属性は、一度に複数のマウスボタンを許可するビットフラグです。

    • 左です。 1 ( var isLeft = evt.button & 1 )
    • 右です。 2 ( var isRight = evt.button & 2 )
    • センターです。 4 ( var isCenter = evt.button & 4 )

    W3C モデル (Firefox でサポート) は、IE モデルよりも柔軟性に欠け、left で一度に許可されるボタンは 1 つだけで、left は 0 として、右は 2 で、中央は 1 . なお、Peter-Paul Koch のように に言及しています。 として、これは非常に直感に反しています。 0 は通常「ボタンがない」ことを意味するからです。

    offsetX そして offsetY 問題あり であり、IEでは避けた方が無難でしょう。より確実な方法として offsetXoffsetY は、IEでは 位置を取得する を取得し、相対的に配置された要素の clientXclientY .

    また、IEでダブルクリックを取得するために click イベントでダブルクリックを取得するには clickdblclick イベントを関数に変換します。Firefox は click と同様に dblclick をダブルクリックした場合、IE 固有の検出が必要です。

  • イベント処理モデルの違い。 IE 独自のモデルと Firefox のモデルは、どちらもイベントを下から上に処理することをサポートしています。 <div><span></span></div> の両方の要素にイベントがある場合、イベントは span では その div という順番ではなく、従来の例えば elm.onclick = function(evt) {} が使われた場合の順序ではありません。

    "Capture" イベントは一般に Firefox などでサポートされているのみで、このイベントは div が発生し span のイベントをトップダウンで表示します。IEでは elm.setCapture() そして elm.releaseCapture() は、マウスイベントをドキュメントから要素にリダイレクトするためのものです ( elm にリダイレクトするためのものですが、パフォーマンスやその他の問題があるため、おそらく避けるべきでしょう。

    • Firefoxです。

      添付ファイル : elm.addEventListener(type, listener, useCapture [true/false])

      切り離す : elm.removeEventListener(type, listener, useCapture)

      ( type は、例えば 'mouseover' がなければ on )

    • IEです。 IEでは、ある要素に与えられたタイプのイベントは1つしか追加できません。同じタイプのイベントが複数追加された場合、例外が発生します。また thiswindow を参照します(従って、あまり有用ではありません)。

      アタッチ : elm.attachEvent(sEvent, fpNotify)

      切り離す : elm.detachEvent(sEvent, fpNotify)

      ( sEvent は、例えば 'onmouseover' )

  • イベント属性の違い。

    • 他のリスニング関数でイベントが処理されるのを止める :

      Firefoxです。 evt.stopPropagation()

      IEです。 evt.cancelBubble = true

    • キーイベントで文字の挿入を止めたり、チェックボックスのチェックを止めたりと。

      Firefox。 evt.preventDefault()

      IEです。 evt.returnValue = false

      を返すだけで falsekeydown , keypress , mousedown , mouseup , clickreset もデフォルトを防止します。

    • イベントを発生させた要素を取得します。

      Firefoxです。 evt.target

      IEです。 evt.srcElement

    • マウスカーソルが離れた要素を取得する。 evt.fromElement はIEでは evt.target である場合、Firefox では onmouseout イベント内であれば evt.relatedTarget

    • マウスカーソルが移動した要素の取得。 evt.toElement はIEでは evt.relatedTarget である場合、Firefox では onmouseout イベント内であれば evt.target

    • 注意 evt.currentTarget (イベントがバインドされた要素)はIEでは等価ではありません。