JQuery — разделение событий onСlick и onDblСlick

от автора

this.window.$.on( 'click', function( event ){ context.toggleActive( ); } ) 			 .on( 'dblclick', function( event ){ context.toggleMaximized( ); } ); 

При разработке JS приложений часто возникает неудобство ( сложно назвать это проблемой ), когда необходимо отделять событие клика, от двойного клика из-за особенностей обработки этих событий — браузерами. Думаю многие из Вас сталкивались с тем что во всех браузерах вначале происходит событие onClick а уже после — onDblClick. Не знаю как Вам, но мне это очень мешает спокойному написанию обработки событий подобного рода.

Но проблема вся в том что каких-то простых и удобных решений подобной задачи — нет. Поэтому пришлось взяться за дело, и написать своё решение.

Плагин


Основа плагина — перехват вызова регистрации события ( on, off, click, dblclick ), с последующей заменой на свои события.

$.fn.on = function( ) // ( types, selector, data, fn, one ) { 	var argumentList = $.extend( true, [], arguments ); 	var eventType = argumentList[0]; 	//.... 	case eventType === 'click' || eventType === 'dblclick': 	{ 		// Инициируем навешивание текущей функции с дополнительными обработками 		onMethod.call( this, 'reg' + eventType,	eventSelector, eventData, 			function( regEvent, event ) 			{ 				// Важная проверка, чтобы знать мы ли это в цепи передачи событий 				if( this === regEvent.target ) 				{ 					// Не даём передать этот сигнал дальше 					regEvent.preventDefault( ); 					regEvent.stopPropagation( ); 						 					// Сбрасываем параметры оригинального вызова 					event.isDefaultPrevented = function returnFalse( ){ return false; }; 					event.isPropagationStopped = function returnFalse( ){ return false; };  					// Вызываем оригинальную функцию 					eventFunc.call( regEvent.target, event ); 								 					// Если исходя из параметров сигнал нужно передать дальше - передаём 					if( !event.isPropagationStopped( ) ) 					{ 						$( event.currentTarget.offsetParent ).trigger( 'click', [ event ] );	 					} 				} 			} 		);  		// Считываем события к событию 		var clickEvents = $._data( this[0], 'events' ) ? $._data( this[0], 'events' )[ 'click' ] : undefined;  		// Если еще не записали ни одного клика - записываем 		if( typeof clickEvents === 'undefined' ) 		{ 			// Непосредственно клик 			onMethod.call( this, 'click', eventSelector, eventData, singleDoubleClick ); 						 			// Для проверки перемещения мыши 			onMethod.call( this, 'mousedown', eventSelector, eventData, startMoving ); 			onMethod.call( this, 'mouseup', eventSelector, eventData, endMoving ); 		} 	} 	//.... } 

После перехвата события — от момента первого клика запускается таймер который считает был ли сдвиг мышки за определённый период.
И если был сдвиг, или не произошло второго клика — то происходит событие onClick, в обратном случае onDblClick.

	var timeOut = 200; // Время ожидания 	var start = { x: 0, y: 0 }; // Точка начала 	var end = { x: 0, y: 0 }; // Точка конца 	var distance = 0; // Расстояние между началом и концом движения 	var maxDistance = 3;  	var onMethod = $.fn.on; // Записываем оригинальный on 	var offMethod = $.fn.off; // Записываем оригинальный off  	var singleDoubleClick = function( event ) 	{ 		// Для каждого объекта в цепи, по которой от сына отцу идет событие, нужно создать свой таймер и счетчик кликов 		// то есть один глобальный объект нельзя держать, если два сына, то клик стает дабл кликом 		event.currentTarget.clicks = ( event.currentTarget.clicks || 0 ) + 1; 		 		// По умолчанию - не даём сигнал дальше 		event.preventDefault( ); 		event.stopPropagation( ); 		 		var timeoutCallback = function( event ) 		{ 			return function( ) 			{ 				// Очищаем таймер 				clearTimeout( event.currentTarget.timer ); 				 				// Учитываем кол-во кликов, дергание мыши и стопинг пропагации 				if( event.currentTarget.clicks === 1 && distance < maxDistance ) 				{ 					$( event.currentTarget ).trigger( 'regclick', [ event ] );	 				} 				else if( event.currentTarget.clicks > 1 && distance < maxDistance ) 				{ 					event.type = 'dblclick'; 					$( event.currentTarget ).trigger( 'regdblclick', [ event ] ); 				} 				 				// Обнуляем счётчик кликов 				event.currentTarget.clicks = 0; 			}; 		};  		// Устанавливаем таймер 		event.currentTarget.timer = setTimeout( timeoutCallback( event ), timeOut ); 	};  	// Начало движения 	var startMoving = function( event ) 	{ 		start = $.getMousePosition( event ); 	};  	// Конец движения 	var endMoving = function( event ) 	{ 		end = $.getMousePosition( event ); 		var dx = end.x - start.x; 		var dy = end.y - start.y; 		distance = Math.sqrt( dx * dx + dy * dy ); 	}; 

Посмотреть на сам плагин можно вот здесь: GitHub
Надеюсь это ещё кому-то пригодиться.

ссылка на оригинал статьи http://habrahabr.ru/post/265009/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *