src/cm/media/js/lib/yui/yui3-3.15.0/build/event-move/event-move.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 YUI.add('event-move', function (Y, NAME) {
       
     2 
       
     3 /**
       
     4  * Adds lower level support for "gesturemovestart", "gesturemove" and "gesturemoveend" events, which can be used to create drag/drop
       
     5  * interactions which work across touch and mouse input devices. They correspond to "touchstart", "touchmove" and "touchend" on a touch input
       
     6  * device, and "mousedown", "mousemove", "mouseup" on a mouse based input device.
       
     7  *
       
     8  * <p>Documentation for the gesturemove triplet of events can be found on the <a href="../classes/YUI.html#event_gesturemove">YUI</a> global,
       
     9  * along with the other supported events.</p>
       
    10 
       
    11  @example
       
    12 
       
    13      YUI().use('event-move', function (Y) {
       
    14          Y.one('#myNode').on('gesturemovestart', function (e) {
       
    15          });
       
    16          Y.one('#myNode').on('gesturemove', function (e) {
       
    17          });
       
    18          Y.one('#myNode').on('gesturemoveend', function (e) {
       
    19          });
       
    20      });
       
    21 
       
    22  * @module event-gestures
       
    23  * @submodule event-move
       
    24  */
       
    25 
       
    26 
       
    27  var GESTURE_MAP = Y.Event._GESTURE_MAP,
       
    28      EVENT = {
       
    29          start: GESTURE_MAP.start,
       
    30          end: GESTURE_MAP.end,
       
    31          move: GESTURE_MAP.move
       
    32      },
       
    33     START = "start",
       
    34     MOVE = "move",
       
    35     END = "end",
       
    36 
       
    37     GESTURE_MOVE = "gesture" + MOVE,
       
    38     GESTURE_MOVE_END = GESTURE_MOVE + END,
       
    39     GESTURE_MOVE_START = GESTURE_MOVE + START,
       
    40 
       
    41     _MOVE_START_HANDLE = "_msh",
       
    42     _MOVE_HANDLE = "_mh",
       
    43     _MOVE_END_HANDLE = "_meh",
       
    44 
       
    45     _DEL_MOVE_START_HANDLE = "_dmsh",
       
    46     _DEL_MOVE_HANDLE = "_dmh",
       
    47     _DEL_MOVE_END_HANDLE = "_dmeh",
       
    48 
       
    49     _MOVE_START = "_ms",
       
    50     _MOVE = "_m",
       
    51 
       
    52     MIN_TIME = "minTime",
       
    53     MIN_DISTANCE = "minDistance",
       
    54     PREVENT_DEFAULT = "preventDefault",
       
    55     BUTTON = "button",
       
    56     OWNER_DOCUMENT = "ownerDocument",
       
    57 
       
    58     CURRENT_TARGET = "currentTarget",
       
    59     TARGET = "target",
       
    60 
       
    61     NODE_TYPE = "nodeType",
       
    62     SUPPORTS_POINTER = Y.config.win && ("msPointerEnabled" in Y.config.win.navigator),
       
    63     MS_TOUCH_ACTION_COUNT = 'msTouchActionCount',
       
    64     MS_INIT_TOUCH_ACTION = 'msInitTouchAction',
       
    65 
       
    66     _defArgsProcessor = function(se, args, delegate) {
       
    67         var iConfig = (delegate) ? 4 : 3,
       
    68             config = (args.length > iConfig) ? Y.merge(args.splice(iConfig,1)[0]) : {};
       
    69 
       
    70         if (!(PREVENT_DEFAULT in config)) {
       
    71             config[PREVENT_DEFAULT] = se.PREVENT_DEFAULT;
       
    72         }
       
    73 
       
    74         return config;
       
    75     },
       
    76 
       
    77     _getRoot = function(node, subscriber) {
       
    78         return subscriber._extra.root || (node.get(NODE_TYPE) === 9) ? node : node.get(OWNER_DOCUMENT);
       
    79     },
       
    80 
       
    81     //Checks to see if the node is the document, and if it is, returns the documentElement.
       
    82     _checkDocumentElem = function(node) {
       
    83         var elem = node.getDOMNode();
       
    84         if (node.compareTo(Y.config.doc) && elem.documentElement) {
       
    85             return elem.documentElement;
       
    86         }
       
    87         else {
       
    88             return false;
       
    89         }
       
    90     },
       
    91 
       
    92     _normTouchFacade = function(touchFacade, touch, params) {
       
    93         touchFacade.pageX = touch.pageX;
       
    94         touchFacade.pageY = touch.pageY;
       
    95         touchFacade.screenX = touch.screenX;
       
    96         touchFacade.screenY = touch.screenY;
       
    97         touchFacade.clientX = touch.clientX;
       
    98         touchFacade.clientY = touch.clientY;
       
    99         touchFacade[TARGET] = touchFacade[TARGET] || touch[TARGET];
       
   100         touchFacade[CURRENT_TARGET] = touchFacade[CURRENT_TARGET] || touch[CURRENT_TARGET];
       
   101 
       
   102         touchFacade[BUTTON] = (params && params[BUTTON]) || 1; // default to left (left as per vendors, not W3C which is 0)
       
   103     },
       
   104 
       
   105     /*
       
   106     In IE10 touch mode, gestures will not work properly unless the -ms-touch-action CSS property is set to something other than 'auto'. Read http://msdn.microsoft.com/en-us/library/windows/apps/hh767313.aspx for more info. To get around this, we set -ms-touch-action: none which is the same as e.preventDefault() on touch environments. This tells the browser to fire DOM events for all touch events, and not perform any default behavior.
       
   107 
       
   108     The user can over-ride this by setting a more lenient -ms-touch-action property on a node (such as pan-x, pan-y, etc.) via CSS when subscribing to the 'gesturemovestart' event.
       
   109     */
       
   110     _setTouchActions = function (node) {
       
   111         var elem = _checkDocumentElem(node) || node.getDOMNode(),
       
   112             num = node.getData(MS_TOUCH_ACTION_COUNT);
       
   113 
       
   114         //Checks to see if msTouchAction is supported.
       
   115         if (SUPPORTS_POINTER) {
       
   116             if (!num) {
       
   117                 num = 0;
       
   118                 node.setData(MS_INIT_TOUCH_ACTION, elem.style.msTouchAction);
       
   119             }
       
   120             elem.style.msTouchAction = Y.Event._DEFAULT_TOUCH_ACTION;
       
   121             num++;
       
   122             node.setData(MS_TOUCH_ACTION_COUNT, num);
       
   123         }
       
   124     },
       
   125 
       
   126     /*
       
   127     Resets the element's -ms-touch-action property back to the original value, This is called on detach() and detachDelegate().
       
   128     */
       
   129     _unsetTouchActions = function (node) {
       
   130         var elem = _checkDocumentElem(node) || node.getDOMNode(),
       
   131             num = node.getData(MS_TOUCH_ACTION_COUNT),
       
   132             initTouchAction = node.getData(MS_INIT_TOUCH_ACTION);
       
   133 
       
   134         if (SUPPORTS_POINTER) {
       
   135             num--;
       
   136             node.setData(MS_TOUCH_ACTION_COUNT, num);
       
   137             if (num === 0 && elem.style.msTouchAction !== initTouchAction) {
       
   138                 elem.style.msTouchAction = initTouchAction;
       
   139             }
       
   140         }
       
   141     },
       
   142 
       
   143     _prevent = function(e, preventDefault) {
       
   144         if (preventDefault) {
       
   145             // preventDefault is a boolean or a function
       
   146             if (!preventDefault.call || preventDefault(e)) {
       
   147                 e.preventDefault();
       
   148             }
       
   149         }
       
   150     },
       
   151 
       
   152     define = Y.Event.define;
       
   153     Y.Event._DEFAULT_TOUCH_ACTION = 'none';
       
   154 
       
   155 /**
       
   156  * Sets up a "gesturemovestart" event, that is fired on touch devices in response to a single finger "touchstart",
       
   157  * and on mouse based devices in response to a "mousedown". The subscriber can specify the minimum time
       
   158  * and distance thresholds which should be crossed before the "gesturemovestart" is fired and for the mouse,
       
   159  * which button should initiate a "gesturemovestart". This event can also be listened for using node.delegate().
       
   160  *
       
   161  * <p>It is recommended that you use Y.bind to set up context and additional arguments for your event handler,
       
   162  * however if you want to pass the context and arguments as additional signature arguments to on/delegate,
       
   163  * you need to provide a null value for the configuration object, e.g: <code>node.on("gesturemovestart", fn, null, context, arg1, arg2, arg3)</code></p>
       
   164  *
       
   165  * @event gesturemovestart
       
   166  * @for YUI
       
   167  * @param type {string} "gesturemovestart"
       
   168  * @param fn {function} The method the event invokes. It receives the event facade of the underlying DOM event (mousedown or touchstart.touches[0]) which contains position co-ordinates.
       
   169  * @param cfg {Object} Optional. An object which specifies:
       
   170  *
       
   171  * <dl>
       
   172  * <dt>minDistance (defaults to 0)</dt>
       
   173  * <dd>The minimum distance threshold which should be crossed before the gesturemovestart is fired</dd>
       
   174  * <dt>minTime (defaults to 0)</dt>
       
   175  * <dd>The minimum time threshold for which the finger/mouse should be help down before the gesturemovestart is fired</dd>
       
   176  * <dt>button (no default)</dt>
       
   177  * <dd>In the case of a mouse input device, if the event should only be fired for a specific mouse button.</dd>
       
   178  * <dt>preventDefault (defaults to false)</dt>
       
   179  * <dd>Can be set to true/false to prevent default behavior as soon as the touchstart or mousedown is received (that is before minTime or minDistance thresholds are crossed, and so before the gesturemovestart listener is notified) so that things like text selection and context popups (on touch devices) can be
       
   180  * prevented. This property can also be set to a function, which returns true or false, based on the event facade passed to it (for example, DragDrop can determine if the target is a valid handle or not before preventing default).</dd>
       
   181  * </dl>
       
   182  *
       
   183  * @return {EventHandle} the detach handle
       
   184  */
       
   185 
       
   186 define(GESTURE_MOVE_START, {
       
   187 
       
   188     on: function (node, subscriber, ce) {
       
   189 
       
   190         //Set -ms-touch-action on IE10 and set preventDefault to true
       
   191         _setTouchActions(node);
       
   192 
       
   193         subscriber[_MOVE_START_HANDLE] = node.on(EVENT[START],
       
   194             this._onStart,
       
   195             this,
       
   196             node,
       
   197             subscriber,
       
   198             ce);
       
   199     },
       
   200 
       
   201     delegate : function(node, subscriber, ce, filter) {
       
   202 
       
   203         var se = this;
       
   204 
       
   205         subscriber[_DEL_MOVE_START_HANDLE] = node.delegate(EVENT[START],
       
   206             function(e) {
       
   207                 se._onStart(e, node, subscriber, ce, true);
       
   208             },
       
   209             filter);
       
   210     },
       
   211 
       
   212     detachDelegate : function(node, subscriber, ce, filter) {
       
   213         var handle = subscriber[_DEL_MOVE_START_HANDLE];
       
   214 
       
   215         if (handle) {
       
   216             handle.detach();
       
   217             subscriber[_DEL_MOVE_START_HANDLE] = null;
       
   218         }
       
   219 
       
   220         _unsetTouchActions(node);
       
   221     },
       
   222 
       
   223     detach: function (node, subscriber, ce) {
       
   224         var startHandle = subscriber[_MOVE_START_HANDLE];
       
   225 
       
   226         if (startHandle) {
       
   227             startHandle.detach();
       
   228             subscriber[_MOVE_START_HANDLE] = null;
       
   229         }
       
   230 
       
   231         _unsetTouchActions(node);
       
   232     },
       
   233 
       
   234     processArgs : function(args, delegate) {
       
   235         var params = _defArgsProcessor(this, args, delegate);
       
   236 
       
   237         if (!(MIN_TIME in params)) {
       
   238             params[MIN_TIME] = this.MIN_TIME;
       
   239         }
       
   240 
       
   241         if (!(MIN_DISTANCE in params)) {
       
   242             params[MIN_DISTANCE] = this.MIN_DISTANCE;
       
   243         }
       
   244 
       
   245         return params;
       
   246     },
       
   247 
       
   248     _onStart : function(e, node, subscriber, ce, delegate) {
       
   249 
       
   250         if (delegate) {
       
   251             node = e[CURRENT_TARGET];
       
   252         }
       
   253 
       
   254         var params = subscriber._extra,
       
   255             fireStart = true,
       
   256             minTime = params[MIN_TIME],
       
   257             minDistance = params[MIN_DISTANCE],
       
   258             button = params.button,
       
   259             preventDefault = params[PREVENT_DEFAULT],
       
   260             root = _getRoot(node, subscriber),
       
   261             startXY;
       
   262 
       
   263         if (e.touches) {
       
   264             if (e.touches.length === 1) {
       
   265                 _normTouchFacade(e, e.touches[0], params);
       
   266             } else {
       
   267                 fireStart = false;
       
   268             }
       
   269         } else {
       
   270             fireStart = (button === undefined) || (button === e.button);
       
   271         }
       
   272 
       
   273 
       
   274         if (fireStart) {
       
   275 
       
   276             _prevent(e, preventDefault);
       
   277 
       
   278             if (minTime === 0 || minDistance === 0) {
       
   279                 this._start(e, node, ce, params);
       
   280 
       
   281             } else {
       
   282 
       
   283                 startXY = [e.pageX, e.pageY];
       
   284 
       
   285                 if (minTime > 0) {
       
   286 
       
   287 
       
   288                     params._ht = Y.later(minTime, this, this._start, [e, node, ce, params]);
       
   289 
       
   290                     params._hme = root.on(EVENT[END], Y.bind(function() {
       
   291                         this._cancel(params);
       
   292                     }, this));
       
   293                 }
       
   294 
       
   295                 if (minDistance > 0) {
       
   296 
       
   297 
       
   298                     params._hm = root.on(EVENT[MOVE], Y.bind(function(em) {
       
   299                         if (Math.abs(em.pageX - startXY[0]) > minDistance || Math.abs(em.pageY - startXY[1]) > minDistance) {
       
   300                             this._start(e, node, ce, params);
       
   301                         }
       
   302                     }, this));
       
   303                 }
       
   304             }
       
   305         }
       
   306     },
       
   307 
       
   308     _cancel : function(params) {
       
   309         if (params._ht) {
       
   310             params._ht.cancel();
       
   311             params._ht = null;
       
   312         }
       
   313         if (params._hme) {
       
   314             params._hme.detach();
       
   315             params._hme = null;
       
   316         }
       
   317         if (params._hm) {
       
   318             params._hm.detach();
       
   319             params._hm = null;
       
   320         }
       
   321     },
       
   322 
       
   323     _start : function(e, node, ce, params) {
       
   324 
       
   325         if (params) {
       
   326             this._cancel(params);
       
   327         }
       
   328 
       
   329         e.type = GESTURE_MOVE_START;
       
   330 
       
   331 
       
   332         node.setData(_MOVE_START, e);
       
   333         ce.fire(e);
       
   334     },
       
   335 
       
   336     MIN_TIME : 0,
       
   337     MIN_DISTANCE : 0,
       
   338     PREVENT_DEFAULT : false
       
   339 });
       
   340 
       
   341 /**
       
   342  * Sets up a "gesturemove" event, that is fired on touch devices in response to a single finger "touchmove",
       
   343  * and on mouse based devices in response to a "mousemove".
       
   344  *
       
   345  * <p>By default this event is only fired when the same node
       
   346  * has received a "gesturemovestart" event. The subscriber can set standAlone to true, in the configuration properties,
       
   347  * if they want to listen for this event without an initial "gesturemovestart".</p>
       
   348  *
       
   349  * <p>By default this event sets up it's internal "touchmove" and "mousemove" DOM listeners on the document element. The subscriber
       
   350  * can set the root configuration property, to specify which node to attach DOM listeners to, if different from the document.</p>
       
   351  *
       
   352  * <p>This event can also be listened for using node.delegate().</p>
       
   353  *
       
   354  * <p>It is recommended that you use Y.bind to set up context and additional arguments for your event handler,
       
   355  * however if you want to pass the context and arguments as additional signature arguments to on/delegate,
       
   356  * you need to provide a null value for the configuration object, e.g: <code>node.on("gesturemove", fn, null, context, arg1, arg2, arg3)</code></p>
       
   357  *
       
   358  * @event gesturemove
       
   359  * @for YUI
       
   360  * @param type {string} "gesturemove"
       
   361  * @param fn {function} The method the event invokes. It receives the event facade of the underlying DOM event (mousemove or touchmove.touches[0]) which contains position co-ordinates.
       
   362  * @param cfg {Object} Optional. An object which specifies:
       
   363  * <dl>
       
   364  * <dt>standAlone (defaults to false)</dt>
       
   365  * <dd>true, if the subscriber should be notified even if a "gesturemovestart" has not occured on the same node.</dd>
       
   366  * <dt>root (defaults to document)</dt>
       
   367  * <dd>The node to which the internal DOM listeners should be attached.</dd>
       
   368  * <dt>preventDefault (defaults to false)</dt>
       
   369  * <dd>Can be set to true/false to prevent default behavior as soon as the touchmove or mousemove is received. As with gesturemovestart, can also be set to function which returns true/false based on the event facade passed to it.</dd>
       
   370  * </dl>
       
   371  *
       
   372  * @return {EventHandle} the detach handle
       
   373  */
       
   374 define(GESTURE_MOVE, {
       
   375 
       
   376     on : function (node, subscriber, ce) {
       
   377 
       
   378         _setTouchActions(node);
       
   379         var root = _getRoot(node, subscriber, EVENT[MOVE]),
       
   380 
       
   381             moveHandle = root.on(EVENT[MOVE],
       
   382                 this._onMove,
       
   383                 this,
       
   384                 node,
       
   385                 subscriber,
       
   386                 ce);
       
   387 
       
   388         subscriber[_MOVE_HANDLE] = moveHandle;
       
   389 
       
   390     },
       
   391 
       
   392     delegate : function(node, subscriber, ce, filter) {
       
   393 
       
   394         var se = this;
       
   395 
       
   396         subscriber[_DEL_MOVE_HANDLE] = node.delegate(EVENT[MOVE],
       
   397             function(e) {
       
   398                 se._onMove(e, node, subscriber, ce, true);
       
   399             },
       
   400             filter);
       
   401     },
       
   402 
       
   403     detach : function (node, subscriber, ce) {
       
   404         var moveHandle = subscriber[_MOVE_HANDLE];
       
   405 
       
   406         if (moveHandle) {
       
   407             moveHandle.detach();
       
   408             subscriber[_MOVE_HANDLE] = null;
       
   409         }
       
   410 
       
   411         _unsetTouchActions(node);
       
   412     },
       
   413 
       
   414     detachDelegate : function(node, subscriber, ce, filter) {
       
   415         var handle = subscriber[_DEL_MOVE_HANDLE];
       
   416 
       
   417         if (handle) {
       
   418             handle.detach();
       
   419             subscriber[_DEL_MOVE_HANDLE] = null;
       
   420         }
       
   421 
       
   422         _unsetTouchActions(node);
       
   423 
       
   424     },
       
   425 
       
   426     processArgs : function(args, delegate) {
       
   427         return _defArgsProcessor(this, args, delegate);
       
   428     },
       
   429 
       
   430     _onMove : function(e, node, subscriber, ce, delegate) {
       
   431 
       
   432         if (delegate) {
       
   433             node = e[CURRENT_TARGET];
       
   434         }
       
   435 
       
   436         var fireMove = subscriber._extra.standAlone || node.getData(_MOVE_START),
       
   437             preventDefault = subscriber._extra.preventDefault;
       
   438 
       
   439 
       
   440         if (fireMove) {
       
   441 
       
   442             if (e.touches) {
       
   443                 if (e.touches.length === 1) {
       
   444                     _normTouchFacade(e, e.touches[0]);
       
   445                 } else {
       
   446                     fireMove = false;
       
   447                 }
       
   448             }
       
   449 
       
   450             if (fireMove) {
       
   451 
       
   452                 _prevent(e, preventDefault);
       
   453 
       
   454 
       
   455                 e.type = GESTURE_MOVE;
       
   456                 ce.fire(e);
       
   457             }
       
   458         }
       
   459     },
       
   460 
       
   461     PREVENT_DEFAULT : false
       
   462 });
       
   463 
       
   464 /**
       
   465  * Sets up a "gesturemoveend" event, that is fired on touch devices in response to a single finger "touchend",
       
   466  * and on mouse based devices in response to a "mouseup".
       
   467  *
       
   468  * <p>By default this event is only fired when the same node
       
   469  * has received a "gesturemove" or "gesturemovestart" event. The subscriber can set standAlone to true, in the configuration properties,
       
   470  * if they want to listen for this event without a preceding "gesturemovestart" or "gesturemove".</p>
       
   471  *
       
   472  * <p>By default this event sets up it's internal "touchend" and "mouseup" DOM listeners on the document element. The subscriber
       
   473  * can set the root configuration property, to specify which node to attach DOM listeners to, if different from the document.</p>
       
   474  *
       
   475  * <p>This event can also be listened for using node.delegate().</p>
       
   476  *
       
   477  * <p>It is recommended that you use Y.bind to set up context and additional arguments for your event handler,
       
   478  * however if you want to pass the context and arguments as additional signature arguments to on/delegate,
       
   479  * you need to provide a null value for the configuration object, e.g: <code>node.on("gesturemoveend", fn, null, context, arg1, arg2, arg3)</code></p>
       
   480  *
       
   481  *
       
   482  * @event gesturemoveend
       
   483  * @for YUI
       
   484  * @param type {string} "gesturemoveend"
       
   485  * @param fn {function} The method the event invokes. It receives the event facade of the underlying DOM event (mouseup or touchend.changedTouches[0]).
       
   486  * @param cfg {Object} Optional. An object which specifies:
       
   487  * <dl>
       
   488  * <dt>standAlone (defaults to false)</dt>
       
   489  * <dd>true, if the subscriber should be notified even if a "gesturemovestart" or "gesturemove" has not occured on the same node.</dd>
       
   490  * <dt>root (defaults to document)</dt>
       
   491  * <dd>The node to which the internal DOM listeners should be attached.</dd>
       
   492  * <dt>preventDefault (defaults to false)</dt>
       
   493  * <dd>Can be set to true/false to prevent default behavior as soon as the touchend or mouseup is received. As with gesturemovestart, can also be set to function which returns true/false based on the event facade passed to it.</dd>
       
   494  * </dl>
       
   495  *
       
   496  * @return {EventHandle} the detach handle
       
   497  */
       
   498 define(GESTURE_MOVE_END, {
       
   499 
       
   500     on : function (node, subscriber, ce) {
       
   501         _setTouchActions(node);
       
   502         var root = _getRoot(node, subscriber),
       
   503 
       
   504             endHandle = root.on(EVENT[END],
       
   505                 this._onEnd,
       
   506                 this,
       
   507                 node,
       
   508                 subscriber,
       
   509                 ce);
       
   510 
       
   511         subscriber[_MOVE_END_HANDLE] = endHandle;
       
   512     },
       
   513 
       
   514     delegate : function(node, subscriber, ce, filter) {
       
   515 
       
   516         var se = this;
       
   517 
       
   518         subscriber[_DEL_MOVE_END_HANDLE] = node.delegate(EVENT[END],
       
   519             function(e) {
       
   520                 se._onEnd(e, node, subscriber, ce, true);
       
   521             },
       
   522             filter);
       
   523     },
       
   524 
       
   525     detachDelegate : function(node, subscriber, ce, filter) {
       
   526         var handle = subscriber[_DEL_MOVE_END_HANDLE];
       
   527 
       
   528         if (handle) {
       
   529             handle.detach();
       
   530             subscriber[_DEL_MOVE_END_HANDLE] = null;
       
   531         }
       
   532 
       
   533         _unsetTouchActions(node);
       
   534 
       
   535     },
       
   536 
       
   537     detach : function (node, subscriber, ce) {
       
   538         var endHandle = subscriber[_MOVE_END_HANDLE];
       
   539 
       
   540         if (endHandle) {
       
   541             endHandle.detach();
       
   542             subscriber[_MOVE_END_HANDLE] = null;
       
   543         }
       
   544 
       
   545         _unsetTouchActions(node);
       
   546     },
       
   547 
       
   548     processArgs : function(args, delegate) {
       
   549         return _defArgsProcessor(this, args, delegate);
       
   550     },
       
   551 
       
   552     _onEnd : function(e, node, subscriber, ce, delegate) {
       
   553 
       
   554         if (delegate) {
       
   555             node = e[CURRENT_TARGET];
       
   556         }
       
   557 
       
   558         var fireMoveEnd = subscriber._extra.standAlone || node.getData(_MOVE) || node.getData(_MOVE_START),
       
   559             preventDefault = subscriber._extra.preventDefault;
       
   560 
       
   561         if (fireMoveEnd) {
       
   562 
       
   563             if (e.changedTouches) {
       
   564                 if (e.changedTouches.length === 1) {
       
   565                     _normTouchFacade(e, e.changedTouches[0]);
       
   566                 } else {
       
   567                     fireMoveEnd = false;
       
   568                 }
       
   569             }
       
   570 
       
   571             if (fireMoveEnd) {
       
   572 
       
   573                 _prevent(e, preventDefault);
       
   574 
       
   575                 e.type = GESTURE_MOVE_END;
       
   576                 ce.fire(e);
       
   577 
       
   578                 node.clearData(_MOVE_START);
       
   579                 node.clearData(_MOVE);
       
   580             }
       
   581         }
       
   582     },
       
   583 
       
   584     PREVENT_DEFAULT : false
       
   585 });
       
   586 
       
   587 
       
   588 }, '@VERSION@', {"requires": ["node-base", "event-touch", "event-synthetic"]});