Модераторы: Sardar, Aliance
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Реализуем addEventListener, не полный интерфейс EventTarget 
:(
    Опции темы
Sardar
Дата 16.4.2006, 17:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 16
Всего: 317



Когда то в теме "Всё о событиях" выкладывал код с реализацией addEventListener для ИЕ. Плюсы по сравнению с attachEvent были в наличии ссылки this указывающей на элемент, а не на window. Capturing mode для событий ИЕ никогда не поддерживал, потому полностью реализовать предписания W3C DOM 2 Event не удасться. Также не реализовывал dispatchEvent т.к. это редко кому в скриптах нужно.

Что получилось в итоге оставляю в посте. На написание натолкнул Burrr приватным письмом, отсюда просьба: народ, вы бы оставляли такие вопросы на форуме, а то у меня редко когда время есть, а отвечать игнором или "нет времени" не хочеться smile

Код
/**
* Реализуем частично интерфейс 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 не реализует сам, да пребудет с вами великая сила smile   


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Здесь публикуют скрипты, которые уже проверены в обсуждениях других тем (при этом полезно поставить ссылки на все смежные обсуждения) или переносятся кем-либо из модераторов по просьбе участников, если видно, что в результате обсуждения темы был написан полезный или интересный скрипт. Третий возможный вариант - участник форума публикует скрипт, заведомо известный как полезный и эффективный, для, возможно, небольшой доработки и обсуждения.
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: Наши скрипты | Следующая тема »


 




[ Время генерации скрипта: 0.0543 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.