Author |
Message |
Shira
Участник форума
Joined: 13 May 2007
Posts: 65
Карма: 0 поощрить/наказать
Location: Россия, Москва
|
Posted: Sat Feb 21, 2009 2:37 pm (написано за 12 минут 11 секунд)
Post subject: onMouseDown - вызывающий объект
|
|
Всем доброго времени суток!!!! Вот к примеру такой html-код: Code (html): | скопировать код в буфер обмена | <table> (december.com/html/4/element/table.html) <tr (december.com/html/4/element/tr.html) id="tr1"> (december.com/html/4/element/.html) <td (december.com/html/4/element/td.html) id="td1"> (december.com/html/4/element/.html)<a (december.com/html/4/element/a.html) id="a1"> (december.com/html/4/element/.html)bla-bla-bla</a></td> <td (december.com/html/4/element/td.html) id="td2"> (december.com/html/4/element/.html)bla-bla-bla</td> </tr> </table> | и примерно такой скрипт javascript: Code (JavaScript): | скопировать код в буфер обмена | function ms_dn(event){ var e = window.event?window.event.srcElement:event.currentTarget; alert(e.tagName); // } // addEventListener(document.getElementById("tr1"), 'mousedown', ms_dn); | Как вы наверное уже догадались при клике на, допустим, ссылку (id="a1"), алетр выведет A, т.е. название тэга ссылки. А хотелось бы в этой функции получать объект некоторый непосредственно вызвал событие, а в событии которого прописана обработка этого самого события. В общем, что бы получать не A, не TD, а именно TR!!! Как так сделать? Быть может есть готовые решения...
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Sun Feb 22, 2009 9:06 am (спустя 18 часов 28 минут; написано за 9 секунд)
Post subject:
|
|
Shira, Code (JavaScript): | скопировать код в буфер обмена | var e = window.event?window.event.srcElement.parentNode.parentNode:event.currentTarget.parentNode.parentNode; |
|
|
Back to top |
|
 |
Shira
Участник форума
Joined: 13 May 2007
Posts: 65
Карма: 0 поощрить/наказать
Location: Россия, Москва
|
Posted: Sun Feb 22, 2009 9:17 am (спустя 11 минут; написано за 1 минуту 46 секунд)
Post subject:
|
|
Александр Михалицын, ну, к примеру, для данного случая это подойдет для клика по ссылке, а для клика по ячейке (TD) нет.... Короче, как я понял, универсального выхода нету...
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Sun Feb 22, 2009 9:25 am (спустя 8 минут; написано за 2 минуты 6 секунд)
Post subject:
|
|
Shira, ммм. Тоесть вам надо чтобы при возникновении события всегда выводило TR? Зачем вы тогда вообще работаете с событием? Не проще ли просто document.getElementById("tr1")?
|
|
Back to top |
|
 |
Shira
Участник форума
Joined: 13 May 2007
Posts: 65
Карма: 0 поощрить/наказать
Location: Россия, Москва
|
Posted: Sun Feb 22, 2009 9:28 am (спустя 2 минуты; написано за 1 минуту 11 секунд)
Post subject:
|
|
Александр Михалицын, так а если не известно какой из TR'ов запускает событие? Я просто так и представлял, что какому тэгу присвоено событие, он и возвращается таргетом....
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Sun Feb 22, 2009 9:42 am (спустя 14 минут; написано за 2 минуты 41 секунду)
Post subject:
|
|
Shira, В случае с addEventListener (obj.addEventListener('sob', func, true/false)), таргет указывает на тот объект, по которому прошло событие (как и в случае с прямым указателем обработчика). Пользоваться надо так: Code (JavaScript): | скопировать код в буфер обмена | <table> <tr id="tr1"> <td id="td1">some_text<a id="a1">bla-bla-bla</a></td> <td id="td2">bla-bla-bla</td> </tr> </table> <script> function interprit(event) { alert(event.target.tagName); } document.getElementById("td1").addEventListener('click', interprit, true); </script> | Кликнете по тд -- укажет на него, на A -- укажет на A.
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 268 поощрить/наказать
Location: Питер
|
Posted: Sun Feb 22, 2009 12:16 pm (спустя 2 часа 34 минуты; написано за 2 минуты 55 секунд)
Post subject:
|
|
Есть такая дока MDC::Comparison_of_Event_Targets (developer.mozilla.org/en/DOM/event/Comparison_of_Event_Targets). К сожалению, подобное не поддерживается в IE. Я написал спец. либу (менеджер событий), предназначенную для разруливания этой проблемы: svn.debugger.ru/repos/jslibs/BrowserExtensions/trunk/eventmanager.js. Можете попробовать использовать её, или вытащить оттуда всё относящееся к "rootEHCaller".
|
|
Back to top |
|
 |
dimagolov
Участник форума
Joined: 04 Feb 2007
Posts: 1664
Карма: 96 поощрить/наказать
Location: Christ Church, Barbados
|
Posted: Sun Feb 22, 2009 5:49 pm (спустя 5 часов 32 минуты; написано за 39 секунд)
Post subject:
|
|
А что мешает просто подниматься по parentNode пока не получем элемент типа tr ?
|
|
Back to top |
|
 |
WingedFox
Профессионал

Joined: 29 Apr 2003
Posts: 4064
Карма: 268 поощрить/наказать
Location: Питер
|
Posted: Sun Feb 22, 2009 5:50 pm (спустя 1 минуту 16 секунд; написано за 46 секунд)
Post subject:
|
|
dimagolov
Некоторые любят вкладывать таблицы в таблицы =) Да и долго это, если документ сложный.
|
|
Back to top |
|
 |
Denis Usenko
Участник форума
Joined: 06 Feb 2006
Posts: 54
Карма: 13 поощрить/наказать
|
Posted: Mon Feb 23, 2009 12:40 am (спустя 6 часов 49 минут; написано за 4 минуты 33 секунды)
Post subject:
|
|
Shira, есть простой но нерекомендуемый способ -- это вешать обработчик напрямую: node.onmousedown = function () {} тогда в ИЕ this будет указывать куда надо. Если нужна возможность вешать любое количество обработчиков, то используйте какой-либо фреймворк либо пишите свой. Можно глянуть на этот код (из книжки Джона): Листинг 6.15. Библиотека addEvent/removeEvent, созданная Дином Эдвардсом Code (JavaScript): | скопировать код в буфер обмена | // addEvent/removeEvent written by Dean Edwards, 2005 // with input from Tino Zijdel // http://dean.edwards.name/weblog/2005/10/add-event/ function addEvent(element, type, handler) { // присвоение каждому обработчику события уникального ID if (!handler.$$guid) handler.$$guid = addEvent.guid++; // создание хэш-таблицы видов событий для элемента if (!element.events) element.events = {}; // создание хэш-таблицы обработчиков событий для каждой пары // элемент-событие var handlers = element.events[type]; if (!handlers) { handlers = element.events[type] = {}; // сохранение существующего обработчика события // (если он существует) if (element["on" + type]) { handlers[0] = element["on" + type]; } } // сохранение обработчика события в хэш-таблице handlers[handler.$$guid] = handler; // назначение глобального обработчика события для выполнения // всей работы element["on" + type] = handleEvent; }; // счетчик, используемый для создания уникальных ID addEvent.guid = 1; function removeEvent(element, type, handler) { // удаление обработчика события из хэш-таблицы if (element.events && element.events[type]) { delete element.events[type][handler.$$guid]; } }; function handleEvent(event) { var returnValue = true; // захват объекта события (IE использует глобальный объект события) event = event || fixEvent(window.event); // получение ссылки на хэш-таблицу обработчиков событий var handlers = this.events[event.type]; // выполнение каждого обработчика события for (var i in handlers) { this.$$handleEvent = handlers[i]; if (this.$$handleEvent(event) === false) { returnValue = false; } } return returnValue; }; // Добавление к объекту события IE некоторых "упущенных" методов function fixEvent(event) { // добавление стандартных методов событий W3C event.preventDefault = fixEvent.preventDefault; event.stopPropagation = fixEvent.stopPropagation; return event; }; fixEvent.preventDefault = function() { this.returnValue = false; }; fixEvent.stopPropagation = function() { this.cancelBubble = true; }; |
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Mon Feb 23, 2009 9:34 am (спустя 8 часов 54 минуты; написано за 1 минуту 39 секунд)
Post subject:
|
|
Denis Usenko wrote: |
это вешать обработчик напрямую: node.onmousedown = function () {} тогда в ИЕ this будет указывать куда надо. | , this указывает на объект для которого установлен текущий обработчик и при addEventListener, а вот при attachEvent (в IE) -- нет. (typeof this.tagName === "undefined").
|
|
Back to top |
|
 |
Shira
Участник форума
Joined: 13 May 2007
Posts: 65
Карма: 0 поощрить/наказать
Location: Россия, Москва
|
Posted: Mon Feb 23, 2009 2:07 pm (спустя 4 часа 33 минуты; написано за 1 минуту 9 секунд)
Post subject:
|
|
Denis Usenko, спасибо! В том случае, если назначать обработчика, как Вы сказали, то this не только в ие указывает на нужный объект!
|
|
Back to top |
|
 |
Shira
Участник форума
Joined: 13 May 2007
Posts: 65
Карма: 0 поощрить/наказать
Location: Россия, Москва
|
Posted: Mon Feb 23, 2009 2:18 pm (спустя 11 минут; написано за 3 минуты 23 секунды)
Post subject:
|
|
Блин, но если такой вариант использовать в firefox, то когда функция-обработчик возвращает false, то firefox все равно продолжает обработку события. Т.е. если кликаю на ссылку в ячейке(а обработка события повешана на ячейку), то он и функцию запускает и совершает клик на ссылку. Есть лекарство? Причем в firefox не помогает ни event.preventDefault(), ни event.stopPropagation()!!!
|
|
Back to top |
|
 |
Denis Usenko
Участник форума
Joined: 06 Feb 2006
Posts: 54
Карма: 13 поощрить/наказать
|
Posted: Mon Feb 23, 2009 11:23 pm (спустя 9 часов 4 минуты; написано за 10 минут 9 секунд)
Post subject:
|
|
Александр Михалицын Александр Михалицын wrote: |
Denis Usenko wrote: |
это вешать обработчик напрямую: node.onmousedown = function () {} тогда в ИЕ this будет указывать куда надо. | , this указывает на объект для которого установлен текущий обработчик и при addEventListener, а вот при attachEvent (в IE) -- нет. | О чем и речь, вроде общеизвестный факт )). Если скрипт маленький и простой, можно юзать прямое присваивание обработчиков, если что-то более серьезное -- юзать один из фреймворков (их намного больше чем два общеизвестных ), либо писать свою работы с событиями. Александр Михалицын wrote: |
(typeof this.tagName === "undefined"). | Точнее ((this === window) == true) Shira Quote: |
Блин, но если такой вариант использовать в firefox, то когда функция-обработчик возвращает false, то firefox все равно продолжает обработку события. Т.е. если кликаю на ссылку в ячейке(а обработка события повешана на ячейку), то он и функцию запускает и совершает клик на ссылку. Есть лекарство? Причем в firefox не помогает ни event.preventDefault(), ни event.stopPropagation()!!! | Если Вы ловите "mousedown", то тоже самое у Вас будет и при addEventListener, проверьте. Ловите "click". Code (html): | скопировать код в буфер обмена | <table (december.com/html/4/element/table.html) border="1" cellpadding="5"> (december.com/html/4/element/.html) <tr> (december.com/html/4/element/tr.html) <td> (december.com/html/4/element/td.html)<a (december.com/html/4/element/a.html) href="2.html"> (december.com/html/4/element/.html)1.1</a></td> <td> (december.com/html/4/element/td.html)<a (december.com/html/4/element/a.html) href="2.html"> (december.com/html/4/element/.html)1.2</a></td> <td> (december.com/html/4/element/td.html)<a (december.com/html/4/element/a.html) href="2.html"> (december.com/html/4/element/.html)1.3</a></td> </tr> <tr> (december.com/html/4/element/tr.html) <td> (december.com/html/4/element/td.html)<a (december.com/html/4/element/a.html) href="2.html"> (december.com/html/4/element/.html)2.1</a></td> <td> (december.com/html/4/element/td.html)<a (december.com/html/4/element/a.html) href="2.html"> (december.com/html/4/element/.html)2.2</a></td> <td> (december.com/html/4/element/td.html)<a (december.com/html/4/element/a.html) href="2.html"> (december.com/html/4/element/.html)2.3</a></td> </tr> </table>
<div (december.com/html/4/element/div.html) id="debug-display"> (december.com/html/4/element/.html)...</div>
<script> (december.com/html/4/element/script.html)
onload = function () { var list = document.getElementsByTagName('td'); for(var i = 0, l = list.length; i < (december.com/html/4/element/.html) l; i++) { var el = list[i]; el.onclick = function () { document.getElementById("debug-display").firstChild.nodeValue = this.innerHTML return false } } }
</script> |
|
|
Back to top |
|
 |
Shira
Участник форума
Joined: 13 May 2007
Posts: 65
Карма: 0 поощрить/наказать
Location: Россия, Москва
|
Posted: Tue Feb 24, 2009 12:05 am (спустя 42 минуты; написано за 27 секунд)
Post subject:
|
|
В общем всем спасибо. проблема решена. Через присвоение напрямую (obj.onmousedown = func_name) не работало в старой мозиле, обновил, заработало! Denis Usenko, почему Вы писали, что это не рекомендуемый способ?
|
|
Back to top |
|
 |
Denis Usenko
Участник форума
Joined: 06 Feb 2006
Posts: 54
Карма: 13 поощрить/наказать
|
Posted: Tue Feb 24, 2009 4:51 am (спустя 4 часа 46 минут; написано за 16 минут 14 секунд)
Post subject:
|
|
Обычно говорят о двух недостатках -- нельзя повесить более одного обработчика, и сложность с утечками в ие. Сейчас проверил, [del]код от Дина Эдвардса течет (Теперь понятно почему несмотря на восторги Джона по поводу этого кода он его не юзает в ДжКвери ),[/del] мой пример тоже, а вот так уже нет: Code (JavaScript): | скопировать код в буфер обмена | onload = function () { var list = document.getElementsByTagName('td'); for(var i = 0, l = list.length; i < l; i++) { list[i]['onclick'] = function () { document.getElementById("debug-display").firstChild.nodeValue = this.innerHTML return false }
} } | То есть такой подход можно юзать, но придется все время контролировать код на memleak в ие. Поэтому для нормальной работы надо или юзать готовую либу (например ту что предложил WingedFox) или посмотреть как делается это в других либах и написать свою. PS. Извиняюсь, напраслину возвел на великого гуру )) Утечек в примере от джона нет, это я так его заюзал ))
|
|
Back to top |
|
 |
Denis Usenko
Участник форума
Joined: 06 Feb 2006
Posts: 54
Карма: 13 поощрить/наказать
|
Posted: Tue Feb 24, 2009 5:27 am (спустя 36 минут; написано за 2 минуты 37 секунд)
Post subject:
|
|
Shira
Нды, насчет утечек при присваивании обработчиков, -- я похоже просто повторяю читанную в интернетах ерунду )) С ними в любом случае проблемы, хоть с attachEvent, хоть присваиванием, а следить за этим надо.
|
|
Back to top |
|
 |
Shira
Участник форума
Joined: 13 May 2007
Posts: 65
Карма: 0 поощрить/наказать
Location: Россия, Москва
|
Posted: Wed Feb 25, 2009 10:40 am (спустя 1 день 5 часов 13 минут; написано за 8 минут 43 секунды)
Post subject:
|
|
Denis Usenko, просто либо я не знаю что такое утечки, либо вообще не понимаю..... зачем следать, что может произойти? + Еще вопрос один. Допустим такой код: Code (JavaScript): | скопировать код в буфер обмена | function ttt(){ ... } ttt.prototype.t1 = 1; ttt.prototype.t2 = 'test'; ttt.prototype.t3 = function(){ document.getElementById('tr1').cl_name = this; // tr1 некий объект в html коде } var temp = new ttt(); temp.t3(); temp.t1 = 3; alert(document.getElementById('tr1').cl_name.t1); | алерт выведет '3' или '1'? Т.е. document.getElementById('tr1').cl_name = this; сработает как присвоение класса с текущими параметрами или ссылка на этот, конкретно созданный, класс?
|
|
Back to top |
|
 |
dimagolov
Участник форума
Joined: 04 Feb 2007
Posts: 1664
Карма: 96 поощрить/наказать
Location: Christ Church, Barbados
|
Posted: Wed Feb 25, 2009 7:17 pm (спустя 8 часов 37 минут; написано за 9 минут 3 секунды)
Post subject:
|
|
Shira wrote: |
алерт выведет '3' или '1'? Т.е. document.getElementById('tr1').cl_name = this; сработает как присвоение класса с текущими параметрами или ссылка на этот, конкретно созданный, класс? | это викторина? Сами не пробовали?
|
|
Back to top |
|
 |
Zeroglif
Участник форума
Joined: 02 Jan 2006
Posts: 293
Карма: 61 поощрить/наказать
|
Posted: Thu Feb 26, 2009 11:20 am (спустя 16 часов 2 минуты; написано за 1 минуту 27 секунд)
Post subject:
|
|
Shira wrote: |
Т.е. document.getElementById('tr1').cl_name = this; сработает как присвоение класса с текущими параметрами или ссылка на этот, конкретно созданный, класс? | В js нет классов! У некой ноды создано новое свойство 'cl_name', значением этого свойства является значение 'this' при вызове метода 'temp.t3()'. Значением 'this' является объект, созданный ранее как 'new ttt()'. Таким образом, мы можем обращаться к одному и тому же объекту 'через document.getElementById('tr1').cl_name' или через 'temp'. Алерт выведет '3', т.к. именно это значение у свойства 't1' в момент вызова алерта.
|
|
Back to top |
|
 |
Александр Михалицын
Модератор
Joined: 23 May 2008
Posts: 1299
Карма: 83 поощрить/наказать
|
Posted: Thu Feb 26, 2009 12:08 pm (спустя 48 минут; написано за 22 секунды)
Post subject:
|
|
Zeroglif, угу. Правильнее было сказать "объект". ;)
|
|
Back to top |
|
 |
Denis Usenko
Участник форума
Joined: 06 Feb 2006
Posts: 54
Карма: 13 поощрить/наказать
|
Posted: Sun Mar 01, 2009 7:37 am (спустя 2 дня 19 часов 28 минут; написано за 11 секунд)
Post subject:
|
|
Shira
Упс, просмотрел обновление темы, хоть и заглядывал на форум. На второй вопрос Вам подробно ответили, а по первому: Shira wrote: |
Denis Usenko, просто либо я не знаю что такое утечки, либо вообще не понимаю..... зачем следать, что может произойти? | держите ссылков: www.codeproject.com/KB/scripting/leakpatterns.aspx
web-log.ru/?p=21
webo.in/articles/habrahabr/24-memory-leaks-detection-tools/
webo.in/articles/habrahabr/18-solving-internet-explorer-memory-leaks/
Существует еще один способ выполнять обработчики в ие так чтобы this указывал на нод, а сами они получали объект Event как аргумент: Code (JavaScript): | скопировать код в буфер обмена | function addEvent(element, type, handler) { element.attachEvent('on'+type, function () { handler.call(element, fixEvent(window.event)) }) }; | Но тут по определению никак не избежать утeчки, так как нод попадает в замыкание. Так вот, исправляя свою поспешную фразу за ДжиКвери. В jQuery используется именно подход Дина Эдвардса, просто на первый взгляд оно сильно отличается, что ввело меня в заблуждение. Переписал код, так чтобы для w3c браузеров использовались стандартные addEventListener/removeEventListener и дополнен объект Event по мелочам. Code (JavaScript): | скопировать код в буфер обмена | /* (function(){
// // //
var win = window, doc = document, huid = 0, // W3C = win.addEventListener,
handle = function () {
var returnValue = true, event = fixEvent(), handlers = this.$E[event.type];
for (var i in handlers) if (handlers[i].call(this, event) === false) returnValue = false;
return returnValue; },
fixEvent = function () {
// var event = win.event, d = doc.documentElement, b = doc.body, button = event.button, target = event.target = event.srcElement || doc;
event.pageX = event.clientX + (d.scrollLeft || b.scrollLeft || 0) - (d.clientLeft || 0); event.pageY = event.clientY + (d.scrollTop || b.scrollTop || 0) - (d.clientTop || 0);
event.relatedTarget = event.fromElement == target ? event.toElement : event.fromElement;
// which -- Returns the numeric keyCode of the key pressed, or the character code (charCode) for an alphanumeric key pressed event.which = event.charCode || event.keyCode || (button < 2 ? 1 : button == 4 ? 2 : 3);
event.preventDefault = preventDefault; event.stopPropagation = stopPropagation; event.stop = stop;
return event; },
preventDefault = function() { this.returnValue = false; },
stopPropagation = function() { this.cancelBubble = true; },
stop = function () { this.preventDefault(); this.stopPropagation(); };
(win.Event && Event.prototype || 0).stop = stop;
win.addEH = W3C ?
function(node, type, handler) { node.addEventListener(type, handler, false); } :
function (node, type, handler) {
var ontype = 'on' + type, events = node.$E || (node.$E = {}), handlers = events[type] || (events[type] = {});
if (!handler.$HUID) handler.$HUID = ++huid;
handlers[huid] = handler; node[ontype] = handle; };
win.delEH = W3C ?
function(node, type, handler) { node.removeEventListener(type, handler, false); } :
function (node, type, handler) { if (node.$E && node.$E[type]) delete node.$E[type][handler.$HUID]; }; })() | Сам думаю использовать это дело, поэтому прошу замечаний/критики по коду.
|
|
Back to top |
|
 |
|