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