vendor: 18,659 bytes, lines 1-714
1var _____WB$wombat$assign$function_____=function(name){return (self._wb_wombat && self._wb_wombat.local_init && self._wb_wombat.local_init(name))||self[name];};if(!self.__WB_pmw){self.__WB_pmw=function(obj){this.__WB_source=obj;return this;}}{ 2let window = _____WB$wombat$assign$function_____("window"); 3let self = _____WB$wombat$assign$function_____("self"); 4let document = _____WB$wombat$assign$function_____("document"); 5let location = _____WB$wombat$assign$function_____("location"); 6let top = _____WB$wombat$assign$function_____("top"); 7let parent = _____WB$wombat$assign$function_____("parent"); 8let frames = _____WB$wombat$assign$function_____("frames"); 9let opens = _____WB$wombat$assign$function_____("opens"); 10 11/*! Hammer.JS - v2.0.4 - 2014-09-28 12 * http://hammerjs.github.io/ 13 * 14 * Copyright (c) 2014 Jorik Tangelder; 15 * Licensed under the MIT license */ 16(function(window, document, exportName, undefined) { 17 'use strict'; 18 19var VENDOR_PREFIXES = ['', 'webkit', 'moz', 'MS', 'ms', 'o']; 20var TEST_ELEMENT = document.createElement('div'); 21 22var TYPE_FUNCTION = 'function'; 23 24var round = Math.round; 25var abs = Math.abs; 26var now = Date.now; 27 28/** 29 * set a timeout with a given scope 30 * @param {Function} fn 31 * @param {Number} timeout 32 * @param {Object} context 33 * @returns {number} 34 */ 35function setTimeoutContext(fn, timeout, context) { 36 return setTimeout(bindFn(fn, context), timeout); 37} 38 39/** 40 * if the argument is an array, we want to execute the fn on each entry 41 * if it aint an array we don't want to do a thing. 42 * this is used by all the methods that accept a single and array argument. 43 * @param {*|Array} arg 44 * @param {String} fn 45 * @param {Object} [context] 46 * @returns {Boolean} 47 */ 48function invokeArrayArg(arg, fn, context) { 49 if (Array.isArray(arg)) { 50 each(arg, context[fn], context); 51 return true; 52 } 53 return false; 54} 55 56/** 57 * walk objects and arrays 58 * @param {Object} obj 59 * @param {Function} iterator 60 * @param {Object} context 61 */ 62function each(obj, iterator, context) { 63 var i; 64 65 if (!obj) { 66 return; 67 } 68 69 if (obj.forEach) { 70 obj.forEach(iterator, context); 71 } else if (obj.length !== undefined) { 72 i = 0; 73 while (i < obj.length) { 74 iterator.call(context, obj[i], i, obj); 75 i++; 76 } 77 } else { 78 for (i in obj) { 79 obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj); 80 } 81 } 82} 83 84/** 85 * extend object. 86 * means that properties in dest will be overwritten by the ones in src. 87 * @param {Object} dest 88 * @param {Object} src 89 * @param {Boolean} [merge] 90 * @returns {Object} dest 91 */ 92function extend(dest, src, merge) { 93 var keys = Object.keys(src); 94 var i = 0; 95 while (i < keys.length) { 96 if (!merge || (merge && dest[keys[i]] === undefined)) { 97 dest[keys[i]] = src[keys[i]]; 98 } 99 i++; 100 } 101 return dest; 102} 103 104/** 105 * merge the values from src in the dest. 106 * means that properties that exist in dest will not be overwritten by src 107 * @param {Object} dest 108 * @param {Object} src 109 * @returns {Object} dest 110 */ 111function merge(dest, src) { 112 return extend(dest, src, true); 113} 114 115/** 116 * simple class inheritance 117 * @param {Function} child 118 * @param {Function} base 119 * @param {Object} [properties] 120 */ 121function inherit(child, base, properties) { 122 var baseP = base.prototype, 123 childP; 124 125 childP = child.prototype = Object.create(baseP); 126 childP.constructor = child; 127 childP._super = baseP; 128 129 if (properties) { 130 extend(childP, properties); 131 } 132} 133 134/** 135 * simple function bind 136 * @param {Function} fn 137 * @param {Object} context 138 * @returns {Function} 139 */ 140function bindFn(fn, context) { 141 return function boundFn() { 142 return fn.apply(context, arguments); 143 }; 144} 145 146/** 147 * let a boolean value also be a function that must return a boolean 148 * this first item in args will be used as the context 149 * @param {Boolean|Function} val 150 * @param {Array} [args] 151 * @returns {Boolean} 152 */ 153function boolOrFn(val, args) { 154 if (typeof val == TYPE_FUNCTION) { 155 return val.apply(args ? args[0] || undefined : undefined, args); 156 } 157 return val; 158} 159 160/** 161 * use the val2 when val1 is undefined 162 * @param {*} val1 163 * @param {*} val2 164 * @returns {*} 165 */ 166function ifUndefined(val1, val2) { 167 return (val1 === undefined) ? val2 : val1; 168} 169 170/** 171 * addEventListener with multiple events at once 172 * @param {EventTarget} target 173 * @param {String} types 174 * @param {Function} handler 175 */ 176function addEventListeners(target, types, handler) { 177 each(splitStr(types), function(type) { 178 target.addEventListener(type, handler, false); 179 }); 180} 181 182/** 183 * removeEventListener with multiple events at once 184 * @param {EventTarget} target 185 * @param {String} types 186 * @param {Function} handler 187 */ 188function removeEventListeners(target, types, handler) { 189 each(splitStr(types), function(type) { 190 target.removeEventListener(type, handler, false); 191 }); 192} 193 194/** 195 * find if a node is in the given parent 196 * @method hasParent 197 * @param {HTMLElement} node 198 * @param {HTMLElement} parent 199 * @return {Boolean} found 200 */ 201function hasParent(node, parent) { 202 while (node) { 203 if (node == parent) { 204 return true; 205 } 206 node = node.parentNode; 207 } 208 return false; 209} 210 211/** 212 * small indexOf wrapper 213 * @param {String} str 214 * @param {String} find 215 * @returns {Boolean} found 216 */ 217function inStr(str, find) { 218 return str.indexOf(find) > -1; 219} 220 221/** 222 * split string on whitespace 223 * @param {String} str 224 * @returns {Array} words 225 */ 226function splitStr(str) { 227 return str.trim().split(/\s+/g); 228} 229 230/** 231 * find if a array contains the object using indexOf or a simple polyFill 232 * @param {Array} src 233 * @param {String} find 234 * @param {String} [findByKey] 235 * @return {Boolean|Number} false when not found, or the index 236 */ 237function inArray(src, find, findByKey) { 238 if (src.indexOf && !findByKey) { 239 return src.indexOf(find); 240 } else { 241 var i = 0; 242 while (i < src.length) { 243 if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) { 244 return i; 245 } 246 i++; 247 } 248 return -1; 249 } 250} 251 252/** 253 * convert array-like objects to real arrays 254 * @param {Object} obj 255 * @returns {Array} 256 */ 257function toArray(obj) { 258 return Array.prototype.slice.call(obj, 0); 259} 260 261/** 262 * unique array with objects based on a key (like 'id') or just by the array's value 263 * @param {Array} src [{id:1},{id:2},{id:1}] 264 * @param {String} [key] 265 * @param {Boolean} [sort=False] 266 * @returns {Array} [{id:1},{id:2}] 267 */ 268function uniqueArray(src, key, sort) { 269 var results = []; 270 var values = []; 271 var i = 0; 272 273 while (i < src.length) { 274 var val = key ? src[i][key] : src[i]; 275 if (inArray(values, val) < 0) { 276 results.push(src[i]); 277 } 278 values[i] = val; 279 i++; 280 } 281 282 if (sort) { 283 if (!key) { 284 results = results.sort(); 285 } else { 286 results = results.sort(function sortUniqueArray(a, b) { 287 return a[key] > b[key]; 288 }); 289 } 290 } 291 292 return results; 293} 294 295/** 296 * get the prefixed property 297 * @param {Object} obj 298 * @param {String} property 299 * @returns {String|Undefined} prefixed 300 */ 301function prefixed(obj, property) { 302 var prefix, prop; 303 var camelProp = property[0].toUpperCase() + property.slice(1); 304 305 var i = 0; 306 while (i < VENDOR_PREFIXES.length) { 307 prefix = VENDOR_PREFIXES[i]; 308 prop = (prefix) ? prefix + camelProp : property; 309 310 if (prop in obj) { 311 return prop; 312 } 313 i++; 314 } 315 return undefined; 316} 317 318/** 319 * get a unique id 320 * @returns {number} uniqueId 321 */ 322var _uniqueId = 1; 323function uniqueId() { 324 return _uniqueId++; 325} 326 327/** 328 * get the window object of an element 329 * @param {HTMLElement} element 330 * @returns {DocumentView|Window} 331 */ 332function getWindowForElement(element) { 333 var doc = element.ownerDocument; 334 return (doc.defaultView || doc.parentWindow); 335} 336 337var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i; 338 339var SUPPORT_TOUCH = ('ontouchstart' in window); 340var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined; 341var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent); 342 343var INPUT_TYPE_TOUCH = 'touch'; 344var INPUT_TYPE_PEN = 'pen'; 345var INPUT_TYPE_MOUSE = 'mouse'; 346var INPUT_TYPE_KINECT = 'kinect'; 347 348var COMPUTE_INTERVAL = 25; 349 350var INPUT_START = 1; 351var INPUT_MOVE = 2; 352var INPUT_END = 4; 353var INPUT_CANCEL = 8; 354 355var DIRECTION_NONE = 1; 356var DIRECTION_LEFT = 2; 357var DIRECTION_RIGHT = 4; 358var DIRECTION_UP = 8; 359var DIRECTION_DOWN = 16; 360 361var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT; 362var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN; 363var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL; 364 365var PROPS_XY = ['x', 'y']; 366var PROPS_CLIENT_XY = ['clientX', 'clientY']; 367 368/** 369 * create new input type manager 370 * @param {Manager} manager 371 * @param {Function} callback 372 * @returns {Input} 373 * @constructor 374 */ 375function Input(manager, callback) { 376 var self = this; 377 this.manager = manager; 378 this.callback = callback; 379 this.element = manager.element; 380 this.target = manager.options.inputTarget; 381 382 // smaller wrapper around the handler, for the scope and the enabled state of the manager, 383 // so when disabled the input events are completely bypassed. 384 this.domHandler = function(ev) { 385 if (boolOrFn(manager.options.enable, [manager])) { 386 self.handler(ev); 387 } 388 }; 389 390 this.init(); 391 392} 393 394Input.prototype = { 395 /** 396 * should handle the inputEvent data and trigger the callback 397 * @virtual 398 */ 399 handler: function() { }, 400 401 /** 402 * bind the events 403 */ 404 init: function() { 405 this.evEl && addEventListeners(this.element, this.evEl, this.domHandler); 406 this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler); 407 this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); 408 }, 409 410 /** 411 * unbind the events 412 */ 413 destroy: function() { 414 this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler); 415 this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler); 416 this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler); 417 } 418}; 419 420/** 421 * create new input type manager 422 * called by the Manager constructor 423 * @param {Hammer} manager 424 * @returns {Input} 425 */ 426function createInputInstance(manager) { 427 var Type; 428 var inputClass = manager.options.inputClass; 429 430 if (inputClass) { 431 Type = inputClass; 432 } else if (SUPPORT_POINTER_EVENTS) { 433 Type = PointerEventInput; 434 } else if (SUPPORT_ONLY_TOUCH) { 435 Type = TouchInput; 436 } else if (!SUPPORT_TOUCH) { 437 Type = MouseInput; 438 } else { 439 Type = TouchMouseInput; 440 } 441 return new (Type)(manager, inputHandler); 442} 443 444/** 445 * handle input events 446 * @param {Manager} manager 447 * @param {String} eventType 448 * @param {Object} input 449 */ 450function inputHandler(manager, eventType, input) { 451 var pointersLen = input.pointers.length; 452 var changedPointersLen = input.changedPointers.length; 453 var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0)); 454 var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0)); 455 456 input.isFirst = !!isFirst; 457 input.isFinal = !!isFinal; 458 459 if (isFirst) { 460 manager.session = {}; 461 } 462 463 // source event is the normalized value of the domEvents 464 // like 'touchstart, mouseup, pointerdown' 465 input.eventType = eventType; 466 467 // compute scale, rotation etc 468 computeInputData(manager, input); 469 470 // emit secret event 471 manager.emit('hammer.input', input); 472 473 manager.recognize(input); 474 manager.session.prevInput = input; 475} 476 477/** 478 * extend the data with some usable properties like scale, rotate, velocity etc 479 * @param {Object} manager 480 * @param {Object} input 481 */ 482function computeInputData(manager, input) { 483 var session = manager.session; 484 var pointers = input.pointers; 485 var pointersLength = pointers.length; 486 487 // store the first input to calculate the distance and direction 488 if (!session.firstInput) { 489 session.firstInput = simpleCloneInputData(input); 490 } 491 492 // to compute scale and rotation we need to store the multiple touches 493 if (pointersLength > 1 && !session.firstMultiple) { 494 session.firstMultiple = simpleCloneInputData(input); 495 } else if (pointersLength === 1) { 496 session.firstMultiple = false; 497 } 498 499 var firstInput = session.firstInput; 500 var firstMultiple = session.firstMultiple; 501 var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center; 502 503 var center = input.center = getCenter(pointers); 504 input.timeStamp = now(); 505 input.deltaTime = input.timeStamp - firstInput.timeStamp; 506 507 input.angle = getAngle(offsetCenter, center); 508 input.distance = getDistance(offsetCenter, center); 509 510 computeDeltaXY(session, input); 511 input.offsetDirection = getDirection(input.deltaX, input.deltaY); 512 513 input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1; 514 input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0; 515 516 computeIntervalInputData(session, input); 517 518 // find the correct target 519 var target = manager.element; 520 if (hasParent(input.srcEvent.target, target)) { 521 target = input.srcEvent.target; 522 } 523 input.target = target; 524} 525 526function computeDeltaXY(session, input) { 527 var center = input.center; 528 var offset = session.offsetDelta || {}; 529 var prevDelta = session.prevDelta || {}; 530 var prevInput = session.prevInput || {}; 531 532 if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) { 533 prevDelta = session.prevDelta = { 534 x: prevInput.deltaX || 0, 535 y: prevInput.deltaY || 0 536 }; 537 538 offset = session.offsetDelta = { 539 x: center.x, 540 y: center.y 541 }; 542 } 543 544 input.deltaX = prevDelta.x + (center.x - offset.x); 545 input.deltaY = prevDelta.y + (center.y - offset.y); 546} 547 548/** 549 * velocity is calculated every x ms 550 * @param {Object} session 551 * @param {Object} input 552 */ 553function computeIntervalInputData(session, input) { 554 var last = session.lastInterval || input, 555 deltaTime = input.timeStamp - last.timeStamp, 556 velocity, velocityX, velocityY, direction; 557 558 if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) { 559 var deltaX = last.deltaX - input.deltaX; 560 var deltaY = last.deltaY - input.deltaY; 561 562 var v = getVelocity(deltaTime, deltaX, deltaY); 563 velocityX = v.x; 564 velocityY = v.y; 565 velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y; 566 direction = getDirection(deltaX, deltaY); 567 568 session.lastInterval = input; 569 } else { 570 // use latest velocity info if it doesn't overtake a minimum period 571 velocity = last.velocity; 572 velocityX = last.velocityX; 573 velocityY = last.velocityY; 574 direction = last.direction; 575 } 576 577 input.velocity = velocity; 578 input.velocityX = velocityX; 579 input.velocityY = velocityY; 580 input.direction = direction; 581} 582 583/** 584 * create a simple clone from the input used for storage of firstInput and firstMultiple 585 * @param {Object} input 586 * @returns {Object} clonedInputData 587 */ 588function simpleCloneInputData(input) { 589 // make a simple copy of the pointers because we will get a reference if we don't 590 // we only need clientXY for the calculations 591 var pointers = []; 592 var i = 0; 593 while (i < input.pointers.length) { 594 pointers[i] = { 595 clientX: round(input.pointers[i].clientX), 596 clientY: round(input.pointers[i].clientY) 597 }; 598 i++; 599 } 600 601 return { 602 timeStamp: now(), 603 pointers: pointers, 604 center: getCenter(pointers), 605 deltaX: input.deltaX, 606 deltaY: input.deltaY 607 }; 608} 609 610/** 611 * get the center of all the pointers 612 * @param {Array} pointers 613 * @return {Object} center contains `x` and `y` properties 614 */ 615function getCenter(pointers) { 616 var pointersLength = pointers.length; 617 618 // no need to loop when only one touch 619 if (pointersLength === 1) { 620 return { 621 x: round(pointers[0].clientX), 622 y: round(pointers[0].clientY) 623 }; 624 } 625 626 var x = 0, y = 0, i = 0; 627 while (i < pointersLength) { 628 x += pointers[i].clientX; 629 y += pointers[i].clientY; 630 i++; 631 } 632 633 return { 634 x: round(x / pointersLength), 635 y: round(y / pointersLength) 636 }; 637} 638 639/** 640 * calculate the velocity between two points. unit is in px per ms. 641 * @param {Number} deltaTime 642 * @param {Number} x 643 * @param {Number} y 644 * @return {Object} velocity `x` and `y` 645 */ 646function getVelocity(deltaTime, x, y) { 647 return { 648 x: x / deltaTime || 0, 649 y: y / deltaTime || 0 650 }; 651} 652 653/** 654 * get the direction between two points 655 * @param {Number} x 656 * @param {Number} y 657 * @return {Number} direction 658 */ 659function getDirection(x, y) { 660 if (x === y) { 661 return DIRECTION_NONE; 662 } 663 664 if (abs(x) >= abs(y)) { 665 return x > 0 ? DIRECTION_LEFT : DIRECTION_RIGHT; 666 } 667 return y > 0 ? DIRECTION_UP : DIRECTION_DOWN; 668} 669 670/** 671 * calculate the absolute distance between two points 672 * @param {Object} p1 {x, y} 673 * @param {Object} p2 {x, y} 674 * @param {Array} [props] containing x and y keys 675 * @return {Number} distance 676 */ 677function getDistance(p1, p2, props) { 678 if (!props) { 679 props = PROPS_XY; 680 } 681 var x = p2[props[0]] - p1[props[0]], 682 y = p2[props[1]] - p1[props[1]]; 683 684 return Math.sqrt((x * x) + (y * y)); 685} 686 687/** 688 * calculate the angle between two coordinates 689 * @param {Object} p1 690 * @param {Object} p2 691 * @param {Array} [props] containing x and y keys 692 * @return {Number} angle 693 */ 694function getAngle(p1, p2, props) { 695 if (!props) { 696 props = PROPS_XY; 697 } 698 var x = p2[props[0]] - p1[props[0]], 699 y = p2[props[1]] - p1[props[1]]; 700 return Math.atan2(y, x) * 180 / Math.PI; 701} 702 703/** 704 * calculate the rotation degrees between two pointersets 705 * @param {Array} start array of pointers 706 * @param {Array} end array of pointers 707 * @return {Number} rotation 708 */ 709function getRotation(start, end) { 710 return getAngle(end[1], end[0], PROPS_CLIENT_XY) - getAngle(start[1], start[0], PROPS_CLIENT_XY); 711} 712 713/** 714 * calculate the scale factor between two pointersets
vendor: 19,901 bytes, lines 715-1424
715 * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out 716 * @param {Array} start array of pointers 717 * @param {Array} end array of pointers 718 * @return {Number} scale 719 */ 720function getScale(start, end) { 721 return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY); 722} 723 724var MOUSE_INPUT_MAP = { 725 mousedown: INPUT_START, 726 mousemove: INPUT_MOVE, 727 mouseup: INPUT_END 728}; 729 730var MOUSE_ELEMENT_EVENTS = 'mousedown'; 731var MOUSE_WINDOW_EVENTS = 'mousemove mouseup'; 732 733/** 734 * Mouse events input 735 * @constructor 736 * @extends Input 737 */ 738function MouseInput() { 739 this.evEl = MOUSE_ELEMENT_EVENTS; 740 this.evWin = MOUSE_WINDOW_EVENTS; 741 742 this.allow = true; // used by Input.TouchMouse to disable mouse events 743 this.pressed = false; // mousedown state 744 745 Input.apply(this, arguments); 746} 747 748inherit(MouseInput, Input, { 749 /** 750 * handle mouse events 751 * @param {Object} ev 752 */ 753 handler: function MEhandler(ev) { 754 var eventType = MOUSE_INPUT_MAP[ev.type]; 755 756 // on start we want to have the left mouse button down 757 if (eventType & INPUT_START && ev.button === 0) { 758 this.pressed = true; 759 } 760 761 if (eventType & INPUT_MOVE && ev.which !== 1) { 762 eventType = INPUT_END; 763 } 764 765 // mouse must be down, and mouse events are allowed (see the TouchMouse input) 766 if (!this.pressed || !this.allow) { 767 return; 768 } 769 770 if (eventType & INPUT_END) { 771 this.pressed = false; 772 } 773 774 this.callback(this.manager, eventType, { 775 pointers: [ev], 776 changedPointers: [ev], 777 pointerType: INPUT_TYPE_MOUSE, 778 srcEvent: ev 779 }); 780 } 781}); 782 783var POINTER_INPUT_MAP = { 784 pointerdown: INPUT_START, 785 pointermove: INPUT_MOVE, 786 pointerup: INPUT_END, 787 pointercancel: INPUT_CANCEL, 788 pointerout: INPUT_CANCEL 789}; 790 791// in IE10 the pointer types is defined as an enum 792var IE10_POINTER_TYPE_ENUM = { 793 2: INPUT_TYPE_TOUCH, 794 3: INPUT_TYPE_PEN, 795 4: INPUT_TYPE_MOUSE, 796 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816 797}; 798 799var POINTER_ELEMENT_EVENTS = 'pointerdown'; 800var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; 801 802// IE10 has prefixed support, and case-sensitive 803if (window.MSPointerEvent) { 804 POINTER_ELEMENT_EVENTS = 'MSPointerDown'; 805 POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel'; 806} 807 808/** 809 * Pointer events input 810 * @constructor 811 * @extends Input 812 */ 813function PointerEventInput() { 814 this.evEl = POINTER_ELEMENT_EVENTS; 815 this.evWin = POINTER_WINDOW_EVENTS; 816 817 Input.apply(this, arguments); 818 819 this.store = (this.manager.session.pointerEvents = []); 820} 821 822inherit(PointerEventInput, Input, { 823 /** 824 * handle mouse events 825 * @param {Object} ev 826 */ 827 handler: function PEhandler(ev) { 828 var store = this.store; 829 var removePointer = false; 830 831 var eventTypeNormalized = ev.type.toLowerCase().replace('ms', ''); 832 var eventType = POINTER_INPUT_MAP[eventTypeNormalized]; 833 var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType; 834 835 var isTouch = (pointerType == INPUT_TYPE_TOUCH); 836 837 // get index of the event in the store 838 var storeIndex = inArray(store, ev.pointerId, 'pointerId'); 839 840 // start and mouse must be down 841 if (eventType & INPUT_START && (ev.button === 0 || isTouch)) { 842 if (storeIndex < 0) { 843 store.push(ev); 844 storeIndex = store.length - 1; 845 } 846 } else if (eventType & (INPUT_END | INPUT_CANCEL)) { 847 removePointer = true; 848 } 849 850 // it not found, so the pointer hasn't been down (so it's probably a hover) 851 if (storeIndex < 0) { 852 return; 853 } 854 855 // update the event in the store 856 store[storeIndex] = ev; 857 858 this.callback(this.manager, eventType, { 859 pointers: store, 860 changedPointers: [ev], 861 pointerType: pointerType, 862 srcEvent: ev 863 }); 864 865 if (removePointer) { 866 // remove from the store 867 store.splice(storeIndex, 1); 868 } 869 } 870}); 871 872var SINGLE_TOUCH_INPUT_MAP = { 873 touchstart: INPUT_START, 874 touchmove: INPUT_MOVE, 875 touchend: INPUT_END, 876 touchcancel: INPUT_CANCEL 877}; 878 879var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart'; 880var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel'; 881 882/** 883 * Touch events input 884 * @constructor 885 * @extends Input 886 */ 887function SingleTouchInput() { 888 this.evTarget = SINGLE_TOUCH_TARGET_EVENTS; 889 this.evWin = SINGLE_TOUCH_WINDOW_EVENTS; 890 this.started = false; 891 892 Input.apply(this, arguments); 893} 894 895inherit(SingleTouchInput, Input, { 896 handler: function TEhandler(ev) { 897 var type = SINGLE_TOUCH_INPUT_MAP[ev.type]; 898 899 // should we handle the touch events? 900 if (type === INPUT_START) { 901 this.started = true; 902 } 903 904 if (!this.started) { 905 return; 906 } 907 908 var touches = normalizeSingleTouches.call(this, ev, type); 909 910 // when done, reset the started state 911 if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) { 912 this.started = false; 913 } 914 915 this.callback(this.manager, type, { 916 pointers: touches[0], 917 changedPointers: touches[1], 918 pointerType: INPUT_TYPE_TOUCH, 919 srcEvent: ev 920 }); 921 } 922}); 923 924/** 925 * @this {TouchInput} 926 * @param {Object} ev 927 * @param {Number} type flag 928 * @returns {undefined|Array} [all, changed] 929 */ 930function normalizeSingleTouches(ev, type) { 931 var all = toArray(ev.touches); 932 var changed = toArray(ev.changedTouches); 933 934 if (type & (INPUT_END | INPUT_CANCEL)) { 935 all = uniqueArray(all.concat(changed), 'identifier', true); 936 } 937 938 return [all, changed]; 939} 940 941var TOUCH_INPUT_MAP = { 942 touchstart: INPUT_START, 943 touchmove: INPUT_MOVE, 944 touchend: INPUT_END, 945 touchcancel: INPUT_CANCEL 946}; 947 948var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel'; 949 950/** 951 * Multi-user touch events input 952 * @constructor 953 * @extends Input 954 */ 955function TouchInput() { 956 this.evTarget = TOUCH_TARGET_EVENTS; 957 this.targetIds = {}; 958 959 Input.apply(this, arguments); 960} 961 962inherit(TouchInput, Input, { 963 handler: function MTEhandler(ev) { 964 var type = TOUCH_INPUT_MAP[ev.type]; 965 var touches = getTouches.call(this, ev, type); 966 if (!touches) { 967 return; 968 } 969 970 this.callback(this.manager, type, { 971 pointers: touches[0], 972 changedPointers: touches[1], 973 pointerType: INPUT_TYPE_TOUCH, 974 srcEvent: ev 975 }); 976 } 977}); 978 979/** 980 * @this {TouchInput} 981 * @param {Object} ev 982 * @param {Number} type flag 983 * @returns {undefined|Array} [all, changed] 984 */ 985function getTouches(ev, type) { 986 var allTouches = toArray(ev.touches); 987 var targetIds = this.targetIds; 988 989 // when there is only one touch, the process can be simplified 990 if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) { 991 targetIds[allTouches[0].identifier] = true; 992 return [allTouches, allTouches]; 993 } 994 995 var i, 996 targetTouches, 997 changedTouches = toArray(ev.changedTouches), 998 changedTargetTouches = [], 999 target = this.target; 1000 1001 // get target touches from touches 1002 targetTouches = allTouches.filter(function(touch) { 1003 return hasParent(touch.target, target); 1004 }); 1005 1006 // collect touches 1007 if (type === INPUT_START) { 1008 i = 0; 1009 while (i < targetTouches.length) { 1010 targetIds[targetTouches[i].identifier] = true; 1011 i++; 1012 } 1013 } 1014 1015 // filter changed touches to only contain touches that exist in the collected target ids 1016 i = 0; 1017 while (i < changedTouches.length) { 1018 if (targetIds[changedTouches[i].identifier]) { 1019 changedTargetTouches.push(changedTouches[i]); 1020 } 1021 1022 // cleanup removed touches 1023 if (type & (INPUT_END | INPUT_CANCEL)) { 1024 delete targetIds[changedTouches[i].identifier]; 1025 } 1026 i++; 1027 } 1028 1029 if (!changedTargetTouches.length) { 1030 return; 1031 } 1032 1033 return [ 1034 // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel' 1035 uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), 1036 changedTargetTouches 1037 ]; 1038} 1039 1040/** 1041 * Combined touch and mouse input 1042 * 1043 * Touch has a higher priority then mouse, and while touching no mouse events are allowed. 1044 * This because touch devices also emit mouse events while doing a touch. 1045 * 1046 * @constructor 1047 * @extends Input 1048 */ 1049function TouchMouseInput() { 1050 Input.apply(this, arguments); 1051 1052 var handler = bindFn(this.handler, this); 1053 this.touch = new TouchInput(this.manager, handler); 1054 this.mouse = new MouseInput(this.manager, handler); 1055} 1056 1057inherit(TouchMouseInput, Input, { 1058 /** 1059 * handle mouse and touch events 1060 * @param {Hammer} manager 1061 * @param {String} inputEvent 1062 * @param {Object} inputData 1063 */ 1064 handler: function TMEhandler(manager, inputEvent, inputData) { 1065 var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH), 1066 isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE); 1067 1068 // when we're in a touch event, so block all upcoming mouse events 1069 // most mobile browser also emit mouseevents, right after touchstart 1070 if (isTouch) { 1071 this.mouse.allow = false; 1072 } else if (isMouse && !this.mouse.allow) { 1073 return; 1074 } 1075 1076 // reset the allowMouse when we're done 1077 if (inputEvent & (INPUT_END | INPUT_CANCEL)) { 1078 this.mouse.allow = true; 1079 } 1080 1081 this.callback(manager, inputEvent, inputData); 1082 }, 1083 1084 /** 1085 * remove the event listeners 1086 */ 1087 destroy: function destroy() { 1088 this.touch.destroy(); 1089 this.mouse.destroy(); 1090 } 1091}); 1092 1093var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction'); 1094var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined; 1095 1096// magical touchAction value 1097var TOUCH_ACTION_COMPUTE = 'compute'; 1098var TOUCH_ACTION_AUTO = 'auto'; 1099var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented 1100var TOUCH_ACTION_NONE = 'none'; 1101var TOUCH_ACTION_PAN_X = 'pan-x'; 1102var TOUCH_ACTION_PAN_Y = 'pan-y'; 1103 1104/** 1105 * Touch Action 1106 * sets the touchAction property or uses the js alternative 1107 * @param {Manager} manager 1108 * @param {String} value 1109 * @constructor 1110 */ 1111function TouchAction(manager, value) { 1112 this.manager = manager; 1113 this.set(value); 1114} 1115 1116TouchAction.prototype = { 1117 /** 1118 * set the touchAction value on the element or enable the polyfill 1119 * @param {String} value 1120 */ 1121 set: function(value) { 1122 // find out the touch-action by the event handlers 1123 if (value == TOUCH_ACTION_COMPUTE) { 1124 value = this.compute(); 1125 } 1126 1127 if (NATIVE_TOUCH_ACTION) { 1128 this.manager.element.style[PREFIXED_TOUCH_ACTION] = value; 1129 } 1130 this.actions = value.toLowerCase().trim(); 1131 }, 1132 1133 /** 1134 * just re-set the touchAction value 1135 */ 1136 update: function() { 1137 this.set(this.manager.options.touchAction); 1138 }, 1139 1140 /** 1141 * compute the value for the touchAction property based on the recognizer's settings 1142 * @returns {String} value 1143 */ 1144 compute: function() { 1145 var actions = []; 1146 each(this.manager.recognizers, function(recognizer) { 1147 if (boolOrFn(recognizer.options.enable, [recognizer])) { 1148 actions = actions.concat(recognizer.getTouchAction()); 1149 } 1150 }); 1151 return cleanTouchActions(actions.join(' ')); 1152 }, 1153 1154 /** 1155 * this method is called on each input cycle and provides the preventing of the browser behavior 1156 * @param {Object} input 1157 */ 1158 preventDefaults: function(input) { 1159 // not needed with native support for the touchAction property 1160 if (NATIVE_TOUCH_ACTION) { 1161 return; 1162 } 1163 1164 var srcEvent = input.srcEvent; 1165 var direction = input.offsetDirection; 1166 1167 // if the touch action did prevented once this session 1168 if (this.manager.session.prevented) { 1169 srcEvent.preventDefault(); 1170 return; 1171 } 1172 1173 var actions = this.actions; 1174 var hasNone = inStr(actions, TOUCH_ACTION_NONE); 1175 var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); 1176 var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); 1177 1178 if (hasNone || 1179 (hasPanY && direction & DIRECTION_HORIZONTAL) || 1180 (hasPanX && direction & DIRECTION_VERTICAL)) { 1181 return this.preventSrc(srcEvent); 1182 } 1183 }, 1184 1185 /** 1186 * call preventDefault to prevent the browser's default behavior (scrolling in most cases) 1187 * @param {Object} srcEvent 1188 */ 1189 preventSrc: function(srcEvent) { 1190 this.manager.session.prevented = true; 1191 srcEvent.preventDefault(); 1192 } 1193}; 1194 1195/** 1196 * when the touchActions are collected they are not a valid value, so we need to clean things up. * 1197 * @param {String} actions 1198 * @returns {*} 1199 */ 1200function cleanTouchActions(actions) { 1201 // none 1202 if (inStr(actions, TOUCH_ACTION_NONE)) { 1203 return TOUCH_ACTION_NONE; 1204 } 1205 1206 var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X); 1207 var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); 1208 1209 // pan-x and pan-y can be combined 1210 if (hasPanX && hasPanY) { 1211 return TOUCH_ACTION_PAN_X + ' ' + TOUCH_ACTION_PAN_Y; 1212 } 1213 1214 // pan-x OR pan-y 1215 if (hasPanX || hasPanY) { 1216 return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y; 1217 } 1218 1219 // manipulation 1220 if (inStr(actions, TOUCH_ACTION_MANIPULATION)) { 1221 return TOUCH_ACTION_MANIPULATION; 1222 } 1223 1224 return TOUCH_ACTION_AUTO; 1225} 1226 1227/** 1228 * Recognizer flow explained; * 1229 * All recognizers have the initial state of POSSIBLE when a input session starts. 1230 * The definition of a input session is from the first input until the last input, with all it's movement in it. * 1231 * Example session for mouse-input: mousedown -> mousemove -> mouseup 1232 * 1233 * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed 1234 * which determines with state it should be. 1235 * 1236 * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to 1237 * POSSIBLE to give it another change on the next cycle. 1238 * 1239 * Possible 1240 * | 1241 * +-----+---------------+ 1242 * | | 1243 * +-----+-----+ | 1244 * | | | 1245 * Failed Cancelled | 1246 * +-------+------+ 1247 * | | 1248 * Recognized Began 1249 * | 1250 * Changed 1251 * | 1252 * Ended/Recognized 1253 */ 1254var STATE_POSSIBLE = 1; 1255var STATE_BEGAN = 2; 1256var STATE_CHANGED = 4; 1257var STATE_ENDED = 8; 1258var STATE_RECOGNIZED = STATE_ENDED; 1259var STATE_CANCELLED = 16; 1260var STATE_FAILED = 32; 1261 1262/** 1263 * Recognizer 1264 * Every recognizer needs to extend from this class. 1265 * @constructor 1266 * @param {Object} options 1267 */ 1268function Recognizer(options) { 1269 this.id = uniqueId(); 1270 1271 this.manager = null; 1272 this.options = merge(options || {}, this.defaults); 1273 1274 // default is enable true 1275 this.options.enable = ifUndefined(this.options.enable, true); 1276 1277 this.state = STATE_POSSIBLE; 1278 1279 this.simultaneous = {}; 1280 this.requireFail = []; 1281} 1282 1283Recognizer.prototype = { 1284 /** 1285 * @virtual 1286 * @type {Object} 1287 */ 1288 defaults: {}, 1289 1290 /** 1291 * set options 1292 * @param {Object} options 1293 * @return {Recognizer} 1294 */ 1295 set: function(options) { 1296 extend(this.options, options); 1297 1298 // also update the touchAction, in case something changed about the directions/enabled state 1299 this.manager && this.manager.touchAction.update(); 1300 return this; 1301 }, 1302 1303 /** 1304 * recognize simultaneous with an other recognizer. 1305 * @param {Recognizer} otherRecognizer 1306 * @returns {Recognizer} this 1307 */ 1308 recognizeWith: function(otherRecognizer) { 1309 if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) { 1310 return this; 1311 } 1312 1313 var simultaneous = this.simultaneous; 1314 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); 1315 if (!simultaneous[otherRecognizer.id]) { 1316 simultaneous[otherRecognizer.id] = otherRecognizer; 1317 otherRecognizer.recognizeWith(this); 1318 } 1319 return this; 1320 }, 1321 1322 /** 1323 * drop the simultaneous link. it doesnt remove the link on the other recognizer. 1324 * @param {Recognizer} otherRecognizer 1325 * @returns {Recognizer} this 1326 */ 1327 dropRecognizeWith: function(otherRecognizer) { 1328 if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) { 1329 return this; 1330 } 1331 1332 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); 1333 delete this.simultaneous[otherRecognizer.id]; 1334 return this; 1335 }, 1336 1337 /** 1338 * recognizer can only run when an other is failing 1339 * @param {Recognizer} otherRecognizer 1340 * @returns {Recognizer} this 1341 */ 1342 requireFailure: function(otherRecognizer) { 1343 if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) { 1344 return this; 1345 } 1346 1347 var requireFail = this.requireFail; 1348 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); 1349 if (inArray(requireFail, otherRecognizer) === -1) { 1350 requireFail.push(otherRecognizer); 1351 otherRecognizer.requireFailure(this); 1352 } 1353 return this; 1354 }, 1355 1356 /** 1357 * drop the requireFailure link. it does not remove the link on the other recognizer. 1358 * @param {Recognizer} otherRecognizer 1359 * @returns {Recognizer} this 1360 */ 1361 dropRequireFailure: function(otherRecognizer) { 1362 if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) { 1363 return this; 1364 } 1365 1366 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this); 1367 var index = inArray(this.requireFail, otherRecognizer); 1368 if (index > -1) { 1369 this.requireFail.splice(index, 1); 1370 } 1371 return this; 1372 }, 1373 1374 /** 1375 * has require failures boolean 1376 * @returns {boolean} 1377 */ 1378 hasRequireFailures: function() { 1379 return this.requireFail.length > 0; 1380 }, 1381 1382 /** 1383 * if the recognizer can recognize simultaneous with an other recognizer 1384 * @param {Recognizer} otherRecognizer 1385 * @returns {Boolean} 1386 */ 1387 canRecognizeWith: function(otherRecognizer) { 1388 return !!this.simultaneous[otherRecognizer.id]; 1389 }, 1390 1391 /** 1392 * You should use `tryEmit` instead of `emit` directly to check 1393 * that all the needed recognizers has failed before emitting. 1394 * @param {Object} input 1395 */ 1396 emit: function(input) { 1397 var self = this; 1398 var state = this.state; 1399 1400 function emit(withState) { 1401 self.manager.emit(self.options.event + (withState ? stateStr(state) : ''), input); 1402 } 1403 1404 // 'panstart' and 'panmove' 1405 if (state < STATE_ENDED) { 1406 emit(true); 1407 } 1408 1409 emit(); // simple 'eventName' events 1410 1411 // panend and pancancel 1412 if (state >= STATE_ENDED) { 1413 emit(true); 1414 } 1415 }, 1416 1417 /** 1418 * Check that all the require failure recognizers has failed, 1419 * if true, it emits a gesture event, 1420 * otherwise, setup the state to FAILED. 1421 * @param {Object} input 1422 */ 1423 tryEmit: function(input) { 1424 if (this.canEmit()) {
vendor: 7,169 bytes, lines 1425-1691
1425 return this.emit(input); 1426 } 1427 // it's failing anyway 1428 this.state = STATE_FAILED; 1429 }, 1430 1431 /** 1432 * can we emit? 1433 * @returns {boolean} 1434 */ 1435 canEmit: function() { 1436 var i = 0; 1437 while (i < this.requireFail.length) { 1438 if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) { 1439 return false; 1440 } 1441 i++; 1442 } 1443 return true; 1444 }, 1445 1446 /** 1447 * update the recognizer 1448 * @param {Object} inputData 1449 */ 1450 recognize: function(inputData) { 1451 // make a new copy of the inputData 1452 // so we can change the inputData without messing up the other recognizers 1453 var inputDataClone = extend({}, inputData); 1454 1455 // is is enabled and allow recognizing? 1456 if (!boolOrFn(this.options.enable, [this, inputDataClone])) { 1457 this.reset(); 1458 this.state = STATE_FAILED; 1459 return; 1460 } 1461 1462 // reset when we've reached the end 1463 if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) { 1464 this.state = STATE_POSSIBLE; 1465 } 1466 1467 this.state = this.process(inputDataClone); 1468 1469 // the recognizer has recognized a gesture 1470 // so trigger an event 1471 if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) { 1472 this.tryEmit(inputDataClone); 1473 } 1474 }, 1475 1476 /** 1477 * return the state of the recognizer 1478 * the actual recognizing happens in this method 1479 * @virtual 1480 * @param {Object} inputData 1481 * @returns {Const} STATE 1482 */ 1483 process: function(inputData) { }, // jshint ignore:line 1484 1485 /** 1486 * return the preferred touch-action 1487 * @virtual 1488 * @returns {Array} 1489 */ 1490 getTouchAction: function() { }, 1491 1492 /** 1493 * called when the gesture isn't allowed to recognize 1494 * like when another is being recognized or it is disabled 1495 * @virtual 1496 */ 1497 reset: function() { } 1498}; 1499 1500/** 1501 * get a usable string, used as event postfix 1502 * @param {Const} state 1503 * @returns {String} state 1504 */ 1505function stateStr(state) { 1506 if (state & STATE_CANCELLED) { 1507 return 'cancel'; 1508 } else if (state & STATE_ENDED) { 1509 return 'end'; 1510 } else if (state & STATE_CHANGED) { 1511 return 'move'; 1512 } else if (state & STATE_BEGAN) { 1513 return 'start'; 1514 } 1515 return ''; 1516} 1517 1518/** 1519 * direction cons to string 1520 * @param {Const} direction 1521 * @returns {String} 1522 */ 1523function directionStr(direction) { 1524 if (direction == DIRECTION_DOWN) { 1525 return 'down'; 1526 } else if (direction == DIRECTION_UP) { 1527 return 'up'; 1528 } else if (direction == DIRECTION_LEFT) { 1529 return 'left'; 1530 } else if (direction == DIRECTION_RIGHT) { 1531 return 'right'; 1532 } 1533 return ''; 1534} 1535 1536/** 1537 * get a recognizer by name if it is bound to a manager 1538 * @param {Recognizer|String} otherRecognizer 1539 * @param {Recognizer} recognizer 1540 * @returns {Recognizer} 1541 */ 1542function getRecognizerByNameIfManager(otherRecognizer, recognizer) { 1543 var manager = recognizer.manager; 1544 if (manager) { 1545 return manager.get(otherRecognizer); 1546 } 1547 return otherRecognizer; 1548} 1549 1550/** 1551 * This recognizer is just used as a base for the simple attribute recognizers. 1552 * @constructor 1553 * @extends Recognizer 1554 */ 1555function AttrRecognizer() { 1556 Recognizer.apply(this, arguments); 1557} 1558 1559inherit(AttrRecognizer, Recognizer, { 1560 /** 1561 * @namespace 1562 * @memberof AttrRecognizer 1563 */ 1564 defaults: { 1565 /** 1566 * @type {Number} 1567 * @default 1 1568 */ 1569 pointers: 1 1570 }, 1571 1572 /** 1573 * Used to check if it the recognizer receives valid input, like input.distance > 10. 1574 * @memberof AttrRecognizer 1575 * @param {Object} input 1576 * @returns {Boolean} recognized 1577 */ 1578 attrTest: function(input) { 1579 var optionPointers = this.options.pointers; 1580 return optionPointers === 0 || input.pointers.length === optionPointers; 1581 }, 1582 1583 /** 1584 * Process the input and return the state for the recognizer 1585 * @memberof AttrRecognizer 1586 * @param {Object} input 1587 * @returns {*} State 1588 */ 1589 process: function(input) { 1590 var state = this.state; 1591 var eventType = input.eventType; 1592 1593 var isRecognized = state & (STATE_BEGAN | STATE_CHANGED); 1594 var isValid = this.attrTest(input); 1595 1596 // on cancel input and we've recognized before, return STATE_CANCELLED 1597 if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) { 1598 return state | STATE_CANCELLED; 1599 } else if (isRecognized || isValid) { 1600 if (eventType & INPUT_END) { 1601 return state | STATE_ENDED; 1602 } else if (!(state & STATE_BEGAN)) { 1603 return STATE_BEGAN; 1604 } 1605 return state | STATE_CHANGED; 1606 } 1607 return STATE_FAILED; 1608 } 1609}); 1610 1611/** 1612 * Pan 1613 * Recognized when the pointer is down and moved in the allowed direction. 1614 * @constructor 1615 * @extends AttrRecognizer 1616 */ 1617function PanRecognizer() { 1618 AttrRecognizer.apply(this, arguments); 1619 1620 this.pX = null; 1621 this.pY = null; 1622} 1623 1624inherit(PanRecognizer, AttrRecognizer, { 1625 /** 1626 * @namespace 1627 * @memberof PanRecognizer 1628 */ 1629 defaults: { 1630 event: 'pan', 1631 threshold: 10, 1632 pointers: 1, 1633 direction: DIRECTION_ALL 1634 }, 1635 1636 getTouchAction: function() { 1637 var direction = this.options.direction; 1638 var actions = []; 1639 if (direction & DIRECTION_HORIZONTAL) { 1640 actions.push(TOUCH_ACTION_PAN_Y); 1641 } 1642 if (direction & DIRECTION_VERTICAL) { 1643 actions.push(TOUCH_ACTION_PAN_X); 1644 } 1645 return actions; 1646 }, 1647 1648 directionTest: function(input) { 1649 var options = this.options; 1650 var hasMoved = true; 1651 var distance = input.distance; 1652 var direction = input.direction; 1653 var x = input.deltaX; 1654 var y = input.deltaY; 1655 1656 // lock to axis? 1657 if (!(direction & options.direction)) { 1658 if (options.direction & DIRECTION_HORIZONTAL) { 1659 direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT; 1660 hasMoved = x != this.pX; 1661 distance = Math.abs(input.deltaX); 1662 } else { 1663 direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN; 1664 hasMoved = y != this.pY; 1665 distance = Math.abs(input.deltaY); 1666 } 1667 } 1668 input.direction = direction; 1669 return hasMoved && distance > options.threshold && direction & options.direction; 1670 }, 1671 1672 attrTest: function(input) { 1673 return AttrRecognizer.prototype.attrTest.call(this, input) && 1674 (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input))); 1675 }, 1676 1677 emit: function(input) { 1678 this.pX = input.deltaX; 1679 this.pY = input.deltaY; 1680 1681 var direction = directionStr(input.direction); 1682 if (direction) { 1683 this.manager.emit(this.options.event + direction, input); 1684 } 1685 1686 this._super.emit.call(this, input); 1687 } 1688}); 1689 1690/** 1691 * Pinch
vendor: 2,938 bytes, lines 1692-1801
1692 * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out). 1693 * @constructor 1694 * @extends AttrRecognizer 1695 */ 1696function PinchRecognizer() { 1697 AttrRecognizer.apply(this, arguments); 1698} 1699 1700inherit(PinchRecognizer, AttrRecognizer, { 1701 /** 1702 * @namespace 1703 * @memberof PinchRecognizer 1704 */ 1705 defaults: { 1706 event: 'pinch', 1707 threshold: 0, 1708 pointers: 2 1709 }, 1710 1711 getTouchAction: function() { 1712 return [TOUCH_ACTION_NONE]; 1713 }, 1714 1715 attrTest: function(input) { 1716 return this._super.attrTest.call(this, input) && 1717 (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN); 1718 }, 1719 1720 emit: function(input) { 1721 this._super.emit.call(this, input); 1722 if (input.scale !== 1) { 1723 var inOut = input.scale < 1 ? 'in' : 'out'; 1724 this.manager.emit(this.options.event + inOut, input); 1725 } 1726 } 1727}); 1728 1729/** 1730 * Press 1731 * Recognized when the pointer is down for x ms without any movement. 1732 * @constructor 1733 * @extends Recognizer 1734 */ 1735function PressRecognizer() { 1736 Recognizer.apply(this, arguments); 1737 1738 this._timer = null; 1739 this._input = null; 1740} 1741 1742inherit(PressRecognizer, Recognizer, { 1743 /** 1744 * @namespace 1745 * @memberof PressRecognizer 1746 */ 1747 defaults: { 1748 event: 'press', 1749 pointers: 1, 1750 time: 500, // minimal time of the pointer to be pressed 1751 threshold: 5 // a minimal movement is ok, but keep it low 1752 }, 1753 1754 getTouchAction: function() { 1755 return [TOUCH_ACTION_AUTO]; 1756 }, 1757 1758 process: function(input) { 1759 var options = this.options; 1760 var validPointers = input.pointers.length === options.pointers; 1761 var validMovement = input.distance < options.threshold; 1762 var validTime = input.deltaTime > options.time; 1763 1764 this._input = input; 1765 1766 // we only allow little movement 1767 // and we've reached an end event, so a tap is possible 1768 if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) { 1769 this.reset(); 1770 } else if (input.eventType & INPUT_START) { 1771 this.reset(); 1772 this._timer = setTimeoutContext(function() { 1773 this.state = STATE_RECOGNIZED; 1774 this.tryEmit(); 1775 }, options.time, this); 1776 } else if (input.eventType & INPUT_END) { 1777 return STATE_RECOGNIZED; 1778 } 1779 return STATE_FAILED; 1780 }, 1781 1782 reset: function() { 1783 clearTimeout(this._timer); 1784 }, 1785 1786 emit: function(input) { 1787 if (this.state !== STATE_RECOGNIZED) { 1788 return; 1789 } 1790 1791 if (input && (input.eventType & INPUT_END)) { 1792 this.manager.emit(this.options.event + 'up', input); 1793 } else { 1794 this._input.timeStamp = now(); 1795 this.manager.emit(this.options.event, this._input); 1796 } 1797 } 1798}); 1799 1800/** 1801 * Rotate
vendor: 4,136 bytes, lines 1802-1947
1802 * Recognized when two or more pointer are moving in a circular motion. 1803 * @constructor 1804 * @extends AttrRecognizer 1805 */ 1806function RotateRecognizer() { 1807 AttrRecognizer.apply(this, arguments); 1808} 1809 1810inherit(RotateRecognizer, AttrRecognizer, { 1811 /** 1812 * @namespace 1813 * @memberof RotateRecognizer 1814 */ 1815 defaults: { 1816 event: 'rotate', 1817 threshold: 0, 1818 pointers: 2 1819 }, 1820 1821 getTouchAction: function() { 1822 return [TOUCH_ACTION_NONE]; 1823 }, 1824 1825 attrTest: function(input) { 1826 return this._super.attrTest.call(this, input) && 1827 (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN); 1828 } 1829}); 1830 1831/** 1832 * Swipe 1833 * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction. 1834 * @constructor 1835 * @extends AttrRecognizer 1836 */ 1837function SwipeRecognizer() { 1838 AttrRecognizer.apply(this, arguments); 1839} 1840 1841inherit(SwipeRecognizer, AttrRecognizer, { 1842 /** 1843 * @namespace 1844 * @memberof SwipeRecognizer 1845 */ 1846 defaults: { 1847 event: 'swipe', 1848 threshold: 10, 1849 velocity: 0.65, 1850 direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL, 1851 pointers: 1 1852 }, 1853 1854 getTouchAction: function() { 1855 return PanRecognizer.prototype.getTouchAction.call(this); 1856 }, 1857 1858 attrTest: function(input) { 1859 var direction = this.options.direction; 1860 var velocity; 1861 1862 if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) { 1863 velocity = input.velocity; 1864 } else if (direction & DIRECTION_HORIZONTAL) { 1865 velocity = input.velocityX; 1866 } else if (direction & DIRECTION_VERTICAL) { 1867 velocity = input.velocityY; 1868 } 1869 1870 return this._super.attrTest.call(this, input) && 1871 direction & input.direction && 1872 input.distance > this.options.threshold && 1873 abs(velocity) > this.options.velocity && input.eventType & INPUT_END; 1874 }, 1875 1876 emit: function(input) { 1877 var direction = directionStr(input.direction); 1878 if (direction) { 1879 this.manager.emit(this.options.event + direction, input); 1880 } 1881 1882 this.manager.emit(this.options.event, input); 1883 } 1884}); 1885 1886/** 1887 * A tap is ecognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur 1888 * between the given interval and position. The delay option can be used to recognize multi-taps without firing 1889 * a single tap. 1890 * 1891 * The eventData from the emitted event contains the property `tapCount`, which contains the amount of 1892 * multi-taps being recognized. 1893 * @constructor 1894 * @extends Recognizer 1895 */ 1896function TapRecognizer() { 1897 Recognizer.apply(this, arguments); 1898 1899 // previous time and center, 1900 // used for tap counting 1901 this.pTime = false; 1902 this.pCenter = false; 1903 1904 this._timer = null; 1905 this._input = null; 1906 this.count = 0; 1907} 1908 1909inherit(TapRecognizer, Recognizer, { 1910 /** 1911 * @namespace 1912 * @memberof PinchRecognizer 1913 */ 1914 defaults: { 1915 event: 'tap', 1916 pointers: 1, 1917 taps: 1, 1918 interval: 300, // max time between the multi-tap taps 1919 time: 250, // max time of the pointer to be down (like finger on the screen) 1920 threshold: 2, // a minimal movement is ok, but keep it low 1921 posThreshold: 10 // a multi-tap can be a bit off the initial position 1922 }, 1923 1924 getTouchAction: function() { 1925 return [TOUCH_ACTION_MANIPULATION]; 1926 }, 1927 1928 process: function(input) { 1929 var options = this.options; 1930 1931 var validPointers = input.pointers.length === options.pointers; 1932 var validMovement = input.distance < options.threshold; 1933 var validTouchTime = input.deltaTime < options.time; 1934 1935 this.reset(); 1936 1937 if ((input.eventType & INPUT_START) && (this.count === 0)) { 1938 return this.failTimeout(); 1939 } 1940 1941 // we only allow little movement 1942 // and we've reached an end event, so a tap is possible 1943 if (validMovement && validTouchTime && validPointers) { 1944 if (input.eventType != INPUT_END) { 1945 return this.failTimeout(); 1946 } 1947
vendor: 10,156 bytes, lines 1948-2269
1948 var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true; 1949 var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold; 1950 1951 this.pTime = input.timeStamp; 1952 this.pCenter = input.center; 1953 1954 if (!validMultiTap || !validInterval) { 1955 this.count = 1; 1956 } else { 1957 this.count += 1; 1958 } 1959 1960 this._input = input; 1961 1962 // if tap count matches we have recognized it, 1963 // else it has began recognizing... 1964 var tapCount = this.count % options.taps; 1965 if (tapCount === 0) { 1966 // no failing requirements, immediately trigger the tap event 1967 // or wait as long as the multitap interval to trigger 1968 if (!this.hasRequireFailures()) { 1969 return STATE_RECOGNIZED; 1970 } else { 1971 this._timer = setTimeoutContext(function() { 1972 this.state = STATE_RECOGNIZED; 1973 this.tryEmit(); 1974 }, options.interval, this); 1975 return STATE_BEGAN; 1976 } 1977 } 1978 } 1979 return STATE_FAILED; 1980 }, 1981 1982 failTimeout: function() { 1983 this._timer = setTimeoutContext(function() { 1984 this.state = STATE_FAILED; 1985 }, this.options.interval, this); 1986 return STATE_FAILED; 1987 }, 1988 1989 reset: function() { 1990 clearTimeout(this._timer); 1991 }, 1992 1993 emit: function() { 1994 if (this.state == STATE_RECOGNIZED ) { 1995 this._input.tapCount = this.count; 1996 this.manager.emit(this.options.event, this._input); 1997 } 1998 } 1999}); 2000 2001/** 2002 * Simple way to create an manager with a default set of recognizers. 2003 * @param {HTMLElement} element 2004 * @param {Object} [options] 2005 * @constructor 2006 */ 2007function Hammer(element, options) { 2008 options = options || {}; 2009 options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset); 2010 return new Manager(element, options); 2011} 2012 2013/** 2014 * @const {string} 2015 */ 2016Hammer.VERSION = '2.0.4'; 2017 2018/** 2019 * default settings 2020 * @namespace 2021 */ 2022Hammer.defaults = { 2023 /** 2024 * set if DOM events are being triggered. 2025 * But this is slower and unused by simple implementations, so disabled by default. 2026 * @type {Boolean} 2027 * @default false 2028 */ 2029 domEvents: false, 2030 2031 /** 2032 * The value for the touchAction property/fallback. 2033 * When set to `compute` it will magically set the correct value based on the added recognizers. 2034 * @type {String} 2035 * @default compute 2036 */ 2037 touchAction: TOUCH_ACTION_COMPUTE, 2038 2039 /** 2040 * @type {Boolean} 2041 * @default true 2042 */ 2043 enable: true, 2044 2045 /** 2046 * EXPERIMENTAL FEATURE -- can be removed/changed 2047 * Change the parent input target element. 2048 * If Null, then it is being set the to main element. 2049 * @type {Null|EventTarget} 2050 * @default null 2051 */ 2052 inputTarget: null, 2053 2054 /** 2055 * force an input class 2056 * @type {Null|Function} 2057 * @default null 2058 */ 2059 inputClass: null, 2060 2061 /** 2062 * Default recognizer setup when calling `Hammer()` 2063 * When creating a new Manager these will be skipped. 2064 * @type {Array} 2065 */ 2066 preset: [ 2067 // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...] 2068 [RotateRecognizer, { enable: false }], 2069 [PinchRecognizer, { enable: false }, ['rotate']], 2070 [SwipeRecognizer,{ direction: DIRECTION_HORIZONTAL }], 2071 [PanRecognizer, { direction: DIRECTION_HORIZONTAL }, ['swipe']], 2072 [TapRecognizer], 2073 [TapRecognizer, { event: 'doubletap', taps: 2 }, ['tap']], 2074 [PressRecognizer] 2075 ], 2076 2077 /** 2078 * Some CSS properties can be used to improve the working of Hammer. 2079 * Add them to this method and they will be set when creating a new Manager. 2080 * @namespace 2081 */ 2082 cssProps: { 2083 /** 2084 * Disables text selection to improve the dragging gesture. Mainly for desktop browsers. 2085 * @type {String} 2086 * @default 'none' 2087 */ 2088 userSelect: 'none', 2089 2090 /** 2091 * Disable the Windows Phone grippers when pressing an element. 2092 * @type {String} 2093 * @default 'none' 2094 */ 2095 touchSelect: 'none', 2096 2097 /** 2098 * Disables the default callout shown when you touch and hold a touch target. 2099 * On iOS, when you touch and hold a touch target such as a link, Safari displays 2100 * a callout containing information about the link. This property allows you to disable that callout. 2101 * @type {String} 2102 * @default 'none' 2103 */ 2104 touchCallout: 'none', 2105 2106 /** 2107 * Specifies whether zooming is enabled. Used by IE10> 2108 * @type {String} 2109 * @default 'none' 2110 */ 2111 contentZooming: 'none', 2112 2113 /** 2114 * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers. 2115 * @type {String} 2116 * @default 'none' 2117 */ 2118 userDrag: 'none', 2119 2120 /** 2121 * Overrides the highlight color shown when the user taps a link or a JavaScript 2122 * clickable element in iOS. This property obeys the alpha value, if specified. 2123 * @type {String} 2124 * @default 'rgba(0,0,0,0)' 2125 */ 2126 tapHighlightColor: 'rgba(0,0,0,0)' 2127 } 2128}; 2129 2130var STOP = 1; 2131var FORCED_STOP = 2; 2132 2133/** 2134 * Manager 2135 * @param {HTMLElement} element 2136 * @param {Object} [options] 2137 * @constructor 2138 */ 2139function Manager(element, options) { 2140 options = options || {}; 2141 2142 this.options = merge(options, Hammer.defaults); 2143 this.options.inputTarget = this.options.inputTarget || element; 2144 2145 this.handlers = {}; 2146 this.session = {}; 2147 this.recognizers = []; 2148 2149 this.element = element; 2150 this.input = createInputInstance(this); 2151 this.touchAction = new TouchAction(this, this.options.touchAction); 2152 2153 toggleCssProps(this, true); 2154 2155 each(options.recognizers, function(item) { 2156 var recognizer = this.add(new (item[0])(item[1])); 2157 item[2] && recognizer.recognizeWith(item[2]); 2158 item[3] && recognizer.requireFailure(item[3]); 2159 }, this); 2160} 2161 2162Manager.prototype = { 2163 /** 2164 * set options 2165 * @param {Object} options 2166 * @returns {Manager} 2167 */ 2168 set: function(options) { 2169 extend(this.options, options); 2170 2171 // Options that need a little more setup 2172 if (options.touchAction) { 2173 this.touchAction.update(); 2174 } 2175 if (options.inputTarget) { 2176 // Clean up existing event listeners and reinitialize 2177 this.input.destroy(); 2178 this.input.target = options.inputTarget; 2179 this.input.init(); 2180 } 2181 return this; 2182 }, 2183 2184 /** 2185 * stop recognizing for this session. 2186 * This session will be discarded, when a new [input]start event is fired. 2187 * When forced, the recognizer cycle is stopped immediately. 2188 * @param {Boolean} [force] 2189 */ 2190 stop: function(force) { 2191 this.session.stopped = force ? FORCED_STOP : STOP; 2192 }, 2193 2194 /** 2195 * run the recognizers! 2196 * called by the inputHandler function on every movement of the pointers (touches) 2197 * it walks through all the recognizers and tries to detect the gesture that is being made 2198 * @param {Object} inputData 2199 */ 2200 recognize: function(inputData) { 2201 var session = this.session; 2202 if (session.stopped) { 2203 return; 2204 } 2205 2206 // run the touch-action polyfill 2207 this.touchAction.preventDefaults(inputData); 2208 2209 var recognizer; 2210 var recognizers = this.recognizers; 2211 2212 // this holds the recognizer that is being recognized. 2213 // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED 2214 // if no recognizer is detecting a thing, it is set to `null` 2215 var curRecognizer = session.curRecognizer; 2216 2217 // reset when the last recognizer is recognized 2218 // or when we're in a new session 2219 if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) { 2220 curRecognizer = session.curRecognizer = null; 2221 } 2222 2223 var i = 0; 2224 while (i < recognizers.length) { 2225 recognizer = recognizers[i]; 2226 2227 // find out if we are allowed try to recognize the input for this one. 2228 // 1. allow if the session is NOT forced stopped (see the .stop() method) 2229 // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one 2230 // that is being recognized. 2231 // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer. 2232 // this can be setup with the `recognizeWith()` method on the recognizer. 2233 if (session.stopped !== FORCED_STOP && ( // 1 2234 !curRecognizer || recognizer == curRecognizer || // 2 2235 recognizer.canRecognizeWith(curRecognizer))) { // 3 2236 recognizer.recognize(inputData); 2237 } else { 2238 recognizer.reset(); 2239 } 2240 2241 // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the 2242 // current active recognizer. but only if we don't already have an active recognizer 2243 if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) { 2244 curRecognizer = session.curRecognizer = recognizer; 2245 } 2246 i++; 2247 } 2248 }, 2249 2250 /** 2251 * get a recognizer by its event name. 2252 * @param {Recognizer|String} recognizer 2253 * @returns {Recognizer|Null} 2254 */ 2255 get: function(recognizer) { 2256 if (recognizer instanceof Recognizer) { 2257 return recognizer; 2258 } 2259 2260 var recognizers = this.recognizers; 2261 for (var i = 0; i < recognizers.length; i++) { 2262 if (recognizers[i].options.event == recognizer) { 2263 return recognizers[i]; 2264 } 2265 } 2266 return null; 2267 }, 2268 2269 /**
2270 * add a recognizer to the manager 2271 * existing recognizers with the same event name will be removed 2272 * @param {Recognizer} recognizer 2273 * @returns {Recognizer|Manager} 2274 */ 2275 add: function(recognizer) { 2276 if (invokeArrayArg(recognizer, 'add', this)) { 2277 return this; 2278 } 2279 2280 // remove existing 2281 var existing = this.get(recognizer.options.event); 2282 if (existing) { 2283 this.remove(existing); 2284 } 2285 2286 this.recognizers.push(recognizer); 2287 recognizer.manager = this; 2288 2289 this.touchAction.update(); 2290 return recognizer; 2291 }, 2292 2293 /** 2294 * remove a recognizer by name or instance 2295 * @param {Recognizer|String} recognizer 2296 * @returns {Manager} 2297 */ 2298 remove: function(recognizer) { 2299 if (invokeArrayArg(recognizer, 'remove', this)) { 2300 return this; 2301 } 2302 2303 var recognizers = this.recognizers; 2304 recognizer = this.get(recognizer); 2305 recognizers.splice(inArray(recognizers, recognizer), 1); 2306 2307 this.touchAction.update(); 2308 return this; 2309 }, 2310 2311 /** 2312 * bind event 2313 * @param {String} events 2314 * @param {Function} handler 2315 * @returns {EventEmitter} this 2316 */ 2317 on: function(events, handler) { 2318 var handlers = this.handlers; 2319 each(splitStr(events), function(event) { 2320 handlers[event] = handlers[event] || []; 2321 handlers[event].push(handler); 2322 }); 2323 return this; 2324 }, 2325 2326 /** 2327 * unbind event, leave emit blank to remove all handlers 2328 * @param {String} events 2329 * @param {Function} [handler] 2330 * @returns {EventEmitter} this 2331 */ 2332 off: function(events, handler) { 2333 var handlers = this.handlers; 2334 each(splitStr(events), function(event) { 2335 if (!handler) { 2336 delete handlers[event]; 2337 } else { 2338 handlers[event].splice(inArray(handlers[event], handler), 1); 2339 } 2340 }); 2341 return this; 2342 }, 2343 2344 /** 2345 * emit event to the listeners 2346 * @param {String} event 2347 * @param {Object} data 2348 */ 2349 emit: function(event, data) { 2350 // we also want to trigger dom events 2351 if (this.options.domEvents) { 2352 triggerDomEvent(event, data); 2353 } 2354 2355 // no handlers, so skip it all 2356 var handlers = this.handlers[event] && this.handlers[event].slice(); 2357 if (!handlers || !handlers.length) { 2358 return; 2359 } 2360 2361 data.type = event; 2362 data.preventDefault = function() { 2363 data.srcEvent.preventDefault(); 2364 }; 2365 2366 var i = 0; 2367 while (i < handlers.length) { 2368 handlers[i](data); 2369 i++; 2370 } 2371 }, 2372 2373 /** 2374 * destroy the manager and unbinds all events 2375 * it doesn't unbind dom events, that is the user own responsibility 2376 */ 2377 destroy: function() { 2378 this.element && toggleCssProps(this, false); 2379 2380 this.handlers = {}; 2381 this.session = {}; 2382 this.input.destroy(); 2383 this.element = null; 2384 } 2385}; 2386 2387/** 2388 * add/remove the css properties as defined in manager.options.cssProps 2389 * @param {Manager} manager 2390 * @param {Boolean} add 2391 */ 2392function toggleCssProps(manager, add) { 2393 var element = manager.element; 2394 each(manager.options.cssProps, function(value, name) { 2395 element.style[prefixed(element.style, name)] = add ? value : ''; 2396 }); 2397} 2398 2399/** 2400 * trigger dom event 2401 * @param {String} event 2402 * @param {Object} data 2403 */ 2404function triggerDomEvent(event, data) { 2405 var gestureEvent = document.createEvent('Event'); 2406 gestureEvent.initEvent(event, true, true); 2407 gestureEvent.gesture = data; 2408 data.target.dispatchEvent(gestureEvent); 2409} 2410 2411extend(Hammer, { 2412 INPUT_START: INPUT_START, 2413 INPUT_MOVE: INPUT_MOVE, 2414 INPUT_END: INPUT_END, 2415 INPUT_CANCEL: INPUT_CANCEL, 2416 2417 STATE_POSSIBLE: STATE_POSSIBLE, 2418 STATE_BEGAN: STATE_BEGAN, 2419 STATE_CHANGED: STATE_CHANGED, 2420 STATE_ENDED: STATE_ENDED, 2421 STATE_RECOGNIZED: STATE_RECOGNIZED, 2422 STATE_CANCELLED: STATE_CANCELLED, 2423 STATE_FAILED: STATE_FAILED, 2424 2425 DIRECTION_NONE: DIRECTION_NONE, 2426 DIRECTION_LEFT: DIRECTION_LEFT, 2427 DIRECTION_RIGHT: DIRECTION_RIGHT, 2428 DIRECTION_UP: DIRECTION_UP, 2429 DIRECTION_DOWN: DIRECTION_DOWN, 2430 DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL, 2431 DIRECTION_VERTICAL: DIRECTION_VERTICAL, 2432 DIRECTION_ALL: DIRECTION_ALL, 2433 2434 Manager: Manager, 2435 Input: Input, 2436 TouchAction: TouchAction, 2437 2438 TouchInput: TouchInput, 2439 MouseInput: MouseInput, 2440 PointerEventInput: PointerEventInput, 2441 TouchMouseInput: TouchMouseInput, 2442 SingleTouchInput: SingleTouchInput, 2443 2444 Recognizer: Recognizer, 2445 AttrRecognizer: AttrRecognizer, 2446 Tap: TapRecognizer, 2447 Pan: PanRecognizer, 2448 Swipe: SwipeRecognizer, 2449 Pinch: PinchRecognizer, 2450 Rotate: RotateRecognizer, 2451 Press: PressRecognizer, 2452 2453 on: addEventListeners, 2454 off: removeEventListeners, 2455 each: each, 2456 merge: merge, 2457 extend: extend, 2458 inherit: inherit, 2459 bindFn: bindFn, 2460 prefixed: prefixed 2461}); 2462 2463if (typeof module != 'undefined' && module.exports) { 2464 module.exports = Hammer; 2465} else { 2466 window[exportName] = Hammer; 2467} 2468 2469})(window, document, 'Hammer'); 2470 2471}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.