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/
Добавить комментарий