[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

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


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