Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

onMouseDown - вызывающий объект (Shira)
Author Message
Shira
Участник форума



Joined: 13 May 2007
Posts: 65
Карма: 0
   поощрить/наказать

Location: Россия, Москва

PostPosted: Sat Feb 21, 2009 2:37 pm (написано за 12 минут 11 секунд)
   Post subject: onMouseDown - вызывающий объект
Reply with quote

Всем доброго времени суток!!!!

Вот к примеру такой 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
View user's profile Send private message Send e-mail
Александр Михалицын
Модератор



Joined: 23 May 2008
Posts: 1299
Карма: 83
   поощрить/наказать


PostPosted: Sun Feb 22, 2009 9:06 am (спустя 18 часов 28 минут; написано за 9 секунд)
   Post subject:
Reply with quote

Shira,
Code (JavaScript): скопировать код в буфер обмена
var e = window.event?window.event.srcElement.parentNode.parentNode:event.currentTarget.parentNode.parentNode;
Back to top
View user's profile Send private message Send e-mail
Shira
Участник форума



Joined: 13 May 2007
Posts: 65
Карма: 0
   поощрить/наказать

Location: Россия, Москва

PostPosted: Sun Feb 22, 2009 9:17 am (спустя 11 минут; написано за 1 минуту 46 секунд)
   Post subject:
Reply with quote

Александр Михалицын, ну, к примеру, для данного случая это подойдет для клика по ссылке, а для клика по ячейке (TD) нет.... Короче, как я понял, универсального выхода нету...
Back to top
View user's profile Send private message Send e-mail
Александр Михалицын
Модератор



Joined: 23 May 2008
Posts: 1299
Карма: 83
   поощрить/наказать


PostPosted: Sun Feb 22, 2009 9:25 am (спустя 8 минут; написано за 2 минуты 6 секунд)
   Post subject:
Reply with quote

Shira,
ммм. Тоесть вам надо чтобы при возникновении события всегда выводило TR? Зачем вы тогда вообще работаете с событием?
Не проще ли просто document.getElementById("tr1")?
Back to top
View user's profile Send private message Send e-mail
Shira
Участник форума



Joined: 13 May 2007
Posts: 65
Карма: 0
   поощрить/наказать

Location: Россия, Москва

PostPosted: Sun Feb 22, 2009 9:28 am (спустя 2 минуты; написано за 1 минуту 11 секунд)
   Post subject:
Reply with quote

Александр Михалицын, так а если не известно какой из TR'ов запускает событие? Я просто так и представлял, что какому тэгу присвоено событие, он и возвращается таргетом....
Back to top
View user's profile Send private message Send e-mail
Александр Михалицын
Модератор



Joined: 23 May 2008
Posts: 1299
Карма: 83
   поощрить/наказать


PostPosted: Sun Feb 22, 2009 9:42 am (спустя 14 минут; написано за 2 минуты 41 секунду)
   Post subject:
Reply with quote

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
View user's profile Send private message Send e-mail
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Sun Feb 22, 2009 12:16 pm (спустя 2 часа 34 минуты; написано за 2 минуты 55 секунд)
   Post subject:
Reply with quote

Есть такая дока 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
View user's profile Send private message
dimagolov
Участник форума



Joined: 04 Feb 2007
Posts: 1664
Карма: 96
   поощрить/наказать

Location: Christ Church, Barbados

PostPosted: Sun Feb 22, 2009 5:49 pm (спустя 5 часов 32 минуты; написано за 39 секунд)
   Post subject:
Reply with quote

А что мешает просто подниматься по parentNode пока не получем элемент типа tr ?
Back to top
View user's profile Send private message
WingedFox
Профессионал



Joined: 29 Apr 2003
Posts: 4064
Карма: 268
   поощрить/наказать

Location: Питер

PostPosted: Sun Feb 22, 2009 5:50 pm (спустя 1 минуту 16 секунд; написано за 46 секунд)
   Post subject:
Reply with quote

dimagolov
Некоторые любят вкладывать таблицы в таблицы =)
Да и долго это, если документ сложный.
Back to top
View user's profile Send private message
Denis Usenko
Участник форума



Joined: 06 Feb 2006
Posts: 54
Карма: 13
   поощрить/наказать


PostPosted: Mon Feb 23, 2009 12:40 am (спустя 6 часов 49 минут; написано за 4 минуты 33 секунды)
   Post subject:
Reply with quote

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
View user's profile Send private message
Александр Михалицын
Модератор



Joined: 23 May 2008
Posts: 1299
Карма: 83
   поощрить/наказать


PostPosted: Mon Feb 23, 2009 9:34 am (спустя 8 часов 54 минуты; написано за 1 минуту 39 секунд)
   Post subject:
Reply with quote

Denis Usenko wrote:
это вешать обработчик напрямую:
node.onmousedown = function () {}
тогда в ИЕ this будет указывать куда надо.
,
this указывает на объект для которого установлен текущий обработчик и при addEventListener, а вот при attachEvent (в IE) -- нет. (typeof this.tagName === "undefined").
Back to top
View user's profile Send private message Send e-mail
Shira
Участник форума



Joined: 13 May 2007
Posts: 65
Карма: 0
   поощрить/наказать

Location: Россия, Москва

PostPosted: Mon Feb 23, 2009 2:07 pm (спустя 4 часа 33 минуты; написано за 1 минуту 9 секунд)
   Post subject:
Reply with quote

Denis Usenko, спасибо! В том случае, если назначать обработчика, как Вы сказали, то this не только в ие указывает на нужный объект! ;-)
Back to top
View user's profile Send private message Send e-mail
Shira
Участник форума



Joined: 13 May 2007
Posts: 65
Карма: 0
   поощрить/наказать

Location: Россия, Москва

PostPosted: Mon Feb 23, 2009 2:18 pm (спустя 11 минут; написано за 3 минуты 23 секунды)
   Post subject:
Reply with quote

Блин, но если такой вариант использовать в firefox, то когда функция-обработчик возвращает false, то firefox все равно продолжает обработку события. Т.е. если кликаю на ссылку в ячейке(а обработка события повешана на ячейку), то он и функцию запускает и совершает клик на ссылку. Есть лекарство?
Причем в firefox не помогает ни event.preventDefault(), ни event.stopPropagation()!!!
Back to top
View user's profile Send private message Send e-mail
Denis Usenko
Участник форума



Joined: 06 Feb 2006
Posts: 54
Карма: 13
   поощрить/наказать


PostPosted: Mon Feb 23, 2009 11:23 pm (спустя 9 часов 4 минуты; написано за 10 минут 9 секунд)
   Post subject:
Reply with quote

Александр Михалицын
Александр Михалицын 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
View user's profile Send private message
Shira
Участник форума



Joined: 13 May 2007
Posts: 65
Карма: 0
   поощрить/наказать

Location: Россия, Москва

PostPosted: Tue Feb 24, 2009 12:05 am (спустя 42 минуты; написано за 27 секунд)
   Post subject:
Reply with quote

В общем всем спасибо. проблема решена. Через присвоение напрямую (obj.onmousedown = func_name) не работало в старой мозиле, обновил, заработало!

Denis Usenko, почему Вы писали, что это не рекомендуемый способ?
Back to top
View user's profile Send private message Send e-mail
Denis Usenko
Участник форума



Joined: 06 Feb 2006
Posts: 54
Карма: 13
   поощрить/наказать


PostPosted: Tue Feb 24, 2009 4:51 am (спустя 4 часа 46 минут; написано за 16 минут 14 секунд)
   Post subject:
Reply with quote

Обычно говорят о двух недостатках -- нельзя повесить более одного обработчика, и сложность с утечками в ие. Сейчас проверил, [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
View user's profile Send private message
Denis Usenko
Участник форума



Joined: 06 Feb 2006
Posts: 54
Карма: 13
   поощрить/наказать


PostPosted: Tue Feb 24, 2009 5:27 am (спустя 36 минут; написано за 2 минуты 37 секунд)
   Post subject:
Reply with quote

Shira
Нды, насчет утечек при присваивании обработчиков, -- я похоже просто повторяю читанную в интернетах ерунду )) С ними в любом случае проблемы, хоть с attachEvent, хоть присваиванием, а следить за этим надо.
Back to top
View user's profile Send private message
Shira
Участник форума



Joined: 13 May 2007
Posts: 65
Карма: 0
   поощрить/наказать

Location: Россия, Москва

PostPosted: Wed Feb 25, 2009 10:40 am (спустя 1 день 5 часов 13 минут; написано за 8 минут 43 секунды)
   Post subject:
Reply with quote

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
View user's profile Send private message Send e-mail
dimagolov
Участник форума



Joined: 04 Feb 2007
Posts: 1664
Карма: 96
   поощрить/наказать

Location: Christ Church, Barbados

PostPosted: Wed Feb 25, 2009 7:17 pm (спустя 8 часов 37 минут; написано за 9 минут 3 секунды)
   Post subject:
Reply with quote

Shira wrote:
алерт выведет '3' или '1'?
Т.е. document.getElementById('tr1').cl_name = this; сработает как присвоение класса с текущими параметрами или ссылка на этот, конкретно созданный, класс?
это викторина? Сами не пробовали?
Back to top
View user's profile Send private message
Zeroglif
Участник форума



Joined: 02 Jan 2006
Posts: 293
Карма: 61
   поощрить/наказать


PostPosted: Thu Feb 26, 2009 11:20 am (спустя 16 часов 2 минуты; написано за 1 минуту 27 секунд)
   Post subject:
Reply with quote

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
View user's profile Send private message
Александр Михалицын
Модератор



Joined: 23 May 2008
Posts: 1299
Карма: 83
   поощрить/наказать


PostPosted: Thu Feb 26, 2009 12:08 pm (спустя 48 минут; написано за 22 секунды)
   Post subject:
Reply with quote

Zeroglif,
угу. Правильнее было сказать "объект". ;)
Back to top
View user's profile Send private message Send e-mail
Denis Usenko
Участник форума



Joined: 06 Feb 2006
Posts: 54
Карма: 13
   поощрить/наказать


PostPosted: Sun Mar 01, 2009 7:37 am (спустя 2 дня 19 часов 28 минут; написано за 11 секунд)
   Post subject:
Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Page 1 of 1    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML