parade 0.9.2 → 0.10.0

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.
Files changed (62) hide show
  1. checksums.yaml +15 -0
  2. data/README.md +77 -53
  3. data/bin/parade +3 -2
  4. data/lib/parade/commands/html_output.rb +1 -0
  5. data/lib/parade/commands/static_html.rb +1 -1
  6. data/lib/parade/helpers/template_generator.rb +13 -12
  7. data/lib/parade/parsers/dsl.rb +8 -0
  8. data/lib/parade/renderers/update_image_paths.rb +20 -17
  9. data/lib/parade/section.rb +13 -2
  10. data/lib/parade/server.rb +24 -11
  11. data/lib/parade/slide.rb +2 -3
  12. data/lib/parade/slide_post_renderers.rb +2 -0
  13. data/lib/parade/version.rb +1 -1
  14. data/lib/public/css/960.css +1 -1
  15. data/lib/public/css/fg.menu.css +37 -11
  16. data/lib/public/css/{theme → jquery-ui}/images/ui-bg_diagonals-small_100_f0efea_40x40.png +0 -0
  17. data/lib/public/css/{theme → jquery-ui}/images/ui-bg_flat_35_f0f0f0_40x100.png +0 -0
  18. data/lib/public/css/{theme → jquery-ui}/images/ui-bg_glass_55_fcf0ba_1x400.png +0 -0
  19. data/lib/public/css/{theme → jquery-ui}/images/ui-bg_glow-ball_25_2e2e28_600x600.png +0 -0
  20. data/lib/public/css/{theme → jquery-ui}/images/ui-bg_highlight-soft_100_f0efea_1x100.png +0 -0
  21. data/lib/public/css/{theme → jquery-ui}/images/ui-bg_highlight-soft_25_327E04_1x100.png +0 -0
  22. data/lib/public/css/{theme → jquery-ui}/images/ui-bg_highlight-soft_25_5A9D1A_1x100.png +0 -0
  23. data/lib/public/css/{theme → jquery-ui}/images/ui-bg_highlight-soft_95_ffedad_1x100.png +0 -0
  24. data/lib/public/css/{theme → jquery-ui}/images/ui-bg_inset-soft_22_3b3b35_1x100.png +0 -0
  25. data/lib/public/css/{theme → jquery-ui}/images/ui-icons_808080_256x240.png +0 -0
  26. data/lib/public/css/{theme → jquery-ui}/images/ui-icons_8DC262_256x240.png +0 -0
  27. data/lib/public/css/{theme → jquery-ui}/images/ui-icons_cd0a0a_256x240.png +0 -0
  28. data/lib/public/css/{theme → jquery-ui}/images/ui-icons_e7e6e4_256x240.png +0 -0
  29. data/lib/public/css/{theme → jquery-ui}/images/ui-icons_eeeeee_256x240.png +0 -0
  30. data/lib/public/css/{theme → jquery-ui}/images/ui-icons_ffffff_256x240.png +0 -0
  31. data/lib/public/css/{theme → jquery-ui}/ui.accordion.css +0 -0
  32. data/lib/public/css/{theme → jquery-ui}/ui.all.css +0 -0
  33. data/lib/public/css/{theme → jquery-ui}/ui.base.css +0 -0
  34. data/lib/public/css/{theme → jquery-ui}/ui.core.css +0 -0
  35. data/lib/public/css/{theme → jquery-ui}/ui.datepicker.css +0 -0
  36. data/lib/public/css/{theme → jquery-ui}/ui.dialog.css +0 -0
  37. data/lib/public/css/{theme → jquery-ui}/ui.progressbar.css +0 -0
  38. data/lib/public/css/{theme → jquery-ui}/ui.resizable.css +0 -0
  39. data/lib/public/css/{theme → jquery-ui}/ui.slider.css +0 -0
  40. data/lib/public/css/{theme → jquery-ui}/ui.tabs.css +0 -0
  41. data/lib/public/css/{theme → jquery-ui}/ui.theme.css +0 -0
  42. data/lib/public/css/mobile.css +179 -0
  43. data/lib/public/css/print.css +16 -0
  44. data/lib/public/css/slide_formats.css +188 -0
  45. data/lib/public/css/themes/archetect.css +19 -217
  46. data/lib/public/css/themes/default.css +86 -0
  47. data/lib/public/css/themes/hack.css +51 -277
  48. data/lib/public/css/themes/merlot.css +20 -375
  49. data/lib/public/css/themes/slate.css +19 -184
  50. data/lib/public/js/hammer.js +1330 -0
  51. data/lib/public/js/parade-mobile.js +4 -0
  52. data/lib/public/js/parade.js +32 -34
  53. data/lib/views/footer.erb +5 -0
  54. data/lib/views/header.erb +12 -10
  55. data/lib/views/help.erb +18 -0
  56. data/lib/views/index.erb +6 -33
  57. data/lib/views/navigation.erb +10 -0
  58. data/lib/views/pdf.erb +8 -2
  59. data/lib/views/{onepage.erb → print.erb} +8 -2
  60. metadata +67 -68
  61. data/lib/public/css/onepage.css +0 -62
  62. data/lib/public/css/parade.css +0 -448
@@ -0,0 +1,1330 @@
1
+ /*! Hammer.JS - v1.0.3 - 2013-03-02
2
+ * http://eightmedia.github.com/hammer.js
3
+ *
4
+ * Copyright (c) 2013 Jorik Tangelder <j.tangelder@gmail.com>;
5
+ * Licensed under the MIT license */
6
+
7
+ (function(window) {
8
+ 'use strict';
9
+
10
+ /**
11
+ * Hammer
12
+ * use this to create instances
13
+ * @param {HTMLElement} element
14
+ * @param {Object} options
15
+ * @returns {Hammer.Instance}
16
+ * @constructor
17
+ */
18
+ var Hammer = function(element, options) {
19
+ return new Hammer.Instance(element, options || {});
20
+ };
21
+
22
+ // default settings
23
+ Hammer.defaults = {
24
+ // add styles and attributes to the element to prevent the browser from doing
25
+ // its native behavior. this doesnt prevent the scrolling, but cancels
26
+ // the contextmenu, tap highlighting etc
27
+ // set to false to disable this
28
+ stop_browser_behavior: {
29
+ userSelect: 'none', // this also triggers onselectstart=false for IE
30
+ touchCallout: 'none',
31
+ touchAction: 'none',
32
+ contentZooming: 'none',
33
+ userDrag: 'none',
34
+ tapHighlightColor: 'rgba(0,0,0,0)'
35
+ }
36
+
37
+ // more settings are defined per gesture at gestures.js
38
+ };
39
+
40
+ // detect touchevents
41
+ Hammer.HAS_POINTEREVENTS = navigator.pointerEnabled || navigator.msPointerEnabled;
42
+ Hammer.HAS_TOUCHEVENTS = ('ontouchstart' in window);
43
+
44
+ // eventtypes per touchevent (start, move, end)
45
+ // are filled by Hammer.event.determineEventTypes on setup
46
+ Hammer.EVENT_TYPES = {};
47
+
48
+ // direction defines
49
+ Hammer.DIRECTION_DOWN = 'down';
50
+ Hammer.DIRECTION_LEFT = 'left';
51
+ Hammer.DIRECTION_UP = 'up';
52
+ Hammer.DIRECTION_RIGHT = 'right';
53
+
54
+ // pointer type
55
+ Hammer.POINTER_MOUSE = 'mouse';
56
+ Hammer.POINTER_TOUCH = 'touch';
57
+ Hammer.POINTER_PEN = 'pen';
58
+
59
+ // touch event defines
60
+ Hammer.EVENT_START = 'start';
61
+ Hammer.EVENT_MOVE = 'move';
62
+ Hammer.EVENT_END = 'end';
63
+
64
+ // plugins namespace
65
+ Hammer.plugins = {};
66
+
67
+ // if the window events are set...
68
+ Hammer.READY = false;
69
+
70
+ /**
71
+ * setup events to detect gestures on the document
72
+ */
73
+ function setup() {
74
+ if(Hammer.READY) {
75
+ return;
76
+ }
77
+
78
+ // find what eventtypes we add listeners to
79
+ Hammer.event.determineEventTypes();
80
+
81
+ // Register all gestures inside Hammer.gestures
82
+ for(var name in Hammer.gestures) {
83
+ if(Hammer.gestures.hasOwnProperty(name)) {
84
+ Hammer.detection.register(Hammer.gestures[name]);
85
+ }
86
+ }
87
+
88
+ // Add touch events on the document
89
+ Hammer.event.onTouch(document, Hammer.EVENT_MOVE, Hammer.detection.detect);
90
+ Hammer.event.onTouch(document, Hammer.EVENT_END, Hammer.detection.endDetect);
91
+
92
+ // Hammer is ready...!
93
+ Hammer.READY = true;
94
+ }
95
+
96
+ /**
97
+ * create new hammer instance
98
+ * all methods should return the instance itself, so it is chainable.
99
+ * @param {HTMLElement} element
100
+ * @param {Object} [options={}]
101
+ * @returns {Hammer.Instance}
102
+ * @constructor
103
+ */
104
+ Hammer.Instance = function(element, options) {
105
+ var self = this;
106
+
107
+ // setup HammerJS window events and register all gestures
108
+ // this also sets up the default options
109
+ setup();
110
+
111
+ this.element = element;
112
+
113
+ // start/stop detection option
114
+ this.enabled = true;
115
+
116
+ // merge options
117
+ this.options = Hammer.utils.extend(
118
+ Hammer.utils.extend({}, Hammer.defaults),
119
+ options || {});
120
+
121
+ // add some css to the element to prevent the browser from doing its native behavoir
122
+ if(this.options.stop_browser_behavior) {
123
+ Hammer.utils.stopDefaultBrowserBehavior(this.element, this.options.stop_browser_behavior);
124
+ }
125
+
126
+ // start detection on touchstart
127
+ Hammer.event.onTouch(element, Hammer.EVENT_START, function(ev) {
128
+ if(self.enabled) {
129
+ Hammer.detection.startDetect(self, ev);
130
+ }
131
+ });
132
+
133
+ // return instance
134
+ return this;
135
+ };
136
+
137
+
138
+ Hammer.Instance.prototype = {
139
+ /**
140
+ * bind events to the instance
141
+ * @param {String} gesture
142
+ * @param {Function} handler
143
+ * @returns {Hammer.Instance}
144
+ */
145
+ on: function onEvent(gesture, handler){
146
+ var gestures = gesture.split(' ');
147
+ for(var t=0; t<gestures.length; t++) {
148
+ this.element.addEventListener(gestures[t], handler, false);
149
+ }
150
+ return this;
151
+ },
152
+
153
+
154
+ /**
155
+ * unbind events to the instance
156
+ * @param {String} gesture
157
+ * @param {Function} handler
158
+ * @returns {Hammer.Instance}
159
+ */
160
+ off: function offEvent(gesture, handler){
161
+ var gestures = gesture.split(' ');
162
+ for(var t=0; t<gestures.length; t++) {
163
+ this.element.removeEventListener(gestures[t], handler, false);
164
+ }
165
+ return this;
166
+ },
167
+
168
+
169
+ /**
170
+ * trigger gesture event
171
+ * @param {String} gesture
172
+ * @param {Object} eventData
173
+ * @returns {Hammer.Instance}
174
+ */
175
+ trigger: function triggerEvent(gesture, eventData){
176
+ // trigger DOM event
177
+ var event = document.createEvent('Event');
178
+ event.initEvent(gesture, true, true);
179
+ event.gesture = eventData;
180
+ this.element.dispatchEvent(event);
181
+ return this;
182
+ },
183
+
184
+
185
+ /**
186
+ * enable of disable hammer.js detection
187
+ * @param {Boolean} state
188
+ * @returns {Hammer.Instance}
189
+ */
190
+ enable: function enable(state) {
191
+ this.enabled = state;
192
+ return this;
193
+ }
194
+ };
195
+
196
+ /**
197
+ * this holds the last move event,
198
+ * used to fix empty touchend issue
199
+ * see the onTouch event for an explanation
200
+ * @type {Object}
201
+ */
202
+ var last_move_event = null;
203
+
204
+
205
+ /**
206
+ * when the mouse is hold down, this is true
207
+ * @type {Boolean}
208
+ */
209
+ var enable_detect = false;
210
+
211
+
212
+ /**
213
+ * when touch events have been fired, this is true
214
+ * @type {Boolean}
215
+ */
216
+ var touch_triggered = false;
217
+
218
+
219
+ Hammer.event = {
220
+ /**
221
+ * simple addEventListener
222
+ * @param {HTMLElement} element
223
+ * @param {String} type
224
+ * @param {Function} handler
225
+ */
226
+ bindDom: function(element, type, handler) {
227
+ var types = type.split(' ');
228
+ for(var t=0; t<types.length; t++) {
229
+ element.addEventListener(types[t], handler, false);
230
+ }
231
+ },
232
+
233
+
234
+ /**
235
+ * touch events with mouse fallback
236
+ * @param {HTMLElement} element
237
+ * @param {String} eventType like Hammer.EVENT_MOVE
238
+ * @param {Function} handler
239
+ */
240
+ onTouch: function onTouch(element, eventType, handler) {
241
+ var self = this;
242
+ this.bindDom(element, Hammer.EVENT_TYPES[eventType], function(ev) {
243
+ var sourceEventType = ev.type.toLowerCase();
244
+
245
+ // onmouseup, but when touchend has been fired we do nothing.
246
+ // this is for touchdevices which also fire a mouseup on touchend
247
+ if(sourceEventType.match(/mouseup/) && touch_triggered) {
248
+ touch_triggered = false;
249
+ return;
250
+ }
251
+
252
+ // mousebutton must be down or a touch event
253
+ if(sourceEventType.match(/touch/) || // touch events are always on screen
254
+ (sourceEventType.match(/mouse/) && ev.which === 1) || // mousedown
255
+ (Hammer.HAS_POINTEREVENTS && sourceEventType.match(/down/)) // pointerevents touch
256
+ ){
257
+ enable_detect = true;
258
+ }
259
+
260
+ // we are in a touch event, set the touch triggered bool to true,
261
+ // this for the conflicts that may occur on ios and android
262
+ if(sourceEventType.match(/touch|pointer/)) {
263
+ touch_triggered = true;
264
+ }
265
+
266
+
267
+ // when touch has been triggered in this detection session
268
+ // and we are now handling a mouse event, we stop that to prevent conflicts
269
+ if(enable_detect && !(touch_triggered && sourceEventType.match(/mouse/))) {
270
+ // update pointer
271
+ if(Hammer.HAS_POINTEREVENTS && eventType != Hammer.EVENT_END) {
272
+ Hammer.PointerEvent.updatePointer(eventType, ev);
273
+ }
274
+
275
+ // because touchend has no touches, and we often want to use these in our gestures,
276
+ // we send the last move event as our eventData in touchend
277
+ if(eventType === Hammer.EVENT_END && last_move_event !== null) {
278
+ ev = last_move_event;
279
+ }
280
+ // store the last move event
281
+ else {
282
+ last_move_event = ev;
283
+ }
284
+ // trigger the handler
285
+ handler.call(Hammer.detection, self.collectEventData(element, eventType, ev));
286
+
287
+ // remove pointer after the handler is done
288
+ if(Hammer.HAS_POINTEREVENTS && eventType == Hammer.EVENT_END) {
289
+ Hammer.PointerEvent.updatePointer(eventType, ev);
290
+ }
291
+ }
292
+
293
+
294
+ // on the end we reset everything
295
+ if(sourceEventType.match(/up|cancel|end/)) {
296
+ enable_detect = false;
297
+ last_move_event = null;
298
+ Hammer.PointerEvent.reset();
299
+ }
300
+ });
301
+ },
302
+
303
+
304
+ /**
305
+ * we have different events for each device/browser
306
+ * determine what we need and set them in the Hammer.EVENT_TYPES constant
307
+ */
308
+ determineEventTypes: function determineEventTypes() {
309
+ // determine the eventtype we want to set
310
+ var types;
311
+ if(Hammer.HAS_POINTEREVENTS) {
312
+ types = Hammer.PointerEvent.getEvents();
313
+ }
314
+ // for non pointer events browsers
315
+ else {
316
+ types = [
317
+ 'touchstart mousedown',
318
+ 'touchmove mousemove',
319
+ 'touchend touchcancel mouseup'];
320
+ }
321
+
322
+ Hammer.EVENT_TYPES[Hammer.EVENT_START] = types[0];
323
+ Hammer.EVENT_TYPES[Hammer.EVENT_MOVE] = types[1];
324
+ Hammer.EVENT_TYPES[Hammer.EVENT_END] = types[2];
325
+ },
326
+
327
+
328
+ /**
329
+ * create touchlist depending on the event
330
+ * @param {Object} ev
331
+ * @param {String} eventType used by the fakemultitouch plugin
332
+ */
333
+ getTouchList: function getTouchList(ev/*, eventType*/) {
334
+ // get the fake pointerEvent touchlist
335
+ if(Hammer.HAS_POINTEREVENTS) {
336
+ return Hammer.PointerEvent.getTouchList();
337
+ }
338
+ // get the touchlist
339
+ else if(ev.touches) {
340
+ return ev.touches;
341
+ }
342
+ // make fake touchlist from mouse position
343
+ else {
344
+ return [{
345
+ identifier: 1,
346
+ pageX: ev.pageX,
347
+ pageY: ev.pageY,
348
+ target: ev.target
349
+ }];
350
+ }
351
+ },
352
+
353
+
354
+ /**
355
+ * collect event data for Hammer js
356
+ * @param {HTMLElement} element
357
+ * @param {String} eventType like Hammer.EVENT_MOVE
358
+ * @param {Object} eventData
359
+ */
360
+ collectEventData: function collectEventData(element, eventType, ev) {
361
+ var touches = this.getTouchList(ev, eventType);
362
+
363
+ // find out pointerType
364
+ var pointerType = Hammer.POINTER_TOUCH;
365
+ if(ev.type.match(/mouse/) || Hammer.PointerEvent.matchType(Hammer.POINTER_MOUSE, ev)) {
366
+ pointerType = Hammer.POINTER_MOUSE;
367
+ }
368
+
369
+ return {
370
+ center : Hammer.utils.getCenter(touches),
371
+ timestamp : ev.timestamp || new Date().getTime(), // for IE
372
+ target : ev.target,
373
+ touches : touches,
374
+ eventType : eventType,
375
+ pointerType : pointerType,
376
+ srcEvent : ev,
377
+
378
+ /**
379
+ * prevent the browser default actions
380
+ * mostly used to disable scrolling of the browser
381
+ */
382
+ preventDefault: function() {
383
+ if(this.srcEvent.preventManipulation) {
384
+ this.srcEvent.preventManipulation();
385
+ }
386
+
387
+ if(this.srcEvent.preventDefault) {
388
+ this.srcEvent.preventDefault();
389
+ }
390
+ },
391
+
392
+ /**
393
+ * stop bubbling the event up to its parents
394
+ */
395
+ stopPropagation: function() {
396
+ this.srcEvent.stopPropagation();
397
+ },
398
+
399
+ /**
400
+ * immediately stop gesture detection
401
+ * might be useful after a swipe was detected
402
+ * @return {*}
403
+ */
404
+ stopDetect: function() {
405
+ return Hammer.detection.stopDetect();
406
+ }
407
+ };
408
+ }
409
+ };
410
+
411
+ Hammer.PointerEvent = {
412
+ /**
413
+ * holds all pointers
414
+ * @type {Object}
415
+ */
416
+ pointers: {},
417
+
418
+ /**
419
+ * get a list of pointers
420
+ * @returns {Array} touchlist
421
+ */
422
+ getTouchList: function() {
423
+ var pointers = this.pointers;
424
+ var touchlist = [];
425
+
426
+ // we can use forEach since pointerEvents only is in IE10
427
+ Object.keys(pointers).sort().forEach(function(id) {
428
+ touchlist.push(pointers[id]);
429
+ });
430
+ return touchlist;
431
+ },
432
+
433
+ /**
434
+ * update the position of a pointer
435
+ * @param {String} type Hammer.EVENT_END
436
+ * @param {Object} pointerEvent
437
+ */
438
+ updatePointer: function(type, pointerEvent) {
439
+ if(type == Hammer.EVENT_END) {
440
+ delete this.pointers[pointerEvent.pointerId];
441
+ }
442
+ else {
443
+ pointerEvent.identifier = pointerEvent.pointerId;
444
+ this.pointers[pointerEvent.pointerId] = pointerEvent;
445
+ }
446
+ },
447
+
448
+ /**
449
+ * check if ev matches pointertype
450
+ * @param {String} pointerType Hammer.POINTER_MOUSE
451
+ * @param {PointerEvent} ev
452
+ */
453
+ matchType: function(pointerType, ev) {
454
+ if(!ev.pointerType) {
455
+ return false;
456
+ }
457
+
458
+ var types = {};
459
+ types[Hammer.POINTER_MOUSE] = (ev.pointerType == ev.MSPOINTER_TYPE_MOUSE || ev.pointerType == Hammer.POINTER_MOUSE);
460
+ types[Hammer.POINTER_TOUCH] = (ev.pointerType == ev.MSPOINTER_TYPE_TOUCH || ev.pointerType == Hammer.POINTER_TOUCH);
461
+ types[Hammer.POINTER_PEN] = (ev.pointerType == ev.MSPOINTER_TYPE_PEN || ev.pointerType == Hammer.POINTER_PEN);
462
+ return types[pointerType];
463
+ },
464
+
465
+
466
+ /**
467
+ * get events
468
+ */
469
+ getEvents: function() {
470
+ return [
471
+ 'pointerdown MSPointerDown',
472
+ 'pointermove MSPointerMove',
473
+ 'pointerup pointercancel MSPointerUp MSPointerCancel'
474
+ ];
475
+ },
476
+
477
+ /**
478
+ * reset the list
479
+ */
480
+ reset: function() {
481
+ this.pointers = {};
482
+ }
483
+ };
484
+
485
+ Hammer.utils = {
486
+ /**
487
+ * extend method,
488
+ * also used for cloning when dest is an empty object
489
+ * @param {Object} dest
490
+ * @param {Object} src
491
+ * @returns {Object} dest
492
+ */
493
+ extend: function extend(dest, src) {
494
+ for (var key in src) {
495
+ dest[key] = src[key];
496
+ }
497
+
498
+ return dest;
499
+ },
500
+
501
+
502
+ /**
503
+ * get the center of all the touches
504
+ * @param {Array} touches
505
+ * @returns {Object} center
506
+ */
507
+ getCenter: function getCenter(touches) {
508
+ var valuesX = [], valuesY = [];
509
+
510
+ for(var t= 0,len=touches.length; t<len; t++) {
511
+ valuesX.push(touches[t].pageX);
512
+ valuesY.push(touches[t].pageY);
513
+ }
514
+
515
+ return {
516
+ pageX: ((Math.min.apply(Math, valuesX) + Math.max.apply(Math, valuesX)) / 2),
517
+ pageY: ((Math.min.apply(Math, valuesY) + Math.max.apply(Math, valuesY)) / 2)
518
+ };
519
+ },
520
+
521
+
522
+ /**
523
+ * calculate the velocity between two points
524
+ * @param {Number} delta_time
525
+ * @param {Number} delta_x
526
+ * @param {Number} delta_y
527
+ * @returns {Object} velocity
528
+ */
529
+ getVelocity: function getSimpleDistance(delta_time, delta_x, delta_y) {
530
+ return {
531
+ x: Math.abs(delta_x / delta_time) || 0,
532
+ y: Math.abs(delta_y / delta_time) || 0
533
+ };
534
+ },
535
+
536
+
537
+ /**
538
+ * calculate the angle between two coordinates
539
+ * @param {Touch} touch1
540
+ * @param {Touch} touch2
541
+ * @returns {Number} angle
542
+ */
543
+ getAngle: function getAngle(touch1, touch2) {
544
+ var y = touch2.pageY - touch1.pageY,
545
+ x = touch2.pageX - touch1.pageX;
546
+ return Math.atan2(y, x) * 180 / Math.PI;
547
+ },
548
+
549
+
550
+ /**
551
+ * angle to direction define
552
+ * @param {Touch} touch1
553
+ * @param {Touch} touch2
554
+ * @returns {String} direction constant, like Hammer.DIRECTION_LEFT
555
+ */
556
+ getDirection: function getDirection(touch1, touch2) {
557
+ var x = Math.abs(touch1.pageX - touch2.pageX),
558
+ y = Math.abs(touch1.pageY - touch2.pageY);
559
+
560
+ if(x >= y) {
561
+ return touch1.pageX - touch2.pageX > 0 ? Hammer.DIRECTION_LEFT : Hammer.DIRECTION_RIGHT;
562
+ }
563
+ else {
564
+ return touch1.pageY - touch2.pageY > 0 ? Hammer.DIRECTION_UP : Hammer.DIRECTION_DOWN;
565
+ }
566
+ },
567
+
568
+
569
+ /**
570
+ * calculate the distance between two touches
571
+ * @param {Touch} touch1
572
+ * @param {Touch} touch2
573
+ * @returns {Number} distance
574
+ */
575
+ getDistance: function getDistance(touch1, touch2) {
576
+ var x = touch2.pageX - touch1.pageX,
577
+ y = touch2.pageY - touch1.pageY;
578
+ return Math.sqrt((x*x) + (y*y));
579
+ },
580
+
581
+
582
+ /**
583
+ * calculate the scale factor between two touchLists (fingers)
584
+ * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
585
+ * @param {Array} start
586
+ * @param {Array} end
587
+ * @returns {Number} scale
588
+ */
589
+ getScale: function getScale(start, end) {
590
+ // need two fingers...
591
+ if(start.length >= 2 && end.length >= 2) {
592
+ return this.getDistance(end[0], end[1]) /
593
+ this.getDistance(start[0], start[1]);
594
+ }
595
+ return 1;
596
+ },
597
+
598
+
599
+ /**
600
+ * calculate the rotation degrees between two touchLists (fingers)
601
+ * @param {Array} start
602
+ * @param {Array} end
603
+ * @returns {Number} rotation
604
+ */
605
+ getRotation: function getRotation(start, end) {
606
+ // need two fingers
607
+ if(start.length >= 2 && end.length >= 2) {
608
+ return this.getAngle(end[1], end[0]) -
609
+ this.getAngle(start[1], start[0]);
610
+ }
611
+ return 0;
612
+ },
613
+
614
+
615
+ /**
616
+ * boolean if the direction is vertical
617
+ * @param {String} direction
618
+ * @returns {Boolean} is_vertical
619
+ */
620
+ isVertical: function isVertical(direction) {
621
+ return (direction == Hammer.DIRECTION_UP || direction == Hammer.DIRECTION_DOWN);
622
+ },
623
+
624
+
625
+ /**
626
+ * stop browser default behavior with css props
627
+ * @param {HtmlElement} element
628
+ * @param {Object} css_props
629
+ */
630
+ stopDefaultBrowserBehavior: function stopDefaultBrowserBehavior(element, css_props) {
631
+ var prop,
632
+ vendors = ['webkit','khtml','moz','ms','o',''];
633
+
634
+ if(!css_props || !element.style) {
635
+ return;
636
+ }
637
+
638
+ // with css properties for modern browsers
639
+ for(var i = 0; i < vendors.length; i++) {
640
+ for(var p in css_props) {
641
+ if(css_props.hasOwnProperty(p)) {
642
+ prop = p;
643
+
644
+ // vender prefix at the property
645
+ if(vendors[i]) {
646
+ prop = vendors[i] + prop.substring(0, 1).toUpperCase() + prop.substring(1);
647
+ }
648
+
649
+ // set the style
650
+ element.style[prop] = css_props[p];
651
+ }
652
+ }
653
+ }
654
+
655
+ // also the disable onselectstart
656
+ if(css_props.userSelect == 'none') {
657
+ element.onselectstart = function() {
658
+ return false;
659
+ };
660
+ }
661
+ }
662
+ };
663
+
664
+ Hammer.detection = {
665
+ // contains all registred Hammer.gestures in the correct order
666
+ gestures: [],
667
+
668
+ // data of the current Hammer.gesture detection session
669
+ current: null,
670
+
671
+ // the previous Hammer.gesture session data
672
+ // is a full clone of the previous gesture.current object
673
+ previous: null,
674
+
675
+ // when this becomes true, no gestures are fired
676
+ stopped: false,
677
+
678
+
679
+ /**
680
+ * start Hammer.gesture detection
681
+ * @param {Hammer.Instance} inst
682
+ * @param {Object} eventData
683
+ */
684
+ startDetect: function startDetect(inst, eventData) {
685
+ // already busy with a Hammer.gesture detection on an element
686
+ if(this.current) {
687
+ return;
688
+ }
689
+
690
+ this.stopped = false;
691
+
692
+ this.current = {
693
+ inst : inst, // reference to HammerInstance we're working for
694
+ startEvent : Hammer.utils.extend({}, eventData), // start eventData for distances, timing etc
695
+ lastEvent : false, // last eventData
696
+ name : '' // current gesture we're in/detected, can be 'tap', 'hold' etc
697
+ };
698
+
699
+ this.detect(eventData);
700
+ },
701
+
702
+
703
+ /**
704
+ * Hammer.gesture detection
705
+ * @param {Object} eventData
706
+ */
707
+ detect: function detect(eventData) {
708
+ if(!this.current || this.stopped) {
709
+ return;
710
+ }
711
+
712
+ // extend event data with calculations about scale, distance etc
713
+ eventData = this.extendEventData(eventData);
714
+
715
+ // instance options
716
+ var inst_options = this.current.inst.options;
717
+
718
+ // call Hammer.gesture handlers
719
+ for(var g=0,len=this.gestures.length; g<len; g++) {
720
+ var gesture = this.gestures[g];
721
+
722
+ // only when the instance options have enabled this gesture
723
+ if(!this.stopped && inst_options[gesture.name] !== false) {
724
+ // if a handler returns false, we stop with the detection
725
+ if(gesture.handler.call(gesture, eventData, this.current.inst) === false) {
726
+ this.stopDetect();
727
+ break;
728
+ }
729
+ }
730
+ }
731
+
732
+ // store as previous event event
733
+ if(this.current) {
734
+ this.current.lastEvent = eventData;
735
+ }
736
+ },
737
+
738
+
739
+ /**
740
+ * end Hammer.gesture detection
741
+ * @param {Object} eventData
742
+ */
743
+ endDetect: function endDetect(eventData) {
744
+ this.detect(eventData);
745
+ this.stopDetect();
746
+ },
747
+
748
+
749
+ /**
750
+ * clear the Hammer.gesture vars
751
+ * this is called on endDetect, but can also be used when a final Hammer.gesture has been detected
752
+ * to stop other Hammer.gestures from being fired
753
+ */
754
+ stopDetect: function stopDetect() {
755
+ // clone current data to the store as the previous gesture
756
+ // used for the double tap gesture, since this is an other gesture detect session
757
+ this.previous = Hammer.utils.extend({}, this.current);
758
+
759
+ // reset the current
760
+ this.current = null;
761
+
762
+ // stopped!
763
+ this.stopped = true;
764
+ },
765
+
766
+
767
+ /**
768
+ * extend eventData for Hammer.gestures
769
+ * @param {Object} ev
770
+ * @returns {Object} ev
771
+ */
772
+ extendEventData: function extendEventData(ev) {
773
+ var startEv = this.current.startEvent;
774
+
775
+ // if the touches change, set the new touches over the startEvent touches
776
+ // this because touchevents don't have all the touches on touchstart, or the
777
+ // user must place his fingers at the EXACT same time on the screen, which is not realistic
778
+ // but, sometimes it happens that both fingers are touching at the EXACT same time
779
+ if(startEv && (ev.touches.length != startEv.touches.length || ev.touches === startEv.touches)) {
780
+ // extend 1 level deep to get the touchlist with the touch objects
781
+ startEv.touches = [];
782
+ for(var i=0,len=ev.touches.length; i<len; i++) {
783
+ startEv.touches.push(Hammer.utils.extend({}, ev.touches[i]));
784
+ }
785
+ }
786
+
787
+ var delta_time = ev.timestamp - startEv.timestamp,
788
+ delta_x = ev.center.pageX - startEv.center.pageX,
789
+ delta_y = ev.center.pageY - startEv.center.pageY,
790
+ velocity = Hammer.utils.getVelocity(delta_time, delta_x, delta_y);
791
+
792
+ Hammer.utils.extend(ev, {
793
+ deltaTime : delta_time,
794
+
795
+ deltaX : delta_x,
796
+ deltaY : delta_y,
797
+
798
+ velocityX : velocity.x,
799
+ velocityY : velocity.y,
800
+
801
+ distance : Hammer.utils.getDistance(startEv.center, ev.center),
802
+ angle : Hammer.utils.getAngle(startEv.center, ev.center),
803
+ direction : Hammer.utils.getDirection(startEv.center, ev.center),
804
+
805
+ scale : Hammer.utils.getScale(startEv.touches, ev.touches),
806
+ rotation : Hammer.utils.getRotation(startEv.touches, ev.touches),
807
+
808
+ startEvent : startEv
809
+ });
810
+
811
+ return ev;
812
+ },
813
+
814
+
815
+ /**
816
+ * register new gesture
817
+ * @param {Object} gesture object, see gestures.js for documentation
818
+ * @returns {Array} gestures
819
+ */
820
+ register: function register(gesture) {
821
+ // add an enable gesture options if there is no given
822
+ var options = gesture.defaults || {};
823
+ if(typeof(options[gesture.name]) == 'undefined') {
824
+ options[gesture.name] = true;
825
+ }
826
+
827
+ // extend Hammer default options with the Hammer.gesture options
828
+ Hammer.utils.extend(Hammer.defaults, options);
829
+
830
+ // set its index
831
+ gesture.index = gesture.index || 1000;
832
+
833
+ // add Hammer.gesture to the list
834
+ this.gestures.push(gesture);
835
+
836
+ // sort the list by index
837
+ this.gestures.sort(function(a, b) {
838
+ if (a.index < b.index) {
839
+ return -1;
840
+ }
841
+ if (a.index > b.index) {
842
+ return 1;
843
+ }
844
+ return 0;
845
+ });
846
+
847
+ return this.gestures;
848
+ }
849
+ };
850
+
851
+
852
+ Hammer.gestures = Hammer.gestures || {};
853
+
854
+ /**
855
+ * Custom gestures
856
+ * ==============================
857
+ *
858
+ * Gesture object
859
+ * --------------------
860
+ * The object structure of a gesture:
861
+ *
862
+ * { name: 'mygesture',
863
+ * index: 1337,
864
+ * defaults: {
865
+ * mygesture_option: true
866
+ * }
867
+ * handler: function(type, ev, inst) {
868
+ * // trigger gesture event
869
+ * inst.trigger(this.name, ev);
870
+ * }
871
+ * }
872
+
873
+ * @param {String} name
874
+ * this should be the name of the gesture, lowercase
875
+ * it is also being used to disable/enable the gesture per instance config.
876
+ *
877
+ * @param {Number} [index=1000]
878
+ * the index of the gesture, where it is going to be in the stack of gestures detection
879
+ * like when you build an gesture that depends on the drag gesture, it is a good
880
+ * idea to place it after the index of the drag gesture.
881
+ *
882
+ * @param {Object} [defaults={}]
883
+ * the default settings of the gesture. these are added to the instance settings,
884
+ * and can be overruled per instance. you can also add the name of the gesture,
885
+ * but this is also added by default (and set to true).
886
+ *
887
+ * @param {Function} handler
888
+ * this handles the gesture detection of your custom gesture and receives the
889
+ * following arguments:
890
+ *
891
+ * @param {Object} eventData
892
+ * event data containing the following properties:
893
+ * timestamp {Number} time the event occurred
894
+ * target {HTMLElement} target element
895
+ * touches {Array} touches (fingers, pointers, mouse) on the screen
896
+ * pointerType {String} kind of pointer that was used. matches Hammer.POINTER_MOUSE|TOUCH
897
+ * center {Object} center position of the touches. contains pageX and pageY
898
+ * deltaTime {Number} the total time of the touches in the screen
899
+ * deltaX {Number} the delta on x axis we haved moved
900
+ * deltaY {Number} the delta on y axis we haved moved
901
+ * velocityX {Number} the velocity on the x
902
+ * velocityY {Number} the velocity on y
903
+ * angle {Number} the angle we are moving
904
+ * direction {String} the direction we are moving. matches Hammer.DIRECTION_UP|DOWN|LEFT|RIGHT
905
+ * distance {Number} the distance we haved moved
906
+ * scale {Number} scaling of the touches, needs 2 touches
907
+ * rotation {Number} rotation of the touches, needs 2 touches *
908
+ * eventType {String} matches Hammer.EVENT_START|MOVE|END
909
+ * srcEvent {Object} the source event, like TouchStart or MouseDown *
910
+ * startEvent {Object} contains the same properties as above,
911
+ * but from the first touch. this is used to calculate
912
+ * distances, deltaTime, scaling etc
913
+ *
914
+ * @param {Hammer.Instance} inst
915
+ * the instance we are doing the detection for. you can get the options from
916
+ * the inst.options object and trigger the gesture event by calling inst.trigger
917
+ *
918
+ *
919
+ * Handle gestures
920
+ * --------------------
921
+ * inside the handler you can get/set Hammer.detection.current. This is the current
922
+ * detection session. It has the following properties
923
+ * @param {String} name
924
+ * contains the name of the gesture we have detected. it has not a real function,
925
+ * only to check in other gestures if something is detected.
926
+ * like in the drag gesture we set it to 'drag' and in the swipe gesture we can
927
+ * check if the current gesture is 'drag' by accessing Hammer.detection.current.name
928
+ *
929
+ * @readonly
930
+ * @param {Hammer.Instance} inst
931
+ * the instance we do the detection for
932
+ *
933
+ * @readonly
934
+ * @param {Object} startEvent
935
+ * contains the properties of the first gesture detection in this session.
936
+ * Used for calculations about timing, distance, etc.
937
+ *
938
+ * @readonly
939
+ * @param {Object} lastEvent
940
+ * contains all the properties of the last gesture detect in this session.
941
+ *
942
+ * after the gesture detection session has been completed (user has released the screen)
943
+ * the Hammer.detection.current object is copied into Hammer.detection.previous,
944
+ * this is usefull for gestures like doubletap, where you need to know if the
945
+ * previous gesture was a tap
946
+ *
947
+ * options that have been set by the instance can be received by calling inst.options
948
+ *
949
+ * You can trigger a gesture event by calling inst.trigger("mygesture", event).
950
+ * The first param is the name of your gesture, the second the event argument
951
+ *
952
+ *
953
+ * Register gestures
954
+ * --------------------
955
+ * When an gesture is added to the Hammer.gestures object, it is auto registered
956
+ * at the setup of the first Hammer instance. You can also call Hammer.detection.register
957
+ * manually and pass your gesture object as a param
958
+ *
959
+ */
960
+
961
+ /**
962
+ * Hold
963
+ * Touch stays at the same place for x time
964
+ * @events hold
965
+ */
966
+ Hammer.gestures.Hold = {
967
+ name: 'hold',
968
+ index: 10,
969
+ defaults: {
970
+ hold_timeout: 500,
971
+ hold_threshold: 1
972
+ },
973
+ timer: null,
974
+ handler: function holdGesture(ev, inst) {
975
+ switch(ev.eventType) {
976
+ case Hammer.EVENT_START:
977
+ // clear any running timers
978
+ clearTimeout(this.timer);
979
+
980
+ // set the gesture so we can check in the timeout if it still is
981
+ Hammer.detection.current.name = this.name;
982
+
983
+ // set timer and if after the timeout it still is hold,
984
+ // we trigger the hold event
985
+ this.timer = setTimeout(function() {
986
+ if(Hammer.detection.current.name == 'hold') {
987
+ inst.trigger('hold', ev);
988
+ }
989
+ }, inst.options.hold_timeout);
990
+ break;
991
+
992
+ // when you move or end we clear the timer
993
+ case Hammer.EVENT_MOVE:
994
+ if(ev.distance > inst.options.hold_threshold) {
995
+ clearTimeout(this.timer);
996
+ }
997
+ break;
998
+
999
+ case Hammer.EVENT_END:
1000
+ clearTimeout(this.timer);
1001
+ break;
1002
+ }
1003
+ }
1004
+ };
1005
+
1006
+
1007
+ /**
1008
+ * Tap/DoubleTap
1009
+ * Quick touch at a place or double at the same place
1010
+ * @events tap, doubletap
1011
+ */
1012
+ Hammer.gestures.Tap = {
1013
+ name: 'tap',
1014
+ index: 100,
1015
+ defaults: {
1016
+ tap_max_touchtime : 250,
1017
+ tap_max_distance : 10,
1018
+ doubletap_distance : 20,
1019
+ doubletap_interval : 300
1020
+ },
1021
+ handler: function tapGesture(ev, inst) {
1022
+ if(ev.eventType == Hammer.EVENT_END) {
1023
+ // previous gesture, for the double tap since these are two different gesture detections
1024
+ var prev = Hammer.detection.previous;
1025
+
1026
+ // when the touchtime is higher then the max touch time
1027
+ // or when the moving distance is too much
1028
+ if(ev.deltaTime > inst.options.tap_max_touchtime ||
1029
+ ev.distance > inst.options.tap_max_distance) {
1030
+ return;
1031
+ }
1032
+
1033
+ // check if double tap
1034
+ if(prev && prev.name == 'tap' &&
1035
+ (ev.timestamp - prev.lastEvent.timestamp) < inst.options.doubletap_interval &&
1036
+ ev.distance < inst.options.doubletap_distance) {
1037
+ Hammer.detection.current.name = 'doubletap';
1038
+ }
1039
+ else {
1040
+ Hammer.detection.current.name = 'tap';
1041
+ }
1042
+
1043
+ inst.trigger(Hammer.detection.current.name, ev);
1044
+ }
1045
+ }
1046
+ };
1047
+
1048
+
1049
+ /**
1050
+ * Swipe
1051
+ * triggers swipe events when the end velocity is above the threshold
1052
+ * @events swipe, swipeleft, swiperight, swipeup, swipedown
1053
+ */
1054
+ Hammer.gestures.Swipe = {
1055
+ name: 'swipe',
1056
+ index: 40,
1057
+ defaults: {
1058
+ // set 0 for unlimited, but this can conflict with transform
1059
+ swipe_max_touches : 1,
1060
+ swipe_velocity : 0.7
1061
+ },
1062
+ handler: function swipeGesture(ev, inst) {
1063
+ if(ev.eventType == Hammer.EVENT_END) {
1064
+ // max touches
1065
+ if(inst.options.swipe_max_touches > 0 &&
1066
+ ev.touches.length > inst.options.swipe_max_touches) {
1067
+ return;
1068
+ }
1069
+
1070
+ // when the distance we moved is too small we skip this gesture
1071
+ // or we can be already in dragging
1072
+ if(ev.velocityX > inst.options.swipe_velocity ||
1073
+ ev.velocityY > inst.options.swipe_velocity) {
1074
+ // trigger swipe events
1075
+ inst.trigger(this.name, ev);
1076
+ inst.trigger(this.name + ev.direction, ev);
1077
+ }
1078
+ }
1079
+ }
1080
+ };
1081
+
1082
+
1083
+ /**
1084
+ * Drag
1085
+ * Move with x fingers (default 1) around on the page. Blocking the scrolling when
1086
+ * moving left and right is a good practice. When all the drag events are blocking
1087
+ * you disable scrolling on that area.
1088
+ * @events drag, drapleft, dragright, dragup, dragdown
1089
+ */
1090
+ Hammer.gestures.Drag = {
1091
+ name: 'drag',
1092
+ index: 50,
1093
+ defaults: {
1094
+ drag_min_distance : 10,
1095
+ // set 0 for unlimited, but this can conflict with transform
1096
+ drag_max_touches : 1,
1097
+ // prevent default browser behavior when dragging occurs
1098
+ // be careful with it, it makes the element a blocking element
1099
+ // when you are using the drag gesture, it is a good practice to set this true
1100
+ drag_block_horizontal : false,
1101
+ drag_block_vertical : false,
1102
+ // drag_lock_to_axis keeps the drag gesture on the axis that it started on,
1103
+ // It disallows vertical directions if the initial direction was horizontal, and vice versa.
1104
+ drag_lock_to_axis : false
1105
+ },
1106
+ triggered: false,
1107
+ handler: function dragGesture(ev, inst) {
1108
+ // current gesture isnt drag, but dragged is true
1109
+ // this means an other gesture is busy. now call dragend
1110
+ if(Hammer.detection.current.name != this.name && this.triggered) {
1111
+ inst.trigger(this.name +'end', ev);
1112
+ this.triggered = false;
1113
+ return;
1114
+ }
1115
+
1116
+ // max touches
1117
+ if(inst.options.drag_max_touches > 0 &&
1118
+ ev.touches.length > inst.options.drag_max_touches) {
1119
+ return;
1120
+ }
1121
+
1122
+ switch(ev.eventType) {
1123
+ case Hammer.EVENT_START:
1124
+ this.triggered = false;
1125
+ break;
1126
+
1127
+ case Hammer.EVENT_MOVE:
1128
+ // when the distance we moved is too small we skip this gesture
1129
+ // or we can be already in dragging
1130
+ if(ev.distance < inst.options.drag_min_distance &&
1131
+ Hammer.detection.current.name != this.name) {
1132
+ return;
1133
+ }
1134
+
1135
+ // we are dragging!
1136
+ Hammer.detection.current.name = this.name;
1137
+
1138
+ // lock drag to axis?
1139
+ var last_direction = Hammer.detection.current.lastEvent.direction;
1140
+ if(inst.options.drag_lock_to_axis && last_direction !== ev.direction) {
1141
+ // keep direction on the axis that the drag gesture started on
1142
+ if(Hammer.utils.isVertical(last_direction)) {
1143
+ ev.direction = (ev.deltaY < 0) ? Hammer.DIRECTION_UP : Hammer.DIRECTION_DOWN;
1144
+ }
1145
+ else {
1146
+ ev.direction = (ev.deltaX < 0) ? Hammer.DIRECTION_LEFT : Hammer.DIRECTION_RIGHT;
1147
+ }
1148
+ }
1149
+
1150
+ // first time, trigger dragstart event
1151
+ if(!this.triggered) {
1152
+ inst.trigger(this.name +'start', ev);
1153
+ this.triggered = true;
1154
+ }
1155
+
1156
+ // trigger normal event
1157
+ inst.trigger(this.name, ev);
1158
+
1159
+ // direction event, like dragdown
1160
+ inst.trigger(this.name + ev.direction, ev);
1161
+
1162
+ // block the browser events
1163
+ if( (inst.options.drag_block_vertical && Hammer.utils.isVertical(ev.direction)) ||
1164
+ (inst.options.drag_block_horizontal && !Hammer.utils.isVertical(ev.direction))) {
1165
+ ev.preventDefault();
1166
+ }
1167
+ break;
1168
+
1169
+ case Hammer.EVENT_END:
1170
+ // trigger dragend
1171
+ if(this.triggered) {
1172
+ inst.trigger(this.name +'end', ev);
1173
+ }
1174
+
1175
+ this.triggered = false;
1176
+ break;
1177
+ }
1178
+ }
1179
+ };
1180
+
1181
+
1182
+ /**
1183
+ * Transform
1184
+ * User want to scale or rotate with 2 fingers
1185
+ * @events transform, pinch, pinchin, pinchout, rotate
1186
+ */
1187
+ Hammer.gestures.Transform = {
1188
+ name: 'transform',
1189
+ index: 45,
1190
+ defaults: {
1191
+ // factor, no scale is 1, zoomin is to 0 and zoomout until higher then 1
1192
+ transform_min_scale : 0.01,
1193
+ // rotation in degrees
1194
+ transform_min_rotation : 1,
1195
+ // prevent default browser behavior when two touches are on the screen
1196
+ // but it makes the element a blocking element
1197
+ // when you are using the transform gesture, it is a good practice to set this true
1198
+ transform_always_block : false
1199
+ },
1200
+ triggered: false,
1201
+ handler: function transformGesture(ev, inst) {
1202
+ // current gesture isnt drag, but dragged is true
1203
+ // this means an other gesture is busy. now call dragend
1204
+ if(Hammer.detection.current.name != this.name && this.triggered) {
1205
+ inst.trigger(this.name +'end', ev);
1206
+ this.triggered = false;
1207
+ return;
1208
+ }
1209
+
1210
+ // atleast multitouch
1211
+ if(ev.touches.length < 2) {
1212
+ return;
1213
+ }
1214
+
1215
+ // prevent default when two fingers are on the screen
1216
+ if(inst.options.transform_always_block) {
1217
+ ev.preventDefault();
1218
+ }
1219
+
1220
+ switch(ev.eventType) {
1221
+ case Hammer.EVENT_START:
1222
+ this.triggered = false;
1223
+ break;
1224
+
1225
+ case Hammer.EVENT_MOVE:
1226
+ var scale_threshold = Math.abs(1-ev.scale);
1227
+ var rotation_threshold = Math.abs(ev.rotation);
1228
+
1229
+ // when the distance we moved is too small we skip this gesture
1230
+ // or we can be already in dragging
1231
+ if(scale_threshold < inst.options.transform_min_scale &&
1232
+ rotation_threshold < inst.options.transform_min_rotation) {
1233
+ return;
1234
+ }
1235
+
1236
+ // we are transforming!
1237
+ Hammer.detection.current.name = this.name;
1238
+
1239
+ // first time, trigger dragstart event
1240
+ if(!this.triggered) {
1241
+ inst.trigger(this.name +'start', ev);
1242
+ this.triggered = true;
1243
+ }
1244
+
1245
+ inst.trigger(this.name, ev); // basic transform event
1246
+
1247
+ // trigger rotate event
1248
+ if(rotation_threshold > inst.options.transform_min_rotation) {
1249
+ inst.trigger('rotate', ev);
1250
+ }
1251
+
1252
+ // trigger pinch event
1253
+ if(scale_threshold > inst.options.transform_min_scale) {
1254
+ inst.trigger('pinch', ev);
1255
+ inst.trigger('pinch'+ ((ev.scale < 1) ? 'in' : 'out'), ev);
1256
+ }
1257
+ break;
1258
+
1259
+ case Hammer.EVENT_END:
1260
+ // trigger dragend
1261
+ if(this.triggered) {
1262
+ inst.trigger(this.name +'end', ev);
1263
+ }
1264
+
1265
+ this.triggered = false;
1266
+ break;
1267
+ }
1268
+ }
1269
+ };
1270
+
1271
+
1272
+ /**
1273
+ * Touch
1274
+ * Called as first, tells the user has touched the screen
1275
+ * @events touch
1276
+ */
1277
+ Hammer.gestures.Touch = {
1278
+ name: 'touch',
1279
+ index: -Infinity,
1280
+ defaults: {
1281
+ // call preventDefault at touchstart, and makes the element blocking by
1282
+ // disabling the scrolling of the page, but it improves gestures like
1283
+ // transforming and dragging.
1284
+ // be careful with using this, it can be very annoying for users to be stuck
1285
+ // on the page
1286
+ prevent_default: false
1287
+ },
1288
+ handler: function touchGesture(ev, inst) {
1289
+ if(inst.options.prevent_default) {
1290
+ ev.preventDefault();
1291
+ }
1292
+
1293
+ if(ev.eventType == Hammer.EVENT_START) {
1294
+ inst.trigger(this.name, ev);
1295
+ }
1296
+ }
1297
+ };
1298
+
1299
+
1300
+ /**
1301
+ * Release
1302
+ * Called as last, tells the user has released the screen
1303
+ * @events release
1304
+ */
1305
+ Hammer.gestures.Release = {
1306
+ name: 'release',
1307
+ index: Infinity,
1308
+ handler: function releaseGesture(ev, inst) {
1309
+ if(ev.eventType == Hammer.EVENT_END) {
1310
+ inst.trigger(this.name, ev);
1311
+ }
1312
+ }
1313
+ };
1314
+
1315
+ // node export
1316
+ if(typeof module === 'object' && typeof module.exports === 'object'){
1317
+ module.exports = Hammer;
1318
+ }
1319
+ // just window export
1320
+ else {
1321
+ window.Hammer = Hammer;
1322
+
1323
+ // requireJS module definition
1324
+ if(typeof window.define === 'function' && window.define.amd) {
1325
+ window.define('hammer', [], function() {
1326
+ return Hammer;
1327
+ });
1328
+ }
1329
+ }
1330
+ })(this);