Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Вопрос по идентичности event.target и DOM (https://javascript.ru/forum/misc/49895-vopros-po-identichnosti-event-target-i-dom.html)

vuler 02.09.2014 15:29

Вопрос по идентичности 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.
Есть варианты решения, через создания обертки или использования классов, но думаю решение намного проще.

vuler 02.09.2014 17:17

В принципе нашел решение, но т.к. 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 и они разом вырубятся - это тоже не хорошо.

Pavel M. 02.09.2014 19:36

Цитата:

Сообщение от vuler
Функцию обязательно надо обзывать, чтобы из ее тела ее можно было отрубить - $('body').off('click',jsksl);
Или можно как-то записать, чтобы не придумывать названия функций постоянно.

можно использовать в названиях событий namespace
например,
$( "form" ).on( "click.validator", ....);
$( "form" ).off( ".validator" );
почитайте, посмотрите самый нижний пример http://api.jquery.com/off/

Rise 03.09.2014 07:03

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');
	});
};

Pavel M. 03.09.2014 08:46

Цитата:

Сообщение от vuler
для объекта боди может быть установленно несколько обработчиков событий

Цитата:

Сообщение от Rise
$(this).off('click');

эта строка удалить ВСЕ обработчики 'click' на document у всех подписчиков - за что их так?

пример http://learn.javascript.ru/play/UYhVe

vuler 04.09.2014 17:16

Всем спасибо за советы.
Не знаю вот на правильном ли я пути теперь.
Присваиваю элементу уникальный номер, чтобы обработчик удалялся только для него. Вообще уникальности пока не много, т.к. в одну секунду может создаться несколько таких элементов с одинаковыми номерами. Вариант добавить - рандом к метке времени. Или сделать вообще массив где для каждой метки времени будут сохраняться все примененные рандомы, тогда будет действительно уникальное значение для каждого вызова функции.
Но может я опять полез в дебри и есть решение попроще? Может для каждого ДОМ элемента существует свой скрытый 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'));
	})
}

Pavel M. 04.09.2014 21:37

а почему не нравился вариант отписки от события, когда вы давали функции имя jsksl и потом делали
$('body').off('click',jsksl);
??

vuler 04.09.2014 21:46

ну например на экране покажутся два блока
$('.div1').hide_by_click();
$('.div2').hide_by_click();

Тогда при клике на втором блоке. $('body').off('click',jsksl); отрубит обработчик и для первого блока.
В принципе выход есть путем хранения в памяти генератора имен, который увеличивает unic на единицу.

Pavel M. 04.09.2014 22:26

Цитата:

Сообщение от vuler
Тогда при клике на втором блоке. $('body').off('click',jsksl); отрубит обработчик и для первого блока.

не отрубит, функция обработчик клика каждый раз создается новая при вызове .hide_by_click()

пример http://learn.javascript.ru/play/buCnwb

кликните пару раз в любом месте

в обработчике делаем $(this).off('click', jsksl); только для #test1

#test2 после этого нормально реагирует на клики


Часовой пояс GMT +3, время: 03:57.