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