| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- var STOP = 1;
- var FORCED_STOP = 2;
- /**
- * Manager
- * @param {HTMLElement} element
- * @param {Object} [options]
- * @constructor
- */
- function Manager(element, options) {
- this.options = assign({}, Hammer.defaults, options || {});
- this.options.inputTarget = this.options.inputTarget || element;
- this.handlers = {};
- this.session = {};
- this.recognizers = [];
- this.oldCssProps = {};
- this.element = element;
- this.input = createInputInstance(this);
- this.touchAction = new TouchAction(this, this.options.touchAction);
- toggleCssProps(this, true);
- each(this.options.recognizers, function(item) {
- var recognizer = this.add(new (item[0])(item[1]));
- item[2] && recognizer.recognizeWith(item[2]);
- item[3] && recognizer.requireFailure(item[3]);
- }, this);
- }
- Manager.prototype = {
- /**
- * set options
- * @param {Object} options
- * @returns {Manager}
- */
- set: function(options) {
- assign(this.options, options);
- // Options that need a little more setup
- if (options.touchAction) {
- this.touchAction.update();
- }
- if (options.inputTarget) {
- // Clean up existing event listeners and reinitialize
- this.input.destroy();
- this.input.target = options.inputTarget;
- this.input.init();
- }
- return this;
- },
- /**
- * stop recognizing for this session.
- * This session will be discarded, when a new [input]start event is fired.
- * When forced, the recognizer cycle is stopped immediately.
- * @param {Boolean} [force]
- */
- stop: function(force) {
- this.session.stopped = force ? FORCED_STOP : STOP;
- },
- /**
- * run the recognizers!
- * called by the inputHandler function on every movement of the pointers (touches)
- * it walks through all the recognizers and tries to detect the gesture that is being made
- * @param {Object} inputData
- */
- recognize: function(inputData) {
- var session = this.session;
- if (session.stopped) {
- return;
- }
- // run the touch-action polyfill
- this.touchAction.preventDefaults(inputData);
- var recognizer;
- var recognizers = this.recognizers;
- // this holds the recognizer that is being recognized.
- // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED
- // if no recognizer is detecting a thing, it is set to `null`
- var curRecognizer = session.curRecognizer;
- // reset when the last recognizer is recognized
- // or when we're in a new session
- if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) {
- curRecognizer = session.curRecognizer = null;
- }
- var i = 0;
- while (i < recognizers.length) {
- recognizer = recognizers[i];
- // find out if we are allowed try to recognize the input for this one.
- // 1. allow if the session is NOT forced stopped (see the .stop() method)
- // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one
- // that is being recognized.
- // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.
- // this can be setup with the `recognizeWith()` method on the recognizer.
- if (session.stopped !== FORCED_STOP && ( // 1
- !curRecognizer || recognizer == curRecognizer || // 2
- recognizer.canRecognizeWith(curRecognizer))) { // 3
- recognizer.recognize(inputData);
- } else {
- recognizer.reset();
- }
- // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the
- // current active recognizer. but only if we don't already have an active recognizer
- if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {
- curRecognizer = session.curRecognizer = recognizer;
- }
- i++;
- }
- },
- /**
- * get a recognizer by its event name.
- * @param {Recognizer|String} recognizer
- * @returns {Recognizer|Null}
- */
- get: function(recognizer) {
- if (recognizer instanceof Recognizer) {
- return recognizer;
- }
- var recognizers = this.recognizers;
- for (var i = 0; i < recognizers.length; i++) {
- if (recognizers[i].options.event == recognizer) {
- return recognizers[i];
- }
- }
- return null;
- },
- /**
- * add a recognizer to the manager
- * existing recognizers with the same event name will be removed
- * @param {Recognizer} recognizer
- * @returns {Recognizer|Manager}
- */
- add: function(recognizer) {
- if (invokeArrayArg(recognizer, 'add', this)) {
- return this;
- }
- // remove existing
- var existing = this.get(recognizer.options.event);
- if (existing) {
- this.remove(existing);
- }
- this.recognizers.push(recognizer);
- recognizer.manager = this;
- this.touchAction.update();
- return recognizer;
- },
- /**
- * remove a recognizer by name or instance
- * @param {Recognizer|String} recognizer
- * @returns {Manager}
- */
- remove: function(recognizer) {
- if (invokeArrayArg(recognizer, 'remove', this)) {
- return this;
- }
- recognizer = this.get(recognizer);
- // let's make sure this recognizer exists
- if (recognizer) {
- var recognizers = this.recognizers;
- var index = inArray(recognizers, recognizer);
- if (index !== -1) {
- recognizers.splice(index, 1);
- this.touchAction.update();
- }
- }
- return this;
- },
- /**
- * bind event
- * @param {String} events
- * @param {Function} handler
- * @returns {EventEmitter} this
- */
- on: function(events, handler) {
- if (events === undefined) {
- return;
- }
- if (handler === undefined) {
- return;
- }
- var handlers = this.handlers;
- each(splitStr(events), function(event) {
- handlers[event] = handlers[event] || [];
- handlers[event].push(handler);
- });
- return this;
- },
- /**
- * unbind event, leave emit blank to remove all handlers
- * @param {String} events
- * @param {Function} [handler]
- * @returns {EventEmitter} this
- */
- off: function(events, handler) {
- if (events === undefined) {
- return;
- }
- var handlers = this.handlers;
- each(splitStr(events), function(event) {
- if (!handler) {
- delete handlers[event];
- } else {
- handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);
- }
- });
- return this;
- },
- /**
- * emit event to the listeners
- * @param {String} event
- * @param {Object} data
- */
- emit: function(event, data) {
- // we also want to trigger dom events
- if (this.options.domEvents) {
- triggerDomEvent(event, data);
- }
- // no handlers, so skip it all
- var handlers = this.handlers[event] && this.handlers[event].slice();
- if (!handlers || !handlers.length) {
- return;
- }
- data.type = event;
- data.preventDefault = function() {
- data.srcEvent.preventDefault();
- };
- var i = 0;
- while (i < handlers.length) {
- handlers[i](data);
- i++;
- }
- },
- /**
- * destroy the manager and unbinds all events
- * it doesn't unbind dom events, that is the user own responsibility
- */
- destroy: function() {
- this.element && toggleCssProps(this, false);
- this.handlers = {};
- this.session = {};
- this.input.destroy();
- this.element = null;
- }
- };
- /**
- * add/remove the css properties as defined in manager.options.cssProps
- * @param {Manager} manager
- * @param {Boolean} add
- */
- function toggleCssProps(manager, add) {
- var element = manager.element;
- if (!element.style) {
- return;
- }
- var prop;
- each(manager.options.cssProps, function(value, name) {
- prop = prefixed(element.style, name);
- if (add) {
- manager.oldCssProps[prop] = element.style[prop];
- element.style[prop] = value;
- } else {
- element.style[prop] = manager.oldCssProps[prop] || '';
- }
- });
- if (!add) {
- manager.oldCssProps = {};
- }
- }
- /**
- * trigger dom event
- * @param {String} event
- * @param {Object} data
- */
- function triggerDomEvent(event, data) {
- var gestureEvent = document.createEvent('Event');
- gestureEvent.initEvent(event, true, true);
- gestureEvent.gesture = data;
- data.target.dispatchEvent(gestureEvent);
- }
|