Когда то в теме "Всё о событиях" выкладывал код с реализацией addEventListener для ИЕ. Плюсы по сравнению с attachEvent были в наличии ссылки this указывающей на элемент, а не на window. Capturing mode для событий ИЕ никогда не поддерживал, потому полностью реализовать предписания W3C DOM 2 Event не удасться. Также не реализовывал dispatchEvent т.к. это редко кому в скриптах нужно. Что получилось в итоге оставляю в посте. На написание натолкнул Burrr приватным письмом, отсюда просьба: народ, вы бы оставляли такие вопросы на форуме, а то у меня редко когда время есть, а отвечать игнором или "нет времени" не хочеться  | Код | /** * Реализуем частично интерфейс EventTarget для DOM элементов в ИЕ. * Методы: * void addEventListener(type, EventListener, useCapture) * void removeEventListener(type, EventListener, useCapture) * * @author [email protected] * @license LGPL - http://opensource.org/licenses/lgpl-license.php * * При использовании этого кода указание всех авторов обязательно. Если вы * внесли существенное изменение в код или исправили ошибку, то вы обязаны по * условиям LGPL лицензии поделиться этим с другими, оставив ваше имя в авторах. * Код можно отсылать на e-mail [email protected] * Либо сюда: http://forum.vingrad.ru/index.php?showtopic=92169 * * http://forum.vingrad.ru/ */
/** Пользуем: * var div = document.getElementById("my_div"); * ensureEventTarget(div); //IE patch * div.addEventListener("mouseover", function(e) { * alert(this.tagName); //ссылка this указывает как нужно на элемент на который повесили событие * var tgt = getEventTarget(e); //на ком было событие, кроссплатформенная фукнция * //помним что под ИЕ это e.srcElement, а под DOM 2 Event e.target * alert(tgt.tagName); * }, * false //только false ибо capturing(true) не поддерживаеться ИЕ * ); */
/* Внимание, эта реализация не позовляет установить обработчика события в * capture режиме, т.к. ИЕ физически этот режим не поддерживает (увы чудес * творить не умеем...) * К счастью мало кто об этом слышал и пользовал этот режим, привычный bubbling * решает почти все проблемы. */
/** * Установить интерфейс EventListener для обьекта. * ИЕ не позволяет добраться до прототипов HTML элементов, придёться вызывать * эту функцию на каждом элементе. Естественно во всех других браузерах мы бы * обращатились к HTMLxxxEelement всего один раз, прозрачно предоставив "новый" * интерфейс. * @param Object obj обьект к которому добавляем необходимые элементы интерфейса EventListener */ function ensureEventTarget(obj) { if(!obj.addEventListener) obj.addEventListener = vin_myAddEventListener; if(!obj.removeEventListener) obj.removeEventListener = vin_myRemoveEventListener; }
//=======================- SPI -=============================== /** Реализуем addEventListener. * @param string name - тип события, обращаемся к DOM 2 Event * @param function func - обработчик события * @param dummyDirection - use capturing, игнорируеться */ function vin_myAddEventListener(name, func, dummyDirection) { if(!this._elisteners) this._elisteners={}; //регистр событий var sname = "~"+name; if(!this._elisteners[sname]) this._elisteners[sname]=[]; //стандартное поведение, если обработч. уже есть, то ничего не делаем for(var i=0; i<this._elisteners[sname].length; i++) if(this._elisteners[sname][i]==func) return; this._elisteners[sname].push(func); this["on"+name]=vin_myEventHandler; //регистрируем традиционное событие }
/** Реализуем removeEventListener. * Интересно что DOM 2 Event не предпологает методов "узнать" зарегистрирован * обработчик или нет, просто удаляй свои и всё. * @param string name - тип события, обращаемся к DOM 2 Event * @param function func - обработчик события * @param dummyDirection - use capturing, игнорируеться */ function vin_myRemoveEventListener(name, func, dummyDirection) { name = "~"+name; if(!this._elisteners || !this._elisteners[name]) return; for(var i=0; i<this._elisteners[name].length; i++) if(this._elisteners[name][i] == func) { this._elisteners[name].splice(i, 1); return; } }
/** Размножаем событие среди всех зарегистрированных обработчиков. * В спецификации порядок не известен, у нас же в порядке добавления. */ function vin_myEventHandler(e) { var evt = window.event? window.event: e; if(!evt) return; //тихо умираем, скрипты не любят исключений... var name = "~"+evt.type; //в принципе JS не многопоточен (исключаем XMLHttpRequest ;-) ) //тогда не реально что бы на одном обьекте одно событие исполнялось множество раз var uniquen = "vin_dont_touch_this_name_Im_trying_to_fuck_IE"+name; if(this._elisteners[name]) for(var i=0; i<this._elisteners[name].length; i++) { //долбанный IE5.0- не знает call и apply у функций... this[uniquen] = this._elisteners[name][i]; this[uniquen](evt); //эстетам предлагаю плюнуть на IE5.0- и юзать: //this._elisteners[name][i].call(this, evt); //а ещё лучше байкотировать ИЕ вообще ;-) } }
//=========================- Array i-face patch -=============================== /* В виду природной отстойности ИЕ5.0- он не имеет человеческого Array, реализуем некоторые необходимые функции. За инфой в спецификацию JS1.3 */
if(!Array.prototype.push) Array.prototype.push=function() { for(var i=0; i<arguments.length; i++) this[this.length]=arguments[i]; return this.length; };
if(!Array.prototype.splice) Array.prototype.splice=function(from, len) { var left=this.slice(0, from); var right=this.slice(from+len); var rem=this.slice(from, from+len); var add=[]; add.length=arguments.length-2; for(var i=2; i<arguments.length; i++) add[i-2]=arguments[i]; var ret=left.concat(add, right); this.length=0; //delete old items; for(var i=0; i<ret.length; i++) this[i]=ret[i]; return rem; }; //===================================- Utilites -=============================== /** Утилита достаёт обьект на котором было возбуждено событие. * @param evt обьект событие */ function getEventTarget(evt) { return evt.srcElement? evt.srcElement: evt.target; }
/** Достать код клавиши по которой нажали. * Функция отучивает ИЕ выдавать разного рода ctrl+char комбинации (<32) как * keyCode. То есть функция всегда возвращает код клавиши - буква латинского * алфавита. Также снимаеться charCode у мозиллы если keyCode == 0, что правильно * для контрольных комбинаций. * Кто реализовывал горячие клавишы поймёт о чём я =) * @param evt обьект событие */ function getKeyCode(evt) { evt = getEventTarget(evt); var key = evt.keyCode? evt.keyCode: evt.charCode; return getKeyCode.convkeys[String(key)]? getKeyCode.convkeys[String(key)]: key; } getKeyCode.convkeys={"1":65,"2":66,"4":68,"12":76,"16":80,"19":83,"20":84,"21":85,"26":90}; |
Тест, я сохранил скрипт выше в файле addevent.js | Код | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html><head><title>Test</title> <script src="addevent.js" type="text/javascript"></script> <style type="text/css"> #etc { border: 1px #555 dotted; text-align: center; padding: 20px; } </style> </head> <body> <div id="etc">Test</div>
<script type="text/javascript"> <!--
var d = document.getElementById("etc"); ensureEventTarget(d);
d.addEventListener("mouseover", function(e) { this.style.color="red"; this.style.fontWeight = "bold"; }, false);
d.addEventListener("mouseout", testOut, false);
function testOut() { this.style.color="black"; this.style.fontWeight = "normal"; }
function testRemove() { var d = document.getElementById("etc"); ensureEventTarget(d); d.removeEventListener("mouseout", testOut, false); } //--> </script> <button onclick="testRemove()">Remove mouseout</button> </body> </html> |
Да не понадобиться вам этот код, да поставим в игнор ИЕ пока он W3C DOM 2 Event не реализует сам, да пребудет с вами великая сила
--------------------
Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут.
|