Вопрос по идентичности event.target и DOM
Всем доброго дня.
Делаю простой скрипт на JQuery. На экране выводится какое-то сообщение или показывается определенный блок и сразу же к нему применяем метод .hide_by_click(). При клике на область отличную от появившегося блока, он исчезает. Вот пример кода function show_next_fadeToggle(){ fly_block=$(this).next(); fly_block.stop().fadeIn(500,function(){ $(this).hide_by_click(); }); jQuery.fn.hide_by_click=function(){ $('body').on('click',{elem:$(this)},function(e){ //alert(e.target); //alert(e.data.elem); //alert(fg.find(e.data.elem).length); //alert(e.target.length); if (e.target.length==e.data.elem.length){ alert('Клик на элементе'); } //alert(e.target.find(e.data.elem).length); if (e.data.elem.find(e.target).length!=0){ alert('Клик на элементе'); }else {//elem.remove(); } }) } В строке e.data.elem.find(e.target).length!=0 идет провека того, что элемент e.data.elem содержится в e.target(в то, по чему мы кликнули) Работает нормально, но вот когда клик производится по самому элементу, т.е. e.target равен e.data.elem начинаются проблемы. т.к. первый это objectHTMLDIVElement второй - object Object. Как сделать провеку что клик был именно по элементу e.data.elem. Есть варианты решения, через создания обертки или использования классов, но думаю решение намного проще. |
В принципе нашел решение, но т.к. javascript знаю не так хорошо, есть еще один маленький вопросик.
jQuery.fn.hide_by_click=function(){ $('body').on('click',{elem:$(this)},function jsksl(e){ if (e.data.elem.get(0)!=$(e.target).get(0) && e.data.elem.find($(e.target)).length==0){ e.data.elem.slideUp('500'); $('body').off('click',jsksl); } }) } Вопрос в имени функции jsksl. Функцию обязательно надо обзывать, чтобы из ее тела ее можно было отрубить - $('body').off('click',jsksl); Или можно как-то записать, чтобы не придумывать названия функций постоянно. Плюс для объекта боди может быть установленно несколько обработчиков событий с функцией jsksl и они разом вырубятся - это тоже не хорошо. |
Цитата:
например, $( "form" ).on( "click.validator", ....); $( "form" ).off( ".validator" ); почитайте, посмотрите самый нижний пример http://api.jquery.com/off/ |
vuler,
jQuery.fn.hide_by_click = function(){ $(document).click({x:this},function(e){ if ($(e.target).closest(e.data.x).length) return; e.data.x.fadeOut(500); $(this).off('click'); }); }; |
Цитата:
Цитата:
пример http://learn.javascript.ru/play/UYhVe |
Всем спасибо за советы.
Не знаю вот на правильном ли я пути теперь. Присваиваю элементу уникальный номер, чтобы обработчик удалялся только для него. Вообще уникальности пока не много, т.к. в одну секунду может создаться несколько таких элементов с одинаковыми номерами. Вариант добавить - рандом к метке времени. Или сделать вообще массив где для каждой метки времени будут сохраняться все примененные рандомы, тогда будет действительно уникальное значение для каждого вызова функции. Но может я опять полез в дебри и есть решение попроще? Может для каждого ДОМ элемента существует свой скрытый ID номер, чтобы можно было их отличать? function now_verbose(){ return new Date().getTime(); } jQuery.fn.hide_by_click=function(){ unic=now_verbose(); $(this).attr('unic_id',unic); $('body').on('click.'+unic,{elem:$(this)},function (e){ if ($(e.target).closest(e.data.elem).length) return; e.data.elem.slideUp('500'); $('body').off('click.'+e.data.elem.attr('unic_id')); }) } |
а почему не нравился вариант отписки от события, когда вы давали функции имя jsksl и потом делали
$('body').off('click',jsksl); ?? |
ну например на экране покажутся два блока
$('.div1').hide_by_click(); $('.div2').hide_by_click(); Тогда при клике на втором блоке. $('body').off('click',jsksl); отрубит обработчик и для первого блока. В принципе выход есть путем хранения в памяти генератора имен, который увеличивает unic на единицу. |
Цитата:
пример http://learn.javascript.ru/play/buCnwb кликните пару раз в любом месте в обработчике делаем $(this).off('click', jsksl); только для #test1 #test2 после этого нормально реагирует на клики |
Часовой пояс GMT +3, время: 03:57. |