UNPKG

bem

Version:
239 lines (182 loc) 7.53 kB
/* * universal pointer-events plugin * универсальные pointer-события * * Copyright (c) 2010-2011 Kir Belevich (deepsweet@yandex-team.ru) * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl.html * * @version 0.3.2 */ (function($) { var events; // тач if ('ontouchstart' in window) { events = { type: 'touch', down: 'touchstart', move: 'touchmove', up: 'touchend', cancel: 'touchcancel' } // ms-поинтер } else if (window.navigator.msPointerEnabled) { events = { type: 'mspointer', down: 'MSPointerDown', move: 'MSPointerMove', up: 'MSPointerUp', cancel: 'MSPointerOut' } // мышь } else { events = { type: 'mouse', down: 'mousedown', move: 'mousemove', up: 'mouseup', cancel: 'mouseleave' } } // pointerdown $.event.special.pointerdown = { // подписываемся setup: function() { $(this).bind(events.down + '.pointerEvents', function(e) { // если мышиные события - запоминаем нажата ли кнопка if (events.type == 'mouse') { this._pointerIsDown = true; } // передаём параметры e.pointer = { x: events.type == 'touch' ? e.originalEvent.touches[0].pageX : e.clientX, y: events.type == 'touch' ? e.originalEvent.touches[0].pageY : e.clientY } // триггерим e.type = 'pointerdown'; $.event.handle.apply(this, arguments); }); }, // отписываемся и забываем teardown: function() { $(this).unbind(events.down + '.pointerEvents'); } }; // pointermove $.event.special.pointermove = { // подписываемся setup: function() { $(this).bind(events.move + '.pointerEvents', function(e) { // если не мышиные события, или мышиные, но кнопка зажата if (events.type != 'mouse' || (events.type == 'mouse' && this._pointerIsDown)) { // передаём параметры e.pointer = { x: events.type == 'touch' ? e.originalEvent.touches[0].pageX : e.clientX, y: events.type == 'touch' ? e.originalEvent.touches[0].pageY : e.clientY } // триггерим e.type = 'pointermove'; $.event.handle.apply(this, arguments); } }); }, // отписываемся и забываем teardown: function() { $(this).unbind(events.move + '.pointerEvents'); } }; // pointerup $.event.special.pointerup = { // подписываемся setup: function() { $(this).bind(events.up + '.pointerEvents', function(e) { // если мышиные события, то забываем, что кнопка была зажата if (events.type == 'mouse') { delete this._pointerIsDown; } // триггерим e.type = 'pointerup'; $.event.handle.apply(this, arguments); }) }, // отписываемся и забываем teardown: function() { $(this).unbind(events.up + '.pointerEvents'); } }; // pointercancel $.event.special.pointercancel = { // подписываемся setup: function() { $(this).bind(events.cancel + '.pointerEvents', function(e) { // если мышиные события, то забываем, что кнопка была зажата if (events.type == 'mouse') { delete this._pointerIsDown; } // триггерим e.type = 'pointercancel'; $.event.handle.apply(this, arguments); }); }, // отписываемся и забываем teardown: function() { $(this).unbind(events.cancel + '.pointerEvents'); } }; // tap $.event.special.tap = { // подписываемся setup: function() { // если мышь, то эмулируем тап через обычный клик // + костыль для Android if (events.type == 'mouse' || /Android/.test(navigator.userAgent)) { $(this).bind('click.tapEvent', function(e) { e.type = 'tap'; $.event.handle.apply(this, arguments); }); } else { var touch = {}; $(this).bind({ 'pointerdown.tapEvent': function(e) { touch.target = this; touch.x1 = e.pointer.x; }, 'pointermove.tapEvent': function(e) { touch.x2 = e.pointer.x; }, 'pointerup.tapEvent': function(e) { // если совсем не было move, или был, но меньше 5 пикселей, то триггерим тап if (!touch.x2 || Math.abs(touch.x2 - touch.x1) < 5) { // предотвращаем мышиные события if (touch.target && touch.target.nodeType !== 9) { // при обычном превенте появляется-прачется адресный тулбар, // т.е. клик как событие происходит, просто нет действия $(document).one('click.preventClick', function(e) { e.preventDefault(); return false; }); // http://cubiq.org/dropbox/clickdelay.html $('body').css('pointer-events', 'none'); setTimeout(function() { $(document).unbind('.preventClick'); $('body').css('pointer-events', 'auto'); }, 750); } e.type = 'tap'; $.event.handle.apply(this, arguments); } touch = {}; }, 'pointercancel.tapEvent': function() { touch = {}; } }); } }, // отписываемся и забываем teardown: function() { $(this).unbind('.tapEvent'); } }; })(jQuery);