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
Сподіваюся дане рішення буде корисним ще комусь.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.