src/core/arbiter.js
- /**
- * @file arbiter.js
- * Contains logic for the dispatcher
- */
-
- import dispatcher from './dispatcher.js';
- import Input from './classes/Input.js';
- import interpreter from './interpreter.js';
- import util from './util.js';
-
- /**
- * Function that handles event flow, negotiating with the interpreter, and dispatcher.
- * 1. Receiving all touch events in the window.
- * 2. Determining which gestures are linked to the target element.
- * 3. Negotiating with the Interpreter what event should occur.
- * 4. Sending events to the dispatcher to emit events to the target.
- * @param {Event} event - The event emitted from the window object.
- * @param {Object} region - The region object of the current listener.
- */
- function arbiter(event, region) {
- var state = region.state;
-
- /*
- Return if a gesture is not in progress and won't be. Also catches the case where a previous
- event is in a partial state (2 finger pan, waits for both inputs to reach touchend)
- */
- if (state.inputs.length === 0 && util.normalizeEvent(event.type) !== 'start') {
- return;
- }
-
- /*
- Check for 'stale' or events that lost focus (e.g. a pan goes off screen/off region.
- Does not affect mobile devices.
- */
- if (typeof event.buttons !== 'undefined' && util.normalizeEvent(event.type) !== 'end' && event.buttons === 0) {
- state.resetInputs();
- return;
- }
-
- //Update the state with the new events. If the event is stopped, return;
- if (!state.updateInputs(event, region.element)) {
- return;
- }
-
- //Retrieve the initial target from any one of the inputs
- var bindings = state.retrieveBindingsByInitialPos();
- if (bindings.length > 0) {
- if (region.preventDefault) {
- util.setMSPreventDefault(region.element);
- event.preventDefault ? event.preventDefault() : (event.returnValue = false);
- } else {
- util.removeMSPreventDefault(region.element);
- }
-
- var toBeDispatched = {};
- var gestures = interpreter(bindings, event, state);
-
- //Determine the deepest path index to emit the event from, to avoid duplicate events being fired.
- gestures.forEach(gesture => {
- //var id = (gesture.binding.gesture.id) ? gesture.binding.gesture.id : gesture.binding.gesture.type;
- var id = gesture.binding.gesture.id;
- if (toBeDispatched[id]) {
- var path = util.getPropagationPath(event);
- if (util.getPathIndex(path, gesture.binding.element) < util.getPathIndex(path, toBeDispatched[id].binding.element)) {
- toBeDispatched[id] = gesture;
- }
- } else {
- toBeDispatched[id] = gesture;
- }
- });
-
- Object.keys(toBeDispatched).forEach(index => {
- var gesture = toBeDispatched[index];
- dispatcher(gesture.binding, gesture.data, gesture.events);
- });
- }
-
- var endCount = 0;
- state.inputs.forEach(input => {
- if (input.getCurrentEventType() === 'end') {
- endCount++;
- }
- });
-
- if (endCount === state.inputs.length) {
- state.resetInputs();
- }
-
- }
- /*arbiter*/
-
- export default arbiter;