2016-08-21 11 views
2

onloadイベントを各画像にバインドして、一度宣言することはできますか?私が試したが、それは(このエラーがスローされます。キャッチされない例外TypeError:不正な呼び出し)...作業を取得するために管理することはできませんJavaScript - HTMLImageElementの.onloadプロトタイプ

HTMLImageElement.prototype.onload = function() 
{ 
     console.log(this, "loaded"); 
}; 

PS:私もこのを返す試みたが、しかしありませんここで問題と思われる...私の現在のコードが機能していない理由に関する提案/説明?

+4

いいえ組み込みプロトタイプを使用しないでください。 – Bergi

+0

http://www.ncyoung.com/?p=194 – mplungjan

+0

@Bergiこれは空のビルトインプロトタイプです。これはイベントリスナーであり、カスタム関数のカスタム境界のために作られています。 –

答えて

1

onloadHTMLElement.prototypeで定義されたアクセサープロパティであるため、このエラーが発生します。

アクセサーをHTML要素でのみ呼び出すことになっていますが、HTML要素ではないHTMLImageElement.prototypeでセッターを呼び出しています。

この機能を定義する場合は、代わりにdefinePropertyを使用してください。

Object.defineProperty(HTMLImageElement.prototype, 'onload', { 
 
    configurable: true, 
 
    enumerable: true, 
 
    value: function() { 
 
    console.log(this, "loaded"); 
 
    } 
 
}); 
 
var img = new Image(); 
 
img.onload();

警告:組み込みのプロトタイプをいじり悪い習慣です。

ただし、これは関数を定義するだけです。この関数の名前がonloadであっても、イメージがロードされたときに関数が魔法のように呼び出されることはありません。

でも、リスナーでさえ内部的なものだからです。そうではありません。画像がロードされると、ブラウザはonloadメソッドを呼び出します。代わりに、onloadメソッドを設定すると、その関数はイベントリスナーとして内部的に格納され、画像がロードされるとブラウザはloadイベントリスナーを実行します。代わりに、適切な方法は、カスタム要素を作成するために、Webコンポーネントを使用することでしょう

var proto = Object.create(HTMLElement.prototype); 
 
proto.createdCallback = function() { 
 
    var img = document.createElement('img'); 
 
    img.src = this.getAttribute('src'); 
 
    img.addEventListener('load', function() { 
 
    console.log('loaded'); 
 
    }); 
 
    this.appendChild(img); 
 
}; 
 
document.registerElement('my-img', {prototype: proto});
<my-img src="/favicon.ico"></my-img>

多くのブラウザのサポートはしかし、まだありません。

+1

'defineProperty'も動作しません。 –

+0

T.Jが述べているように、どちらも動作しません。私は、ドキュメント内のすべての単一イメージのデフォルトの読み込み動作をセットアップしようとしています。回避策はありますか? –

+0

なぜ機能しないのですか?スニペットを参照してください、それは動作します。 – Oriol

2

プロトタイプではハンドラを設定できません。 loadがバブルをしないため

は実際に、私は、あなたが特定画像要素にloadを夢中にされていない場合は、画像のロードのための事前通知を取得する方法を認識していませんよ。

私は2つだけの一般的な「どこかにロードされたいくつかの画像」を実装する2つの方法を知っているメカニズム:

  1. 使用は明らかに複数のレベルに不満足であるタイマーループ、。しかし、それは機能します。それはむしろquerySelectorAllが行うようスナップショットを作成するよりも、継続的に更新(ライブ)HTMLCollectionimgの要素への参照を返すように、実際のクエリ(document.getElementsByTagName("img")は)悪くはないです。次に、Array.prototypeメソッドを使用することができます(必要に応じて、中間配列の作成を避けるために直接)。

  2. は、彼らのcompleteプロパティがtrueでない場合は、その後loadハンドラをフックアップ、新たに追加されimg要素や変更、既存のimg要素にsrc属性を監視するために変異オブザーバを使用してください。 JavaScriptコードは1つのUIスレッドで実行されていますが、ブラウザはマルチスレッドですから、JavaScriptコードが実行されているときでも、プロパティはブラウザによって変更される可能性があります。

+0

あなたの答えをありがとう。私は突然変異オブザーバを設定しようとしましたが、静的な要素(文書そのものに書かれているもの)を取り上げているようには見えません。 Observerの変異について読んだことがありますが、実際には現在のDOMの変化を検出するように設計されています。 –

+0

@ Bilal075_:HTMLのマークアップは、DOM内の要素になります(その目的です)。あなたが変異オブザーバのアプローチを行った場合は、すでに存在する要素のチェックを開始し、オブザーバを使って新しい 'img'要素や' src'が変更された 'img'要素を監視する必要があります。 –

+0

しかし、HTMLの '*'マークアップ '*に最初からあったこれらの要素に、(プログラムで)onloadリスナー*を追加する方法はありますか? –

0

イメージがロードされているかどうかを確認するために、しばらく前に何かを書いたことがあります。そうでない場合は、デフォルトイメージを表示します。同じアプローチを使用することができます。

$(document).ready(function() { 
    // loop every image in the page 
    $("img").each(function() { 
     // naturalWidth is the actual width of the image 
     // if 0, img is not loaded 
     // or the loaded img's width is 0. if so, do further check 
     if (this.naturalWidth === 0) { // not loaded 
      this.dataset.src = this.src; // keep the original src 
      this.src = "image404.jpg"; 
     } else { 
      // loaded 
     } 
    }); 
}); 
+0

ありがとうございますが、これはパフォーマンスの駆逐艦です。 –

0

これは、少なくともオペラ(プレスト)とFirefox(その他のブラウザを試していない)で、任意の画像のローディングのための通知を提供します。 scriptタグはHEAD要素に配置されているため、bodyコンテンツがロードされる前に実行され、イベントリスナーがインストールされます。

document.addEventListener('load', function(e) { 
    if ((!e.target.tagName) || (e.target.tagName.toLowerCase() != 'img')) return; 
    // do stuff here 
}, true); 

もちろん、tagNameにフィルタリングを変更することにより、それはまた、そのようなスクリプトタグとして、ロード・イベントを発生させ、他の要素のローディングに応答するのに役立つであろう。

関連する問題