JavaScript – écrasant .oncharge le prototype de HTMLImageElement (s)

Est-il possible de lier un événement onload à chaque image, en le déclarant une fois? J'ai essayé, mais je ne parviens pas à fonctionner … (cette erreur est lancée: Uncaught TypeError: Invocation illégale )

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

PS: J'ai également essayé de revenir, mais ne semble pas être le problème ici … des suggestions / explications sur la raison pour laquelle mon code actuel ne fonctionne pas?

Vous ne pouvez pas configurer un gestionnaire sur le prototype, non.

En fait, je ne connais aucun moyen d'obtenir une notification proactive pour la charge d'image si vous n'avez pas accroché la load sur l'élément d'image spécifique , car la load ne fait pas de bulle.

Je ne connais que deux façons de mettre en place un mécanisme général "quelque image quelque part chargé"

  1. Utilisez une boucle de minuterie, qui est manifestement insatisfaisante sur plusieurs niveaux. Mais ça fonctionne. La requête réelle ( document.getElementsByTagName("img") n'est pas si mauvaise puisqu'elle renvoie une référence à la HTMLCollection continue mise à jour (en direct) des éléments img , plutôt que de créer un instantané comme querySelectorAll . Ensuite, vous pouvez utiliser les méthodes Array.prototype (directement, pour éviter de créer un tableau intermédiaire, si vous le souhaitez).

  2. Utilisez un observateur de mutation pour surveiller les nouveaux éléments img ajoutés ou l'attribut src sur les éléments img existants en cours de modification, puis branchez un gestionnaire de load si leur propriété complete n'est pas vraie. (Vous devez être prudent avec les conditions de course, la propriété peut être modifiée par le navigateur même si votre code JavaScript est en cours d'exécution, car votre code JavaScript fonctionne sur un seul thread UI, mais le navigateur est multi-thread.)

Vous obtenez cette erreur car onload est une propriété d' HTMLElement.prototype définie dans HTMLElement.prototype .

Vous êtes censé appeler l'accesseur uniquement sur des éléments HTML, mais vous appelez le setter sur HTMLImageElement.prototype , qui n'est pas un élément HTML.

Si vous souhaitez définir cette fonction, utilisez defineProperty place.

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

J'ai écrit quelque chose de similaire il y a quelque temps pour vérifier si une image est chargée ou non, et sinon, afficher une image par défaut. Vous pouvez utiliser la même approche.

 $(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 } }); });