web-dev-qa-db-ja.com

すべてのブラウザーの画像読み込み時のJavaScript / jQueryイベントリスナー

私はこれをできるだけ多くのブラウザに実装する方法を探しています:

_var image = new Image();
image.addEventListener("load", function() {
                               alert("loaded");
}, false);
image.src = "image_url.jpg";
_

これはIEでは機能しませんでしたので、Googleで調べたところ、9未満のIEは.addEventListener()をサポートしていないことがわかりました。.bind()ですが、Image()では機能しません。IEでも機能するようにするには、何を変更する必要がありますか?

22
matteok

IEは代わりにattachEventをサポートします。

image.attachEvent("onload", function() {
    // ...
});

JQueryでは、次のように書くことができます

$(image).load(function() {
    // ...
});

イベントに関しては、jQueryを使用する可能性がある場合は、ブラウザーの互換性に対応するため、jQueryを使用することをお勧めします。あなたのコードはすべての主要なブラウザで動作し、あなたはそれについて心配する必要はありません。

IEでロードイベントが発生するためには、画像がキャッシュからロードされないことを確認する必要があることにも注意してください。そうでない場合、IEはロードイベントを発生しません。

これを行うには、次のように、画像のURLの最後にダミー変数を追加します

image.setAttribute( 'src', image.getAttribute('src') + '?v=' + Math.random() );

JQuery loadメソッドを使用した既知の問題には、次のものがあります。

画像で使用した場合のロードイベントの注意事項

開発者が.load()ショートカットを使用して解決しようとする一般的な課題は、画像(または画像のコレクション)が完全に読み込まれたときに関数を実行することです。これには、注意すべきいくつかの既知の警告があります。これらは:

  • それは一貫して動作せず、確実にクロスブラウザではありません
  • 画像のsrcが以前と同じsrcに設定されている場合、WebKitで正しく起動しません
  • DOMツリーを正しくバブルアップしません
  • ブラウザーのキャッシュに既に存在する画像については、起動を停止できます

詳細は jQuery docs を参照してください。

29
Jose Faeti

.attachEvent()ではなく .addEventListener() を使用する必要があります。

if (image.addEventListener) {
  image.addEventListener('load', function() {
       /* do stuff */ 
  });
} else {
  // it's IE!
  image.attachEvent('onload', function() {
    /* do stuff */
  });
}
7
Alex

new Imageは基本的に<img>タグを返すので、jQueryで http://jsfiddle.net/pimvdb/LAuUR/1/ のようにコーディングできます。

$("<img>", { src: '...' })
    .bind('load', function() {
        alert('yay');
    });

EDIT:有効な画像をロードする場合

$('.buttons').html('');

var range = [];
for (var i = 1; i <=50; i++) range.Push(i);

range.forEach(function(i) {
  var img_src = 'http://i.imgur.com/' + i + '.jpg';
  var $img = $("<img>", {
    src: img_src
  });

  $img.on('load', function() {
    $('.buttons').append($img);
  });

  $img.on('error', function() {
  });

});
2
pimvdb

attachEvent を使用できますが、 addEventListener リスナーを自分で追加することをお勧めします。イベントリスナーを追加するためのMDNリンクのコードは次のとおりです。

if (!Element.prototype.addEventListener) {
    var oListeners = {};
    function runListeners(oEvent) {
        if (!oEvent) { oEvent = window.event; }
        for (var iLstId = 0, iElId = 0, oEvtListeners = oListeners[oEvent.type]; iElId < oEvtListeners.aEls.length; iElId++) {
            if (oEvtListeners.aEls[iElId] === this) {
                for (iLstId; iLstId < oEvtListeners.aEvts[iElId].length; iLstId++) { oEvtListeners.aEvts[iElId][iLstId].call(this, oEvent); }
                break;
            }
        }
    }
    Element.prototype.addEventListener = function (sEventType, fListener /*, useCapture (will be ignored!) */) {
        if (oListeners.hasOwnProperty(sEventType)) {
            var oEvtListeners = oListeners[sEventType];
            for (var nElIdx = -1, iElId = 0; iElId < oEvtListeners.aEls.length; iElId++) {
                if (oEvtListeners.aEls[iElId] === this) { nElIdx = iElId; break; }
            }
            if (nElIdx === -1) {
                oEvtListeners.aEls.Push(this);
                oEvtListeners.aEvts.Push([fListener]);
                this["on" + sEventType] = runListeners;
            } else {
                var aElListeners = oEvtListeners.aEvts[nElIdx];
                if (this["on" + sEventType] !== runListeners) {
                    aElListeners.splice(0);
                    this["on" + sEventType] = runListeners;
                }
                for (var iLstId = 0; iLstId < aElListeners.length; iLstId++) {
                    if (aElListeners[iLstId] === fListener) { return; }
                }           
                aElListeners.Push(fListener);
            }
        } else {
            oListeners[sEventType] = { aEls: [this], aEvts: [ [fListener] ] };
            this["on" + sEventType] = runListeners;
        }
    };
    Element.prototype.removeEventListener = function (sEventType, fListener /*, useCapture (will be ignored!) */) {
        if (!oListeners.hasOwnProperty(sEventType)) { return; }
        var oEvtListeners = oListeners[sEventType];
        for (var nElIdx = -1, iElId = 0; iElId < oEvtListeners.aEls.length; iElId++) {
            if (oEvtListeners.aEls[iElId] === this) { nElIdx = iElId; break; }
        }
        if (nElIdx === -1) { return; }
        for (var iLstId = 0, aElListeners = oEvtListeners.aEvts[nElIdx]; iLstId < aElListeners.length; iLstId++) {
            if (aElListeners[iLstId] === fListener) { aElListeners.splice(iLstId, 1); }
        }
    };
}
2
Shef

これを行う最善の方法は、jQueryの組み込みload()またはプレーンJSの代わりに、jQueryとjQueryプラグイン imagesLoaded を使用することです。プラグインは、jQueryドキュメントが参照するさまざまなブラウザーの癖、つまり、キャッシュされた画像と、新しい画像のsrcが同じ場合のコールバックの再起動を処理します。 jquery.imagesloaded.min.js をダウンロードし、<script src="jquery.imagesloaded.min.js"></script>を使用して追加するだけです。

$(image).imagesLoaded(function() {
    alert("loaded");
});
1
tobek