Home Reference Source Test

src/core/arbiter.js

  1. /**
  2. * @file arbiter.js
  3. * Contains logic for the dispatcher
  4. */
  5.  
  6. import dispatcher from './dispatcher.js';
  7. import Input from './classes/Input.js';
  8. import interpreter from './interpreter.js';
  9. import util from './util.js';
  10.  
  11. /**
  12. * Function that handles event flow, negotiating with the interpreter, and dispatcher.
  13. * 1. Receiving all touch events in the window.
  14. * 2. Determining which gestures are linked to the target element.
  15. * 3. Negotiating with the Interpreter what event should occur.
  16. * 4. Sending events to the dispatcher to emit events to the target.
  17. * @param {Event} event - The event emitted from the window object.
  18. * @param {Object} region - The region object of the current listener.
  19. */
  20. function arbiter(event, region) {
  21. var state = region.state;
  22.  
  23. /*
  24. Return if a gesture is not in progress and won't be. Also catches the case where a previous
  25. event is in a partial state (2 finger pan, waits for both inputs to reach touchend)
  26. */
  27. if (state.inputs.length === 0 && util.normalizeEvent(event.type) !== 'start') {
  28. return;
  29. }
  30.  
  31. /*
  32. Check for 'stale' or events that lost focus (e.g. a pan goes off screen/off region.
  33. Does not affect mobile devices.
  34. */
  35. if (typeof event.buttons !== 'undefined' && util.normalizeEvent(event.type) !== 'end' && event.buttons === 0) {
  36. state.resetInputs();
  37. return;
  38. }
  39.  
  40. //Update the state with the new events. If the event is stopped, return;
  41. if (!state.updateInputs(event, region.element)) {
  42. return;
  43. }
  44.  
  45. //Retrieve the initial target from any one of the inputs
  46. var bindings = state.retrieveBindingsByInitialPos();
  47. if (bindings.length > 0) {
  48. if (region.preventDefault) {
  49. util.setMSPreventDefault(region.element);
  50. event.preventDefault ? event.preventDefault() : (event.returnValue = false);
  51. } else {
  52. util.removeMSPreventDefault(region.element);
  53. }
  54.  
  55. var toBeDispatched = {};
  56. var gestures = interpreter(bindings, event, state);
  57.  
  58. //Determine the deepest path index to emit the event from, to avoid duplicate events being fired.
  59. gestures.forEach(gesture => {
  60. //var id = (gesture.binding.gesture.id) ? gesture.binding.gesture.id : gesture.binding.gesture.type;
  61. var id = gesture.binding.gesture.id;
  62. if (toBeDispatched[id]) {
  63. var path = util.getPropagationPath(event);
  64. if (util.getPathIndex(path, gesture.binding.element) < util.getPathIndex(path, toBeDispatched[id].binding.element)) {
  65. toBeDispatched[id] = gesture;
  66. }
  67. } else {
  68. toBeDispatched[id] = gesture;
  69. }
  70. });
  71.  
  72. Object.keys(toBeDispatched).forEach(index => {
  73. var gesture = toBeDispatched[index];
  74. dispatcher(gesture.binding, gesture.data, gesture.events);
  75. });
  76. }
  77.  
  78. var endCount = 0;
  79. state.inputs.forEach(input => {
  80. if (input.getCurrentEventType() === 'end') {
  81. endCount++;
  82. }
  83. });
  84.  
  85. if (endCount === state.inputs.length) {
  86. state.resetInputs();
  87. }
  88.  
  89. }
  90. /*arbiter*/
  91.  
  92. export default arbiter;