Ошибка переопределения элемента addEventListener в Firefox - PullRequest
2 голосов
/ 25 января 2011

Я пытаюсь переопределить метод addEventListener объекта Element кросс-браузерным способом. Цель состоит в том, чтобы я мог асинхронно загружать некоторые сторонние сценарии, и эти сценарии вызывают этот метод преждевременно.

Я создал файл HTML, который отлично работает в Chrome, но в Firefox я получаю следующее исключение:

«Недопустимая операция с объектом-прототипом WrappedNative» nsresult: «0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)"

Если вы закомментируете строки в файле, которые изменяют методы INSTANCE, это работает. Но мне нужно сделать это на «типе класса» (то есть прототипе).

Любые предложения будут оценены.

Спасибо, Guypo

Вот файл, который я создал

<html><body>
<img id="testImg" src="http://www.blaze.io/wp-content/themes/Blaze/images/header_logoB.png">
<script>
function myLog(msg) { "undefined" != typeof(console) && console.log("Log: " + msg); }
function customListener(type, event, useCapture) {
  // Register the event
  myLog('Registering event');
  this._origListener.apply(this, arguments);
}
// Also tried HTMLImageElement
Element.prototype._origListener = Element.prototype.addEventListener;
Element.prototype.addEventListener = customListener;

var img = document.getElementById("testImg");
// Uncommenting these lines works - but in the real case I can't access these objects
//img._origListener = img.addEventListener;
//img.addEventListener = customListener;
img.addEventListener('load',function() { myLog('load callback'); }, false);

</script>
</body>
</html>

Ответы [ 2 ]

5 голосов
/ 08 мая 2011

Как говорит Марсель, это имеет отношение к способу экспонирования объектов. Проблема в том, что если вы переопределите предопределенное свойство интерфейса, оно не изменится в интерфейсах, которые наследуют от него (по крайней мере, в Firefox).

Хотя я согласен с замечаниями Марселя, на самом деле способ сделать это. Вы должны переопределить свойство минимально возможного интерфейса объекта, для которого вы хотите сделать это. В вашем случае это будет HTMLImageElement.

Это поможет:

(function() {
    var _interfaces = [ HTMLDivElement, HTMLImageElement /* ... (add as many as needed) */ ];
    for (var i = 0; i < _interfaces.length; i++) {
        (function(original) {
            _interfaces[i].prototype.addEventListener = function(type, listener, useCapture) {

                // DO SOMETHING HERE

                return original.apply(this, arguments);
            }
        })(_interfaces[i].prototype.addEventListener);
    }
})();
0 голосов
/ 25 января 2011
  1. Пожалуйста, используйте действительный Doctype, предпочтительно тот, который переводит браузеры в режим (Почти) Стандартов (<!DOCTYPE html> хорошо).оператор, вам не нужны скобки (но это не больно)

  2. Самое важное: не пытаться манипулировать DOM Element 's prototype: это хост-объекты, и вы не можете полагаться на хост-объекты, раскрывающие любой основных функций JavaScript объекта.Хуже того, может быть снижение производительности, и вы можете сломать другие вещи.Держитесь подальше от этой техники.Для получения дополнительной информации читайте Что не так с расширением DOM .

Чего вы хотите достичь, чтобы вы хотели, чтобы ваши слушатели событий вызывались автоматически прииспользуя сторонние скрипты?

...