Как ссылаться на объект вызывающей стороны ("this") с помощью attachEvent - PullRequest
13 голосов
/ 04 января 2011

Используя метод .attachEvent() в IE, как я могу ссылаться на объект вызывающего (элемент, который вызвал событие) с помощью this? В браузерах normal , использующих .addEventListener, переменная this указывает на элемент, а в IE - на объект window.

Мне нужно, чтобы он работал со следующим кодом:

var element = //the element, doesn't matter how it is obtained
element.addAnEvent = function(name, funct){
   if(element.addEventListener) // Works in NORMAL browsers...
   else if(element.attachEvent){
     element.attachEvent("on"+name, funct);
     //where the value of "this" in funct should point to "element"
   }
}

Я только что создал этот код, он не точно такой же, как мой код, но если он работает с ним, он работает со мной!

Ответы [ 4 ]

16 голосов
/ 04 января 2011

С эта статья причудливого режима в отношении attachEvent:

  1. События всегда пузырьковые, без возможности захвата.
  2. Функция обработки событийссылается, а не копируется, , поэтому ключевое слово this всегда относится к окну и совершенно бесполезно .

Результатом этих двух недостатков является то, что когда событие всплывает, ононевозможно узнать, какой элемент HTML в настоящее время обрабатывает событие.Я объясню эту проблему более подробно на странице «Порядок событий».

Поскольку модель добавления событий Microsoft поддерживается только в Windows Explorer 5 и выше, ее нельзя использовать для кросс-браузерных сценариев.Но даже для приложений, использующих только Explorer-on-Windows, лучше не использовать его, поскольку проблема пузырей может быть довольно сложной в сложных приложениях.

Я не тестировал ее, но возможный обходной путь можетбыть обернуть обработчик в анонимную функцию, которая вызывает ваш обработчик через funct.call().

else if(element.attachEvent){
   element.attachEvent("on"+name, function(){ funct.call( element ) });
}

Мои извинения за непроверенное решение.Мне это не нравится, но сейчас я не могу легко добраться до IE.

10 голосов
/ 04 января 2011

Если вы находитесь в IE, вы можете получить объект «вызывающий», как вы его называете, путем доступа к window.event.srcElement в функции обработчика событий.Этот объект обычно упоминается как событие target или source .

var funct = function(event) {
    if ( !event ) {
        event = window.event;
    }

    var callerElement = event.target || event.srcElement;

    // Do stuff
};

Этот код не проверен, но он должен направить вас в правильном направлении.

0 голосов
/ 04 января 2011

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

Element.prototype.addAnEvent = function(name, funct){
   if(this.addEventListener) // Works in NORMAL browsers...
   {
     this.addEventListener(name,funct, false);
   }
   else if(this.attachEvent){
     var _this = this;
     this.attachEvent("on"+name, function(){funct.apply(_this);});
     //where the value of "this" in funct should point to "element"
   }
};

Таким образом, он будет работать для всех ваших текущих и будущих элементов (, и вам нужно будет запустить его только один раз ).

0 голосов
/ 04 января 2011

Свяжите это.Ну, вы не можете использовать Function.prototype.bind, который добавляется в javascript 1.8.5, но вы можете использовать closure и Function.prototype.apply.

var element = //the element, doesn't matter how it is obtained
element.addAnEvent = function(name, funct){
   if(element.addEventListener) // Works in NORMAL browsers...
     //...
   else if(element.attachEvent){
     element.attachEvent("on"+name, function() {
       //call funct with 'this' == 'element'
       return funct.apply(element, arguments);
     });
   }
}
...