[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/event-tap/ -> event-tap.js (source)

   1  /*
   2  YUI 3.17.2 (build 9c3c78e)
   3  Copyright 2014 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      EVT_START = GESTURE_MAP.start,
  35      EVT_TAP = 'tap',
  36      POINTER_EVENT_TEST = /pointer/i,
  37  
  38      HANDLES = {
  39          START: 'Y_TAP_ON_START_HANDLE',
  40          END: 'Y_TAP_ON_END_HANDLE',
  41          CANCEL: 'Y_TAP_ON_CANCEL_HANDLE'
  42      };
  43  
  44  function detachHandles(subscription, handles) {
  45      handles = handles || Y.Object.values(HANDLES);
  46  
  47      Y.Array.each(handles, function (item) {
  48          var handle = subscription[item];
  49          if (handle) {
  50              handle.detach();
  51              subscription[item] = null;
  52          }
  53      });
  54  
  55  }
  56  
  57  
  58  /**
  59  Sets up a "tap" event, that is fired on touch devices in response to a tap event (finger down, finder up).
  60  This event can be used instead of listening for click events which have a 500ms delay on most touch devices.
  61  This event can also be listened for using node.delegate().
  62  
  63  @event tap
  64  @param type {string} "tap"
  65  @param fn {function} The method the event invokes. It receives the event facade of the underlying DOM event.
  66  @for Event
  67  @return {EventHandle} the detach handle
  68  */
  69  Y.Event.define(EVT_TAP, {
  70      publishConfig: {
  71          preventedFn: function (e) {
  72              var sub = e.target.once('click', function (click) {
  73                  click.preventDefault();
  74              });
  75  
  76              // Make sure to detach the subscription during the next event loop
  77              // so this doesn't `preventDefault()` on the wrong click event.
  78              setTimeout(function () {
  79                  sub.detach();
  80              //Setting this to `0` causes the detachment to occur before the click
  81              //comes in on Android 4.0.3-4.0.4. 100ms seems to be a reliable number here
  82              //that works across the board.
  83              }, 100);
  84          }
  85      },
  86  
  87      processArgs: function (args, isDelegate) {
  88  
  89          //if we return for the delegate use case, then the `filter` argument
  90          //returns undefined, and we have to get the filter from sub._extra[0] (ugly)
  91  
  92          if (!isDelegate) {
  93              var extra = args[3];
  94              // remove the extra arguments from the array as specified by
  95              // http://yuilibrary.com/yui/docs/event/synths.html
  96              args.splice(3,1);
  97              return extra;
  98          }
  99      },
 100      /**
 101      This function should set up the node that will eventually fire the event.
 102  
 103      Usage:
 104  
 105          node.on('tap', function (e) {
 106          });
 107  
 108      @method on
 109      @param {Node} node
 110      @param {Array} subscription
 111      @param {Boolean} notifier
 112      @public
 113      @static
 114      **/
 115      on: function (node, subscription, notifier) {
 116          subscription[HANDLES.START] = node.on(EVT_START, this._start, this, node, subscription, notifier);
 117      },
 118  
 119      /**
 120      Detaches all event subscriptions set up by the event-tap module
 121  
 122      @method detach
 123      @param {Node} node
 124      @param {Array} subscription
 125      @param {Boolean} notifier
 126      @public
 127      @static
 128      **/
 129      detach: function (node, subscription, notifier) {
 130          detachHandles(subscription);
 131      },
 132  
 133      /**
 134      Event delegation for the 'tap' event. The delegated event will use a
 135      supplied selector or filtering function to test if the event references at least one
 136      node that should trigger the subscription callback.
 137  
 138      Usage:
 139  
 140          node.delegate('tap', function (e) {
 141          }, 'li a');
 142  
 143      @method delegate
 144      @param {Node} node
 145      @param {Array} subscription
 146      @param {Boolean} notifier
 147      @param {String | Function} filter
 148      @public
 149      @static
 150      **/
 151      delegate: function (node, subscription, notifier, filter) {
 152          subscription[HANDLES.START] = Y.delegate(EVT_START, function (e) {
 153              this._start(e, node, subscription, notifier, true);
 154          }, node, filter, this);
 155      },
 156  
 157      /**
 158      Detaches the delegated event subscriptions set up by the event-tap module.
 159      Only used if you use node.delegate(...) instead of node.on(...);
 160  
 161      @method detachDelegate
 162      @param {Node} node
 163      @param {Array} subscription
 164      @param {Boolean} notifier
 165      @public
 166      @static
 167      **/
 168      detachDelegate: function (node, subscription, notifier) {
 169          detachHandles(subscription);
 170      },
 171  
 172      /**
 173      Called when the monitor(s) are tapped on, either through touchstart or mousedown.
 174  
 175      @method _start
 176      @param {DOMEventFacade} event
 177      @param {Node} node
 178      @param {Array} subscription
 179      @param {Boolean} notifier
 180      @param {Boolean} delegate
 181      @protected
 182      @static
 183      **/
 184      _start: function (event, node, subscription, notifier, delegate) {
 185  
 186          var context = {
 187                  canceled: false,
 188                  eventType: event.type
 189              },
 190              preventMouse = subscription.preventMouse || false;
 191  
 192          //move ways to quit early to the top.
 193          // no right clicks
 194          if (event.button && event.button === 3) {
 195              return;
 196          }
 197  
 198          // for now just support a 1 finger count (later enhance via config)
 199          if (event.touches && event.touches.length !== 1) {
 200              return;
 201          }
 202  
 203          context.node = delegate ? event.currentTarget : node;
 204  
 205          //There is a double check in here to support event simulation tests, in which
 206          //event.touches can be undefined when simulating 'touchstart' on touch devices.
 207          if (event.touches) {
 208            context.startXY = [ event.touches[0].pageX, event.touches[0].pageY ];
 209          }
 210          else {
 211            context.startXY = [ event.pageX, event.pageY ];
 212          }
 213  
 214          //If `onTouchStart()` was called by a touch event, set up touch event subscriptions.
 215          //Otherwise, set up mouse/pointer event event subscriptions.
 216          if (event.touches) {
 217  
 218              subscription[HANDLES.END] = node.once('touchend', this._end, this, node, subscription, notifier, delegate, context);
 219              subscription[HANDLES.CANCEL] = node.once('touchcancel', this.detach, this, node, subscription, notifier, delegate, context);
 220  
 221              //Since this is a touch* event, there will be corresponding mouse events
 222              //that will be fired. We don't want these events to get picked up and fire
 223              //another `tap` event, so we'll set this variable to `true`.
 224              subscription.preventMouse = true;
 225          }
 226  
 227          //Only add these listeners if preventMouse is `false`
 228          //ie: not when touch events have already been subscribed to
 229          else if (context.eventType.indexOf('mouse') !== -1 && !preventMouse) {
 230              subscription[HANDLES.END] = node.once('mouseup', this._end, this, node, subscription, notifier, delegate, context);
 231              subscription[HANDLES.CANCEL] = node.once('mousecancel', this.detach, this, node, subscription, notifier, delegate, context);
 232          }
 233  
 234          //If a mouse event comes in after a touch event, it will go in here and
 235          //reset preventMouse to `true`.
 236          //If a mouse event comes in without a prior touch event, preventMouse will be
 237          //false in any case, so this block doesn't do anything.
 238          else if (context.eventType.indexOf('mouse') !== -1 && preventMouse) {
 239              subscription.preventMouse = false;
 240          }
 241  
 242          else if (POINTER_EVENT_TEST.test(context.eventType)) {
 243              subscription[HANDLES.END] = node.once(GESTURE_MAP.end, this._end, this, node, subscription, notifier, delegate, context);
 244              subscription[HANDLES.CANCEL] = node.once(GESTURE_MAP.cancel, this.detach, this, node, subscription, notifier, delegate, context);
 245          }
 246  
 247      },
 248  
 249  
 250      /**
 251      Called when the monitor(s) fires a touchend event (or the mouse equivalent).
 252      This method fires the 'tap' event if certain requirements are met.
 253  
 254      @method _end
 255      @param {DOMEventFacade} event
 256      @param {Node} node
 257      @param {Array} subscription
 258      @param {Boolean} notifier
 259      @param {Boolean} delegate
 260      @param {Object} context
 261      @protected
 262      @static
 263      **/
 264      _end: function (event, node, subscription, notifier, delegate, context) {
 265          var startXY = context.startXY,
 266              endXY,
 267              clientXY,
 268              sensitivity = 15;
 269  
 270          if (subscription._extra && subscription._extra.sensitivity >= 0) {
 271              sensitivity = subscription._extra.sensitivity;
 272          }
 273  
 274          //There is a double check in here to support event simulation tests, in which
 275          //event.touches can be undefined when simulating 'touchstart' on touch devices.
 276          if (event.changedTouches) {
 277            endXY = [ event.changedTouches[0].pageX, event.changedTouches[0].pageY ];
 278            clientXY = [event.changedTouches[0].clientX, event.changedTouches[0].clientY];
 279          }
 280          else {
 281            endXY = [ event.pageX, event.pageY ];
 282            clientXY = [event.clientX, event.clientY];
 283          }
 284  
 285          // make sure mouse didn't move
 286          if (Math.abs(endXY[0] - startXY[0]) <= sensitivity && Math.abs(endXY[1] - startXY[1]) <= sensitivity) {
 287  
 288              event.type = EVT_TAP;
 289              event.pageX = endXY[0];
 290              event.pageY = endXY[1];
 291              event.clientX = clientXY[0];
 292              event.clientY = clientXY[1];
 293              event.currentTarget = context.node;
 294  
 295              notifier.fire(event);
 296          }
 297  
 298          detachHandles(subscription, [HANDLES.END, HANDLES.CANCEL]);
 299      }
 300  });
 301  
 302  
 303  }, '3.17.2', {"requires": ["node-base", "event-base", "event-touch", "event-synthetic"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1