@ms-atlas/datastudio 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of @ms-atlas/datastudio might be problematic. Click here for more details.

Files changed (38) hide show
  1. package/ExternalLibraries/Monaco/vs/loader.js +2166 -0
  2. package/ExternalLibraries/URI.min.js +1901 -0
  3. package/ExternalLibraries/crossroads.min.js +453 -0
  4. package/ExternalLibraries/css.js +165 -0
  5. package/ExternalLibraries/d3.min.js +10857 -0
  6. package/ExternalLibraries/es6-promise.min.js +363 -0
  7. package/ExternalLibraries/hammer.js +2224 -0
  8. package/ExternalLibraries/hull.js +444 -0
  9. package/ExternalLibraries/i18n.min.js +115 -0
  10. package/ExternalLibraries/jquery-ui-timepicker-addon.min.css +76 -0
  11. package/ExternalLibraries/jquery-ui-timepicker-addon.min.js +1918 -0
  12. package/ExternalLibraries/jquery-ui.js +17201 -0
  13. package/ExternalLibraries/jquery-ui.min.css +1454 -0
  14. package/ExternalLibraries/jquery.history.js +2173 -0
  15. package/ExternalLibraries/jquery.min.js +5168 -0
  16. package/ExternalLibraries/jquery.mockjax.min.js +445 -0
  17. package/ExternalLibraries/jquery.modal.js +173 -0
  18. package/ExternalLibraries/jstree.js +10086 -0
  19. package/ExternalLibraries/jstree.style.css +1048 -0
  20. package/ExternalLibraries/jwt-decode.min.js +142 -0
  21. package/ExternalLibraries/knockout-latest.debug.js +7375 -0
  22. package/ExternalLibraries/knockout.mapping.min.js +534 -0
  23. package/ExternalLibraries/moment.js +3389 -0
  24. package/ExternalLibraries/q.js +1974 -0
  25. package/ExternalLibraries/require.js +2230 -0
  26. package/ExternalLibraries/signals.min.js +179 -0
  27. package/ExternalLibraries/text.js +445 -0
  28. package/ExternalLibraries/uuid.js +274 -0
  29. package/datastudio.application.mainpage.js +1502 -0
  30. package/datastudio.application.shared.js +626 -0
  31. package/datastudio.bootstrapper.js +517 -0
  32. package/fonts.css +14 -0
  33. package/nls/resx.js +1 -0
  34. package/nls/root/resx.js +22 -0
  35. package/package.json +22 -0
  36. package/scripts/application/sourceMapper.js +15 -0
  37. package/scripts/libs/adal/adal.js +720 -0
  38. package/stylesheets/main.css +8879 -0
@@ -0,0 +1,2224 @@
1
+ /*! Hammer.JS - v1.1.3 - 2014-05-22
2
+ * http://eightmedia.github.io/hammer.js
3
+ *
4
+ * Copyright (c) 2014 Jorik Tangelder <j.tangelder@gmail.com>;
5
+ * Licensed under the MIT license */
6
+
7
+ (function (window, undefined) {
8
+ "use strict";
9
+
10
+ /**
11
+ * @main
12
+ * @module hammer
13
+ *
14
+ * @class Hammer
15
+ * @static
16
+ */
17
+
18
+ /**
19
+ * Hammer, use this to create instances
20
+ * ````
21
+ * var hammertime = new Hammer(myElement);
22
+ * ````
23
+ *
24
+ * @method Hammer
25
+ * @param {HTMLElement} element
26
+ * @param {Object} [options={}]
27
+ * @return {Hammer.Instance}
28
+ */
29
+ var Hammer = function Hammer(element, options) {
30
+ return new Hammer.Instance(element, options || {});
31
+ };
32
+
33
+ /**
34
+ * version, as defined in package.json
35
+ * the value will be set at each build
36
+ * @property VERSION
37
+ * @final
38
+ * @type {String}
39
+ */
40
+ Hammer.VERSION = "1.1.3";
41
+
42
+ /**
43
+ * default settings.
44
+ * more settings are defined per gesture at `/gestures`. Each gesture can be disabled/enabled
45
+ * by setting it's name (like `swipe`) to false.
46
+ * You can set the defaults for all instances by changing this object before creating an instance.
47
+ * @example
48
+ * ````
49
+ * Hammer.defaults.drag = false;
50
+ * Hammer.defaults.behavior.touchAction = 'pan-y';
51
+ * delete Hammer.defaults.behavior.userSelect;
52
+ * ````
53
+ * @property defaults
54
+ * @type {Object}
55
+ */
56
+ Hammer.defaults = {
57
+ /**
58
+ * this setting object adds styles and attributes to the element to prevent the browser from doing
59
+ * its native behavior. The css properties are auto prefixed for the browsers when needed.
60
+ * @property defaults.behavior
61
+ * @type {Object}
62
+ */
63
+ behavior: {
64
+ /**
65
+ * Disables text selection to improve the dragging gesture. When the value is `none` it also sets
66
+ * `onselectstart=false` for IE on the element. Mainly for desktop browsers.
67
+ * @property defaults.behavior.userSelect
68
+ * @type {String}
69
+ * @default 'none'
70
+ */
71
+ userSelect: "none",
72
+
73
+ /**
74
+ * Specifies whether and how a given region can be manipulated by the user (for instance, by panning or zooming).
75
+ * Used by Chrome 35> and IE10>. By default this makes the element blocking any touch event.
76
+ * @property defaults.behavior.touchAction
77
+ * @type {String}
78
+ * @default: 'pan-y'
79
+ */
80
+ touchAction: "pan-y",
81
+
82
+ /**
83
+ * Disables the default callout shown when you touch and hold a touch target.
84
+ * On iOS, when you touch and hold a touch target such as a link, Safari displays
85
+ * a callout containing information about the link. This property allows you to disable that callout.
86
+ * @property defaults.behavior.touchCallout
87
+ * @type {String}
88
+ * @default 'none'
89
+ */
90
+ touchCallout: "none",
91
+
92
+ /**
93
+ * Specifies whether zooming is enabled. Used by IE10>
94
+ * @property defaults.behavior.contentZooming
95
+ * @type {String}
96
+ * @default 'none'
97
+ */
98
+ contentZooming: "none",
99
+
100
+ /**
101
+ * Specifies that an entire element should be draggable instead of its contents.
102
+ * Mainly for desktop browsers.
103
+ * @property defaults.behavior.userDrag
104
+ * @type {String}
105
+ * @default 'none'
106
+ */
107
+ userDrag: "none",
108
+
109
+ /**
110
+ * Overrides the highlight color shown when the user taps a link or a JavaScript
111
+ * clickable element in Safari on iPhone. This property obeys the alpha value, if specified.
112
+ *
113
+ * If you don't specify an alpha value, Safari on iPhone applies a default alpha value
114
+ * to the color. To disable tap highlighting, set the alpha value to 0 (invisible).
115
+ * If you set the alpha value to 1.0 (opaque), the element is not visible when tapped.
116
+ * @property defaults.behavior.tapHighlightColor
117
+ * @type {String}
118
+ * @default 'rgba(0,0,0,0)'
119
+ */
120
+ tapHighlightColor: "rgba(0,0,0,0)",
121
+ },
122
+ };
123
+
124
+ /**
125
+ * hammer document where the base events are added at
126
+ * @property DOCUMENT
127
+ * @type {HTMLElement}
128
+ * @default window.document
129
+ */
130
+ Hammer.DOCUMENT = document;
131
+
132
+ /**
133
+ * detect support for pointer events
134
+ * @property HAS_POINTEREVENTS
135
+ * @type {Boolean}
136
+ */
137
+ Hammer.HAS_POINTEREVENTS =
138
+ navigator.pointerEnabled || navigator.msPointerEnabled;
139
+
140
+ /**
141
+ * detect support for touch events
142
+ * @property HAS_TOUCHEVENTS
143
+ * @type {Boolean}
144
+ */
145
+ Hammer.HAS_TOUCHEVENTS = "ontouchstart" in window;
146
+
147
+ /**
148
+ * detect mobile browsers
149
+ * @property IS_MOBILE
150
+ * @type {Boolean}
151
+ */
152
+ Hammer.IS_MOBILE = /mobile|tablet|ip(ad|hone|od)|android|silk/i.test(
153
+ navigator.userAgent
154
+ );
155
+
156
+ /**
157
+ * detect if we want to support mouseevents at all
158
+ * @property NO_MOUSEEVENTS
159
+ * @type {Boolean}
160
+ */
161
+ Hammer.NO_MOUSEEVENTS =
162
+ (Hammer.HAS_TOUCHEVENTS && Hammer.IS_MOBILE) || Hammer.HAS_POINTEREVENTS;
163
+
164
+ /**
165
+ * interval in which Hammer recalculates current velocity/direction/angle in ms
166
+ * @property CALCULATE_INTERVAL
167
+ * @type {Number}
168
+ * @default 25
169
+ */
170
+ Hammer.CALCULATE_INTERVAL = 25;
171
+
172
+ /**
173
+ * eventtypes per touchevent (start, move, end) are filled by `Event.determineEventTypes` on `setup`
174
+ * the object contains the DOM event names per type (`EVENT_START`, `EVENT_MOVE`, `EVENT_END`)
175
+ * @property EVENT_TYPES
176
+ * @private
177
+ * @writeOnce
178
+ * @type {Object}
179
+ */
180
+ var EVENT_TYPES = {};
181
+
182
+ /**
183
+ * direction strings, for safe comparisons
184
+ * @property DIRECTION_DOWN|LEFT|UP|RIGHT
185
+ * @final
186
+ * @type {String}
187
+ * @default 'down' 'left' 'up' 'right'
188
+ */
189
+ var DIRECTION_DOWN = (Hammer.DIRECTION_DOWN = "down");
190
+ var DIRECTION_LEFT = (Hammer.DIRECTION_LEFT = "left");
191
+ var DIRECTION_UP = (Hammer.DIRECTION_UP = "up");
192
+ var DIRECTION_RIGHT = (Hammer.DIRECTION_RIGHT = "right");
193
+
194
+ /**
195
+ * pointertype strings, for safe comparisons
196
+ * @property POINTER_MOUSE|TOUCH|PEN
197
+ * @final
198
+ * @type {String}
199
+ * @default 'mouse' 'touch' 'pen'
200
+ */
201
+ var POINTER_MOUSE = (Hammer.POINTER_MOUSE = "mouse");
202
+ var POINTER_TOUCH = (Hammer.POINTER_TOUCH = "touch");
203
+ var POINTER_PEN = (Hammer.POINTER_PEN = "pen");
204
+
205
+ /**
206
+ * eventtypes
207
+ * @property EVENT_START|MOVE|END|RELEASE|TOUCH
208
+ * @final
209
+ * @type {String}
210
+ * @default 'start' 'change' 'move' 'end' 'release' 'touch'
211
+ */
212
+ var EVENT_START = (Hammer.EVENT_START = "start");
213
+ var EVENT_MOVE = (Hammer.EVENT_MOVE = "move");
214
+ var EVENT_END = (Hammer.EVENT_END = "end");
215
+ var EVENT_RELEASE = (Hammer.EVENT_RELEASE = "release");
216
+ var EVENT_TOUCH = (Hammer.EVENT_TOUCH = "touch");
217
+
218
+ /**
219
+ * if the window events are set...
220
+ * @property READY
221
+ * @writeOnce
222
+ * @type {Boolean}
223
+ * @default false
224
+ */
225
+ Hammer.READY = false;
226
+
227
+ /**
228
+ * plugins namespace
229
+ * @property plugins
230
+ * @type {Object}
231
+ */
232
+ Hammer.plugins = Hammer.plugins || {};
233
+
234
+ /**
235
+ * gestures namespace
236
+ * see `/gestures` for the definitions
237
+ * @property gestures
238
+ * @type {Object}
239
+ */
240
+ Hammer.gestures = Hammer.gestures || {};
241
+
242
+ /**
243
+ * setup events to detect gestures on the document
244
+ * this function is called when creating an new instance
245
+ * @private
246
+ */
247
+ function setup() {
248
+ if (Hammer.READY) {
249
+ return;
250
+ }
251
+
252
+ // find what eventtypes we add listeners to
253
+ Event.determineEventTypes();
254
+
255
+ // Register all gestures inside Hammer.gestures
256
+ Utils.each(Hammer.gestures, function (gesture) {
257
+ Detection.register(gesture);
258
+ });
259
+
260
+ // Add touch events on the document
261
+ Event.onTouch(Hammer.DOCUMENT, EVENT_MOVE, Detection.detect);
262
+ Event.onTouch(Hammer.DOCUMENT, EVENT_END, Detection.detect);
263
+
264
+ // Hammer is ready...!
265
+ Hammer.READY = true;
266
+ }
267
+
268
+ /**
269
+ * @module hammer
270
+ *
271
+ * @class Utils
272
+ * @static
273
+ */
274
+ var Utils = (Hammer.utils = {
275
+ /**
276
+ * extend method, could also be used for cloning when `dest` is an empty object.
277
+ * changes the dest object
278
+ * @method extend
279
+ * @param {Object} dest
280
+ * @param {Object} src
281
+ * @param {Boolean} [merge=false] do a merge
282
+ * @return {Object} dest
283
+ */
284
+ extend: function extend(dest, src, merge) {
285
+ for (var key in src) {
286
+ if (!src.hasOwnProperty(key) || (dest[key] !== undefined && merge)) {
287
+ continue;
288
+ }
289
+ dest[key] = src[key];
290
+ }
291
+ return dest;
292
+ },
293
+
294
+ /**
295
+ * simple addEventListener wrapper
296
+ * @method on
297
+ * @param {HTMLElement} element
298
+ * @param {String} type
299
+ * @param {Function} handler
300
+ */
301
+ on: function on(element, type, handler) {
302
+ element.addEventListener(type, handler, false);
303
+ },
304
+
305
+ /**
306
+ * simple removeEventListener wrapper
307
+ * @method off
308
+ * @param {HTMLElement} element
309
+ * @param {String} type
310
+ * @param {Function} handler
311
+ */
312
+ off: function off(element, type, handler) {
313
+ element.removeEventListener(type, handler, false);
314
+ },
315
+
316
+ /**
317
+ * forEach over arrays and objects
318
+ * @method each
319
+ * @param {Object|Array} obj
320
+ * @param {Function} iterator
321
+ * @param {any} iterator.item
322
+ * @param {Number} iterator.index
323
+ * @param {Object|Array} iterator.obj the source object
324
+ * @param {Object} context value to use as `this` in the iterator
325
+ */
326
+ each: function each(obj, iterator, context) {
327
+ var i, len;
328
+
329
+ // native forEach on arrays
330
+ if ("forEach" in obj) {
331
+ obj.forEach(iterator, context);
332
+ // arrays
333
+ } else if (obj.length !== undefined) {
334
+ for (i = 0, len = obj.length; i < len; i++) {
335
+ if (iterator.call(context, obj[i], i, obj) === false) {
336
+ return;
337
+ }
338
+ }
339
+ // objects
340
+ } else {
341
+ for (i in obj) {
342
+ if (
343
+ obj.hasOwnProperty(i) &&
344
+ iterator.call(context, obj[i], i, obj) === false
345
+ ) {
346
+ return;
347
+ }
348
+ }
349
+ }
350
+ },
351
+
352
+ /**
353
+ * find if a string contains the string using indexOf
354
+ * @method inStr
355
+ * @param {String} src
356
+ * @param {String} find
357
+ * @return {Boolean} found
358
+ */
359
+ inStr: function inStr(src, find) {
360
+ return src.indexOf(find) > -1;
361
+ },
362
+
363
+ /**
364
+ * find if a array contains the object using indexOf or a simple polyfill
365
+ * @method inArray
366
+ * @param {String} src
367
+ * @param {String} find
368
+ * @return {Boolean|Number} false when not found, or the index
369
+ */
370
+ inArray: function inArray(src, find) {
371
+ if (src.indexOf) {
372
+ var index = src.indexOf(find);
373
+ return index === -1 ? false : index;
374
+ } else {
375
+ for (var i = 0, len = src.length; i < len; i++) {
376
+ if (src[i] === find) {
377
+ return i;
378
+ }
379
+ }
380
+ return false;
381
+ }
382
+ },
383
+
384
+ /**
385
+ * convert an array-like object (`arguments`, `touchlist`) to an array
386
+ * @method toArray
387
+ * @param {Object} obj
388
+ * @return {Array}
389
+ */
390
+ toArray: function toArray(obj) {
391
+ return Array.prototype.slice.call(obj, 0);
392
+ },
393
+
394
+ /**
395
+ * find if a node is in the given parent
396
+ * @method hasParent
397
+ * @param {HTMLElement} node
398
+ * @param {HTMLElement} parent
399
+ * @return {Boolean} found
400
+ */
401
+ hasParent: function hasParent(node, parent) {
402
+ while (node) {
403
+ if (node == parent) {
404
+ return true;
405
+ }
406
+ node = node.parentNode;
407
+ }
408
+ return false;
409
+ },
410
+
411
+ /**
412
+ * get the center of all the touches
413
+ * @method getCenter
414
+ * @param {Array} touches
415
+ * @return {Object} center contains `pageX`, `pageY`, `clientX` and `clientY` properties
416
+ */
417
+ getCenter: function getCenter(touches) {
418
+ var pageX = [],
419
+ pageY = [],
420
+ clientX = [],
421
+ clientY = [],
422
+ min = Math.min,
423
+ max = Math.max;
424
+
425
+ // no need to loop when only one touch
426
+ if (touches.length === 1) {
427
+ return {
428
+ pageX: touches[0].pageX,
429
+ pageY: touches[0].pageY,
430
+ clientX: touches[0].clientX,
431
+ clientY: touches[0].clientY,
432
+ };
433
+ }
434
+
435
+ Utils.each(touches, function (touch) {
436
+ pageX.push(touch.pageX);
437
+ pageY.push(touch.pageY);
438
+ clientX.push(touch.clientX);
439
+ clientY.push(touch.clientY);
440
+ });
441
+
442
+ return {
443
+ pageX: (min.apply(Math, pageX) + max.apply(Math, pageX)) / 2,
444
+ pageY: (min.apply(Math, pageY) + max.apply(Math, pageY)) / 2,
445
+ clientX: (min.apply(Math, clientX) + max.apply(Math, clientX)) / 2,
446
+ clientY: (min.apply(Math, clientY) + max.apply(Math, clientY)) / 2,
447
+ };
448
+ },
449
+
450
+ /**
451
+ * calculate the velocity between two points. unit is in px per ms.
452
+ * @method getVelocity
453
+ * @param {Number} deltaTime
454
+ * @param {Number} deltaX
455
+ * @param {Number} deltaY
456
+ * @return {Object} velocity `x` and `y`
457
+ */
458
+ getVelocity: function getVelocity(deltaTime, deltaX, deltaY) {
459
+ return {
460
+ x: Math.abs(deltaX / deltaTime) || 0,
461
+ y: Math.abs(deltaY / deltaTime) || 0,
462
+ };
463
+ },
464
+
465
+ /**
466
+ * calculate the angle between two coordinates
467
+ * @method getAngle
468
+ * @param {Touch} touch1
469
+ * @param {Touch} touch2
470
+ * @return {Number} angle
471
+ */
472
+ getAngle: function getAngle(touch1, touch2) {
473
+ var x = touch2.clientX - touch1.clientX,
474
+ y = touch2.clientY - touch1.clientY;
475
+
476
+ return (Math.atan2(y, x) * 180) / Math.PI;
477
+ },
478
+
479
+ /**
480
+ * do a small comparision to get the direction between two touches.
481
+ * @method getDirection
482
+ * @param {Touch} touch1
483
+ * @param {Touch} touch2
484
+ * @return {String} direction matches `DIRECTION_LEFT|RIGHT|UP|DOWN`
485
+ */
486
+ getDirection: function getDirection(touch1, touch2) {
487
+ var x = Math.abs(touch1.clientX - touch2.clientX),
488
+ y = Math.abs(touch1.clientY - touch2.clientY);
489
+
490
+ if (x >= y) {
491
+ return touch1.clientX - touch2.clientX > 0
492
+ ? DIRECTION_LEFT
493
+ : DIRECTION_RIGHT;
494
+ }
495
+ return touch1.clientY - touch2.clientY > 0
496
+ ? DIRECTION_UP
497
+ : DIRECTION_DOWN;
498
+ },
499
+
500
+ /**
501
+ * calculate the distance between two touches
502
+ * @method getDistance
503
+ * @param {Touch}touch1
504
+ * @param {Touch} touch2
505
+ * @return {Number} distance
506
+ */
507
+ getDistance: function getDistance(touch1, touch2) {
508
+ var x = touch2.clientX - touch1.clientX,
509
+ y = touch2.clientY - touch1.clientY;
510
+
511
+ return Math.sqrt(x * x + y * y);
512
+ },
513
+
514
+ /**
515
+ * calculate the scale factor between two touchLists
516
+ * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
517
+ * @method getScale
518
+ * @param {Array} start array of touches
519
+ * @param {Array} end array of touches
520
+ * @return {Number} scale
521
+ */
522
+ getScale: function getScale(start, end) {
523
+ // need two fingers...
524
+ if (start.length >= 2 && end.length >= 2) {
525
+ return (
526
+ this.getDistance(end[0], end[1]) /
527
+ this.getDistance(start[0], start[1])
528
+ );
529
+ }
530
+ return 1;
531
+ },
532
+
533
+ /**
534
+ * calculate the rotation degrees between two touchLists
535
+ * @method getRotation
536
+ * @param {Array} start array of touches
537
+ * @param {Array} end array of touches
538
+ * @return {Number} rotation
539
+ */
540
+ getRotation: function getRotation(start, end) {
541
+ // need two fingers
542
+ if (start.length >= 2 && end.length >= 2) {
543
+ return (
544
+ this.getAngle(end[1], end[0]) - this.getAngle(start[1], start[0])
545
+ );
546
+ }
547
+ return 0;
548
+ },
549
+
550
+ /**
551
+ * find out if the direction is vertical *
552
+ * @method isVertical
553
+ * @param {String} direction matches `DIRECTION_UP|DOWN`
554
+ * @return {Boolean} is_vertical
555
+ */
556
+ isVertical: function isVertical(direction) {
557
+ return direction == DIRECTION_UP || direction == DIRECTION_DOWN;
558
+ },
559
+
560
+ /**
561
+ * set css properties with their prefixes
562
+ * @param {HTMLElement} element
563
+ * @param {String} prop
564
+ * @param {String} value
565
+ * @param {Boolean} [toggle=true]
566
+ * @return {Boolean}
567
+ */
568
+ setPrefixedCss: function setPrefixedCss(element, prop, value, toggle) {
569
+ var prefixes = ["", "Webkit", "Moz", "O", "ms"];
570
+ prop = Utils.toCamelCase(prop);
571
+
572
+ for (var i = 0; i < prefixes.length; i++) {
573
+ var p = prop;
574
+ // prefixes
575
+ if (prefixes[i]) {
576
+ p = prefixes[i] + p.slice(0, 1).toUpperCase() + p.slice(1);
577
+ }
578
+
579
+ // test the style
580
+ if (p in element.style) {
581
+ element.style[p] = ((toggle == null || toggle) && value) || "";
582
+ break;
583
+ }
584
+ }
585
+ },
586
+
587
+ /**
588
+ * toggle browser default behavior by setting css properties.
589
+ * `userSelect='none'` also sets `element.onselectstart` to false
590
+ * `userDrag='none'` also sets `element.ondragstart` to false
591
+ *
592
+ * @method toggleBehavior
593
+ * @param {HtmlElement} element
594
+ * @param {Object} props
595
+ * @param {Boolean} [toggle=true]
596
+ */
597
+ toggleBehavior: function toggleBehavior(element, props, toggle) {
598
+ if (!props || !element || !element.style) {
599
+ return;
600
+ }
601
+
602
+ // set the css properties
603
+ Utils.each(props, function (value, prop) {
604
+ Utils.setPrefixedCss(element, prop, value, toggle);
605
+ });
606
+
607
+ var falseFn =
608
+ toggle &&
609
+ function () {
610
+ return false;
611
+ };
612
+
613
+ // also the disable onselectstart
614
+ if (props.userSelect == "none") {
615
+ element.onselectstart = falseFn;
616
+ }
617
+ // and disable ondragstart
618
+ if (props.userDrag == "none") {
619
+ element.ondragstart = falseFn;
620
+ }
621
+ },
622
+
623
+ /**
624
+ * convert a string with underscores to camelCase
625
+ * so prevent_default becomes preventDefault
626
+ * @param {String} str
627
+ * @return {String} camelCaseStr
628
+ */
629
+ toCamelCase: function toCamelCase(str) {
630
+ return str.replace(/[_-]([a-z])/g, function (s) {
631
+ return s[1].toUpperCase();
632
+ });
633
+ },
634
+ });
635
+
636
+ /**
637
+ * @module hammer
638
+ */
639
+ /**
640
+ * @class Event
641
+ * @static
642
+ */
643
+ var Event = (Hammer.event = {
644
+ /**
645
+ * when touch events have been fired, this is true
646
+ * this is used to stop mouse events
647
+ * @property prevent_mouseevents
648
+ * @private
649
+ * @type {Boolean}
650
+ */
651
+ preventMouseEvents: false,
652
+
653
+ /**
654
+ * if EVENT_START has been fired
655
+ * @property started
656
+ * @private
657
+ * @type {Boolean}
658
+ */
659
+ started: false,
660
+
661
+ /**
662
+ * when the mouse is hold down, this is true
663
+ * @property should_detect
664
+ * @private
665
+ * @type {Boolean}
666
+ */
667
+ shouldDetect: false,
668
+
669
+ /**
670
+ * simple event binder with a hook and support for multiple types
671
+ * @method on
672
+ * @param {HTMLElement} element
673
+ * @param {String} type
674
+ * @param {Function} handler
675
+ * @param {Function} [hook]
676
+ * @param {Object} hook.type
677
+ */
678
+ on: function on(element, type, handler, hook) {
679
+ var types = type.split(" ");
680
+ Utils.each(types, function (type) {
681
+ Utils.on(element, type, handler);
682
+ hook && hook(type);
683
+ });
684
+ },
685
+
686
+ /**
687
+ * simple event unbinder with a hook and support for multiple types
688
+ * @method off
689
+ * @param {HTMLElement} element
690
+ * @param {String} type
691
+ * @param {Function} handler
692
+ * @param {Function} [hook]
693
+ * @param {Object} hook.type
694
+ */
695
+ off: function off(element, type, handler, hook) {
696
+ var types = type.split(" ");
697
+ Utils.each(types, function (type) {
698
+ Utils.off(element, type, handler);
699
+ hook && hook(type);
700
+ });
701
+ },
702
+
703
+ /**
704
+ * the core touch event handler.
705
+ * this finds out if we should to detect gestures
706
+ * @method onTouch
707
+ * @param {HTMLElement} element
708
+ * @param {String} eventType matches `EVENT_START|MOVE|END`
709
+ * @param {Function} handler
710
+ * @return onTouchHandler {Function} the core event handler
711
+ */
712
+ onTouch: function onTouch(element, eventType, handler) {
713
+ var self = this;
714
+
715
+ var onTouchHandler = function onTouchHandler(ev) {
716
+ var srcType = ev.type.toLowerCase(),
717
+ isPointer = Hammer.HAS_POINTEREVENTS,
718
+ isMouse = Utils.inStr(srcType, "mouse"),
719
+ triggerType;
720
+
721
+ // if we are in a mouseevent, but there has been a touchevent triggered in this session
722
+ // we want to do nothing. simply break out of the event.
723
+ if (isMouse && self.preventMouseEvents) {
724
+ return;
725
+
726
+ // mousebutton must be down
727
+ } else if (isMouse && eventType == EVENT_START && ev.button === 0) {
728
+ self.preventMouseEvents = false;
729
+ self.shouldDetect = true;
730
+ } else if (isPointer && eventType == EVENT_START) {
731
+ self.shouldDetect =
732
+ ev.buttons === 1 || PointerEvent.matchType(POINTER_TOUCH, ev);
733
+ // just a valid start event, but no mouse
734
+ } else if (!isMouse && eventType == EVENT_START) {
735
+ self.preventMouseEvents = true;
736
+ self.shouldDetect = true;
737
+ }
738
+
739
+ // update the pointer event before entering the detection
740
+ if (isPointer && eventType != EVENT_END) {
741
+ PointerEvent.updatePointer(eventType, ev);
742
+ }
743
+
744
+ // we are in a touch/down state, so allowed detection of gestures
745
+ if (self.shouldDetect) {
746
+ triggerType = self.doDetect.call(
747
+ self,
748
+ ev,
749
+ eventType,
750
+ element,
751
+ handler
752
+ );
753
+ }
754
+
755
+ // ...and we are done with the detection
756
+ // so reset everything to start each detection totally fresh
757
+ if (triggerType == EVENT_END) {
758
+ self.preventMouseEvents = false;
759
+ self.shouldDetect = false;
760
+ PointerEvent.reset();
761
+ // update the pointerevent object after the detection
762
+ }
763
+
764
+ if (isPointer && eventType == EVENT_END) {
765
+ PointerEvent.updatePointer(eventType, ev);
766
+ }
767
+ };
768
+
769
+ this.on(element, EVENT_TYPES[eventType], onTouchHandler);
770
+ return onTouchHandler;
771
+ },
772
+
773
+ /**
774
+ * the core detection method
775
+ * this finds out what hammer-touch-events to trigger
776
+ * @method doDetect
777
+ * @param {Object} ev
778
+ * @param {String} eventType matches `EVENT_START|MOVE|END`
779
+ * @param {HTMLElement} element
780
+ * @param {Function} handler
781
+ * @return {String} triggerType matches `EVENT_START|MOVE|END`
782
+ */
783
+ doDetect: function doDetect(ev, eventType, element, handler) {
784
+ var touchList = this.getTouchList(ev, eventType);
785
+ var touchListLength = touchList.length;
786
+ var triggerType = eventType;
787
+ var triggerChange = touchList.trigger; // used by fakeMultitouch plugin
788
+ var changedLength = touchListLength;
789
+
790
+ // at each touchstart-like event we want also want to trigger a TOUCH event...
791
+ if (eventType == EVENT_START) {
792
+ triggerChange = EVENT_TOUCH;
793
+ // ...the same for a touchend-like event
794
+ } else if (eventType == EVENT_END) {
795
+ triggerChange = EVENT_RELEASE;
796
+
797
+ // keep track of how many touches have been removed
798
+ changedLength =
799
+ touchList.length - (ev.changedTouches ? ev.changedTouches.length : 1);
800
+ }
801
+
802
+ // after there are still touches on the screen,
803
+ // we just want to trigger a MOVE event. so change the START or END to a MOVE
804
+ // but only after detection has been started, the first time we actualy want a START
805
+ if (changedLength > 0 && this.started) {
806
+ triggerType = EVENT_MOVE;
807
+ }
808
+
809
+ // detection has been started, we keep track of this, see above
810
+ this.started = true;
811
+
812
+ // generate some event data, some basic information
813
+ var evData = this.collectEventData(element, triggerType, touchList, ev);
814
+
815
+ // trigger the triggerType event before the change (TOUCH, RELEASE) events
816
+ // but the END event should be at last
817
+ if (eventType != EVENT_END) {
818
+ handler.call(Detection, evData);
819
+ }
820
+
821
+ // trigger a change (TOUCH, RELEASE) event, this means the length of the touches changed
822
+ if (triggerChange) {
823
+ evData.changedLength = changedLength;
824
+ evData.eventType = triggerChange;
825
+
826
+ handler.call(Detection, evData);
827
+
828
+ evData.eventType = triggerType;
829
+ delete evData.changedLength;
830
+ }
831
+
832
+ // trigger the END event
833
+ if (triggerType == EVENT_END) {
834
+ handler.call(Detection, evData);
835
+
836
+ // ...and we are done with the detection
837
+ // so reset everything to start each detection totally fresh
838
+ this.started = false;
839
+ }
840
+
841
+ return triggerType;
842
+ },
843
+
844
+ /**
845
+ * we have different events for each device/browser
846
+ * determine what we need and set them in the EVENT_TYPES constant
847
+ * the `onTouch` method is bind to these properties.
848
+ * @method determineEventTypes
849
+ * @return {Object} events
850
+ */
851
+ determineEventTypes: function determineEventTypes() {
852
+ var types;
853
+ if (Hammer.HAS_POINTEREVENTS) {
854
+ if (window.PointerEvent) {
855
+ types = [
856
+ "pointerdown",
857
+ "pointermove",
858
+ "pointerup pointercancel lostpointercapture",
859
+ ];
860
+ } else {
861
+ types = [
862
+ "MSPointerDown",
863
+ "MSPointerMove",
864
+ "MSPointerUp MSPointerCancel MSLostPointerCapture",
865
+ ];
866
+ }
867
+ } else if (Hammer.NO_MOUSEEVENTS) {
868
+ types = ["touchstart", "touchmove", "touchend touchcancel"];
869
+ } else {
870
+ types = [
871
+ "touchstart mousedown",
872
+ "touchmove mousemove",
873
+ "touchend touchcancel mouseup",
874
+ ];
875
+ }
876
+
877
+ EVENT_TYPES[EVENT_START] = types[0];
878
+ EVENT_TYPES[EVENT_MOVE] = types[1];
879
+ EVENT_TYPES[EVENT_END] = types[2];
880
+ return EVENT_TYPES;
881
+ },
882
+
883
+ /**
884
+ * create touchList depending on the event
885
+ * @method getTouchList
886
+ * @param {Object} ev
887
+ * @param {String} eventType
888
+ * @return {Array} touches
889
+ */
890
+ getTouchList: function getTouchList(ev, eventType) {
891
+ // get the fake pointerEvent touchlist
892
+ if (Hammer.HAS_POINTEREVENTS) {
893
+ return PointerEvent.getTouchList();
894
+ }
895
+
896
+ // get the touchlist
897
+ if (ev.touches) {
898
+ if (eventType == EVENT_MOVE) {
899
+ return ev.touches;
900
+ }
901
+
902
+ var identifiers = [];
903
+ var concat = [].concat(
904
+ Utils.toArray(ev.touches),
905
+ Utils.toArray(ev.changedTouches)
906
+ );
907
+ var touchList = [];
908
+
909
+ Utils.each(concat, function (touch) {
910
+ if (Utils.inArray(identifiers, touch.identifier) === false) {
911
+ touchList.push(touch);
912
+ }
913
+ identifiers.push(touch.identifier);
914
+ });
915
+
916
+ return touchList;
917
+ }
918
+
919
+ // make fake touchList from mouse position
920
+ ev.identifier = 1;
921
+ return [ev];
922
+ },
923
+
924
+ /**
925
+ * collect basic event data
926
+ * @method collectEventData
927
+ * @param {HTMLElement} element
928
+ * @param {String} eventType matches `EVENT_START|MOVE|END`
929
+ * @param {Array} touches
930
+ * @param {Object} ev
931
+ * @return {Object} ev
932
+ */
933
+ collectEventData: function collectEventData(
934
+ element,
935
+ eventType,
936
+ touches,
937
+ ev
938
+ ) {
939
+ // find out pointerType
940
+ var pointerType = POINTER_TOUCH;
941
+ if (
942
+ Utils.inStr(ev.type, "mouse") ||
943
+ PointerEvent.matchType(POINTER_MOUSE, ev)
944
+ ) {
945
+ pointerType = POINTER_MOUSE;
946
+ } else if (PointerEvent.matchType(POINTER_PEN, ev)) {
947
+ pointerType = POINTER_PEN;
948
+ }
949
+
950
+ return {
951
+ center: Utils.getCenter(touches),
952
+ timeStamp: Date.now(),
953
+ target: ev.target,
954
+ touches: touches,
955
+ eventType: eventType,
956
+ pointerType: pointerType,
957
+ srcEvent: ev,
958
+
959
+ /**
960
+ * prevent the browser default actions
961
+ * mostly used to disable scrolling of the browser
962
+ */
963
+ preventDefault: function () {
964
+ var srcEvent = this.srcEvent;
965
+ srcEvent.preventManipulation && srcEvent.preventManipulation();
966
+ srcEvent.preventDefault && srcEvent.preventDefault();
967
+ },
968
+
969
+ /**
970
+ * stop bubbling the event up to its parents
971
+ */
972
+ stopPropagation: function () {
973
+ this.srcEvent.stopPropagation();
974
+ },
975
+
976
+ /**
977
+ * immediately stop gesture detection
978
+ * might be useful after a swipe was detected
979
+ * @return {*}
980
+ */
981
+ stopDetect: function () {
982
+ return Detection.stopDetect();
983
+ },
984
+ };
985
+ },
986
+ });
987
+
988
+ /**
989
+ * @module hammer
990
+ *
991
+ * @class PointerEvent
992
+ * @static
993
+ */
994
+ var PointerEvent = (Hammer.PointerEvent = {
995
+ /**
996
+ * holds all pointers, by `identifier`
997
+ * @property pointers
998
+ * @type {Object}
999
+ */
1000
+ pointers: {},
1001
+
1002
+ /**
1003
+ * get the pointers as an array
1004
+ * @method getTouchList
1005
+ * @return {Array} touchlist
1006
+ */
1007
+ getTouchList: function getTouchList() {
1008
+ var touchlist = [];
1009
+ // we can use forEach since pointerEvents only is in IE10
1010
+ Utils.each(this.pointers, function (pointer) {
1011
+ touchlist.push(pointer);
1012
+ });
1013
+
1014
+ return touchlist;
1015
+ },
1016
+
1017
+ /**
1018
+ * update the position of a pointer
1019
+ * @method updatePointer
1020
+ * @param {String} eventType matches `EVENT_START|MOVE|END`
1021
+ * @param {Object} pointerEvent
1022
+ */
1023
+ updatePointer: function updatePointer(eventType, pointerEvent) {
1024
+ if (eventType == EVENT_END) {
1025
+ delete this.pointers[pointerEvent.pointerId];
1026
+ } else {
1027
+ pointerEvent.identifier = pointerEvent.pointerId;
1028
+ this.pointers[pointerEvent.pointerId] = pointerEvent;
1029
+ }
1030
+ },
1031
+
1032
+ /**
1033
+ * check if ev matches pointertype
1034
+ * @method matchType
1035
+ * @param {String} pointerType matches `POINTER_MOUSE|TOUCH|PEN`
1036
+ * @param {PointerEvent} ev
1037
+ */
1038
+ matchType: function matchType(pointerType, ev) {
1039
+ if (!ev.pointerType) {
1040
+ return false;
1041
+ }
1042
+
1043
+ var pt = ev.pointerType,
1044
+ types = {};
1045
+
1046
+ types[POINTER_MOUSE] = pt === (ev.MSPOINTER_TYPE_MOUSE || POINTER_MOUSE);
1047
+ types[POINTER_TOUCH] = pt === (ev.MSPOINTER_TYPE_TOUCH || POINTER_TOUCH);
1048
+ types[POINTER_PEN] = pt === (ev.MSPOINTER_TYPE_PEN || POINTER_PEN);
1049
+ return types[pointerType];
1050
+ },
1051
+
1052
+ /**
1053
+ * reset the stored pointers
1054
+ * @method reset
1055
+ */
1056
+ reset: function resetList() {
1057
+ this.pointers = {};
1058
+ },
1059
+ });
1060
+
1061
+ /**
1062
+ * @module hammer
1063
+ *
1064
+ * @class Detection
1065
+ * @static
1066
+ */
1067
+ var Detection = (Hammer.detection = {
1068
+ // contains all registred Hammer.gestures in the correct order
1069
+ gestures: [],
1070
+
1071
+ // data of the current Hammer.gesture detection session
1072
+ current: null,
1073
+
1074
+ // the previous Hammer.gesture session data
1075
+ // is a full clone of the previous gesture.current object
1076
+ previous: null,
1077
+
1078
+ // when this becomes true, no gestures are fired
1079
+ stopped: false,
1080
+
1081
+ /**
1082
+ * start Hammer.gesture detection
1083
+ * @method startDetect
1084
+ * @param {Hammer.Instance} inst
1085
+ * @param {Object} eventData
1086
+ */
1087
+ startDetect: function startDetect(inst, eventData) {
1088
+ // already busy with a Hammer.gesture detection on an element
1089
+ if (this.current) {
1090
+ return;
1091
+ }
1092
+
1093
+ this.stopped = false;
1094
+
1095
+ // holds current session
1096
+ this.current = {
1097
+ inst: inst, // reference to HammerInstance we're working for
1098
+ startEvent: Utils.extend({}, eventData), // start eventData for distances, timing etc
1099
+ lastEvent: false, // last eventData
1100
+ lastCalcEvent: false, // last eventData for calculations.
1101
+ futureCalcEvent: false, // last eventData for calculations.
1102
+ lastCalcData: {}, // last lastCalcData
1103
+ name: "", // current gesture we're in/detected, can be 'tap', 'hold' etc
1104
+ };
1105
+
1106
+ this.detect(eventData);
1107
+ },
1108
+
1109
+ /**
1110
+ * Hammer.gesture detection
1111
+ * @method detect
1112
+ * @param {Object} eventData
1113
+ * @return {any}
1114
+ */
1115
+ detect: function detect(eventData) {
1116
+ if (!this.current || this.stopped) {
1117
+ return;
1118
+ }
1119
+
1120
+ // extend event data with calculations about scale, distance etc
1121
+ eventData = this.extendEventData(eventData);
1122
+
1123
+ // hammer instance and instance options
1124
+ var inst = this.current.inst,
1125
+ instOptions = inst.options;
1126
+
1127
+ // call Hammer.gesture handlers
1128
+ Utils.each(
1129
+ this.gestures,
1130
+ function triggerGesture(gesture) {
1131
+ // only when the instance options have enabled this gesture
1132
+ if (!this.stopped && inst.enabled && instOptions[gesture.name]) {
1133
+ gesture.handler.call(gesture, eventData, inst);
1134
+ }
1135
+ },
1136
+ this
1137
+ );
1138
+
1139
+ // store as previous event event
1140
+ if (this.current) {
1141
+ this.current.lastEvent = eventData;
1142
+ }
1143
+
1144
+ if (eventData.eventType == EVENT_END) {
1145
+ this.stopDetect();
1146
+ }
1147
+
1148
+ return eventData;
1149
+ },
1150
+
1151
+ /**
1152
+ * clear the Hammer.gesture vars
1153
+ * this is called on endDetect, but can also be used when a final Hammer.gesture has been detected
1154
+ * to stop other Hammer.gestures from being fired
1155
+ * @method stopDetect
1156
+ */
1157
+ stopDetect: function stopDetect() {
1158
+ // clone current data to the store as the previous gesture
1159
+ // used for the double tap gesture, since this is an other gesture detect session
1160
+ this.previous = Utils.extend({}, this.current);
1161
+
1162
+ // reset the current
1163
+ this.current = null;
1164
+ this.stopped = true;
1165
+ },
1166
+
1167
+ /**
1168
+ * calculate velocity, angle and direction
1169
+ * @method getVelocityData
1170
+ * @param {Object} ev
1171
+ * @param {Object} center
1172
+ * @param {Number} deltaTime
1173
+ * @param {Number} deltaX
1174
+ * @param {Number} deltaY
1175
+ */
1176
+ getCalculatedData: function getCalculatedData(
1177
+ ev,
1178
+ center,
1179
+ deltaTime,
1180
+ deltaX,
1181
+ deltaY
1182
+ ) {
1183
+ var cur = this.current,
1184
+ recalc = false,
1185
+ calcEv = cur.lastCalcEvent,
1186
+ calcData = cur.lastCalcData;
1187
+
1188
+ if (
1189
+ calcEv &&
1190
+ ev.timeStamp - calcEv.timeStamp > Hammer.CALCULATE_INTERVAL
1191
+ ) {
1192
+ center = calcEv.center;
1193
+ deltaTime = ev.timeStamp - calcEv.timeStamp;
1194
+ deltaX = ev.center.clientX - calcEv.center.clientX;
1195
+ deltaY = ev.center.clientY - calcEv.center.clientY;
1196
+ recalc = true;
1197
+ }
1198
+
1199
+ if (ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) {
1200
+ cur.futureCalcEvent = ev;
1201
+ }
1202
+
1203
+ if (!cur.lastCalcEvent || recalc) {
1204
+ calcData.velocity = Utils.getVelocity(deltaTime, deltaX, deltaY);
1205
+ calcData.angle = Utils.getAngle(center, ev.center);
1206
+ calcData.direction = Utils.getDirection(center, ev.center);
1207
+
1208
+ cur.lastCalcEvent = cur.futureCalcEvent || ev;
1209
+ cur.futureCalcEvent = ev;
1210
+ }
1211
+
1212
+ ev.velocityX = calcData.velocity.x;
1213
+ ev.velocityY = calcData.velocity.y;
1214
+ ev.interimAngle = calcData.angle;
1215
+ ev.interimDirection = calcData.direction;
1216
+ },
1217
+
1218
+ /**
1219
+ * extend eventData for Hammer.gestures
1220
+ * @method extendEventData
1221
+ * @param {Object} ev
1222
+ * @return {Object} ev
1223
+ */
1224
+ extendEventData: function extendEventData(ev) {
1225
+ var cur = this.current,
1226
+ startEv = cur.startEvent,
1227
+ lastEv = cur.lastEvent || startEv;
1228
+
1229
+ // update the start touchlist to calculate the scale/rotation
1230
+ if (ev.eventType == EVENT_TOUCH || ev.eventType == EVENT_RELEASE) {
1231
+ startEv.touches = [];
1232
+ Utils.each(ev.touches, function (touch) {
1233
+ startEv.touches.push({
1234
+ clientX: touch.clientX,
1235
+ clientY: touch.clientY,
1236
+ });
1237
+ });
1238
+ }
1239
+
1240
+ var deltaTime = ev.timeStamp - startEv.timeStamp,
1241
+ deltaX = ev.center.clientX - startEv.center.clientX,
1242
+ deltaY = ev.center.clientY - startEv.center.clientY;
1243
+
1244
+ this.getCalculatedData(ev, lastEv.center, deltaTime, deltaX, deltaY);
1245
+
1246
+ Utils.extend(ev, {
1247
+ startEvent: startEv,
1248
+
1249
+ deltaTime: deltaTime,
1250
+ deltaX: deltaX,
1251
+ deltaY: deltaY,
1252
+
1253
+ distance: Utils.getDistance(startEv.center, ev.center),
1254
+ angle: Utils.getAngle(startEv.center, ev.center),
1255
+ direction: Utils.getDirection(startEv.center, ev.center),
1256
+ scale: Utils.getScale(startEv.touches, ev.touches),
1257
+ rotation: Utils.getRotation(startEv.touches, ev.touches),
1258
+ });
1259
+
1260
+ return ev;
1261
+ },
1262
+
1263
+ /**
1264
+ * register new gesture
1265
+ * @method register
1266
+ * @param {Object} gesture object, see `gestures/` for documentation
1267
+ * @return {Array} gestures
1268
+ */
1269
+ register: function register(gesture) {
1270
+ // add an enable gesture options if there is no given
1271
+ var options = gesture.defaults || {};
1272
+ if (options[gesture.name] === undefined) {
1273
+ options[gesture.name] = true;
1274
+ }
1275
+
1276
+ // extend Hammer default options with the Hammer.gesture options
1277
+ Utils.extend(Hammer.defaults, options, true);
1278
+
1279
+ // set its index
1280
+ gesture.index = gesture.index || 1000;
1281
+
1282
+ // add Hammer.gesture to the list
1283
+ this.gestures.push(gesture);
1284
+
1285
+ // sort the list by index
1286
+ this.gestures.sort(function (a, b) {
1287
+ if (a.index < b.index) {
1288
+ return -1;
1289
+ }
1290
+ if (a.index > b.index) {
1291
+ return 1;
1292
+ }
1293
+ return 0;
1294
+ });
1295
+
1296
+ return this.gestures;
1297
+ },
1298
+ });
1299
+
1300
+ /**
1301
+ * @module hammer
1302
+ */
1303
+
1304
+ /**
1305
+ * create new hammer instance
1306
+ * all methods should return the instance itself, so it is chainable.
1307
+ *
1308
+ * @class Instance
1309
+ * @constructor
1310
+ * @param {HTMLElement} element
1311
+ * @param {Object} [options={}] options are merged with `Hammer.defaults`
1312
+ * @return {Hammer.Instance}
1313
+ */
1314
+ Hammer.Instance = function (element, options) {
1315
+ var self = this;
1316
+
1317
+ // setup HammerJS window events and register all gestures
1318
+ // this also sets up the default options
1319
+ setup();
1320
+
1321
+ /**
1322
+ * @property element
1323
+ * @type {HTMLElement}
1324
+ */
1325
+ this.element = element;
1326
+
1327
+ /**
1328
+ * @property enabled
1329
+ * @type {Boolean}
1330
+ * @protected
1331
+ */
1332
+ this.enabled = true;
1333
+
1334
+ /**
1335
+ * options, merged with the defaults
1336
+ * options with an _ are converted to camelCase
1337
+ * @property options
1338
+ * @type {Object}
1339
+ */
1340
+ Utils.each(options, function (value, name) {
1341
+ delete options[name];
1342
+ options[Utils.toCamelCase(name)] = value;
1343
+ });
1344
+
1345
+ this.options = Utils.extend(
1346
+ Utils.extend({}, Hammer.defaults),
1347
+ options || {}
1348
+ );
1349
+
1350
+ // add some css to the element to prevent the browser from doing its native behavoir
1351
+ if (this.options.behavior) {
1352
+ Utils.toggleBehavior(this.element, this.options.behavior, true);
1353
+ }
1354
+
1355
+ /**
1356
+ * event start handler on the element to start the detection
1357
+ * @property eventStartHandler
1358
+ * @type {Object}
1359
+ */
1360
+ this.eventStartHandler = Event.onTouch(element, EVENT_START, function (ev) {
1361
+ if (self.enabled && ev.eventType == EVENT_START) {
1362
+ Detection.startDetect(self, ev);
1363
+ } else if (ev.eventType == EVENT_TOUCH) {
1364
+ Detection.detect(ev);
1365
+ }
1366
+ });
1367
+
1368
+ /**
1369
+ * keep a list of user event handlers which needs to be removed when calling 'dispose'
1370
+ * @property eventHandlers
1371
+ * @type {Array}
1372
+ */
1373
+ this.eventHandlers = [];
1374
+ };
1375
+
1376
+ Hammer.Instance.prototype = {
1377
+ /**
1378
+ * bind events to the instance
1379
+ * @method on
1380
+ * @chainable
1381
+ * @param {String} gestures multiple gestures by splitting with a space
1382
+ * @param {Function} handler
1383
+ * @param {Object} handler.ev event object
1384
+ */
1385
+ on: function onEvent(gestures, handler) {
1386
+ var self = this;
1387
+ Event.on(self.element, gestures, handler, function (type) {
1388
+ self.eventHandlers.push({ gesture: type, handler: handler });
1389
+ });
1390
+ return self;
1391
+ },
1392
+
1393
+ /**
1394
+ * unbind events to the instance
1395
+ * @method off
1396
+ * @chainable
1397
+ * @param {String} gestures
1398
+ * @param {Function} handler
1399
+ */
1400
+ off: function offEvent(gestures, handler) {
1401
+ var self = this;
1402
+
1403
+ Event.off(self.element, gestures, handler, function (type) {
1404
+ var index = Utils.inArray({ gesture: type, handler: handler });
1405
+ if (index !== false) {
1406
+ self.eventHandlers.splice(index, 1);
1407
+ }
1408
+ });
1409
+ return self;
1410
+ },
1411
+
1412
+ /**
1413
+ * trigger gesture event
1414
+ * @method trigger
1415
+ * @chainable
1416
+ * @param {String} gesture
1417
+ * @param {Object} [eventData]
1418
+ */
1419
+ trigger: function triggerEvent(gesture, eventData) {
1420
+ // optional
1421
+ if (!eventData) {
1422
+ eventData = {};
1423
+ }
1424
+
1425
+ // create DOM event
1426
+ var event = Hammer.DOCUMENT.createEvent("Event");
1427
+ event.initEvent(gesture, true, true);
1428
+ event.gesture = eventData;
1429
+
1430
+ // trigger on the target if it is in the instance element,
1431
+ // this is for event delegation tricks
1432
+ var element = this.element;
1433
+ if (Utils.hasParent(eventData.target, element)) {
1434
+ element = eventData.target;
1435
+ }
1436
+
1437
+ element.dispatchEvent(event);
1438
+ return this;
1439
+ },
1440
+
1441
+ /**
1442
+ * enable of disable hammer.js detection
1443
+ * @method enable
1444
+ * @chainable
1445
+ * @param {Boolean} state
1446
+ */
1447
+ enable: function enable(state) {
1448
+ this.enabled = state;
1449
+ return this;
1450
+ },
1451
+
1452
+ /**
1453
+ * dispose this hammer instance
1454
+ * @method dispose
1455
+ * @return {Null}
1456
+ */
1457
+ dispose: function dispose() {
1458
+ var i, eh;
1459
+
1460
+ // undo all changes made by stop_browser_behavior
1461
+ Utils.toggleBehavior(this.element, this.options.behavior, false);
1462
+
1463
+ // unbind all custom event handlers
1464
+ for (i = -1; (eh = this.eventHandlers[++i]); ) {
1465
+ Utils.off(this.element, eh.gesture, eh.handler);
1466
+ }
1467
+
1468
+ this.eventHandlers = [];
1469
+
1470
+ // unbind the start event listener
1471
+ Event.off(this.element, EVENT_TYPES[EVENT_START], this.eventStartHandler);
1472
+
1473
+ return null;
1474
+ },
1475
+ };
1476
+
1477
+ /**
1478
+ * @module gestures
1479
+ */
1480
+ /**
1481
+ * Move with x fingers (default 1) around on the page.
1482
+ * Preventing the default browser behavior is a good way to improve feel and working.
1483
+ * ````
1484
+ * hammertime.on("drag", function(ev) {
1485
+ * console.log(ev);
1486
+ * ev.gesture.preventDefault();
1487
+ * });
1488
+ * ````
1489
+ *
1490
+ * @class Drag
1491
+ * @static
1492
+ */
1493
+ /**
1494
+ * @event drag
1495
+ * @param {Object} ev
1496
+ */
1497
+ /**
1498
+ * @event dragstart
1499
+ * @param {Object} ev
1500
+ */
1501
+ /**
1502
+ * @event dragend
1503
+ * @param {Object} ev
1504
+ */
1505
+ /**
1506
+ * @event drapleft
1507
+ * @param {Object} ev
1508
+ */
1509
+ /**
1510
+ * @event dragright
1511
+ * @param {Object} ev
1512
+ */
1513
+ /**
1514
+ * @event dragup
1515
+ * @param {Object} ev
1516
+ */
1517
+ /**
1518
+ * @event dragdown
1519
+ * @param {Object} ev
1520
+ */
1521
+
1522
+ /**
1523
+ * @param {String} name
1524
+ */
1525
+ (function (name) {
1526
+ var triggered = false;
1527
+
1528
+ function dragGesture(ev, inst) {
1529
+ var cur = Detection.current;
1530
+
1531
+ // max touches
1532
+ if (
1533
+ inst.options.dragMaxTouches > 0 &&
1534
+ ev.touches.length > inst.options.dragMaxTouches
1535
+ ) {
1536
+ return;
1537
+ }
1538
+
1539
+ switch (ev.eventType) {
1540
+ case EVENT_START:
1541
+ triggered = false;
1542
+ break;
1543
+
1544
+ case EVENT_MOVE:
1545
+ // when the distance we moved is too small we skip this gesture
1546
+ // or we can be already in dragging
1547
+ if (ev.distance < inst.options.dragMinDistance && cur.name != name) {
1548
+ return;
1549
+ }
1550
+
1551
+ var startCenter = cur.startEvent.center;
1552
+
1553
+ // we are dragging!
1554
+ if (cur.name != name) {
1555
+ cur.name = name;
1556
+ if (inst.options.dragDistanceCorrection && ev.distance > 0) {
1557
+ // When a drag is triggered, set the event center to dragMinDistance pixels from the original event center.
1558
+ // Without this correction, the dragged distance would jumpstart at dragMinDistance pixels instead of at 0.
1559
+ // It might be useful to save the original start point somewhere
1560
+ var factor = Math.abs(inst.options.dragMinDistance / ev.distance);
1561
+ startCenter.pageX += ev.deltaX * factor;
1562
+ startCenter.pageY += ev.deltaY * factor;
1563
+ startCenter.clientX += ev.deltaX * factor;
1564
+ startCenter.clientY += ev.deltaY * factor;
1565
+
1566
+ // recalculate event data using new start point
1567
+ ev = Detection.extendEventData(ev);
1568
+ }
1569
+ }
1570
+
1571
+ // lock drag to axis?
1572
+ if (
1573
+ cur.lastEvent.dragLockToAxis ||
1574
+ (inst.options.dragLockToAxis &&
1575
+ inst.options.dragLockMinDistance <= ev.distance)
1576
+ ) {
1577
+ ev.dragLockToAxis = true;
1578
+ }
1579
+
1580
+ // keep direction on the axis that the drag gesture started on
1581
+ var lastDirection = cur.lastEvent.direction;
1582
+ if (ev.dragLockToAxis && lastDirection !== ev.direction) {
1583
+ if (Utils.isVertical(lastDirection)) {
1584
+ ev.direction = ev.deltaY < 0 ? DIRECTION_UP : DIRECTION_DOWN;
1585
+ } else {
1586
+ ev.direction = ev.deltaX < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
1587
+ }
1588
+ }
1589
+
1590
+ // first time, trigger dragstart event
1591
+ if (!triggered) {
1592
+ inst.trigger(name + "start", ev);
1593
+ triggered = true;
1594
+ }
1595
+
1596
+ // trigger events
1597
+ inst.trigger(name, ev);
1598
+ inst.trigger(name + ev.direction, ev);
1599
+
1600
+ var isVertical = Utils.isVertical(ev.direction);
1601
+
1602
+ // block the browser events
1603
+ if (
1604
+ (inst.options.dragBlockVertical && isVertical) ||
1605
+ (inst.options.dragBlockHorizontal && !isVertical)
1606
+ ) {
1607
+ ev.preventDefault();
1608
+ }
1609
+ break;
1610
+
1611
+ case EVENT_RELEASE:
1612
+ if (triggered && ev.changedLength <= inst.options.dragMaxTouches) {
1613
+ inst.trigger(name + "end", ev);
1614
+ triggered = false;
1615
+ }
1616
+ break;
1617
+
1618
+ case EVENT_END:
1619
+ triggered = false;
1620
+ break;
1621
+ }
1622
+ }
1623
+
1624
+ Hammer.gestures.Drag = {
1625
+ name: name,
1626
+ index: 50,
1627
+ handler: dragGesture,
1628
+ defaults: {
1629
+ /**
1630
+ * minimal movement that have to be made before the drag event gets triggered
1631
+ * @property dragMinDistance
1632
+ * @type {Number}
1633
+ * @default 10
1634
+ */
1635
+ dragMinDistance: 10,
1636
+
1637
+ /**
1638
+ * Set dragDistanceCorrection to true to make the starting point of the drag
1639
+ * be calculated from where the drag was triggered, not from where the touch started.
1640
+ * Useful to avoid a jerk-starting drag, which can make fine-adjustments
1641
+ * through dragging difficult, and be visually unappealing.
1642
+ * @property dragDistanceCorrection
1643
+ * @type {Boolean}
1644
+ * @default true
1645
+ */
1646
+ dragDistanceCorrection: true,
1647
+
1648
+ /**
1649
+ * set 0 for unlimited, but this can conflict with transform
1650
+ * @property dragMaxTouches
1651
+ * @type {Number}
1652
+ * @default 1
1653
+ */
1654
+ dragMaxTouches: 1,
1655
+
1656
+ /**
1657
+ * prevent default browser behavior when dragging occurs
1658
+ * be careful with it, it makes the element a blocking element
1659
+ * when you are using the drag gesture, it is a good practice to set this true
1660
+ * @property dragBlockHorizontal
1661
+ * @type {Boolean}
1662
+ * @default false
1663
+ */
1664
+ dragBlockHorizontal: false,
1665
+
1666
+ /**
1667
+ * same as `dragBlockHorizontal`, but for vertical movement
1668
+ * @property dragBlockVertical
1669
+ * @type {Boolean}
1670
+ * @default false
1671
+ */
1672
+ dragBlockVertical: false,
1673
+
1674
+ /**
1675
+ * dragLockToAxis keeps the drag gesture on the axis that it started on,
1676
+ * It disallows vertical directions if the initial direction was horizontal, and vice versa.
1677
+ * @property dragLockToAxis
1678
+ * @type {Boolean}
1679
+ * @default false
1680
+ */
1681
+ dragLockToAxis: false,
1682
+
1683
+ /**
1684
+ * drag lock only kicks in when distance > dragLockMinDistance
1685
+ * This way, locking occurs only when the distance has become large enough to reliably determine the direction
1686
+ * @property dragLockMinDistance
1687
+ * @type {Number}
1688
+ * @default 25
1689
+ */
1690
+ dragLockMinDistance: 25,
1691
+ },
1692
+ };
1693
+ })("drag");
1694
+
1695
+ /**
1696
+ * @module gestures
1697
+ */
1698
+ /**
1699
+ * trigger a simple gesture event, so you can do anything in your handler.
1700
+ * only usable if you know what your doing...
1701
+ *
1702
+ * @class Gesture
1703
+ * @static
1704
+ */
1705
+ /**
1706
+ * @event gesture
1707
+ * @param {Object} ev
1708
+ */
1709
+ Hammer.gestures.Gesture = {
1710
+ name: "gesture",
1711
+ index: 1337,
1712
+ handler: function releaseGesture(ev, inst) {
1713
+ inst.trigger(this.name, ev);
1714
+ },
1715
+ };
1716
+
1717
+ /**
1718
+ * @module gestures
1719
+ */
1720
+ /**
1721
+ * Touch stays at the same place for x time
1722
+ *
1723
+ * @class Hold
1724
+ * @static
1725
+ */
1726
+ /**
1727
+ * @event hold
1728
+ * @param {Object} ev
1729
+ */
1730
+
1731
+ /**
1732
+ * @param {String} name
1733
+ */
1734
+ (function (name) {
1735
+ var timer;
1736
+
1737
+ function holdGesture(ev, inst) {
1738
+ var options = inst.options,
1739
+ current = Detection.current;
1740
+
1741
+ switch (ev.eventType) {
1742
+ case EVENT_START:
1743
+ clearTimeout(timer);
1744
+
1745
+ // set the gesture so we can check in the timeout if it still is
1746
+ current.name = name;
1747
+
1748
+ // set timer and if after the timeout it still is hold,
1749
+ // we trigger the hold event
1750
+ timer = setTimeout(function () {
1751
+ if (current && current.name == name) {
1752
+ inst.trigger(name, ev);
1753
+ }
1754
+ }, options.holdTimeout);
1755
+ break;
1756
+
1757
+ case EVENT_MOVE:
1758
+ if (ev.distance > options.holdThreshold) {
1759
+ clearTimeout(timer);
1760
+ }
1761
+ break;
1762
+
1763
+ case EVENT_RELEASE:
1764
+ clearTimeout(timer);
1765
+ break;
1766
+ }
1767
+ }
1768
+
1769
+ Hammer.gestures.Hold = {
1770
+ name: name,
1771
+ index: 10,
1772
+ defaults: {
1773
+ /**
1774
+ * @property holdTimeout
1775
+ * @type {Number}
1776
+ * @default 500
1777
+ */
1778
+ holdTimeout: 500,
1779
+
1780
+ /**
1781
+ * movement allowed while holding
1782
+ * @property holdThreshold
1783
+ * @type {Number}
1784
+ * @default 2
1785
+ */
1786
+ holdThreshold: 2,
1787
+ },
1788
+ handler: holdGesture,
1789
+ };
1790
+ })("hold");
1791
+
1792
+ /**
1793
+ * @module gestures
1794
+ */
1795
+ /**
1796
+ * when a touch is being released from the page
1797
+ *
1798
+ * @class Release
1799
+ * @static
1800
+ */
1801
+ /**
1802
+ * @event release
1803
+ * @param {Object} ev
1804
+ */
1805
+ Hammer.gestures.Release = {
1806
+ name: "release",
1807
+ index: Infinity,
1808
+ handler: function releaseGesture(ev, inst) {
1809
+ if (ev.eventType == EVENT_RELEASE) {
1810
+ inst.trigger(this.name, ev);
1811
+ }
1812
+ },
1813
+ };
1814
+
1815
+ /**
1816
+ * @module gestures
1817
+ */
1818
+ /**
1819
+ * triggers swipe events when the end velocity is above the threshold
1820
+ * for best usage, set `preventDefault` (on the drag gesture) to `true`
1821
+ * ````
1822
+ * hammertime.on("dragleft swipeleft", function(ev) {
1823
+ * console.log(ev);
1824
+ * ev.gesture.preventDefault();
1825
+ * });
1826
+ * ````
1827
+ *
1828
+ * @class Swipe
1829
+ * @static
1830
+ */
1831
+ /**
1832
+ * @event swipe
1833
+ * @param {Object} ev
1834
+ */
1835
+ /**
1836
+ * @event swipeleft
1837
+ * @param {Object} ev
1838
+ */
1839
+ /**
1840
+ * @event swiperight
1841
+ * @param {Object} ev
1842
+ */
1843
+ /**
1844
+ * @event swipeup
1845
+ * @param {Object} ev
1846
+ */
1847
+ /**
1848
+ * @event swipedown
1849
+ * @param {Object} ev
1850
+ */
1851
+ Hammer.gestures.Swipe = {
1852
+ name: "swipe",
1853
+ index: 40,
1854
+ defaults: {
1855
+ /**
1856
+ * @property swipeMinTouches
1857
+ * @type {Number}
1858
+ * @default 1
1859
+ */
1860
+ swipeMinTouches: 1,
1861
+
1862
+ /**
1863
+ * @property swipeMaxTouches
1864
+ * @type {Number}
1865
+ * @default 1
1866
+ */
1867
+ swipeMaxTouches: 1,
1868
+
1869
+ /**
1870
+ * horizontal swipe velocity
1871
+ * @property swipeVelocityX
1872
+ * @type {Number}
1873
+ * @default 0.6
1874
+ */
1875
+ swipeVelocityX: 0.6,
1876
+
1877
+ /**
1878
+ * vertical swipe velocity
1879
+ * @property swipeVelocityY
1880
+ * @type {Number}
1881
+ * @default 0.6
1882
+ */
1883
+ swipeVelocityY: 0.6,
1884
+ },
1885
+
1886
+ handler: function swipeGesture(ev, inst) {
1887
+ if (ev.eventType == EVENT_RELEASE) {
1888
+ var touches = ev.touches.length,
1889
+ options = inst.options;
1890
+
1891
+ // max touches
1892
+ if (
1893
+ touches < options.swipeMinTouches ||
1894
+ touches > options.swipeMaxTouches
1895
+ ) {
1896
+ return;
1897
+ }
1898
+
1899
+ // when the distance we moved is too small we skip this gesture
1900
+ // or we can be already in dragging
1901
+ if (
1902
+ ev.velocityX > options.swipeVelocityX ||
1903
+ ev.velocityY > options.swipeVelocityY
1904
+ ) {
1905
+ // trigger swipe events
1906
+ inst.trigger(this.name, ev);
1907
+ inst.trigger(this.name + ev.direction, ev);
1908
+ }
1909
+ }
1910
+ },
1911
+ };
1912
+
1913
+ /**
1914
+ * @module gestures
1915
+ */
1916
+ /**
1917
+ * Single tap and a double tap on a place
1918
+ *
1919
+ * @class Tap
1920
+ * @static
1921
+ */
1922
+ /**
1923
+ * @event tap
1924
+ * @param {Object} ev
1925
+ */
1926
+ /**
1927
+ * @event doubletap
1928
+ * @param {Object} ev
1929
+ */
1930
+
1931
+ /**
1932
+ * @param {String} name
1933
+ */
1934
+ (function (name) {
1935
+ var hasMoved = false;
1936
+
1937
+ function tapGesture(ev, inst) {
1938
+ var options = inst.options,
1939
+ current = Detection.current,
1940
+ prev = Detection.previous,
1941
+ sincePrev,
1942
+ didDoubleTap;
1943
+
1944
+ switch (ev.eventType) {
1945
+ case EVENT_START:
1946
+ hasMoved = false;
1947
+ break;
1948
+
1949
+ case EVENT_MOVE:
1950
+ hasMoved = hasMoved || ev.distance > options.tapMaxDistance;
1951
+ break;
1952
+
1953
+ case EVENT_END:
1954
+ if (
1955
+ !Utils.inStr(ev.srcEvent.type, "cancel") &&
1956
+ ev.deltaTime < options.tapMaxTime &&
1957
+ !hasMoved
1958
+ ) {
1959
+ // previous gesture, for the double tap since these are two different gesture detections
1960
+ sincePrev =
1961
+ prev && prev.lastEvent && ev.timeStamp - prev.lastEvent.timeStamp;
1962
+ didDoubleTap = false;
1963
+
1964
+ // check if double tap
1965
+ if (
1966
+ prev &&
1967
+ prev.name == name &&
1968
+ sincePrev &&
1969
+ sincePrev < options.doubleTapInterval &&
1970
+ ev.distance < options.doubleTapDistance
1971
+ ) {
1972
+ inst.trigger("doubletap", ev);
1973
+ didDoubleTap = true;
1974
+ }
1975
+
1976
+ // do a single tap
1977
+ if (!didDoubleTap || options.tapAlways) {
1978
+ current.name = name;
1979
+ inst.trigger(current.name, ev);
1980
+ }
1981
+ }
1982
+ break;
1983
+ }
1984
+ }
1985
+
1986
+ Hammer.gestures.Tap = {
1987
+ name: name,
1988
+ index: 100,
1989
+ handler: tapGesture,
1990
+ defaults: {
1991
+ /**
1992
+ * max time of a tap, this is for the slow tappers
1993
+ * @property tapMaxTime
1994
+ * @type {Number}
1995
+ * @default 250
1996
+ */
1997
+ tapMaxTime: 250,
1998
+
1999
+ /**
2000
+ * max distance of movement of a tap, this is for the slow tappers
2001
+ * @property tapMaxDistance
2002
+ * @type {Number}
2003
+ * @default 10
2004
+ */
2005
+ tapMaxDistance: 10,
2006
+
2007
+ /**
2008
+ * always trigger the `tap` event, even while double-tapping
2009
+ * @property tapAlways
2010
+ * @type {Boolean}
2011
+ * @default true
2012
+ */
2013
+ tapAlways: true,
2014
+
2015
+ /**
2016
+ * max distance between two taps
2017
+ * @property doubleTapDistance
2018
+ * @type {Number}
2019
+ * @default 20
2020
+ */
2021
+ doubleTapDistance: 20,
2022
+
2023
+ /**
2024
+ * max time between two taps
2025
+ * @property doubleTapInterval
2026
+ * @type {Number}
2027
+ * @default 300
2028
+ */
2029
+ doubleTapInterval: 300,
2030
+ },
2031
+ };
2032
+ })("tap");
2033
+
2034
+ /**
2035
+ * @module gestures
2036
+ */
2037
+ /**
2038
+ * when a touch is being touched at the page
2039
+ *
2040
+ * @class Touch
2041
+ * @static
2042
+ */
2043
+ /**
2044
+ * @event touch
2045
+ * @param {Object} ev
2046
+ */
2047
+ Hammer.gestures.Touch = {
2048
+ name: "touch",
2049
+ index: -Infinity,
2050
+ defaults: {
2051
+ /**
2052
+ * call preventDefault at touchstart, and makes the element blocking by disabling the scrolling of the page,
2053
+ * but it improves gestures like transforming and dragging.
2054
+ * be careful with using this, it can be very annoying for users to be stuck on the page
2055
+ * @property preventDefault
2056
+ * @type {Boolean}
2057
+ * @default false
2058
+ */
2059
+ preventDefault: false,
2060
+
2061
+ /**
2062
+ * disable mouse events, so only touch (or pen!) input triggers events
2063
+ * @property preventMouse
2064
+ * @type {Boolean}
2065
+ * @default false
2066
+ */
2067
+ preventMouse: false,
2068
+ },
2069
+ handler: function touchGesture(ev, inst) {
2070
+ if (inst.options.preventMouse && ev.pointerType == POINTER_MOUSE) {
2071
+ ev.stopDetect();
2072
+ return;
2073
+ }
2074
+
2075
+ if (inst.options.preventDefault) {
2076
+ ev.preventDefault();
2077
+ }
2078
+
2079
+ if (ev.eventType == EVENT_TOUCH) {
2080
+ inst.trigger("touch", ev);
2081
+ }
2082
+ },
2083
+ };
2084
+
2085
+ /**
2086
+ * @module gestures
2087
+ */
2088
+ /**
2089
+ * User want to scale or rotate with 2 fingers
2090
+ * Preventing the default browser behavior is a good way to improve feel and working. This can be done with the
2091
+ * `preventDefault` option.
2092
+ *
2093
+ * @class Transform
2094
+ * @static
2095
+ */
2096
+ /**
2097
+ * @event transform
2098
+ * @param {Object} ev
2099
+ */
2100
+ /**
2101
+ * @event transformstart
2102
+ * @param {Object} ev
2103
+ */
2104
+ /**
2105
+ * @event transformend
2106
+ * @param {Object} ev
2107
+ */
2108
+ /**
2109
+ * @event pinchin
2110
+ * @param {Object} ev
2111
+ */
2112
+ /**
2113
+ * @event pinchout
2114
+ * @param {Object} ev
2115
+ */
2116
+ /**
2117
+ * @event rotate
2118
+ * @param {Object} ev
2119
+ */
2120
+
2121
+ /**
2122
+ * @param {String} name
2123
+ */
2124
+ (function (name) {
2125
+ var triggered = false;
2126
+
2127
+ function transformGesture(ev, inst) {
2128
+ switch (ev.eventType) {
2129
+ case EVENT_START:
2130
+ triggered = false;
2131
+ break;
2132
+
2133
+ case EVENT_MOVE:
2134
+ // at least multitouch
2135
+ if (ev.touches.length < 2) {
2136
+ return;
2137
+ }
2138
+
2139
+ var scaleThreshold = Math.abs(1 - ev.scale);
2140
+ var rotationThreshold = Math.abs(ev.rotation);
2141
+
2142
+ // when the distance we moved is too small we skip this gesture
2143
+ // or we can be already in dragging
2144
+ if (
2145
+ scaleThreshold < inst.options.transformMinScale &&
2146
+ rotationThreshold < inst.options.transformMinRotation
2147
+ ) {
2148
+ return;
2149
+ }
2150
+
2151
+ // we are transforming!
2152
+ Detection.current.name = name;
2153
+
2154
+ // first time, trigger dragstart event
2155
+ if (!triggered) {
2156
+ inst.trigger(name + "start", ev);
2157
+ triggered = true;
2158
+ }
2159
+
2160
+ inst.trigger(name, ev); // basic transform event
2161
+
2162
+ // trigger rotate event
2163
+ if (rotationThreshold > inst.options.transformMinRotation) {
2164
+ inst.trigger("rotate", ev);
2165
+ }
2166
+
2167
+ // trigger pinch event
2168
+ if (scaleThreshold > inst.options.transformMinScale) {
2169
+ inst.trigger("pinch", ev);
2170
+ inst.trigger("pinch" + (ev.scale < 1 ? "in" : "out"), ev);
2171
+ }
2172
+ break;
2173
+
2174
+ case EVENT_RELEASE:
2175
+ if (triggered && ev.changedLength < 2) {
2176
+ inst.trigger(name + "end", ev);
2177
+ triggered = false;
2178
+ }
2179
+ break;
2180
+ }
2181
+ }
2182
+
2183
+ Hammer.gestures.Transform = {
2184
+ name: name,
2185
+ index: 45,
2186
+ defaults: {
2187
+ /**
2188
+ * minimal scale factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1
2189
+ * @property transformMinScale
2190
+ * @type {Number}
2191
+ * @default 0.01
2192
+ */
2193
+ transformMinScale: 0.01,
2194
+
2195
+ /**
2196
+ * rotation in degrees
2197
+ * @property transformMinRotation
2198
+ * @type {Number}
2199
+ * @default 1
2200
+ */
2201
+ transformMinRotation: 1,
2202
+ },
2203
+
2204
+ handler: transformGesture,
2205
+ };
2206
+ })("transform");
2207
+
2208
+ /**
2209
+ * @module hammer
2210
+ */
2211
+
2212
+ // AMD export
2213
+ if (typeof define == "function" && define.amd) {
2214
+ define([], function () {
2215
+ return Hammer;
2216
+ });
2217
+ // commonjs export
2218
+ } else if (typeof module !== "undefined" && module.exports) {
2219
+ module.exports = Hammer;
2220
+ // browser export
2221
+ } else {
2222
+ window.Hammer = Hammer;
2223
+ }
2224
+ })(window);