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 +4 -4
- data/README.md +24 -3
- data/lib/hammerjs/rails/version.rb +1 -1
- data/vendor/assets/javascripts/angular.hammer.js +611 -0
- data/vendor/assets/javascripts/angular.hammer.min.js +8 -0
- data/vendor/assets/javascripts/angular.hammer.min.js.map +1 -0
- data/vendor/assets/javascripts/hammer-time.js +179 -0
- data/vendor/assets/javascripts/hammer-time.min.js +1 -0
- data/vendor/assets/javascripts/hammer.js +2701 -2029
- data/vendor/assets/javascripts/hammer.min.js +6 -5
- data/vendor/assets/javascripts/hammer.min.js.map +1 -0
- data/vendor/assets/javascripts/hammer.min.map +1 -1
- data/vendor/assets/javascripts/touch-emulator.js +362 -0
- metadata +8 -3
- data/vendor/assets/javascripts/hammer.fakemultitouch.js +0 -81
- data/vendor/assets/javascripts/hammer.showtouches.js +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60cbf689d427f28c8443a8488749f0073bcdc507
|
4
|
+
data.tar.gz: e4a42dbacaff263b422bf89e985b4365df6d6869
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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://
|
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
|
-
|
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
|
@@ -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);
|