src/cm/media/js/lib/yui/yui_3.10.3/build/event-tap/event-tap.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-tap', function (Y, NAME) {
       
     9 
       
    10 /**
       
    11 The tap module provides a gesture events, "tap", which normalizes user interactions
       
    12 across touch and mouse or pointer based input devices.  This can be used by application developers
       
    13 to build input device agnostic components which behave the same in response to either touch or mouse based
       
    14 interaction.
       
    15 
       
    16 'tap' is like a touchscreen 'click', only it requires much less finger-down time since it listens to touch events,
       
    17 but reverts to mouse events if touch is not supported.
       
    18 
       
    19 @example
       
    20 
       
    21     YUI().use('event-tap', function (Y) {
       
    22         Y.one('#my-button').on('tap', function (e) {
       
    23         });
       
    24     });
       
    25 
       
    26 @module event
       
    27 @submodule event-tap
       
    28 @author Andres Garza, matuzak and tilo mitra
       
    29 @since 3.7.0
       
    30 
       
    31 */
       
    32 var doc = Y.config.doc,
       
    33     GESTURE_MAP = Y.Event._GESTURE_MAP,
       
    34     SUPPORTS_TOUCHES = !!(doc && doc.createTouch),
       
    35     EVT_START = GESTURE_MAP.start,
       
    36     EVT_MOVE = GESTURE_MAP.move,
       
    37     EVT_END = GESTURE_MAP.end,
       
    38     EVT_CANCEL = GESTURE_MAP.cancel,
       
    39     EVT_TAP = 'tap',
       
    40 
       
    41     HANDLES = {
       
    42         START: 'Y_TAP_ON_START_HANDLE',
       
    43         MOVE: 'Y_TAP_ON_MOVE_HANDLE',
       
    44         END: 'Y_TAP_ON_END_HANDLE',
       
    45         CANCEL: 'Y_TAP_ON_CANCEL_HANDLE'
       
    46     };
       
    47 
       
    48 function detachHelper(subscription, handles, subset, context) {
       
    49 
       
    50     handles = subset ? handles : [ handles.START, handles.MOVE, handles.END, handles.CANCEL ];
       
    51 
       
    52     Y.Array.each(handles, function (item, index, array) {
       
    53         var handle = subscription[item];
       
    54         if (handle) {
       
    55             handle.detach();
       
    56             subscription[item] = null;
       
    57         }
       
    58     });
       
    59 
       
    60 }
       
    61 
       
    62 
       
    63 /**
       
    64 Sets up a "tap" event, that is fired on touch devices in response to a tap event (finger down, finder up).
       
    65 This event can be used instead of listening for click events which have a 500ms delay on most touch devices.
       
    66 This event can also be listened for using node.delegate().
       
    67 
       
    68 @event tap
       
    69 @param type {string} "tap"
       
    70 @param fn {function} The method the event invokes. It receives the event facade of the underlying DOM event.
       
    71 @for Event
       
    72 @return {EventHandle} the detach handle
       
    73 */
       
    74 Y.Event.define(EVT_TAP, {
       
    75 
       
    76     /**
       
    77     This function should set up the node that will eventually fire the event.
       
    78 
       
    79     Usage:
       
    80 
       
    81         node.on('tap', function (e) {
       
    82         });
       
    83 
       
    84     @method on
       
    85     @param {Y.Node} node
       
    86     @param {Array} subscription
       
    87     @param {Boolean} notifier
       
    88     @public
       
    89     @static
       
    90     **/
       
    91     on: function (node, subscription, notifier) {
       
    92         subscription[HANDLES.START] = node.on(EVT_START, this.touchStart, this, node, subscription, notifier);
       
    93     },
       
    94 
       
    95     /**
       
    96     Detaches all event subscriptions set up by the event-tap module
       
    97 
       
    98     @method detach
       
    99     @param {Y.Node} node
       
   100     @param {Array} subscription
       
   101     @param {Boolean} notifier
       
   102     @public
       
   103     @static
       
   104     **/
       
   105     detach: function (node, subscription, notifier) {
       
   106         detachHelper(subscription, HANDLES);
       
   107     },
       
   108 
       
   109     /**
       
   110     Event delegation for the 'tap' event. The delegated event will use a
       
   111     supplied selector or filtering function to test if the event references at least one
       
   112     node that should trigger the subscription callback.
       
   113 
       
   114     Usage:
       
   115 
       
   116         node.delegate('tap', function (e) {
       
   117         }, 'li a');
       
   118 
       
   119     @method delegate
       
   120     @param {Y.Node} node
       
   121     @param {Array} subscription
       
   122     @param {Boolean} notifier
       
   123     @param {String | Function} filter
       
   124     @public
       
   125     @static
       
   126     **/
       
   127     delegate: function (node, subscription, notifier, filter) {
       
   128         subscription[HANDLES.START] = node.delegate(EVT_START, function (e) {
       
   129             this.touchStart(e, node, subscription, notifier, true);
       
   130         }, filter, this);
       
   131     },
       
   132 
       
   133     /**
       
   134     Detaches the delegated event subscriptions set up by the event-tap module.
       
   135     Only used if you use node.delegate(...) instead of node.on(...);
       
   136 
       
   137     @method detachDelegate
       
   138     @param {Y.Node} node
       
   139     @param {Array} subscription
       
   140     @param {Boolean} notifier
       
   141     @public
       
   142     @static
       
   143     **/
       
   144     detachDelegate: function (node, subscription, notifier) {
       
   145         detachHelper(subscription, HANDLES);
       
   146     },
       
   147 
       
   148 
       
   149     /**
       
   150     Called when the monitor(s) are tapped on, either through touchstart or mousedown.
       
   151 
       
   152     @method touchStart
       
   153     @param {DOMEventFacade} event
       
   154     @param {Y.Node} node
       
   155     @param {Array} subscription
       
   156     @param {Boolean} notifier
       
   157     @param {Boolean} delegate
       
   158     @protected
       
   159     @static
       
   160     **/
       
   161     touchStart: function (event, node, subscription, notifier, delegate) {
       
   162 
       
   163         var context = {
       
   164                 canceled: false
       
   165             };
       
   166         //move ways to quit early to the top.
       
   167 
       
   168         // no right clicks
       
   169         if (event.button && event.button === 3) {
       
   170             return;
       
   171         }
       
   172 
       
   173         // for now just support a 1 finger count (later enhance via config)
       
   174         if (event.touches && event.touches.length !== 1) {
       
   175             return;
       
   176         }
       
   177 
       
   178         context.node = delegate ? event.currentTarget : node;
       
   179 
       
   180         //There is a double check in here to support event simulation tests, in which
       
   181         //event.touches can be undefined when simulating 'touchstart' on touch devices.
       
   182         if (SUPPORTS_TOUCHES && event.touches) {
       
   183           context.startXY = [ event.touches[0].pageX, event.touches[0].pageY ];
       
   184         }
       
   185         else {
       
   186           context.startXY = [ event.pageX, event.pageY ];
       
   187         }
       
   188 
       
   189         //Possibly outdated issue: something is off with the move that it attaches it but never triggers the handler
       
   190         subscription[HANDLES.MOVE] = node.once(EVT_MOVE, this.touchMove, this, node, subscription, notifier, delegate, context);
       
   191         subscription[HANDLES.END] = node.once(EVT_END, this.touchEnd, this, node, subscription, notifier, delegate, context);
       
   192         subscription[HANDLES.CANCEL] = node.once(EVT_CANCEL, this.touchMove, this, node, subscription, notifier, delegate, context);
       
   193     },
       
   194 
       
   195     /**
       
   196     Called when the monitor(s) fires a touchmove or touchcancel event (or the mouse equivalent).
       
   197     This method detaches event handlers so that 'tap' is not fired.
       
   198 
       
   199     @method touchMove
       
   200     @param {DOMEventFacade} event
       
   201     @param {Y.Node} node
       
   202     @param {Array} subscription
       
   203     @param {Boolean} notifier
       
   204     @param {Boolean} delegate
       
   205     @param {Object} context
       
   206     @protected
       
   207     @static
       
   208     **/
       
   209     touchMove: function (event, node, subscription, notifier, delegate, context) {
       
   210         detachHelper(subscription, [ HANDLES.MOVE, HANDLES.END, HANDLES.CANCEL ], true, context);
       
   211         context.cancelled = true;
       
   212 
       
   213     },
       
   214 
       
   215     /**
       
   216     Called when the monitor(s) fires a touchend event (or the mouse equivalent).
       
   217     This method fires the 'tap' event if certain requirements are met.
       
   218 
       
   219     @method touchEnd
       
   220     @param {DOMEventFacade} event
       
   221     @param {Y.Node} node
       
   222     @param {Array} subscription
       
   223     @param {Boolean} notifier
       
   224     @param {Boolean} delegate
       
   225     @param {Object} context
       
   226     @protected
       
   227     @static
       
   228     **/
       
   229     touchEnd: function (event, node, subscription, notifier, delegate, context) {
       
   230         var startXY = context.startXY,
       
   231             endXY,
       
   232             clientXY;
       
   233 
       
   234         //There is a double check in here to support event simulation tests, in which
       
   235         //event.touches can be undefined when simulating 'touchstart' on touch devices.
       
   236         if (SUPPORTS_TOUCHES && event.changedTouches) {
       
   237           endXY = [ event.changedTouches[0].pageX, event.changedTouches[0].pageY ];
       
   238           clientXY = [event.changedTouches[0].clientX, event.changedTouches[0].clientY];
       
   239         }
       
   240         else {
       
   241           endXY = [ event.pageX, event.pageY ];
       
   242           clientXY = [event.clientX, event.clientY];
       
   243         }
       
   244 
       
   245         detachHelper(subscription, [ HANDLES.MOVE, HANDLES.END, HANDLES.CANCEL ], true, context);
       
   246 
       
   247         // make sure mouse didn't move
       
   248         if (Math.abs(endXY[0] - startXY[0]) === 0 && Math.abs(endXY[1] - startXY[1]) === 0) {
       
   249 
       
   250             event.type = EVT_TAP;
       
   251             event.pageX = endXY[0];
       
   252             event.pageY = endXY[1];
       
   253             event.clientX = clientXY[0];
       
   254             event.clientY = clientXY[1];
       
   255             event.currentTarget = context.node;
       
   256 
       
   257             notifier.fire(event);
       
   258         }
       
   259     }
       
   260 });
       
   261 
       
   262 
       
   263 }, '3.10.3', {"requires": ["node-base", "event-base", "event-touch", "event-synthetic"]});