hammerjs-rails 2.0.6 → 2.0.8

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1d0f6a1f09711b6a340416c8ceba8dcb6e719272
4
- data.tar.gz: 985935288d286be2d13ab6401b333e0cfacb0ea8
3
+ metadata.gz: 60cbf689d427f28c8443a8488749f0073bcdc507
4
+ data.tar.gz: e4a42dbacaff263b422bf89e985b4365df6d6869
5
5
  SHA512:
6
- metadata.gz: d09d5dfcc07a0958cc7cc25e99416da0c6cd82686b0fd653111877d30ccc524fc530d1c9d0d0ccf7a627c8f204337a94c8e1771b04f21dff4709abf5ca7bb83f
7
- data.tar.gz: 94445121e4c04b33bd1cb541719df0c0e6bbac663b511f3e8b9aa3fb5843ae58f7a8fe01510e6cb87453aef94bc92c5747be62749e4861c46e03aabd2c66f430
6
+ metadata.gz: 70cdbc14231f2dd0e8ea7942c3e15d126755bd3ca17643c71dbcd87e6a6565e8f8c0fe7f121fb83387ac6f43d88167511cf7078801fe3233328c475d737d2930
7
+ data.tar.gz: cab5dc96e5d77b5cd34fb4f321354716ef8f93f384c2cd3bc15b49243286131138967f3a1d68e8977005943b694b2beb29c4fb0da9befe1d47d75b3658336e63
data/README.md CHANGED
@@ -1,7 +1,17 @@
1
1
  hammerjs-rails
2
2
  ==============
3
3
 
4
- [Hammer.js](http://eightmedia.github.io/hammer.js/) packaged for Rails assets pipeline
4
+ [Hammer.js](http://hammerjs.github.io/) packaged for Rails assets pipeline
5
+
6
+ ## Includes
7
+
8
+ - [Hammer.js](https://github.com/hammerjs/hammer.js/tree/master/)
9
+ - [Hammer.js jQuery Extension](http://hammerjs.github.io/jquery-plugin/)
10
+ - [Hammer.js Angular Extension](http://ryanmullins.github.io/angular-hammer/)
11
+ - [HammerTime](https://github.com/hammerjs/hammer-time)
12
+ - [TouchEmulator](https://github.com/hammerjs/touchemulator)
13
+
14
+ Plus source map files for Hammer.js & the Angular extension.
5
15
 
6
16
  ## Usage
7
17
 
@@ -11,10 +21,21 @@ Add this line to your application's Gemfile:
11
21
  gem 'hammerjs-rails'
12
22
  ```
13
23
 
14
- Add update your Javascript manifest file (application.js):
24
+ And choose what you'd like to add to your JavaScript manifest file (application.js):
15
25
 
16
26
  ```js
17
27
  //= require hammer
28
+ //= require hammer.min
29
+
30
+ //= require jquery.hammer
31
+
32
+ //= require angular.hammer
33
+ //= require angular.hammer.min
34
+
35
+ //= require hammer-time
36
+ //= require hammer-time.min
37
+
38
+ //= require touch-emulator
18
39
  ```
19
40
 
20
41
  ## Contributing
@@ -23,4 +44,4 @@ Add update your Javascript manifest file (application.js):
23
44
  2. Create your feature branch (`git checkout -b my-new-feature`)
24
45
  3. Commit your changes (`git commit -am 'Add some feature'`)
25
46
  4. Push to the branch (`git push origin my-new-feature`)
26
- 5. Create new Pull Request
47
+ 5. Create new Pull Request
@@ -1,5 +1,5 @@
1
1
  module Hammerjs
2
2
  module Rails
3
- VERSION = '2.0.6'
3
+ VERSION = '2.0.8'
4
4
  end
5
5
  end
@@ -0,0 +1,611 @@
1
+ // ---- Angular Hammer ----
2
+
3
+ // Copyright (c) 2015 Ryan S Mullins <ryan@ryanmullins.org>
4
+ // Licensed under the MIT Software License
5
+ //
6
+ // (fairly heavy) modifications by James Wilson <me@unbui.lt>
7
+ //
8
+
9
+ (function (angular, Hammer) {
10
+ 'use strict';
11
+
12
+ // Checking to make sure Hammer and Angular are defined
13
+
14
+ if (typeof angular === 'undefined') {
15
+ throw Error("angular-hammer: AngularJS (angular) is undefined but is necessary.");
16
+ }
17
+ if (typeof Hammer === 'undefined') {
18
+ throw Error("angular-hammer: HammerJS (Hammer) is undefined but is necessary.");
19
+ }
20
+
21
+ /**
22
+ * Mapping of the gesture event names with the Angular attribute directive
23
+ * names. Follows the form: <directiveName>:<eventName>.
24
+ *
25
+ * @type {Array}
26
+ */
27
+ var gestureTypes = [
28
+ 'hmCustom:custom',
29
+ 'hmSwipe:swipe',
30
+ 'hmSwipeleft:swipeleft',
31
+ 'hmSwiperight:swiperight',
32
+ 'hmSwipeup:swipeup',
33
+ 'hmSwipedown:swipedown',
34
+ 'hmPan:pan',
35
+ 'hmPanstart:panstart',
36
+ 'hmPanmove:panmove',
37
+ 'hmPanend:panend',
38
+ 'hmPancancel:pancancel',
39
+ 'hmPanleft:panleft',
40
+ 'hmPanright:panright',
41
+ 'hmPanup:panup',
42
+ 'hmPandown:pandown',
43
+ 'hmPress:press',
44
+ 'hmPressup:pressup',
45
+ 'hmRotate:rotate',
46
+ 'hmRotatestart:rotatestart',
47
+ 'hmRotatemove:rotatemove',
48
+ 'hmRotateend:rotateend',
49
+ 'hmRotatecancel:rotatecancel',
50
+ 'hmPinch:pinch',
51
+ 'hmPinchstart:pinchstart',
52
+ 'hmPinchmove:pinchmove',
53
+ 'hmPinchend:pinchend',
54
+ 'hmPinchcancel:pinchcancel',
55
+ 'hmPinchin:pinchin',
56
+ 'hmPinchout:pinchout',
57
+ 'hmTap:tap',
58
+ 'hmDoubletap:doubletap'
59
+ ];
60
+
61
+ // ---- Module Definition ----
62
+
63
+ /**
64
+ * @module hmTouchEvents
65
+ * @description Angular.js module for adding Hammer.js event listeners to HTML
66
+ * elements using attribute directives
67
+ * @requires angular
68
+ * @requires hammer
69
+ */
70
+ var NAME = 'hmTouchEvents';
71
+ var hmTouchEvents = angular.module('hmTouchEvents', []);
72
+
73
+ /**
74
+ * Provides a common interface for configuring global manager and recognizer
75
+ * options. Allows things like tap duration etc to be defaulted globally and
76
+ * overridden on a per-directive basis as needed.
77
+ *
78
+ * @return {Object} functions to add manager and recognizer options.
79
+ */
80
+ hmTouchEvents.provider(NAME, function(){
81
+
82
+ var self = this;
83
+ var defaultRecognizerOpts = false;
84
+ var recognizerOptsHash = {};
85
+ var managerOpts = {};
86
+
87
+ //
88
+ // In order to use the Hamme rpresets provided, we need
89
+ // to map the recognizer fn to some name:
90
+ //
91
+ var recognizerFnToName = {};
92
+ recognizerFnToName[ Hammer.Tap.toString() ] = "tap";
93
+ recognizerFnToName[ Hammer.Pan.toString() ] = "pan";
94
+ recognizerFnToName[ Hammer.Pinch.toString() ] = "pinch";
95
+ recognizerFnToName[ Hammer.Press.toString() ] = "press";
96
+ recognizerFnToName[ Hammer.Rotate.toString() ] = "rotate";
97
+ recognizerFnToName[ Hammer.Swipe.toString() ] = "swipe";
98
+
99
+ //
100
+ // normalize opts, setting its name as it should be keyed by
101
+ // and any must-have options. currently only doubletap is treated
102
+ // specially. each _name leads to a new recognizer.
103
+ //
104
+ function normalizeRecognizerOptions(opts){
105
+ opts = angular.copy(opts);
106
+
107
+ if(opts.event){
108
+
109
+ if(opts.event == "doubletap"){
110
+ opts.type = "tap";
111
+ if(!opts.taps) opts.taps = 2;
112
+ opts._name = "doubletap";
113
+ } else {
114
+ opts._name = false;
115
+ }
116
+
117
+ } else {
118
+ opts._name = opts.type || false;
119
+ }
120
+
121
+ return opts;
122
+ }
123
+ //
124
+ // create default opts for some eventName.
125
+ // again, treat doubletap specially.
126
+ //
127
+ function defaultOptionsForEvent(eventName){
128
+ if(eventName == "custom"){
129
+ throw Error(NAME+"Provider: no defaults exist for custom events");
130
+ }
131
+ var ty = getRecognizerTypeFromeventName(eventName);
132
+ return normalizeRecognizerOptions(
133
+ eventName == "doubletap"
134
+ ? {type:ty, event:"doubletap"}
135
+ : {type:ty}
136
+ );
137
+ }
138
+
139
+ //
140
+ // Make use of presets from Hammer.defaults.preset array
141
+ // in angular-hammer events.
142
+ //
143
+ self.applyHammerPresets = function(){
144
+ var hammerPresets = Hammer.defaults.preset;
145
+
146
+ //add every preset that, when normalized, has a _name.
147
+ //this precludes most custom events.
148
+ angular.forEach(hammerPresets, function(presetArr){
149
+
150
+ var data = presetArr[1];
151
+ if(!data.type) data.type = recognizerFnToName[presetArr[0]];
152
+ data = normalizeRecognizerOptions(data);
153
+ if(!data._name) return;
154
+ recognizerOptsHash[data._name] = data;
155
+ });
156
+ }
157
+
158
+ //
159
+ // Add a manager option (key/val to extend or object to set all):
160
+ //
161
+ self.addManagerOption = function(name, val){
162
+ if(typeof name == "object"){
163
+ angular.extend(managerOpts, name);
164
+ }
165
+ else {
166
+ managerOpts[name] = val;
167
+ }
168
+ }
169
+
170
+ //
171
+ // Add a recognizer option:
172
+ //
173
+ self.addRecognizerOption = function(val){
174
+ if(Array.isArray(val)){
175
+ for(var i = 0; i < val.length; i++) self.addRecognizerOption(val[i]);
176
+ return;
177
+ }
178
+ if(typeof val !== "object"){
179
+ throw Error(NAME+"Provider: addRecognizerOption: should be object or array of objects");
180
+ }
181
+ val = normalizeRecognizerOptions(val);
182
+
183
+ //hash by name if present, else if no event name,
184
+ //set as defaults.
185
+ if(val._name){
186
+ recognizerOptsHash[val.type] = val;
187
+ } else if(!val.event){
188
+ defaultRecognizerOpts = val;
189
+ }
190
+
191
+ }
192
+
193
+ //provide an interface to this that the hm-* directives use
194
+ //to extend their recognizer/manager opts.
195
+ self.$get = function(){
196
+ return {
197
+ extendWithDefaultManagerOpts: function(opts){
198
+ if(typeof opts != "object"){
199
+ opts = {};
200
+ } else {
201
+ opts = angular.copy(opts);
202
+ }
203
+ for(var name in managerOpts) {
204
+ if(!opts[name]) opts[name] = angular.copy(managerOpts[name]);
205
+ }
206
+ return opts;
207
+ },
208
+ extendWithDefaultRecognizerOpts: function(eventName, opts){
209
+ if(typeof opts !== "object"){
210
+ opts = [];
211
+ }
212
+ if(!Array.isArray(opts)){
213
+ opts = [opts];
214
+ }
215
+
216
+ //dont apply anything if this is custom event
217
+ //(beyond normalizing opts to an array):
218
+ if(eventName == "custom") return opts;
219
+
220
+ var recognizerType = getRecognizerTypeFromeventName(eventName);
221
+ var specificOpts = recognizerOptsHash[eventName] || recognizerOptsHash[recognizerType];
222
+
223
+ //get the last opt provided that matches the type or eventName
224
+ //that we have. normalizing removes any eventnames we dont care about
225
+ //(everything but doubletap at the moment).
226
+ var foundOpt;
227
+ var isExactMatch = false;
228
+ var defaults = angular.extend({}, defaultRecognizerOpts || {}, specificOpts || {});
229
+ opts.forEach(function(opt){
230
+
231
+ if(!opt.event && !opt.type){
232
+ return angular.extend(defaults, opt);
233
+ }
234
+ if(isExactMatch){
235
+ return;
236
+ }
237
+
238
+ //more specific wins over less specific.
239
+ if(opt.event == eventName){
240
+ foundOpt = opt;
241
+ isExactMatch = true;
242
+ } else if(!opt.event && opt.type == recognizerType){
243
+ foundOpt = opt;
244
+ }
245
+
246
+ });
247
+ if(!foundOpt) foundOpt = defaultOptionsForEvent(eventName);
248
+ else foundOpt = normalizeRecognizerOptions(foundOpt);
249
+
250
+
251
+ return [angular.extend(defaults, foundOpt)];
252
+ }
253
+ };
254
+ };
255
+
256
+ });
257
+
258
+ /**
259
+ * Iterates through each gesture type mapping and creates a directive for
260
+ * each of the
261
+ *
262
+ * @param {String} type Mapping in the form of <directiveName>:<eventName>
263
+ * @return None
264
+ */
265
+ angular.forEach(gestureTypes, function (type) {
266
+ var directive = type.split(':'),
267
+ directiveName = directive[0],
268
+ eventName = directive[1];
269
+
270
+ hmTouchEvents.directive(directiveName, ['$parse', '$window', NAME, function ($parse, $window, defaultEvents) {
271
+ return {
272
+ restrict: 'A',
273
+ scope: false,
274
+ link: function (scope, element, attrs) {
275
+
276
+ // Check for Hammer and required functionality.
277
+ // error if they arent found as unexpected behaviour otherwise
278
+ if (!Hammer || !$window.addEventListener) {
279
+ throw Error(NAME+": window.Hammer or window.addEventListener not found, can't add event "+directiveName);
280
+ }
281
+
282
+ var hammer = element.data('hammer'),
283
+ managerOpts = defaultEvents.extendWithDefaultManagerOpts( scope.$eval(attrs.hmManagerOptions) ),
284
+ recognizerOpts = defaultEvents.extendWithDefaultRecognizerOpts( eventName, scope.$eval(attrs.hmRecognizerOptions) );
285
+
286
+ // Check for a manager, make one if needed and destroy it when
287
+ // the scope is destroyed
288
+ if (!hammer) {
289
+ hammer = new Hammer.Manager(element[0], managerOpts);
290
+ element.data('hammer', hammer);
291
+ scope.$on('$destroy', function () {
292
+ hammer.destroy();
293
+ });
294
+ }
295
+
296
+ // Obtain and wrap our handler function to do a couple of bits for
297
+ // us if options provided.
298
+ var handlerExpr = $parse(attrs[directiveName]).bind(null,scope);
299
+ var handler = function (event) {
300
+ event.element = element;
301
+
302
+ // Default invokeApply to true, overridden by recognizer option
303
+ var invokeApply = true;
304
+
305
+ var recognizer = hammer.get(getRecognizerTypeFromeventName(event.type));
306
+ if (recognizer) {
307
+ var opts = recognizer.options;
308
+ if (opts.preventDefault) {
309
+ event.preventDefault();
310
+ }
311
+ if (opts.stopPropagation) {
312
+ event.srcEvent.stopPropagation();
313
+ }
314
+
315
+ invokeApply = angular.isUndefined(opts.invokeApply) || opts.invokeApply;
316
+ }
317
+
318
+ if (invokeApply) {
319
+ scope.$apply(function(){
320
+ handlerExpr({ '$event': event });
321
+ });
322
+ } else {
323
+ handlerExpr({ '$event': event });
324
+ }
325
+ };
326
+
327
+ // The recognizer options are normalized to an array. This array
328
+ // contains whatever events we wish to add (our prior extending
329
+ // takes care of that), but we do a couple of specific things
330
+ // depending on this directive so that events play nice together.
331
+ angular.forEach(recognizerOpts, function (options) {
332
+
333
+ if(eventName !== 'custom'){
334
+
335
+ if (eventName === 'doubletap' && hammer.get('tap')) {
336
+ options.recognizeWith = 'tap';
337
+ }
338
+ else if (options.type == "pan" && hammer.get('swipe')) {
339
+ options.recognizeWith = 'swipe';
340
+ }
341
+ else if (options.type == "pinch" && hammer.get('rotate')) {
342
+ options.recognizeWith = 'rotate';
343
+ }
344
+
345
+ }
346
+
347
+ //add the recognizer with these options:
348
+ setupRecognizerWithOptions(
349
+ hammer,
350
+ applyManagerOptions(managerOpts, options),
351
+ element
352
+ );
353
+
354
+ //if custom there may be multiple events to apply, which
355
+ //we do here. else, we'll only ever add one.
356
+ hammer.on(eventName, handler);
357
+
358
+ });
359
+
360
+ }
361
+ };
362
+ }]);
363
+ });
364
+
365
+ // ---- Private Functions -----
366
+
367
+ /**
368
+ * Adds a gesture recognizer to a given manager. The type of recognizer to
369
+ * add is determined by the value of the options.type property.
370
+ *
371
+ * @param {Object} manager Hammer.js manager object assigned to an element
372
+ * @param {String} type Options that define the recognizer to add
373
+ * @return {Object} Reference to the new gesture recognizer, if
374
+ * successful, null otherwise.
375
+ */
376
+ function addRecognizer (manager, name) {
377
+ if (manager === undefined || name === undefined) { return null; }
378
+
379
+ var recognizer;
380
+
381
+ if (name.indexOf('pan') > -1) {
382
+ recognizer = new Hammer.Pan();
383
+ } else if (name.indexOf('pinch') > -1) {
384
+ recognizer = new Hammer.Pinch();
385
+ } else if (name.indexOf('press') > -1) {
386
+ recognizer = new Hammer.Press();
387
+ } else if (name.indexOf('rotate') > -1) {
388
+ recognizer = new Hammer.Rotate();
389
+ } else if (name.indexOf('swipe') > -1) {
390
+ recognizer = new Hammer.Swipe();
391
+ } else {
392
+ recognizer = new Hammer.Tap();
393
+ }
394
+
395
+ manager.add(recognizer);
396
+ return recognizer;
397
+ }
398
+
399
+ /**
400
+ * Applies certain manager options to individual recognizer options.
401
+ *
402
+ * @param {Object} managerOpts Manager options
403
+ * @param {Object} recognizerOpts Recognizer options
404
+ * @return None
405
+ */
406
+ function applyManagerOptions (managerOpts, recognizerOpts) {
407
+ if (managerOpts) {
408
+ recognizerOpts.preventGhosts = managerOpts.preventGhosts;
409
+ }
410
+
411
+ return recognizerOpts;
412
+ }
413
+
414
+ /**
415
+ * Extracts the type of recognizer that should be instantiated from a given
416
+ * event name. Used only when no recognizer options are provided.
417
+ *
418
+ * @param {String} eventName Name to derive the recognizer type from
419
+ * @return {string} Type of recognizer that fires events with that name
420
+ */
421
+ function getRecognizerTypeFromeventName (eventName) {
422
+ if (eventName.indexOf('pan') > -1) {
423
+ return 'pan';
424
+ } else if (eventName.indexOf('pinch') > -1) {
425
+ return 'pinch';
426
+ } else if (eventName.indexOf('press') > -1) {
427
+ return 'press';
428
+ } else if (eventName.indexOf('rotate') > -1) {
429
+ return 'rotate';
430
+ } else if (eventName.indexOf('swipe') > -1) {
431
+ return 'swipe';
432
+ } else if (eventName.indexOf('tap') > -1) {
433
+ return 'tap';
434
+ } else {
435
+ return "custom";
436
+ }
437
+ }
438
+
439
+ /**
440
+ * Applies the passed options object to the appropriate gesture recognizer.
441
+ * Recognizers are created if they do not already exist. See the README for a
442
+ * description of the options object that can be passed to this function.
443
+ *
444
+ * @param {Object} manager Hammer.js manager object assigned to an element
445
+ * @param {Object} options Options applied to a recognizer managed by manager
446
+ * @return None
447
+ */
448
+ function setupRecognizerWithOptions (manager, options, element) {
449
+ if (manager == null || options == null || options.type == null) {
450
+ return console.error('ERROR: Angular Hammer could not setup the' +
451
+ ' recognizer. Values of the passed manager and options: ', manager, options);
452
+ }
453
+
454
+ var recognizer = manager.get(options._name);
455
+ if (!recognizer) {
456
+ recognizer = addRecognizer(manager, options._name);
457
+ }
458
+
459
+ if (!options.directions) {
460
+ if (options._name === 'pan' || options._name === 'swipe') {
461
+ options.directions = 'DIRECTION_ALL';
462
+ } else if (options._name.indexOf('left') > -1) {
463
+ options.directions = 'DIRECTION_LEFT';
464
+ } else if (options._name.indexOf('right') > -1) {
465
+ options.directions = 'DIRECTION_RIGHT';
466
+ } else if (options._name.indexOf('up') > -1) {
467
+ options.directions = 'DIRECTION_UP';
468
+ } else if (options._name.indexOf('down') > -1) {
469
+ options.directions = 'DIRECTION_DOWN';
470
+ } else {
471
+ options.directions = '';
472
+ }
473
+ }
474
+
475
+ options.direction = parseDirections(options.directions);
476
+ recognizer.set(options);
477
+
478
+ if (typeof options.recognizeWith === 'string') {
479
+ var recognizeWithRecognizer;
480
+
481
+ if (manager.get(options.recognizeWith) == null){
482
+ recognizeWithRecognizer = addRecognizer(manager, options.recognizeWith);
483
+ }
484
+
485
+ if (recognizeWithRecognizer != null) {
486
+ recognizer.recognizeWith(recognizeWithRecognizer);
487
+ }
488
+ }
489
+
490
+ if (typeof options.dropRecognizeWith === 'string' &&
491
+ manager.get(options.dropRecognizeWith) != null) {
492
+ recognizer.dropRecognizeWith(manager.get(options.dropRecognizeWith));
493
+ }
494
+
495
+ if (typeof options.requireFailure === 'string') {
496
+ var requireFailureRecognizer;
497
+
498
+ if (manager.get(options.requireFailure) == null){
499
+ requireFailureRecognizer = addRecognizer(manager, {type:options.requireFailure});
500
+ }
501
+
502
+ if (requireFailureRecognizer != null) {
503
+ recognizer.requireFailure(requireFailureRecognizer);
504
+ }
505
+ }
506
+
507
+ if (typeof options.dropRequireFailure === 'string' &&
508
+ manager.get(options.dropRequireFailure) != null) {
509
+ recognizer.dropRequireFailure(manager.get(options.dropRequireFailure));
510
+ }
511
+
512
+ if (options.preventGhosts === true && element != null) {
513
+ preventGhosts(element);
514
+ }
515
+ }
516
+
517
+ /**
518
+ * Parses the value of the directions property of any Angular Hammer options
519
+ * object and converts them into the standard Hammer.js directions values.
520
+ *
521
+ * @param {String} dirs Direction names separated by '|' characters
522
+ * @return {Number} Hammer.js direction value
523
+ */
524
+ function parseDirections (dirs) {
525
+ var directions = 0;
526
+
527
+ angular.forEach(dirs.split('|'), function (direction) {
528
+ if (Hammer.hasOwnProperty(direction)) {
529
+ directions = directions | Hammer[direction];
530
+ }
531
+ });
532
+
533
+ return directions;
534
+ }
535
+
536
+ // ---- Preventing Ghost Clicks ----
537
+
538
+ /**
539
+ * Modified from: https://gist.github.com/jtangelder/361052976f044200ea17
540
+ *
541
+ * Prevent click events after a touchend.
542
+ *
543
+ * Inspired/copy-paste from this article of Google by Ryan Fioravanti
544
+ * https://developers.google.com/mobile/articles/fast_buttons#ghost
545
+ */
546
+
547
+ function preventGhosts (element) {
548
+ if (!element) { return; }
549
+
550
+ var coordinates = [],
551
+ threshold = 25,
552
+ timeout = 2500;
553
+
554
+ if ('ontouchstart' in window) {
555
+ element[0].addEventListener('touchstart', resetCoordinates, true);
556
+ element[0].addEventListener('touchend', registerCoordinates, true);
557
+ element[0].addEventListener('click', preventGhostClick, true);
558
+ element[0].addEventListener('mouseup', preventGhostClick, true);
559
+ }
560
+
561
+ /**
562
+ * prevent clicks if they're in a registered XY region
563
+ * @param {MouseEvent} ev
564
+ */
565
+ function preventGhostClick (ev) {
566
+ for (var i = 0; i < coordinates.length; i++) {
567
+ var x = coordinates[i][0];
568
+ var y = coordinates[i][1];
569
+
570
+ // within the range, so prevent the click
571
+ if (Math.abs(ev.clientX - x) < threshold &&
572
+ Math.abs(ev.clientY - y) < threshold) {
573
+ ev.stopPropagation();
574
+ ev.preventDefault();
575
+ break;
576
+ }
577
+ }
578
+ }
579
+
580
+ /**
581
+ * reset the coordinates array
582
+ */
583
+ function resetCoordinates () {
584
+ coordinates = [];
585
+ }
586
+
587
+ /**
588
+ * remove the first coordinates set from the array
589
+ */
590
+ function popCoordinates () {
591
+ coordinates.splice(0, 1);
592
+ }
593
+
594
+ /**
595
+ * if it is an final touchend, we want to register it's place
596
+ * @param {TouchEvent} ev
597
+ */
598
+ function registerCoordinates (ev) {
599
+ // touchend is triggered on every releasing finger
600
+ // changed touches always contain the removed touches on a touchend
601
+ // the touches object might contain these also at some browsers (firefox os)
602
+ // so touches - changedTouches will be 0 or lower, like -1, on the final touchend
603
+ if(ev.touches.length - ev.changedTouches.length <= 0) {
604
+ var touch = ev.changedTouches[0];
605
+ coordinates.push([touch.clientX, touch.clientY]);
606
+
607
+ setTimeout(popCoordinates, timeout);
608
+ }
609
+ }
610
+ }
611
+ })(angular, Hammer);