123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- (function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
- typeof define === 'function' && define.amd ? define(factory) :
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.propagating = factory());
- }(this, (function () { 'use strict';
- var _firstTarget = null; // singleton, will contain the target element where the touch event started
- /**
- * Extend an Hammer.js instance with event propagation.
- *
- * Features:
- * - Events emitted by hammer will propagate in order from child to parent
- * elements.
- * - Events are extended with a function `event.stopPropagation()` to stop
- * propagation to parent elements.
- * - An option `preventDefault` to stop all default browser behavior.
- *
- * Usage:
- * var hammer = propagatingHammer(new Hammer(element));
- * var hammer = propagatingHammer(new Hammer(element), {preventDefault: true});
- *
- * @param {Hammer.Manager} hammer An hammer instance.
- * @param {Object} [options] Available options:
- * - `preventDefault: true | false | 'mouse' | 'touch' | 'pen'`.
- * Enforce preventing the default browser behavior.
- * Cannot be set to `false`.
- * @return {Hammer.Manager} Returns the same hammer instance with extended
- * functionality
- */
- function propagating(hammer, options) {
- var _options = options || {
- preventDefault: false
- };
- if (hammer.Manager) {
- // This looks like the Hammer constructor.
- // Overload the constructors with our own.
- var Hammer = hammer;
- var PropagatingHammer = function(element, options) {
- var o = Object.create(_options);
- if (options) Hammer.assign(o, options);
- return propagating(new Hammer(element, o), o);
- };
- Hammer.assign(PropagatingHammer, Hammer);
- PropagatingHammer.Manager = function (element, options) {
- var o = Object.create(_options);
- if (options) Hammer.assign(o, options);
- return propagating(new Hammer.Manager(element, o), o);
- };
- return PropagatingHammer;
- }
- // create a wrapper object which will override the functions
- // `on`, `off`, `destroy`, and `emit` of the hammer instance
- var wrapper = Object.create(hammer);
- // attach to DOM element
- var element = hammer.element;
- if(!element.hammer) element.hammer = [];
- element.hammer.push(wrapper);
- // register an event to catch the start of a gesture and store the
- // target in a singleton
- hammer.on('hammer.input', function (event) {
- if (_options.preventDefault === true || (_options.preventDefault === event.pointerType)) {
- event.preventDefault();
- }
- if (event.isFirst) {
- _firstTarget = event.target;
- }
- });
- /** @type {Object.<String, Array.<function>>} */
- wrapper._handlers = {};
- /**
- * Register a handler for one or multiple events
- * @param {String} events A space separated string with events
- * @param {function} handler A callback function, called as handler(event)
- * @returns {Hammer.Manager} Returns the hammer instance
- */
- wrapper.on = function (events, handler) {
- // register the handler
- split(events).forEach(function (event) {
- var _handlers = wrapper._handlers[event];
- if (!_handlers) {
- wrapper._handlers[event] = _handlers = [];
- // register the static, propagated handler
- hammer.on(event, propagatedHandler);
- }
- _handlers.push(handler);
- });
- return wrapper;
- };
- /**
- * Unregister a handler for one or multiple events
- * @param {String} events A space separated string with events
- * @param {function} [handler] Optional. The registered handler. If not
- * provided, all handlers for given events
- * are removed.
- * @returns {Hammer.Manager} Returns the hammer instance
- */
- wrapper.off = function (events, handler) {
- // unregister the handler
- split(events).forEach(function (event) {
- var _handlers = wrapper._handlers[event];
- if (_handlers) {
- _handlers = handler ? _handlers.filter(function (h) {
- return h !== handler;
- }) : [];
- if (_handlers.length > 0) {
- wrapper._handlers[event] = _handlers;
- }
- else {
- // remove static, propagated handler
- hammer.off(event, propagatedHandler);
- delete wrapper._handlers[event];
- }
- }
- });
- return wrapper;
- };
- /**
- * Emit to the event listeners
- * @param {string} eventType
- * @param {Event} event
- */
- wrapper.emit = function(eventType, event) {
- _firstTarget = event.target;
- hammer.emit(eventType, event);
- };
- wrapper.destroy = function () {
- // Detach from DOM element
- var hammers = hammer.element.hammer;
- var idx = hammers.indexOf(wrapper);
- if(idx !== -1) hammers.splice(idx,1);
- if(!hammers.length) delete hammer.element.hammer;
- // clear all handlers
- wrapper._handlers = {};
- // call original hammer destroy
- hammer.destroy();
- };
- // split a string with space separated words
- function split(events) {
- return events.match(/[^ ]+/g);
- }
- /**
- * A static event handler, applying event propagation.
- * @param {Object} event
- */
- function propagatedHandler(event) {
- // let only a single hammer instance handle this event
- if (event.type !== 'hammer.input') {
- // it is possible that the same srcEvent is used with multiple hammer events,
- // we keep track on which events are handled in an object _handled
- if (!event.srcEvent._handled) {
- event.srcEvent._handled = {};
- }
- if (event.srcEvent._handled[event.type]) {
- return;
- }
- else {
- event.srcEvent._handled[event.type] = true;
- }
- }
- // attach a stopPropagation function to the event
- var stopped = false;
- event.stopPropagation = function () {
- stopped = true;
- };
- //wrap the srcEvent's stopPropagation to also stop hammer propagation:
- var srcStop = event.srcEvent.stopPropagation.bind(event.srcEvent);
- if(typeof srcStop == "function") {
- event.srcEvent.stopPropagation = function(){
- srcStop();
- event.stopPropagation();
- };
- }
- // attach firstTarget property to the event
- event.firstTarget = _firstTarget;
- // propagate over all elements (until stopped)
- var elem = _firstTarget;
- while (elem && !stopped) {
- var elemHammer = elem.hammer;
- if(elemHammer){
- var _handlers;
- for(var k = 0; k < elemHammer.length; k++){
- _handlers = elemHammer[k]._handlers[event.type];
- if(_handlers) for (var i = 0; i < _handlers.length && !stopped; i++) {
- _handlers[i](event);
- }
- }
- }
- elem = elem.parentNode;
- }
- }
- return wrapper;
- }
- return propagating;
- })));
|