src/cm/media/js/lib/yui/yui_3.10.3/build/event-flick/event-flick.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-flick', function (Y, NAME) {
       
     9 
       
    10 /**
       
    11  * The gestures module provides gesture events such as "flick", which normalize user interactions
       
    12  * across touch and mouse or pointer based input devices. This layer 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  * <p>Documentation for events added by this module can be found in the event document for the <a href="../classes/YUI.html#events">YUI</a> global.</p>
       
    17  *
       
    18  *
       
    19  @example
       
    20 
       
    21      YUI().use('event-flick', function (Y) {
       
    22          Y.one('#myNode').on('flick', function (e) {
       
    23          });
       
    24      });
       
    25 
       
    26  *
       
    27  * @module event-gestures
       
    28  */
       
    29 
       
    30 /**
       
    31  * Adds support for a "flick" event, which is fired at the end of a touch or mouse based flick gesture, and provides
       
    32  * velocity of the flick, along with distance and time information.
       
    33  *
       
    34  * <p>Documentation for the flick event can be found on the <a href="../classes/YUI.html#event_flick">YUI</a> global,
       
    35  * along with the other supported events.</p>
       
    36  *
       
    37  * @module event-gestures
       
    38  * @submodule event-flick
       
    39  */
       
    40 var GESTURE_MAP = Y.Event._GESTURE_MAP,
       
    41     EVENT = {
       
    42         start: GESTURE_MAP.start,
       
    43         end: GESTURE_MAP.end,
       
    44         move: GESTURE_MAP.move
       
    45     },
       
    46     START = "start",
       
    47     END = "end",
       
    48     MOVE = "move",
       
    49 
       
    50     OWNER_DOCUMENT = "ownerDocument",
       
    51     MIN_VELOCITY = "minVelocity",
       
    52     MIN_DISTANCE = "minDistance",
       
    53     PREVENT_DEFAULT = "preventDefault",
       
    54 
       
    55     _FLICK_START = "_fs",
       
    56     _FLICK_START_HANDLE = "_fsh",
       
    57     _FLICK_END_HANDLE = "_feh",
       
    58     _FLICK_MOVE_HANDLE = "_fmh",
       
    59 
       
    60     NODE_TYPE = "nodeType";
       
    61 
       
    62 /**
       
    63  * Sets up a "flick" event, that is fired whenever the user initiates a flick gesture on the node
       
    64  * where the listener is attached. The subscriber can specify a minimum distance or velocity for
       
    65  * which the event is to be fired. The subscriber can also specify if there is a particular axis which
       
    66  * they are interested in - "x" or "y". If no axis is specified, the axis along which there was most distance
       
    67  * covered is used.
       
    68  *
       
    69  * <p>It is recommended that you use Y.bind to set up context and additional arguments for your event handler,
       
    70  * however if you want to pass the context and arguments as additional signature arguments to "on",
       
    71  * you need to provide a null value for the configuration object, e.g: <code>node.on("flick", fn, null, context, arg1, arg2, arg3)</code></p>
       
    72  *
       
    73  * @event flick
       
    74  * @for YUI
       
    75  * @param type {string} "flick"
       
    76  * @param fn {function} The method the event invokes. It receives an event facade with an e.flick object containing the flick related properties: e.flick.time, e.flick.distance, e.flick.velocity and e.flick.axis, e.flick.start.
       
    77  * @param cfg {Object} Optional. An object which specifies any of the following:
       
    78  * <dl>
       
    79  * <dt>minDistance (in pixels, defaults to 10)</dt>
       
    80  * <dd>The minimum distance between start and end points, which would qualify the gesture as a flick.</dd>
       
    81  * <dt>minVelocity (in pixels/ms, defaults to 0)</dt>
       
    82  * <dd>The minimum velocity which would qualify the gesture as a flick.</dd>
       
    83  * <dt>preventDefault (defaults to false)</dt>
       
    84  * <dd>Can be set to true/false to prevent default behavior as soon as the touchstart/touchend or mousedown/mouseup is received so that things like scrolling or text selection can be
       
    85  * prevented. This property can also be set to a function, which returns true or false, based on the event facade passed to it.</dd>
       
    86  * <dt>axis (no default)</dt>
       
    87  * <dd>Can be set to "x" or "y" if you want to constrain the flick velocity and distance to a single axis. If not
       
    88  * defined, the axis along which the maximum distance was covered is used.</dd>
       
    89  * </dl>
       
    90  * @return {EventHandle} the detach handle
       
    91  */
       
    92 
       
    93 Y.Event.define('flick', {
       
    94 
       
    95     on: function (node, subscriber, ce) {
       
    96 
       
    97         var startHandle = node.on(EVENT[START],
       
    98             this._onStart,
       
    99             this,
       
   100             node,
       
   101             subscriber,
       
   102             ce);
       
   103 
       
   104         subscriber[_FLICK_START_HANDLE] = startHandle;
       
   105     },
       
   106 
       
   107     detach: function (node, subscriber, ce) {
       
   108 
       
   109         var startHandle = subscriber[_FLICK_START_HANDLE],
       
   110             endHandle = subscriber[_FLICK_END_HANDLE];
       
   111 
       
   112         if (startHandle) {
       
   113             startHandle.detach();
       
   114             subscriber[_FLICK_START_HANDLE] = null;
       
   115         }
       
   116 
       
   117         if (endHandle) {
       
   118             endHandle.detach();
       
   119             subscriber[_FLICK_END_HANDLE] = null;
       
   120         }
       
   121     },
       
   122 
       
   123     processArgs: function(args) {
       
   124         var params = (args.length > 3) ? Y.merge(args.splice(3, 1)[0]) : {};
       
   125 
       
   126         if (!(MIN_VELOCITY in params)) {
       
   127             params[MIN_VELOCITY] = this.MIN_VELOCITY;
       
   128         }
       
   129 
       
   130         if (!(MIN_DISTANCE in params)) {
       
   131             params[MIN_DISTANCE] = this.MIN_DISTANCE;
       
   132         }
       
   133 
       
   134         if (!(PREVENT_DEFAULT in params)) {
       
   135             params[PREVENT_DEFAULT] = this.PREVENT_DEFAULT;
       
   136         }
       
   137 
       
   138         return params;
       
   139     },
       
   140 
       
   141     _onStart: function(e, node, subscriber, ce) {
       
   142 
       
   143         var start = true, // always true for mouse
       
   144             endHandle,
       
   145             moveHandle,
       
   146             doc,
       
   147             preventDefault = subscriber._extra.preventDefault,
       
   148             origE = e;
       
   149 
       
   150         if (e.touches) {
       
   151             start = (e.touches.length === 1);
       
   152             e = e.touches[0];
       
   153         }
       
   154 
       
   155         if (start) {
       
   156 
       
   157             if (preventDefault) {
       
   158                 // preventDefault is a boolean or function
       
   159                 if (!preventDefault.call || preventDefault(e)) {
       
   160                     origE.preventDefault();
       
   161                 }
       
   162             }
       
   163 
       
   164             e.flick = {
       
   165                 time : new Date().getTime()
       
   166             };
       
   167 
       
   168             subscriber[_FLICK_START] = e;
       
   169 
       
   170             endHandle = subscriber[_FLICK_END_HANDLE];
       
   171 
       
   172             doc = (node.get(NODE_TYPE) === 9) ? node : node.get(OWNER_DOCUMENT);
       
   173             if (!endHandle) {
       
   174                 endHandle = doc.on(EVENT[END], Y.bind(this._onEnd, this), null, node, subscriber, ce);
       
   175                 subscriber[_FLICK_END_HANDLE] = endHandle;
       
   176             }
       
   177 
       
   178             subscriber[_FLICK_MOVE_HANDLE] = doc.once(EVENT[MOVE], Y.bind(this._onMove, this), null, node, subscriber, ce);
       
   179         }
       
   180     },
       
   181 
       
   182     _onMove: function(e, node, subscriber, ce) {
       
   183         var start = subscriber[_FLICK_START];
       
   184 
       
   185         // Start timing from first move.
       
   186         if (start && start.flick) {
       
   187             start.flick.time = new Date().getTime();
       
   188         }
       
   189     },
       
   190 
       
   191     _onEnd: function(e, node, subscriber, ce) {
       
   192 
       
   193         var endTime = new Date().getTime(),
       
   194             start = subscriber[_FLICK_START],
       
   195             valid = !!start,
       
   196             endEvent = e,
       
   197             startTime,
       
   198             time,
       
   199             preventDefault,
       
   200             params,
       
   201             xyDistance,
       
   202             distance,
       
   203             velocity,
       
   204             axis,
       
   205             moveHandle = subscriber[_FLICK_MOVE_HANDLE];
       
   206 
       
   207         if (moveHandle) {
       
   208             moveHandle.detach();
       
   209             delete subscriber[_FLICK_MOVE_HANDLE];
       
   210         }
       
   211 
       
   212         if (valid) {
       
   213 
       
   214             if (e.changedTouches) {
       
   215                 if (e.changedTouches.length === 1 && e.touches.length === 0) {
       
   216                     endEvent = e.changedTouches[0];
       
   217                 } else {
       
   218                     valid = false;
       
   219                 }
       
   220             }
       
   221 
       
   222             if (valid) {
       
   223 
       
   224                 params = subscriber._extra;
       
   225                 preventDefault = params[PREVENT_DEFAULT];
       
   226 
       
   227                 if (preventDefault) {
       
   228                     // preventDefault is a boolean or function
       
   229                     if (!preventDefault.call || preventDefault(e)) {
       
   230                         e.preventDefault();
       
   231                     }
       
   232                 }
       
   233 
       
   234                 startTime = start.flick.time;
       
   235                 endTime = new Date().getTime();
       
   236                 time = endTime - startTime;
       
   237 
       
   238                 xyDistance = [
       
   239                     endEvent.pageX - start.pageX,
       
   240                     endEvent.pageY - start.pageY
       
   241                 ];
       
   242 
       
   243                 if (params.axis) {
       
   244                     axis = params.axis;
       
   245                 } else {
       
   246                     axis = (Math.abs(xyDistance[0]) >= Math.abs(xyDistance[1])) ? 'x' : 'y';
       
   247                 }
       
   248 
       
   249                 distance = xyDistance[(axis === 'x') ? 0 : 1];
       
   250                 velocity = (time !== 0) ? distance/time : 0;
       
   251 
       
   252                 if (isFinite(velocity) && (Math.abs(distance) >= params[MIN_DISTANCE]) && (Math.abs(velocity)  >= params[MIN_VELOCITY])) {
       
   253 
       
   254                     e.type = "flick";
       
   255                     e.flick = {
       
   256                         time:time,
       
   257                         distance: distance,
       
   258                         velocity:velocity,
       
   259                         axis: axis,
       
   260                         start : start
       
   261                     };
       
   262 
       
   263                     ce.fire(e);
       
   264 
       
   265                 }
       
   266 
       
   267                 subscriber[_FLICK_START] = null;
       
   268             }
       
   269         }
       
   270     },
       
   271 
       
   272     MIN_VELOCITY : 0,
       
   273     MIN_DISTANCE : 0,
       
   274     PREVENT_DEFAULT : false
       
   275 });
       
   276 
       
   277 
       
   278 }, '3.10.3', {"requires": ["node-base", "event-touch", "event-synthetic"]});