fabric-rails 1.0.12 → 1.0.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/CHANGELOG.md +16 -0
  2. data/README.md +1 -1
  3. data/lib/fabric/rails/version.rb +2 -2
  4. data/vendor/assets/javascripts/event.js +1909 -0
  5. data/vendor/assets/javascripts/fabric.js +64 -16464
  6. data/vendor/assets/javascripts/fabric/HEADER.js +31 -0
  7. data/vendor/assets/javascripts/fabric/canvas.class.js +1007 -0
  8. data/vendor/assets/javascripts/fabric/canvas_animation.mixin.js +113 -0
  9. data/vendor/assets/javascripts/fabric/canvas_events.mixin.js +482 -0
  10. data/vendor/assets/javascripts/fabric/canvas_gestures.mixin.js +79 -0
  11. data/vendor/assets/javascripts/fabric/canvas_serialization.mixin.js +311 -0
  12. data/vendor/assets/javascripts/fabric/circle.class.js +182 -0
  13. data/vendor/assets/javascripts/fabric/color.class.js +284 -0
  14. data/vendor/assets/javascripts/fabric/ellipse.class.js +169 -0
  15. data/vendor/assets/javascripts/fabric/freedrawing.class.js +256 -0
  16. data/vendor/assets/javascripts/fabric/gradient.class.js +211 -0
  17. data/vendor/assets/javascripts/fabric/group.class.js +556 -0
  18. data/vendor/assets/javascripts/fabric/image.class.js +418 -0
  19. data/vendor/assets/javascripts/fabric/image_filters.js +809 -0
  20. data/vendor/assets/javascripts/fabric/intersection.class.js +178 -0
  21. data/vendor/assets/javascripts/fabric/line.class.js +188 -0
  22. data/vendor/assets/javascripts/fabric/log.js +26 -0
  23. data/vendor/assets/javascripts/fabric/node.js +149 -0
  24. data/vendor/assets/javascripts/fabric/object.class.js +1068 -0
  25. data/vendor/assets/javascripts/fabric/object_geometry.mixin.js +308 -0
  26. data/vendor/assets/javascripts/fabric/object_interactivity.mixin.js +496 -0
  27. data/vendor/assets/javascripts/fabric/object_origin.mixin.js +207 -0
  28. data/vendor/assets/javascripts/fabric/object_straightening.mixin.js +94 -0
  29. data/vendor/assets/javascripts/fabric/observable.mixin.js +91 -0
  30. data/vendor/assets/javascripts/fabric/parser.js +750 -0
  31. data/vendor/assets/javascripts/fabric/path.class.js +794 -0
  32. data/vendor/assets/javascripts/fabric/path_group.class.js +240 -0
  33. data/vendor/assets/javascripts/fabric/pattern.class.js +69 -0
  34. data/vendor/assets/javascripts/fabric/point.class.js +327 -0
  35. data/vendor/assets/javascripts/fabric/polygon.class.js +184 -0
  36. data/vendor/assets/javascripts/fabric/polyline.class.js +157 -0
  37. data/vendor/assets/javascripts/fabric/rect.class.js +298 -0
  38. data/vendor/assets/javascripts/fabric/scout.js +45 -0
  39. data/vendor/assets/javascripts/fabric/shadow.class.js +70 -0
  40. data/vendor/assets/javascripts/fabric/stateful.js +88 -0
  41. data/vendor/assets/javascripts/fabric/static_canvas.class.js +1298 -0
  42. data/vendor/assets/javascripts/fabric/text.class.js +934 -0
  43. data/vendor/assets/javascripts/fabric/triangle.class.js +108 -0
  44. data/vendor/assets/javascripts/fabric/util/anim_ease.js +360 -0
  45. data/vendor/assets/javascripts/fabric/util/dom_event.js +237 -0
  46. data/vendor/assets/javascripts/fabric/util/dom_misc.js +245 -0
  47. data/vendor/assets/javascripts/fabric/util/dom_request.js +72 -0
  48. data/vendor/assets/javascripts/fabric/util/dom_style.js +71 -0
  49. data/vendor/assets/javascripts/fabric/util/lang_array.js +250 -0
  50. data/vendor/assets/javascripts/fabric/util/lang_class.js +97 -0
  51. data/vendor/assets/javascripts/fabric/util/lang_function.js +35 -0
  52. data/vendor/assets/javascripts/fabric/util/lang_object.js +34 -0
  53. data/vendor/assets/javascripts/fabric/util/lang_string.js +60 -0
  54. data/vendor/assets/javascripts/fabric/util/misc.js +406 -0
  55. data/vendor/assets/javascripts/json2.js +491 -0
  56. metadata +53 -2
@@ -1,3 +1,11 @@
1
+ ## 1.0.12.1 (28 February 2013)
2
+
3
+ - now use fabric.js source files and compile as needed via sprockets
4
+
5
+ ## 1.0.12 (21 February 2013)
6
+
7
+ - fabric.js version 1.0.12
8
+
1
9
  ## 1.0.11 (19 February 2013)
2
10
 
3
11
  - fabric.js version 1.0.11
@@ -6,6 +14,14 @@
6
14
 
7
15
  - fabric.js version 1.0.10
8
16
 
17
+ ## 0.9.17 (19 February 2013)
18
+
19
+ - fabric.js version 0.9.17
20
+
21
+ ## 0.9.16 (19 February 2013)
22
+
23
+ - fabric.js version 0.9.16
24
+
9
25
  ## 0.0.8 (19 September 2012)
10
26
 
11
27
  - fabric.js version 0.9.8
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  This gem provides:
6
6
 
7
- * fabric.js 0.9.8
7
+ * fabric.js 1.0.12
8
8
 
9
9
  ## Installation
10
10
 
@@ -1,6 +1,6 @@
1
1
  module Fabric
2
2
  module Rails
3
- VERSION = "1.0.12"
4
- FABRIC_VERSION = "1.0.12"
3
+ VERSION = "1.0.12.1"
4
+ FABRIC_VERSION = "1.0.12.1"
5
5
  end
6
6
  end
@@ -0,0 +1,1909 @@
1
+ if (typeof document == 'undefined' && typeof navigator == 'undefined') {
2
+ var document = fabric.document;
3
+ var navigator = fabric.window.navigator;
4
+ }
5
+
6
+ /*
7
+ ----------------------------------------------------
8
+ Event.js : 1.1.1 : 2012/11/19 : MIT License
9
+ ----------------------------------------------------
10
+ https://github.com/mudcube/Event.js
11
+ ----------------------------------------------------
12
+ 1 : click, dblclick, dbltap
13
+ 1+ : tap, longpress, drag, swipe
14
+ 2+ : pinch, rotate
15
+ : mousewheel, devicemotion, shake
16
+ ----------------------------------------------------
17
+ TODO
18
+ ----------------------------------------------------
19
+ * switch configuration to 4th argument on addEventListener
20
+ * bbox calculation for elements scaled with transform.
21
+ ----------------------------------------------------
22
+ NOTES
23
+ ----------------------------------------------------
24
+ * When using other libraries that may have built in "Event" namespace,
25
+ i.e. Typescript, you can use "eventjs" instead of "Event" for all example calls.
26
+ ----------------------------------------------------
27
+ REQUIREMENTS: querySelector, querySelectorAll
28
+ ----------------------------------------------------
29
+ * There are two ways to add/remove events with this library.
30
+ ----------------------------------------------------
31
+ // Retains "this" attribute as target, and overrides native addEventListener.
32
+ target.addEventListener(type, listener, useCapture);
33
+ target.removeEventListener(type, listener, useCapture);
34
+
35
+ // Attempts to perform as fast as possible.
36
+ Event.add(type, listener, configure);
37
+ Event.remove(type, listener, configure);
38
+
39
+ * You can turn prototyping on/off for individual features.
40
+ ----------------------------------------------------
41
+ Event.modifyEventListener = true; // add custom *EventListener commands to HTMLElements.
42
+ Event.modifySelectors = true; // add bulk *EventListener commands on NodeLists from querySelectorAll and others.
43
+
44
+ * Example of setting up a single listener with a custom configuration.
45
+ ----------------------------------------------------
46
+ // optional configuration.
47
+ var configure = {
48
+ fingers: 2, // listen for specifically two fingers.
49
+ snap: 90 // snap to 90 degree intervals.
50
+ };
51
+ // adding with addEventListener()
52
+ target.addEventListener("swipe", function(event) {
53
+ // additional variables can be found on the event object.
54
+ console.log(event.velocity, event.angle, event.fingers);
55
+ }, configure);
56
+
57
+ // adding with Event.add()
58
+ Event.add("swipe", function(event, self) {
59
+ // additional variables can be found on the self object.
60
+ console.log(self.velocity, self.angle, self.fingers);
61
+ }, configure);
62
+
63
+ * Multiple listeners glued together.
64
+ ----------------------------------------------------
65
+ // adding with addEventListener()
66
+ target.addEventListener("click swipe", function(event) { });
67
+
68
+ // adding with Event.add()
69
+ Event.add(target, "click swipe", function(event, self) { });
70
+
71
+ * Use query selectors to create an event (querySelectorAll)
72
+ ----------------------------------------------------
73
+ // adding events to NodeList from querySelectorAll()
74
+ document.querySelectorAll("#element a.link").addEventListener("click", callback);
75
+
76
+ // adding with Event.add()
77
+ Event.add("#element a.link", "click", callback);
78
+
79
+ * Listen for selector to become available (querySelector)
80
+ ----------------------------------------------------
81
+ Event.add("body", "ready", callback);
82
+ // or...
83
+ Event.add({
84
+ target: "body",
85
+ type: "ready",
86
+ timeout: 10000, // set a timeout to stop checking.
87
+ interval: 30, // set how often to check for element.
88
+ listener: callback
89
+ });
90
+
91
+ * Multiple listeners bound to one callback w/ single configuration.
92
+ ----------------------------------------------------
93
+ var bindings = Event.add({
94
+ target: target,
95
+ type: "click swipe",
96
+ snap: 90, // snap to 90 degree intervals.
97
+ minFingers: 2, // minimum required fingers to start event.
98
+ maxFingers: 4, // maximum fingers in one event.
99
+ listener: function(event, self) {
100
+ console.log(self.gesture); // will be click or swipe.
101
+ console.log(self.x);
102
+ console.log(self.y);
103
+ console.log(self.identifier);
104
+ console.log(self.start);
105
+ console.log(self.fingers); // somewhere between "2" and "4".
106
+ self.pause(); // disable event.
107
+ self.resume(); // enable event.
108
+ self.remove(); // remove event.
109
+ }
110
+ });
111
+
112
+ * Multiple listeners bound to multiple callbacks w/ single configuration.
113
+ ----------------------------------------------------
114
+ var bindings = Event.add({
115
+ target: target,
116
+ minFingers: 1,
117
+ maxFingers: 12,
118
+ listeners: {
119
+ click: function(event, self) {
120
+ self.remove(); // removes this click listener.
121
+ },
122
+ swipe: function(event, self) {
123
+ binding.remove(); // removes both the click + swipe listeners.
124
+ }
125
+ }
126
+ });
127
+
128
+ * Multiple listeners bound to multiple callbacks w/ multiple configurations.
129
+ ----------------------------------------------------
130
+ var binding = Event.add({
131
+ target: target,
132
+ listeners: {
133
+ longpress: {
134
+ fingers: 1,
135
+ wait: 500, // milliseconds
136
+ listener: function(event, self) {
137
+ console.log(self.fingers); // "1" finger.
138
+ }
139
+ },
140
+ drag: {
141
+ fingers: 3,
142
+ position: "relative", // "relative", "absolute", "difference", "move"
143
+ listener: function(event, self) {
144
+ console.log(self.fingers); // "3" fingers.
145
+ console.log(self.x); // coordinate is relative to edge of target.
146
+ }
147
+ }
148
+ }
149
+ });
150
+
151
+ * Capturing an event and manually forwarding it to a proxy (tiered events).
152
+ ----------------------------------------------------
153
+ Event.add(target, "down", function(event, self) {
154
+ var x = event.pageX; // local variables that wont change.
155
+ var y = event.pageY;
156
+ Event.proxy.drag({
157
+ event: event,
158
+ target: target,
159
+ listener: function(event, self) {
160
+ console.log(x - event.pageX); // measure movement.
161
+ console.log(y - event.pageY);
162
+ }
163
+ });
164
+ });
165
+ ----------------------------------------------------
166
+
167
+ * Event proxies.
168
+ * type, fingers, state, start, x, y, position, bbox
169
+ * rotation, scale, velocity, angle, delay, timeout
170
+ ----------------------------------------------------
171
+ // "Click" :: fingers, minFingers, maxFingers.
172
+ Event.add(window, "click", function(event, self) {
173
+ console.log(self.gesture, self.x, self.y);
174
+ });
175
+ // "Double-Click" :: fingers, minFingers, maxFingers.
176
+ Event.add(window, "dblclick", function(event, self) {
177
+ console.log(self.gesture, self.x, self.y);
178
+ });
179
+ // "Drag" :: fingers, maxFingers, position
180
+ Event.add(window, "drag", function(event, self) {
181
+ console.log(self.gesture, self.fingers, self.state, self.start, self.x, self.y, self.bbox);
182
+ });
183
+ // "Gesture" :: fingers, minFingers, maxFingers.
184
+ Event.add(window, "gesture", function(event, self) {
185
+ console.log(self.gesture, self.fingers, self.state, self.rotation, self.scale);
186
+ });
187
+ // "Swipe" :: fingers, minFingers, maxFingers, snap, threshold.
188
+ Event.add(window, "swipe", function(event, self) {
189
+ console.log(self.gesture, self.fingers, self.velocity, self.angle, self.start, self.x, self.y);
190
+ });
191
+ // "Tap" :: fingers, minFingers, maxFingers, timeout.
192
+ Event.add(window, "tap", function(event, self) {
193
+ console.log(self.gesture, self.fingers);
194
+ });
195
+ // "Longpress" :: fingers, minFingers, maxFingers, delay.
196
+ Event.add(window, "longpress", function(event, self) {
197
+ console.log(self.gesture, self.fingers);
198
+ });
199
+ //
200
+ Event.add(window, "shake", function(event, self) {
201
+ console.log(self.gesture, self.acceleration, self.accelerationIncludingGravity);
202
+ });
203
+ //
204
+ Event.add(window, "devicemotion", function(event, self) {
205
+ console.log(self.gesture, self.acceleration, self.accelerationIncludingGravity);
206
+ });
207
+ //
208
+ Event.add(window, "wheel", function(event, self) {
209
+ console.log(self.gesture, self.state, self.wheelDelta);
210
+ });
211
+
212
+ * Stop, prevent and cancel.
213
+ ----------------------------------------------------
214
+ Event.stop(event); // stop bubble.
215
+ Event.prevent(event); // prevent default.
216
+ Event.cancel(event); // stop and prevent.
217
+
218
+ * Track for proper command/control-key for Mac/PC.
219
+ ----------------------------------------------------
220
+ Event.add(window, "keyup keydown", Event.proxy.metaTracker);
221
+ console.log(Event.proxy.metaKey);
222
+
223
+ * Test for event features, in this example Drag & Drop file support.
224
+ ----------------------------------------------------
225
+ console.log(Event.supports('dragstart') && Event.supports('drop') && !!window.FileReader);
226
+
227
+ */
228
+
229
+ if (typeof(Event) === "undefined")
230
+ var Event = {};
231
+ if (typeof(eventjs) === "undefined")
232
+ var eventjs = Event;
233
+
234
+ Event = (function(root) {
235
+ "use strict";
236
+
237
+ // Add custom *EventListener commands to HTMLElements.
238
+ root.modifyEventListener = false;
239
+
240
+ // Add bulk *EventListener commands on NodeLists from querySelectorAll and others.
241
+ root.modifySelectors = false;
242
+
243
+ // Event maintenance.
244
+ root.add = function(target, type, listener, configure) {
245
+ return eventManager(target, type, listener, configure, "add");
246
+ };
247
+
248
+ root.remove = function(target, type, listener, configure) {
249
+ return eventManager(target, type, listener, configure, "remove");
250
+ };
251
+
252
+ root.stop = function(event) {
253
+ if (event.stopPropagation)
254
+ event.stopPropagation();
255
+ event.cancelBubble = true; // <= IE8
256
+ event.bubble = 0;
257
+ };
258
+
259
+ root.prevent = function(event) {
260
+ if (event.preventDefault)
261
+ event.preventDefault();
262
+ event.returnValue = false; // <= IE8
263
+ };
264
+
265
+ root.cancel = function(event) {
266
+ root.stop(event);
267
+ root.prevent(event);
268
+ };
269
+
270
+ // Check whether event is natively supported (via @kangax)
271
+ root.supports = function(target, type) {
272
+ if (typeof(target) === "string") {
273
+ type = target;
274
+ target = window;
275
+ }
276
+ type = "on" + type;
277
+ if (type in target)
278
+ return true;
279
+ if (!target.setAttribute)
280
+ target = document.createElement("div");
281
+ if (target.setAttribute && target.removeAttribute) {
282
+ target.setAttribute(type, "");
283
+ var isSupported = typeof target[type] === "function";
284
+ if (typeof target[type] !== "undefined")
285
+ target[type] = null;
286
+ target.removeAttribute(type);
287
+ return isSupported;
288
+ }
289
+ };
290
+
291
+ var clone = function(obj) {
292
+ if (!obj || typeof (obj) !== 'object')
293
+ return obj;
294
+ var temp = new obj.constructor();
295
+ for (var key in obj) {
296
+ if (!obj[key] || typeof (obj[key]) !== 'object') {
297
+ temp[key] = obj[key];
298
+ } else { // clone sub-object
299
+ temp[key] = clone(obj[key]);
300
+ }
301
+ }
302
+ return temp;
303
+ };
304
+
305
+ /// Handle custom *EventListener commands.
306
+ var eventManager = function(target, type, listener, configure, trigger, fromOverwrite) {
307
+ configure = configure || {};
308
+ // Check for element to load on interval (before onload).
309
+ if (typeof(target) === "string" && type === "ready") {
310
+ var time = (new Date()).getTime();
311
+ var timeout = configure.timeout;
312
+ var ms = configure.interval || 1000 / 60;
313
+ var interval = window.setInterval(function() {
314
+ if ((new Date()).getTime() - time > timeout) {
315
+ window.clearInterval(interval);
316
+ }
317
+ if (document.querySelector(target)) {
318
+ window.clearInterval(interval);
319
+ listener();
320
+ }
321
+ }, ms);
322
+ return;
323
+ }
324
+ // Get DOM element from Query Selector.
325
+ if (typeof(target) === "string") {
326
+ target = document.querySelectorAll(target);
327
+ if (target.length === 0)
328
+ return createError("Missing target on listener!"); // No results.
329
+ if (target.length === 1) { // Single target.
330
+ target = target[0];
331
+ }
332
+ }
333
+ /// Handle multiple targets.
334
+ var event;
335
+ var events = {};
336
+ if (target.length > 0) {
337
+ for (var n0 = 0, length0 = target.length; n0 < length0; n0++) {
338
+ event = eventManager(target[n0], type, listener, clone(configure), trigger);
339
+ if (event)
340
+ events[n0] = event;
341
+ }
342
+ return createBatchCommands(events);
343
+ }
344
+ // Check for multiple events in one string.
345
+ if (type.indexOf && type.indexOf(" ") !== -1)
346
+ type = type.split(" ");
347
+ if (type.indexOf && type.indexOf(",") !== -1)
348
+ type = type.split(",");
349
+ // Attach or remove multiple events associated with a target.
350
+ if (typeof(type) !== "string") { // Has multiple events.
351
+ if (typeof(type.length) === "number") { // Handle multiple listeners glued together.
352
+ for (var n1 = 0, length1 = type.length; n1 < length1; n1++) { // Array [type]
353
+ event = eventManager(target, type[n1], listener, clone(configure), trigger);
354
+ if (event)
355
+ events[type[n1]] = event;
356
+ }
357
+ } else { // Handle multiple listeners.
358
+ for (var key in type) { // Object {type}
359
+ if (typeof(type[key]) === "function") { // without configuration.
360
+ event = eventManager(target, key, type[key], clone(configure), trigger);
361
+ } else { // with configuration.
362
+ event = eventManager(target, key, type[key].listener, clone(type[key]), trigger);
363
+ }
364
+ if (event)
365
+ events[key] = event;
366
+ }
367
+ }
368
+ return createBatchCommands(events);
369
+ }
370
+ // Ensure listener is a function.
371
+ if (typeof(listener) !== "function")
372
+ return createError("Listener is not a function!");
373
+ // Generate a unique wrapper identifier.
374
+ var useCapture = configure.useCapture || false;
375
+ var id = normalize(type) + getID(target) + "." + getID(listener) + "." + (useCapture ? 1 : 0);
376
+ // Handle the event.
377
+ if (root.Gesture && root.Gesture._gestureHandlers[type]) { // Fire custom event.
378
+ if (trigger === "remove") { // Remove event listener.
379
+ if (!wrappers[id])
380
+ return; // Already removed.
381
+ wrappers[id].remove();
382
+ delete wrappers[id];
383
+ } else if (trigger === "add") { // Attach event listener.
384
+ if (wrappers[id])
385
+ return wrappers[id]; // Already attached.
386
+ // Retains "this" orientation.
387
+ if (configure.useCall && !root.modifyEventListener) {
388
+ var tmp = listener;
389
+ listener = function(event, self) {
390
+ for (var key in self)
391
+ event[key] = self[key];
392
+ return tmp.call(target, event);
393
+ };
394
+ }
395
+ // Create listener proxy.
396
+ configure.gesture = type;
397
+ configure.target = target;
398
+ configure.listener = listener;
399
+ configure.fromOverwrite = fromOverwrite;
400
+ // Record wrapper.
401
+ wrappers[id] = root.proxy[type](configure);
402
+ }
403
+ } else { // Fire native event.
404
+ type = normalize(type);
405
+ if (trigger === "remove") { // Remove event listener.
406
+ if (!wrappers[id])
407
+ return; // Already removed.
408
+ target[remove](type, listener, useCapture);
409
+ delete wrappers[id];
410
+ } else if (trigger === "add") { // Attach event listener.
411
+ if (wrappers[id])
412
+ return wrappers[id]; // Already attached.
413
+ target[add](type, listener, useCapture);
414
+ // Record wrapper.
415
+ wrappers[id] = {
416
+ type: type,
417
+ target: target,
418
+ listener: listener,
419
+ remove: function() {
420
+ root.remove(target, type, listener, configure);
421
+ }
422
+ };
423
+ }
424
+ }
425
+ return wrappers[id];
426
+ };
427
+
428
+ /// Perform batch actions on multiple events.
429
+ var createBatchCommands = function(events) {
430
+ return {
431
+ remove: function() { // Remove multiple events.
432
+ for (var key in events) {
433
+ events[key].remove();
434
+ }
435
+ },
436
+ add: function() { // Add multiple events.
437
+ for (var key in events) {
438
+ events[key].add();
439
+ }
440
+ }
441
+ };
442
+ };
443
+
444
+ /// Display error message in console.
445
+ var createError = function(message) {
446
+ if (typeof(console) === "undefined")
447
+ return;
448
+ if (typeof(console.error) === "undefined")
449
+ return;
450
+ console.error(message);
451
+ };
452
+
453
+ /// Handle naming discrepancies between platforms.
454
+ var normalize = (function() {
455
+ var translate = {};
456
+ return function(type) {
457
+ if (!root.pointerType) {
458
+ if (window.navigator.msPointerEnabled) {
459
+ root.pointerType = "mspointer";
460
+ translate = {
461
+ "mousedown": "MSPointerDown",
462
+ "mousemove": "MSPointerMove",
463
+ "mouseup": "MSPointerUp"
464
+ };
465
+ } else if (root.supports("touchstart")) {
466
+ root.pointerType = "touch";
467
+ translate = {
468
+ "mousedown": "touchstart",
469
+ "mouseup": "touchend",
470
+ "mousemove": "touchmove"
471
+ };
472
+ } else {
473
+ root.pointerType = "mouse";
474
+ }
475
+ }
476
+ if (translate[type])
477
+ type = translate[type];
478
+ if (!document.addEventListener) { // IE
479
+ return "on" + type;
480
+ } else {
481
+ return type;
482
+ }
483
+ };
484
+ })();
485
+
486
+ /// Event wrappers to keep track of all events placed in the window.
487
+ var wrappers = {};
488
+ var counter = 0;
489
+ var getID = function(object) {
490
+ if (object === window)
491
+ return "#window";
492
+ if (object === document)
493
+ return "#document";
494
+ if (!object)
495
+ return createError("Missing target on listener!");
496
+ if (!object.uniqueID)
497
+ object.uniqueID = "id" + counter++;
498
+ return object.uniqueID;
499
+ };
500
+
501
+ /// Detect platforms native *EventListener command.
502
+ var add = document.addEventListener ? "addEventListener" : "attachEvent";
503
+ var remove = document.removeEventListener ? "removeEventListener" : "detachEvent";
504
+
505
+ /*
506
+ Pointer.js
507
+ ------------------------
508
+ Modified from; https://github.com/borismus/pointer.js
509
+ */
510
+
511
+ root.createPointerEvent = function(event, self, preventRecord) {
512
+ var eventName = self.gesture;
513
+ var target = self.target;
514
+ var pts = event.changedTouches || root.proxy.getCoords(event);
515
+ if (pts.length) {
516
+ var pt = pts[0];
517
+ self.pointers = preventRecord ? [] : pts;
518
+ self.pageX = pt.pageX;
519
+ self.pageY = pt.pageY;
520
+ self.x = self.pageX;
521
+ self.y = self.pageY;
522
+ }
523
+ ///
524
+ var newEvent = document.createEvent("Event");
525
+ newEvent.initEvent(eventName, true, true);
526
+ newEvent.originalEvent = event;
527
+ for (var k in self) {
528
+ if (k === "target")
529
+ continue;
530
+ newEvent[k] = self[k];
531
+ }
532
+ target.dispatchEvent(newEvent);
533
+ };
534
+
535
+ /// Allows *EventListener to use custom event proxies.
536
+ if (root.modifyEventListener && window.HTMLElement)
537
+ (function() {
538
+ var augmentEventListener = function(proto) {
539
+ var recall = function(trigger) { // overwrite native *EventListener's
540
+ var handle = trigger + "EventListener";
541
+ var handler = proto[handle];
542
+ proto[handle] = function(type, listener, useCapture) {
543
+ if (root.Gesture && root.Gesture._gestureHandlers[type]) { // capture custom events.
544
+ var configure = useCapture;
545
+ if (typeof(useCapture) === "object") {
546
+ configure.useCall = true;
547
+ } else { // convert to configuration object.
548
+ configure = {
549
+ useCall: true,
550
+ useCapture: useCapture
551
+ };
552
+ }
553
+ eventManager(this, type, listener, configure, trigger, true);
554
+ handler.call(this, type, listener, useCapture);
555
+ } else { // use native function.
556
+ handler.call(this, normalize(type), listener, useCapture);
557
+ }
558
+ };
559
+ };
560
+ recall("add");
561
+ recall("remove");
562
+ };
563
+ // NOTE: overwriting HTMLElement doesn't do anything in Firefox.
564
+ if (navigator.userAgent.match(/Firefox/)) {
565
+ // TODO: fix Firefox for the general case.
566
+ augmentEventListener(HTMLDivElement.prototype);
567
+ augmentEventListener(HTMLCanvasElement.prototype);
568
+ } else {
569
+ augmentEventListener(HTMLElement.prototype);
570
+ }
571
+ augmentEventListener(document);
572
+ augmentEventListener(window);
573
+ })();
574
+
575
+ /// Allows querySelectorAll and other NodeLists to perform *EventListener commands in bulk.
576
+ if (root.modifySelectors)
577
+ (function() {
578
+ var proto = NodeList.prototype;
579
+ proto.removeEventListener = function(type, listener, useCapture) {
580
+ for (var n = 0, length = this.length; n < length; n++) {
581
+ this[n].removeEventListener(type, listener, useCapture);
582
+ }
583
+ };
584
+ proto.addEventListener = function(type, listener, useCapture) {
585
+ for (var n = 0, length = this.length; n < length; n++) {
586
+ this[n].addEventListener(type, listener, useCapture);
587
+ }
588
+ };
589
+ })();
590
+
591
+ return root;
592
+
593
+ })(Event);
594
+ /*
595
+ ----------------------------------------------------
596
+ Event.proxy : 0.4.2 : 2012/07/29 : MIT License
597
+ ----------------------------------------------------
598
+ https://github.com/mudcube/Event.js
599
+ ----------------------------------------------------
600
+ Pointer Gestures
601
+ ----------------------------------------------------
602
+ 1 : click, dblclick, dbltap
603
+ 1+ : tap, taphold, drag, swipe
604
+ 2+ : pinch, rotate
605
+ ----------------------------------------------------
606
+ Gyroscope Gestures
607
+ ----------------------------------------------------
608
+ * shake
609
+ ----------------------------------------------------
610
+ Fixes issues with
611
+ ----------------------------------------------------
612
+ * mousewheel-Firefox uses DOMMouseScroll and does not return wheelDelta.
613
+ * devicemotion-Fixes issue where event.acceleration is not returned.
614
+ ----------------------------------------------------
615
+ Ideas for the future
616
+ ----------------------------------------------------
617
+ * Keyboard, GamePad, and other input abstractions.
618
+ * Event batching - i.e. for every x fingers down a new gesture is created.
619
+ */
620
+
621
+ if (typeof(Event) === "undefined")
622
+ var Event = {};
623
+ if (typeof(Event.proxy) === "undefined")
624
+ Event.proxy = {};
625
+
626
+ Event.proxy = (function(root) {
627
+ "use strict";
628
+
629
+ /*
630
+ Create a new pointer gesture instance.
631
+ */
632
+
633
+ root.pointerSetup = function(conf, self) {
634
+ /// Configure.
635
+ conf.doc = conf.target.ownerDocument || conf.target; // Associated document.
636
+ conf.minFingers = conf.minFingers || conf.fingers || 1; // Minimum required fingers.
637
+ conf.maxFingers = conf.maxFingers || conf.fingers || Infinity; // Maximum allowed fingers.
638
+ conf.position = conf.position || "relative"; // Determines what coordinate system points are returned.
639
+ delete conf.fingers; //-
640
+ /// Convenience data.
641
+ self = self || {};
642
+ self.gesture = conf.gesture;
643
+ self.target = conf.target;
644
+ self.pointerType = Event.pointerType;
645
+ ///
646
+ if (Event.modifyEventListener && conf.fromOverwrite)
647
+ conf.listener = Event.createPointerEvent;
648
+ /// Convenience commands.
649
+ var fingers = 0;
650
+ var type = self.gesture.indexOf("pointer") === 0 && Event.modifyEventListener ? "pointer" : "mouse";
651
+ self.listener = conf.listener;
652
+ self.proxy = function(listener) {
653
+ self.defaultListener = conf.listener;
654
+ conf.listener = listener;
655
+ listener(conf.event, self);
656
+ };
657
+ self.remove = function() {
658
+ if (conf.onPointerDown)
659
+ Event.remove(conf.target, type + "down", conf.onPointerDown);
660
+ if (conf.onPointerMove)
661
+ Event.remove(conf.doc, type + "move", conf.onPointerMove);
662
+ if (conf.onPointerUp)
663
+ Event.remove(conf.doc, type + "up", conf.onPointerUp);
664
+ };
665
+ self.resume = function(opt) {
666
+ if (conf.onPointerMove && (!opt || opt.move))
667
+ Event.add(conf.doc, type + "move", conf.onPointerMove);
668
+ if (conf.onPointerUp && (!opt || opt.move))
669
+ Event.add(conf.doc, type + "up", conf.onPointerUp);
670
+ conf.fingers = fingers;
671
+ };
672
+ self.pause = function(opt) {
673
+ fingers = conf.fingers;
674
+ if (conf.onPointerMove && (!opt || opt.move))
675
+ Event.remove(conf.doc, type + "move", conf.onPointerMove);
676
+ if (conf.onPointerUp && (!opt || opt.up))
677
+ Event.remove(conf.doc, type + "up", conf.onPointerUp);
678
+ conf.fingers = 0;
679
+ };
680
+ ///
681
+ return self;
682
+ };
683
+
684
+ /*
685
+ Begin proxied pointer command.
686
+ */
687
+
688
+ root.pointerStart = function(event, self, conf) {
689
+ var addTouchStart = function(touch, sid) {
690
+ var bbox = conf.bbox;
691
+ var pt = track[sid] = {};
692
+ ///
693
+ switch (conf.position) {
694
+ case "absolute": // Absolute from within window.
695
+ pt.offsetX = 0;
696
+ pt.offsetY = 0;
697
+ break;
698
+ case "difference": // Relative from origin.
699
+ pt.offsetX = touch.pageX;
700
+ pt.offsetY = touch.pageY;
701
+ break;
702
+ case "move": // Move target element.
703
+ pt.offsetX = touch.pageX - bbox.x1;
704
+ pt.offsetY = touch.pageY - bbox.y1;
705
+ break;
706
+ default: // Relative from within target.
707
+ pt.offsetX = bbox.x1;
708
+ pt.offsetY = bbox.y1;
709
+ break;
710
+ }
711
+ ///
712
+ if (conf.position === "relative") {
713
+ var x = (touch.pageX + bbox.scrollLeft - pt.offsetX) * bbox.scaleX;
714
+ var y = (touch.pageY + bbox.scrollTop - pt.offsetY) * bbox.scaleY;
715
+ } else {
716
+ var x = (touch.pageX - pt.offsetX);
717
+ var y = (touch.pageY - pt.offsetY);
718
+ }
719
+ ///
720
+ pt.rotation = 0;
721
+ pt.scale = 1;
722
+ pt.startTime = pt.moveTime = (new Date).getTime();
723
+ pt.move = {x: x, y: y};
724
+ pt.start = {x: x, y: y};
725
+ ///
726
+ conf.fingers++;
727
+ };
728
+ ///
729
+ conf.event = event;
730
+ if (self.defaultListener) {
731
+ conf.listener = self.defaultListener;
732
+ delete self.defaultListener;
733
+ }
734
+ ///
735
+ var isTouchStart = !conf.fingers;
736
+ var track = conf.tracker;
737
+ var touches = event.changedTouches || root.getCoords(event);
738
+ var length = touches.length;
739
+ // Adding touch events to tracking.
740
+ for (var i = 0; i < length; i++) {
741
+ var touch = touches[i];
742
+ var sid = touch.identifier || Infinity; // Touch ID.
743
+ // Track the current state of the touches.
744
+ if (conf.fingers) {
745
+ if (conf.fingers >= conf.maxFingers) {
746
+ var ids = [];
747
+ for (var sid in conf.tracker)
748
+ ids.push(sid);
749
+ self.identifier = ids.join(",");
750
+ return isTouchStart;
751
+ }
752
+ var fingers = 0; // Finger ID.
753
+ for (var rid in track) {
754
+ // Replace removed finger.
755
+ if (track[rid].up) {
756
+ delete track[rid];
757
+ addTouchStart(touch, sid);
758
+ conf.cancel = true;
759
+ break;
760
+ }
761
+ fingers++;
762
+ }
763
+ // Add additional finger.
764
+ if (track[sid])
765
+ continue;
766
+ addTouchStart(touch, sid);
767
+ } else { // Start tracking fingers.
768
+ track = conf.tracker = {};
769
+ self.bbox = conf.bbox = root.getBoundingBox(conf.target);
770
+ conf.fingers = 0;
771
+ conf.cancel = false;
772
+ addTouchStart(touch, sid);
773
+ }
774
+ }
775
+ ///
776
+ var ids = [];
777
+ for (var sid in conf.tracker)
778
+ ids.push(sid);
779
+ self.identifier = ids.join(",");
780
+ ///
781
+ return isTouchStart;
782
+ };
783
+
784
+ /*
785
+ End proxied pointer command.
786
+ */
787
+
788
+ root.pointerEnd = function(event, self, conf, onPointerUp) {
789
+ // Record changed touches have ended (iOS changedTouches is not reliable).
790
+ var touches = event.touches || [];
791
+ var length = touches.length;
792
+ var exists = {};
793
+ for (var i = 0; i < length; i++) {
794
+ var touch = touches[i];
795
+ var sid = touch.identifier;
796
+ exists[sid || Infinity] = true;
797
+ }
798
+ for (var sid in conf.tracker) {
799
+ var track = conf.tracker[sid];
800
+ if (exists[sid] || track.up)
801
+ continue;
802
+ if (onPointerUp) { // add changedTouches to mouse.
803
+ onPointerUp({
804
+ pageX: track.pageX,
805
+ pageY: track.pageY,
806
+ changedTouches: [{
807
+ pageX: track.pageX,
808
+ pageY: track.pageY,
809
+ identifier: sid === "Infinity" ? Infinity : sid
810
+ }]
811
+ }, "up");
812
+ }
813
+ track.up = true;
814
+ conf.fingers--;
815
+ }
816
+ /* // This should work but fails in Safari on iOS4 so not using it.
817
+ var touches = event.changedTouches || root.getCoords(event);
818
+ var length = touches.length;
819
+ // Record changed touches have ended (this should work).
820
+ for (var i = 0; i < length; i ++) {
821
+ var touch = touches[i];
822
+ var sid = touch.identifier || Infinity;
823
+ var track = conf.tracker[sid];
824
+ if (track && !track.up) {
825
+ if (onPointerUp) { // add changedTouches to mouse.
826
+ onPointerUp({
827
+ changedTouches: [{
828
+ pageX: track.pageX,
829
+ pageY: track.pageY,
830
+ identifier: sid === "Infinity" ? Infinity : sid
831
+ }]
832
+ }, "up");
833
+ }
834
+ track.up = true;
835
+ conf.fingers --;
836
+ }
837
+ } */
838
+ // Wait for all fingers to be released.
839
+ if (conf.fingers !== 0)
840
+ return false;
841
+ // Record total number of fingers gesture used.
842
+ var ids = [];
843
+ conf.gestureFingers = 0;
844
+ for (var sid in conf.tracker) {
845
+ conf.gestureFingers++;
846
+ ids.push(sid);
847
+ }
848
+ self.identifier = ids.join(",");
849
+ // Our pointer gesture has ended.
850
+ return true;
851
+ };
852
+
853
+ /*
854
+ Returns mouse coords in an array to match event.*Touches
855
+ ------------------------------------------------------------
856
+ var touch = event.changedTouches || root.getCoords(event);
857
+ */
858
+
859
+ root.getCoords = function(event) {
860
+ if (typeof(event.pageX) !== "undefined") { // Desktop browsers.
861
+ root.getCoords = function(event) {
862
+ return Array({
863
+ type: "mouse",
864
+ x: event.pageX,
865
+ y: event.pageY,
866
+ pageX: event.pageX,
867
+ pageY: event.pageY,
868
+ identifier: Infinity
869
+ });
870
+ };
871
+ } else { // Internet Explorer <= 8.0
872
+ root.getCoords = function(event) {
873
+ event = event || window.event;
874
+ return Array({
875
+ type: "mouse",
876
+ x: event.clientX + document.documentElement.scrollLeft,
877
+ y: event.clientY + document.documentElement.scrollTop,
878
+ pageX: event.clientX + document.documentElement.scrollLeft,
879
+ pageY: event.clientY + document.documentElement.scrollTop,
880
+ identifier: Infinity
881
+ });
882
+ };
883
+ }
884
+ return root.getCoords(event);
885
+ };
886
+
887
+ /*
888
+ Returns single coords in an object.
889
+ ------------------------------------------------------------
890
+ var mouse = root.getCoord(event);
891
+ */
892
+
893
+ root.getCoord = function(event) {
894
+ if ("ontouchstart" in window) { // Mobile browsers.
895
+ var pX = 0;
896
+ var pY = 0;
897
+ root.getCoord = function(event) {
898
+ var touches = event.changedTouches;
899
+ if (touches.length) { // ontouchstart + ontouchmove
900
+ return {
901
+ x: pX = touches[0].pageX,
902
+ y: pY = touches[0].pageY
903
+ };
904
+ } else { // ontouchend
905
+ return {
906
+ x: pX,
907
+ y: pY
908
+ };
909
+ }
910
+ };
911
+ } else if (typeof(event.pageX) !== "undefined" && typeof(event.pageY) !== "undefined") { // Desktop browsers.
912
+ root.getCoord = function(event) {
913
+ return {
914
+ x: event.pageX,
915
+ y: event.pageY
916
+ };
917
+ };
918
+ } else { // Internet Explorer <=8.0
919
+ root.getCoord = function(event) {
920
+ event = event || window.event;
921
+ return {
922
+ x: event.clientX + document.documentElement.scrollLeft,
923
+ y: event.clientY + document.documentElement.scrollTop
924
+ };
925
+ };
926
+ }
927
+ return root.getCoord(event);
928
+ };
929
+
930
+ /*
931
+ Get target scale and position in space.
932
+ */
933
+
934
+ root.getBoundingBox = function(o) {
935
+ if (o === window || o === document)
936
+ o = document.body;
937
+ ///
938
+ var bbox = {
939
+ x1: 0,
940
+ y1: 0,
941
+ x2: 0,
942
+ y2: 0,
943
+ scrollLeft: 0,
944
+ scrollTop: 0
945
+ };
946
+ ///
947
+ if (o === document.body) {
948
+ bbox.height = window.innerHeight;
949
+ bbox.width = window.innerWidth;
950
+ } else {
951
+ bbox.height = o.offsetHeight;
952
+ bbox.width = o.offsetWidth;
953
+ }
954
+ /// Get the scale of the element.
955
+ bbox.scaleX = o.width / bbox.width || 1;
956
+ bbox.scaleY = o.height / bbox.height || 1;
957
+ /// Get the offset of element.
958
+ var tmp = o;
959
+ while (tmp !== null) {
960
+ bbox.x1 += tmp.offsetLeft;
961
+ bbox.y1 += tmp.offsetTop;
962
+ tmp = tmp.offsetParent;
963
+ }
964
+ ;
965
+ /// Get the scroll of container element.
966
+ var tmp = o.parentNode;
967
+ while (tmp !== null) {
968
+ if (tmp === document.body)
969
+ break;
970
+ if (tmp.scrollTop === undefined)
971
+ break;
972
+ bbox.scrollLeft += tmp.scrollLeft;
973
+ bbox.scrollTop += tmp.scrollTop;
974
+ tmp = tmp.parentNode;
975
+ }
976
+ ;
977
+ /// Record the extent of box.
978
+ bbox.x2 = bbox.x1 + bbox.width;
979
+ bbox.y2 = bbox.y1 + bbox.height;
980
+ ///
981
+ return bbox;
982
+ };
983
+
984
+ /*
985
+ Keep track of metaKey, the proper ctrlKey for users platform.
986
+ */
987
+
988
+ (function() {
989
+ var agent = navigator.userAgent.toLowerCase();
990
+ var mac = agent.indexOf("macintosh") !== -1;
991
+ if (mac && agent.indexOf("khtml") !== -1) { // chrome, safari.
992
+ var watch = {91: true, 93: true};
993
+ } else if (mac && agent.indexOf("firefox") !== -1) { // mac firefox.
994
+ var watch = {224: true};
995
+ } else { // windows, linux, or mac opera.
996
+ var watch = {17: true};
997
+ }
998
+ root.isMetaKey = function(event) {
999
+ return !!watch[event.keyCode];
1000
+ };
1001
+ root.metaTracker = function(event) {
1002
+ if (watch[event.keyCode]) {
1003
+ root.metaKey = event.type === "keydown";
1004
+ }
1005
+ };
1006
+ })();
1007
+
1008
+ return root;
1009
+
1010
+ })(Event.proxy);
1011
+ /*
1012
+ "Click" event proxy.
1013
+ ----------------------------------------------------
1014
+ Event.add(window, "click", function(event, self) {});
1015
+ */
1016
+
1017
+ if (typeof(Event) === "undefined")
1018
+ var Event = {};
1019
+ if (typeof(Event.proxy) === "undefined")
1020
+ Event.proxy = {};
1021
+
1022
+ Event.proxy = (function(root) {
1023
+ "use strict";
1024
+
1025
+ root.click = function(conf) {
1026
+ conf.maxFingers = conf.maxFingers || conf.fingers || 1;
1027
+ // Setting up local variables.
1028
+ var EVENT;
1029
+ // Tracking the events.
1030
+ conf.onPointerDown = function(event) {
1031
+ if (root.pointerStart(event, self, conf)) {
1032
+ Event.add(conf.doc, "mousemove", conf.onPointerMove).listener(event);
1033
+ Event.add(conf.doc, "mouseup", conf.onPointerUp);
1034
+ }
1035
+ };
1036
+ conf.onPointerMove = function(event) {
1037
+ EVENT = event;
1038
+ };
1039
+ conf.onPointerUp = function(event) {
1040
+ if (root.pointerEnd(event, self, conf)) {
1041
+ Event.remove(conf.doc, "mousemove", conf.onPointerMove);
1042
+ Event.remove(conf.doc, "mouseup", conf.onPointerUp);
1043
+ if (EVENT.cancelBubble && ++EVENT.bubble > 1)
1044
+ return;
1045
+ var pointers = EVENT.changedTouches || root.getCoords(EVENT);
1046
+ var pointer = pointers[0];
1047
+ var bbox = conf.bbox;
1048
+ var newbbox = root.getBoundingBox(conf.target);
1049
+ if (conf.position === "relative") {
1050
+ var ax = (pointer.pageX + bbox.scrollLeft - bbox.x1) * bbox.scaleX;
1051
+ var ay = (pointer.pageY + bbox.scrollTop - bbox.y1) * bbox.scaleY;
1052
+ } else {
1053
+ var ax = (pointer.pageX - bbox.x1);
1054
+ var ay = (pointer.pageY - bbox.y1);
1055
+ }
1056
+ if (ax > 0 && ax < bbox.width && // Within target coordinates.
1057
+ ay > 0 && ay < bbox.height &&
1058
+ bbox.scrollTop === newbbox.scrollTop) {
1059
+ conf.listener(EVENT, self);
1060
+ }
1061
+ }
1062
+ };
1063
+ // Generate maintenance commands, and other configurations.
1064
+ var self = root.pointerSetup(conf);
1065
+ self.state = "click";
1066
+ // Attach events.
1067
+ Event.add(conf.target, "mousedown", conf.onPointerDown);
1068
+ // Return this object.
1069
+ return self;
1070
+ };
1071
+
1072
+ Event.Gesture = Event.Gesture || {};
1073
+ Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {};
1074
+ Event.Gesture._gestureHandlers.click = root.click;
1075
+
1076
+ return root;
1077
+
1078
+ })(Event.proxy);
1079
+ /*
1080
+ "Double-Click" aka "Double-Tap" event proxy.
1081
+ ----------------------------------------------------
1082
+ Event.add(window, "dblclick", function(event, self) {});
1083
+ ----------------------------------------------------
1084
+ Touch an target twice for <= 700ms, with less than 25 pixel drift.
1085
+ */
1086
+
1087
+ if (typeof(Event) === "undefined")
1088
+ var Event = {};
1089
+ if (typeof(Event.proxy) === "undefined")
1090
+ Event.proxy = {};
1091
+
1092
+ Event.proxy = (function(root) {
1093
+ "use strict";
1094
+
1095
+ root.dbltap =
1096
+ root.dblclick = function(conf) {
1097
+ conf.maxFingers = conf.maxFingers || conf.fingers || 1;
1098
+ // Setting up local variables.
1099
+ var delay = 700; // in milliseconds
1100
+ var time0, time1, timeout;
1101
+ var pointer0, pointer1;
1102
+ // Tracking the events.
1103
+ conf.onPointerDown = function(event) {
1104
+ var pointers = event.changedTouches || root.getCoords(event);
1105
+ if (time0 && !time1) { // Click #2
1106
+ pointer1 = pointers[0];
1107
+ time1 = (new Date).getTime() - time0;
1108
+ } else { // Click #1
1109
+ pointer0 = pointers[0];
1110
+ time0 = (new Date).getTime();
1111
+ time1 = 0;
1112
+ clearTimeout(timeout);
1113
+ timeout = setTimeout(function() {
1114
+ time0 = 0;
1115
+ }, delay);
1116
+ }
1117
+ if (root.pointerStart(event, self, conf)) {
1118
+ Event.add(conf.doc, "mousemove", conf.onPointerMove).listener(event);
1119
+ Event.add(conf.doc, "mouseup", conf.onPointerUp);
1120
+ }
1121
+ };
1122
+ conf.onPointerMove = function(event) {
1123
+ if (time0 && !time1) {
1124
+ var pointers = event.changedTouches || root.getCoords(event);
1125
+ pointer1 = pointers[0];
1126
+ }
1127
+ var bbox = conf.bbox;
1128
+ if (conf.position === "relative") {
1129
+ var ax = (pointer1.pageX + bbox.scrollLeft - bbox.x1) * bbox.scaleX;
1130
+ var ay = (pointer1.pageY + bbox.scrollTop - bbox.y1) * bbox.scaleY;
1131
+ } else {
1132
+ var ax = (pointer1.pageX - bbox.x1);
1133
+ var ay = (pointer1.pageY - bbox.y1);
1134
+ }
1135
+ if (!(ax > 0 && ax < bbox.width && // Within target coordinates..
1136
+ ay > 0 && ay < bbox.height &&
1137
+ Math.abs(pointer1.pageX - pointer0.pageX) <= 25 && // Within drift deviance.
1138
+ Math.abs(pointer1.pageY - pointer0.pageY) <= 25)) {
1139
+ // Cancel out this listener.
1140
+ Event.remove(conf.doc, "mousemove", conf.onPointerMove);
1141
+ clearTimeout(timeout);
1142
+ time0 = time1 = 0;
1143
+ }
1144
+ };
1145
+ conf.onPointerUp = function(event) {
1146
+ if (root.pointerEnd(event, self, conf)) {
1147
+ Event.remove(conf.doc, "mousemove", conf.onPointerMove);
1148
+ Event.remove(conf.doc, "mouseup", conf.onPointerUp);
1149
+ }
1150
+ if (time0 && time1) {
1151
+ if (time1 <= delay && !(event.cancelBubble && ++event.bubble > 1)) {
1152
+ self.state = conf.gesture;
1153
+ conf.listener(event, self);
1154
+ }
1155
+ clearTimeout(timeout);
1156
+ time0 = time1 = 0;
1157
+ }
1158
+ };
1159
+ // Generate maintenance commands, and other configurations.
1160
+ var self = root.pointerSetup(conf);
1161
+ self.state = "dblclick";
1162
+ // Attach events.
1163
+ Event.add(conf.target, "mousedown", conf.onPointerDown);
1164
+ // Return this object.
1165
+ return self;
1166
+ };
1167
+
1168
+ Event.Gesture = Event.Gesture || {};
1169
+ Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {};
1170
+ Event.Gesture._gestureHandlers.dbltap = root.dbltap;
1171
+ Event.Gesture._gestureHandlers.dblclick = root.dblclick;
1172
+
1173
+ return root;
1174
+
1175
+ })(Event.proxy);
1176
+ /*
1177
+ "Drag" event proxy (1+ fingers).
1178
+ ----------------------------------------------------
1179
+ CONFIGURE: maxFingers, position.
1180
+ ----------------------------------------------------
1181
+ Event.add(window, "drag", function(event, self) {
1182
+ console.log(self.gesture, self.state, self.start, self.x, self.y, self.bbox);
1183
+ });
1184
+ */
1185
+
1186
+ if (typeof(Event) === "undefined")
1187
+ var Event = {};
1188
+ if (typeof(Event.proxy) === "undefined")
1189
+ Event.proxy = {};
1190
+
1191
+ Event.proxy = (function(root) {
1192
+ "use strict";
1193
+
1194
+ root.dragElement = function(that, event) {
1195
+ root.drag({
1196
+ event: event,
1197
+ target: that,
1198
+ position: "move",
1199
+ listener: function(event, self) {
1200
+ that.style.left = self.x + "px";
1201
+ that.style.top = self.y + "px";
1202
+ Event.prevent(event);
1203
+ }
1204
+ });
1205
+ };
1206
+
1207
+ root.drag = function(conf) {
1208
+ conf.gesture = "drag";
1209
+ conf.onPointerDown = function(event) {
1210
+ if (root.pointerStart(event, self, conf)) {
1211
+ if (!conf.monitor) {
1212
+ Event.add(conf.doc, "mousemove", conf.onPointerMove);
1213
+ Event.add(conf.doc, "mouseup", conf.onPointerUp);
1214
+ }
1215
+ }
1216
+ // Process event listener.
1217
+ conf.onPointerMove(event, "down");
1218
+ };
1219
+ conf.onPointerMove = function(event, state) {
1220
+ if (!conf.tracker)
1221
+ return conf.onPointerDown(event);
1222
+ var bbox = conf.bbox;
1223
+ var touches = event.changedTouches || root.getCoords(event);
1224
+ var length = touches.length;
1225
+ for (var i = 0; i < length; i++) {
1226
+ var touch = touches[i];
1227
+ var identifier = touch.identifier || Infinity;
1228
+ var pt = conf.tracker[identifier];
1229
+ // Identifier defined outside of listener.
1230
+ if (!pt)
1231
+ continue;
1232
+ pt.pageX = touch.pageX;
1233
+ pt.pageY = touch.pageY;
1234
+ // Record data.
1235
+ self.state = state || "move";
1236
+ self.identifier = identifier;
1237
+ self.start = pt.start;
1238
+ self.fingers = conf.fingers;
1239
+ if (conf.position === "relative") {
1240
+ self.x = (pt.pageX + bbox.scrollLeft - pt.offsetX) * bbox.scaleX;
1241
+ self.y = (pt.pageY + bbox.scrollTop - pt.offsetY) * bbox.scaleY;
1242
+ } else {
1243
+ self.x = (pt.pageX - pt.offsetX);
1244
+ self.y = (pt.pageY - pt.offsetY);
1245
+ }
1246
+ ///
1247
+ conf.listener(event, self);
1248
+ }
1249
+ };
1250
+ conf.onPointerUp = function(event) {
1251
+ // Remove tracking for touch.
1252
+ if (root.pointerEnd(event, self, conf, conf.onPointerMove)) {
1253
+ if (!conf.monitor) {
1254
+ Event.remove(conf.doc, "mousemove", conf.onPointerMove);
1255
+ Event.remove(conf.doc, "mouseup", conf.onPointerUp);
1256
+ }
1257
+ }
1258
+ };
1259
+ // Generate maintenance commands, and other configurations.
1260
+ var self = root.pointerSetup(conf);
1261
+ // Attach events.
1262
+ if (conf.event) {
1263
+ conf.onPointerDown(conf.event);
1264
+ } else { //
1265
+ Event.add(conf.target, "mousedown", conf.onPointerDown);
1266
+ if (conf.monitor) {
1267
+ Event.add(conf.doc, "mousemove", conf.onPointerMove);
1268
+ Event.add(conf.doc, "mouseup", conf.onPointerUp);
1269
+ }
1270
+ }
1271
+ // Return this object.
1272
+ return self;
1273
+ };
1274
+
1275
+ Event.Gesture = Event.Gesture || {};
1276
+ Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {};
1277
+ Event.Gesture._gestureHandlers.drag = root.drag;
1278
+
1279
+ return root;
1280
+
1281
+ })(Event.proxy);
1282
+ /*
1283
+ "Gesture" event proxy (2+ fingers).
1284
+ ----------------------------------------------------
1285
+ CONFIGURE: minFingers, maxFingers.
1286
+ ----------------------------------------------------
1287
+ Event.add(window, "gesture", function(event, self) {
1288
+ console.log(self.rotation, self.scale, self.fingers, self.state);
1289
+ });
1290
+ */
1291
+
1292
+ if (typeof(Event) === "undefined")
1293
+ var Event = {};
1294
+ if (typeof(Event.proxy) === "undefined")
1295
+ Event.proxy = {};
1296
+
1297
+ Event.proxy = (function(root) {
1298
+ "use strict";
1299
+
1300
+ var RAD_DEG = Math.PI / 180;
1301
+
1302
+ root.gesture = function(conf) {
1303
+ conf.minFingers = conf.minFingers || conf.fingers || 2;
1304
+ // Tracking the events.
1305
+ conf.onPointerDown = function(event) {
1306
+ var fingers = conf.fingers;
1307
+ if (root.pointerStart(event, self, conf)) {
1308
+ Event.add(conf.doc, "mousemove", conf.onPointerMove);
1309
+ Event.add(conf.doc, "mouseup", conf.onPointerUp);
1310
+ }
1311
+ // Record gesture start.
1312
+ if (conf.fingers === conf.minFingers && fingers !== conf.fingers) {
1313
+ self.fingers = conf.minFingers;
1314
+ self.scale = 1;
1315
+ self.rotation = 0;
1316
+ self.state = "start";
1317
+ var sids = ""; //- FIXME(mud): can generate duplicate IDs.
1318
+ for (var key in conf.tracker)
1319
+ sids += key;
1320
+ self.identifier = parseInt(sids);
1321
+ conf.listener(event, self);
1322
+ }
1323
+ };
1324
+ ///
1325
+ conf.onPointerMove = function(event, state) {
1326
+ var bbox = conf.bbox;
1327
+ var points = conf.tracker;
1328
+ var touches = event.changedTouches || root.getCoords(event);
1329
+ var length = touches.length;
1330
+ // Update tracker coordinates.
1331
+ for (var i = 0; i < length; i++) {
1332
+ var touch = touches[i];
1333
+ var sid = touch.identifier || Infinity;
1334
+ var pt = points[sid];
1335
+ // Check whether "pt" is used by another gesture.
1336
+ if (!pt)
1337
+ continue;
1338
+ // Find the actual coordinates.
1339
+ if (conf.position === "relative") {
1340
+ pt.move.x = (touch.pageX + bbox.scrollLeft - bbox.x1) * bbox.scaleX;
1341
+ pt.move.y = (touch.pageY + bbox.scrollTop - bbox.y1) * bbox.scaleY;
1342
+ } else {
1343
+ pt.move.x = (touch.pageX - bbox.x1);
1344
+ pt.move.y = (touch.pageY - bbox.y1);
1345
+ }
1346
+ }
1347
+ ///
1348
+ if (conf.fingers < conf.minFingers)
1349
+ return;
1350
+ ///
1351
+ var touches = [];
1352
+ var scale = 0;
1353
+ var rotation = 0;
1354
+ /// Calculate centroid of gesture.
1355
+ var centroidx = 0;
1356
+ var centroidy = 0;
1357
+ var length = 0;
1358
+ for (var sid in points) {
1359
+ var touch = points[sid];
1360
+ if (touch.up)
1361
+ continue;
1362
+ centroidx += touch.move.x;
1363
+ centroidy += touch.move.y;
1364
+ length++;
1365
+ }
1366
+ centroidx /= length;
1367
+ centroidy /= length;
1368
+ ///
1369
+ for (var sid in points) {
1370
+ var touch = points[sid];
1371
+ if (touch.up)
1372
+ continue;
1373
+ var start = touch.start;
1374
+ if (!start.distance) {
1375
+ var dx = start.x - centroidx;
1376
+ var dy = start.y - centroidy;
1377
+ start.distance = Math.sqrt(dx * dx + dy * dy);
1378
+ start.angle = Math.atan2(dx, dy) / RAD_DEG;
1379
+ }
1380
+ // Calculate scale.
1381
+ var dx = touch.move.x - centroidx;
1382
+ var dy = touch.move.y - centroidy;
1383
+ var distance = Math.sqrt(dx * dx + dy * dy);
1384
+ scale += distance / start.distance;
1385
+ // Calculate rotation.
1386
+ var angle = Math.atan2(dx, dy) / RAD_DEG;
1387
+ var rotate = (start.angle - angle + 360) % 360 - 180;
1388
+ touch.DEG2 = touch.DEG1; // Previous degree.
1389
+ touch.DEG1 = rotate > 0 ? rotate : -rotate; // Current degree.
1390
+ if (typeof(touch.DEG2) !== "undefined") {
1391
+ if (rotate > 0) {
1392
+ touch.rotation += touch.DEG1 - touch.DEG2;
1393
+ } else {
1394
+ touch.rotation -= touch.DEG1 - touch.DEG2;
1395
+ }
1396
+ rotation += touch.rotation;
1397
+ }
1398
+ // Attach current points to self.
1399
+ touches.push(touch.move);
1400
+ }
1401
+ ///
1402
+ self.touches = touches;
1403
+ self.fingers = conf.fingers;
1404
+ self.scale = scale / conf.fingers;
1405
+ self.rotation = rotation / conf.fingers;
1406
+ self.state = "change";
1407
+ conf.listener(event, self);
1408
+ };
1409
+ conf.onPointerUp = function(event) {
1410
+ // Remove tracking for touch.
1411
+ var fingers = conf.fingers;
1412
+ if (root.pointerEnd(event, self, conf)) {
1413
+ Event.remove(conf.doc, "mousemove", conf.onPointerMove);
1414
+ Event.remove(conf.doc, "mouseup", conf.onPointerUp);
1415
+ }
1416
+ // Check whether fingers has dropped below minFingers.
1417
+ if (fingers === conf.minFingers && conf.fingers < conf.minFingers) {
1418
+ self.fingers = conf.fingers;
1419
+ self.state = "end";
1420
+ conf.listener(event, self);
1421
+ }
1422
+ };
1423
+ // Generate maintenance commands, and other configurations.
1424
+ var self = root.pointerSetup(conf);
1425
+ // Attach events.
1426
+ Event.add(conf.target, "mousedown", conf.onPointerDown);
1427
+ // Return this object.
1428
+ return self;
1429
+ };
1430
+
1431
+ Event.Gesture = Event.Gesture || {};
1432
+ Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {};
1433
+ Event.Gesture._gestureHandlers.gesture = root.gesture;
1434
+
1435
+ return root;
1436
+
1437
+ })(Event.proxy);
1438
+ /*
1439
+ "Pointer" event proxy (1+ fingers).
1440
+ ----------------------------------------------------
1441
+ CONFIGURE: minFingers, maxFingers.
1442
+ ----------------------------------------------------
1443
+ Event.add(window, "gesture", function(event, self) {
1444
+ console.log(self.rotation, self.scale, self.fingers, self.state);
1445
+ });
1446
+ */
1447
+
1448
+ if (typeof(Event) === "undefined")
1449
+ var Event = {};
1450
+ if (typeof(Event.proxy) === "undefined")
1451
+ Event.proxy = {};
1452
+
1453
+ Event.proxy = (function(root) {
1454
+ "use strict";
1455
+
1456
+ root.pointerdown =
1457
+ root.pointermove =
1458
+ root.pointerup = function(conf) {
1459
+ if (conf.target.isPointerEmitter)
1460
+ return;
1461
+ // Tracking the events.
1462
+ var isDown = true;
1463
+ conf.onPointerDown = function(event) {
1464
+ isDown = false;
1465
+ self.gesture = "pointerdown";
1466
+ conf.listener(event, self);
1467
+ };
1468
+ conf.onPointerMove = function(event) {
1469
+ self.gesture = "pointermove";
1470
+ conf.listener(event, self, isDown);
1471
+ };
1472
+ conf.onPointerUp = function(event) {
1473
+ isDown = true;
1474
+ self.gesture = "pointerup";
1475
+ conf.listener(event, self, true);
1476
+ };
1477
+ // Generate maintenance commands, and other configurations.
1478
+ var self = root.pointerSetup(conf);
1479
+ // Attach events.
1480
+ Event.add(conf.target, "mousedown", conf.onPointerDown);
1481
+ Event.add(conf.target, "mousemove", conf.onPointerMove);
1482
+ Event.add(conf.doc, "mouseup", conf.onPointerUp);
1483
+ // Return this object.
1484
+ conf.target.isPointerEmitter = true;
1485
+ return self;
1486
+ };
1487
+
1488
+ Event.Gesture = Event.Gesture || {};
1489
+ Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {};
1490
+ Event.Gesture._gestureHandlers.pointerdown = root.pointerdown;
1491
+ Event.Gesture._gestureHandlers.pointermove = root.pointermove;
1492
+ Event.Gesture._gestureHandlers.pointerup = root.pointerup;
1493
+
1494
+ return root;
1495
+
1496
+ })(Event.proxy);
1497
+ /*
1498
+ "Device Motion" and "Shake" event proxy.
1499
+ ----------------------------------------------------
1500
+ http://developer.android.com/reference/android/hardware/SensorEvent.html#values
1501
+ ----------------------------------------------------
1502
+ Event.add(window, "shake", function(event, self) {});
1503
+ Event.add(window, "devicemotion", function(event, self) {
1504
+ console.log(self.acceleration, self.accelerationIncludingGravity);
1505
+ });
1506
+ */
1507
+
1508
+ if (typeof(Event) === "undefined")
1509
+ var Event = {};
1510
+ if (typeof(Event.proxy) === "undefined")
1511
+ Event.proxy = {};
1512
+
1513
+ Event.proxy = (function(root) {
1514
+ "use strict";
1515
+
1516
+ root.shake = function(conf) {
1517
+ // Externally accessible data.
1518
+ var self = {
1519
+ gesture: "devicemotion",
1520
+ acceleration: {},
1521
+ accelerationIncludingGravity: {},
1522
+ target: conf.target,
1523
+ listener: conf.listener,
1524
+ remove: function() {
1525
+ window.removeEventListener('devicemotion', onDeviceMotion, false);
1526
+ }
1527
+ };
1528
+ // Setting up local variables.
1529
+ var threshold = 4; // Gravitational threshold.
1530
+ var timeout = 1000; // Timeout between shake events.
1531
+ var timeframe = 200; // Time between shakes.
1532
+ var shakes = 3; // Minimum shakes to trigger event.
1533
+ var lastShake = (new Date).getTime();
1534
+ var gravity = {x: 0, y: 0, z: 0};
1535
+ var delta = {
1536
+ x: {count: 0, value: 0},
1537
+ y: {count: 0, value: 0},
1538
+ z: {count: 0, value: 0}
1539
+ };
1540
+ // Tracking the events.
1541
+ var onDeviceMotion = function(e) {
1542
+ var alpha = 0.8; // Low pass filter.
1543
+ var o = e.accelerationIncludingGravity;
1544
+ gravity.x = alpha * gravity.x + (1 - alpha) * o.x;
1545
+ gravity.y = alpha * gravity.y + (1 - alpha) * o.y;
1546
+ gravity.z = alpha * gravity.z + (1 - alpha) * o.z;
1547
+ self.accelerationIncludingGravity = gravity;
1548
+ self.acceleration.x = o.x - gravity.x;
1549
+ self.acceleration.y = o.y - gravity.y;
1550
+ self.acceleration.z = o.z - gravity.z;
1551
+ ///
1552
+ if (conf.gesture === "devicemotion") {
1553
+ conf.listener(e, self);
1554
+ return;
1555
+ }
1556
+ var data = "xyz";
1557
+ var now = (new Date).getTime();
1558
+ for (var n = 0, length = data.length; n < length; n++) {
1559
+ var letter = data[n];
1560
+ var ACCELERATION = self.acceleration[letter];
1561
+ var DELTA = delta[letter];
1562
+ var abs = Math.abs(ACCELERATION);
1563
+ /// Check whether another shake event was recently registered.
1564
+ if (now - lastShake < timeout)
1565
+ continue;
1566
+ /// Check whether delta surpasses threshold.
1567
+ if (abs > threshold) {
1568
+ var idx = now * ACCELERATION / abs;
1569
+ var span = Math.abs(idx + DELTA.value);
1570
+ // Check whether last delta was registered within timeframe.
1571
+ if (DELTA.value && span < timeframe) {
1572
+ DELTA.value = idx;
1573
+ DELTA.count++;
1574
+ // Check whether delta count has enough shakes.
1575
+ if (DELTA.count === shakes) {
1576
+ conf.listener(e, self);
1577
+ // Reset tracking.
1578
+ lastShake = now;
1579
+ DELTA.value = 0;
1580
+ DELTA.count = 0;
1581
+ }
1582
+ } else {
1583
+ // Track first shake.
1584
+ DELTA.value = idx;
1585
+ DELTA.count = 1;
1586
+ }
1587
+ }
1588
+ }
1589
+ };
1590
+ // Attach events.
1591
+ if (!window.addEventListener)
1592
+ return;
1593
+ window.addEventListener('devicemotion', onDeviceMotion, false);
1594
+ // Return this object.
1595
+ return self;
1596
+ };
1597
+
1598
+ Event.Gesture = Event.Gesture || {};
1599
+ Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {};
1600
+ Event.Gesture._gestureHandlers.shake = root.shake;
1601
+
1602
+ return root;
1603
+
1604
+ })(Event.proxy);
1605
+ /*
1606
+ "Swipe" event proxy (1+ fingers).
1607
+ ----------------------------------------------------
1608
+ CONFIGURE: snap, threshold, maxFingers.
1609
+ ----------------------------------------------------
1610
+ Event.add(window, "swipe", function(event, self) {
1611
+ console.log(self.velocity, self.angle);
1612
+ });
1613
+ */
1614
+
1615
+ if (typeof(Event) === "undefined")
1616
+ var Event = {};
1617
+ if (typeof(Event.proxy) === "undefined")
1618
+ Event.proxy = {};
1619
+
1620
+ Event.proxy = (function(root) {
1621
+ "use strict";
1622
+
1623
+ var RAD_DEG = Math.PI / 180;
1624
+
1625
+ root.swipe = function(conf) {
1626
+ conf.snap = conf.snap || 90; // angle snap.
1627
+ conf.threshold = conf.threshold || 1; // velocity threshold.
1628
+ // Tracking the events.
1629
+ conf.onPointerDown = function(event) {
1630
+ if (root.pointerStart(event, self, conf)) {
1631
+ Event.add(conf.doc, "mousemove", conf.onPointerMove).listener(event);
1632
+ Event.add(conf.doc, "mouseup", conf.onPointerUp);
1633
+ }
1634
+ };
1635
+ conf.onPointerMove = function(event) {
1636
+ var touches = event.changedTouches || root.getCoords(event);
1637
+ var length = touches.length;
1638
+ for (var i = 0; i < length; i++) {
1639
+ var touch = touches[i];
1640
+ var sid = touch.identifier || Infinity;
1641
+ var o = conf.tracker[sid];
1642
+ // Identifier defined outside of listener.
1643
+ if (!o)
1644
+ continue;
1645
+ o.move.x = touch.pageX;
1646
+ o.move.y = touch.pageY;
1647
+ o.moveTime = (new Date).getTime();
1648
+ }
1649
+ };
1650
+ conf.onPointerUp = function(event) {
1651
+ if (root.pointerEnd(event, self, conf)) {
1652
+ Event.remove(conf.doc, "mousemove", conf.onPointerMove);
1653
+ Event.remove(conf.doc, "mouseup", conf.onPointerUp);
1654
+ ///
1655
+ var velocity1;
1656
+ var velocity2
1657
+ var degree1;
1658
+ var degree2;
1659
+ /// Calculate centroid of gesture.
1660
+ var start = {x: 0, y: 0};
1661
+ var endx = 0;
1662
+ var endy = 0;
1663
+ var length = 0;
1664
+ ///
1665
+ for (var sid in conf.tracker) {
1666
+ var touch = conf.tracker[sid];
1667
+ var xdist = touch.move.x - touch.start.x;
1668
+ var ydist = touch.move.y - touch.start.y;
1669
+
1670
+ endx += touch.move.x;
1671
+ endy += touch.move.y;
1672
+ start.x += touch.start.x;
1673
+ start.y += touch.start.y;
1674
+ length++;
1675
+
1676
+
1677
+ var distance = Math.sqrt(xdist * xdist + ydist * ydist);
1678
+ var ms = touch.moveTime - touch.startTime;
1679
+ var degree2 = Math.atan2(xdist, ydist) / RAD_DEG + 180;
1680
+ var velocity2 = ms ? distance / ms : 0;
1681
+ if (typeof(degree1) === "undefined") {
1682
+ degree1 = degree2;
1683
+ velocity1 = velocity2;
1684
+ } else if (Math.abs(degree2 - degree1) <= 20) {
1685
+ degree1 = (degree1 + degree2) / 2;
1686
+ velocity1 = (velocity1 + velocity2) / 2;
1687
+ } else {
1688
+ return;
1689
+ }
1690
+ }
1691
+ ///
1692
+ if (velocity1 > conf.threshold) {
1693
+ start.x /= length;
1694
+ start.y /= length;
1695
+ self.start = start;
1696
+ self.x = endx / length;
1697
+ self.y = endy / length;
1698
+ self.angle = -((((degree1 / conf.snap + 0.5) >> 0) * conf.snap || 360) - 360);
1699
+ self.velocity = velocity1;
1700
+ self.fingers = conf.gestureFingers;
1701
+ self.state = "swipe";
1702
+ conf.listener(event, self);
1703
+ }
1704
+ }
1705
+ };
1706
+ // Generate maintenance commands, and other configurations.
1707
+ var self = root.pointerSetup(conf);
1708
+ // Attach events.
1709
+ Event.add(conf.target, "mousedown", conf.onPointerDown);
1710
+ // Return this object.
1711
+ return self;
1712
+ };
1713
+
1714
+ Event.Gesture = Event.Gesture || {};
1715
+ Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {};
1716
+ Event.Gesture._gestureHandlers.swipe = root.swipe;
1717
+
1718
+ return root;
1719
+
1720
+ })(Event.proxy);
1721
+ /*
1722
+ "Tap" and "Longpress" event proxy.
1723
+ ----------------------------------------------------
1724
+ CONFIGURE: delay (longpress), timeout (tap).
1725
+ ----------------------------------------------------
1726
+ Event.add(window, "tap", function(event, self) {
1727
+ console.log(self.fingers);
1728
+ });
1729
+ ----------------------------------------------------
1730
+ multi-finger tap // touch an target for <= 250ms.
1731
+ multi-finger longpress // touch an target for >= 500ms
1732
+ */
1733
+
1734
+ if (typeof(Event) === "undefined")
1735
+ var Event = {};
1736
+ if (typeof(Event.proxy) === "undefined")
1737
+ Event.proxy = {};
1738
+
1739
+ Event.proxy = (function(root) {
1740
+ "use strict";
1741
+
1742
+ root.tap =
1743
+ root.longpress = function(conf) {
1744
+ conf.delay = conf.delay || 500;
1745
+ conf.timeout = conf.timeout || 250;
1746
+ // Setting up local variables.
1747
+ var timestamp, timeout;
1748
+ // Tracking the events.
1749
+ conf.onPointerDown = function(event) {
1750
+ if (root.pointerStart(event, self, conf)) {
1751
+ timestamp = (new Date).getTime();
1752
+ // Initialize event listeners.
1753
+ Event.add(conf.doc, "mousemove", conf.onPointerMove).listener(event);
1754
+ Event.add(conf.doc, "mouseup", conf.onPointerUp);
1755
+ // Make sure this is a "longpress" event.
1756
+ if (conf.gesture !== "longpress")
1757
+ return;
1758
+ timeout = setTimeout(function() {
1759
+ if (event.cancelBubble && ++event.bubble > 1)
1760
+ return;
1761
+ // Make sure no fingers have been changed.
1762
+ var fingers = 0;
1763
+ for (var key in conf.tracker) {
1764
+ if (conf.tracker[key].end === true)
1765
+ return;
1766
+ if (conf.cancel)
1767
+ return;
1768
+ fingers++;
1769
+ }
1770
+ // Send callback.
1771
+ self.state = "start";
1772
+ self.fingers = fingers;
1773
+ conf.listener(event, self);
1774
+ }, conf.delay);
1775
+ }
1776
+ };
1777
+ conf.onPointerMove = function(event) {
1778
+ var bbox = conf.bbox;
1779
+ var touches = event.changedTouches || root.getCoords(event);
1780
+ var length = touches.length;
1781
+ for (var i = 0; i < length; i++) {
1782
+ var touch = touches[i];
1783
+ var identifier = touch.identifier || Infinity;
1784
+ var pt = conf.tracker[identifier];
1785
+ if (!pt)
1786
+ continue;
1787
+ if (conf.position === "relative") {
1788
+ var x = (touch.pageX + bbox.scrollLeft - bbox.x1) * bbox.scaleX;
1789
+ var y = (touch.pageY + bbox.scrollTop - bbox.y1) * bbox.scaleY;
1790
+ } else {
1791
+ var x = (touch.pageX - bbox.x1);
1792
+ var y = (touch.pageY - bbox.y1);
1793
+ }
1794
+ if (!(x > 0 && x < bbox.width && // Within target coordinates..
1795
+ y > 0 && y < bbox.height &&
1796
+ Math.abs(x - pt.start.x) <= 25 && // Within drift deviance.
1797
+ Math.abs(y - pt.start.y) <= 25)) {
1798
+ // Cancel out this listener.
1799
+ Event.remove(conf.doc, "mousemove", conf.onPointerMove);
1800
+ conf.cancel = true;
1801
+ return;
1802
+ }
1803
+ }
1804
+ };
1805
+ conf.onPointerUp = function(event) {
1806
+ if (root.pointerEnd(event, self, conf)) {
1807
+ clearTimeout(timeout);
1808
+ Event.remove(conf.doc, "mousemove", conf.onPointerMove);
1809
+ Event.remove(conf.doc, "mouseup", conf.onPointerUp);
1810
+ if (event.cancelBubble && ++event.bubble > 1)
1811
+ return;
1812
+ // Callback release on longpress.
1813
+ if (conf.gesture === "longpress") {
1814
+ if (self.state === "start") {
1815
+ self.state = "end";
1816
+ conf.listener(event, self);
1817
+ }
1818
+ return;
1819
+ }
1820
+ // Cancel event due to movement.
1821
+ if (conf.cancel)
1822
+ return;
1823
+ // Ensure delay is within margins.
1824
+ if ((new Date).getTime() - timestamp > conf.timeout)
1825
+ return;
1826
+ // Send callback.
1827
+ self.state = "tap";
1828
+ self.fingers = conf.gestureFingers;
1829
+ conf.listener(event, self);
1830
+ }
1831
+ };
1832
+ // Generate maintenance commands, and other configurations.
1833
+ var self = root.pointerSetup(conf);
1834
+ // Attach events.
1835
+ Event.add(conf.target, "mousedown", conf.onPointerDown);
1836
+ // Return this object.
1837
+ return self;
1838
+ };
1839
+
1840
+ Event.Gesture = Event.Gesture || {};
1841
+ Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {};
1842
+ Event.Gesture._gestureHandlers.tap = root.tap;
1843
+ Event.Gesture._gestureHandlers.longpress = root.longpress;
1844
+
1845
+ return root;
1846
+
1847
+ })(Event.proxy);
1848
+ /*
1849
+ "Mouse Wheel" event proxy.
1850
+ ----------------------------------------------------
1851
+ Event.add(window, "wheel", function(event, self) {
1852
+ console.log(self.state, self.wheelDelta);
1853
+ });
1854
+ */
1855
+
1856
+ if (typeof(Event) === "undefined")
1857
+ var Event = {};
1858
+ if (typeof(Event.proxy) === "undefined")
1859
+ Event.proxy = {};
1860
+
1861
+ Event.proxy = (function(root) {
1862
+ "use strict";
1863
+
1864
+ root.wheel = function(conf) {
1865
+ // Configure event listener.
1866
+ var interval;
1867
+ var timeout = conf.timeout || 150;
1868
+ var count = 0;
1869
+ // Externally accessible data.
1870
+ var self = {
1871
+ gesture: "wheel",
1872
+ state: "start",
1873
+ wheelDelta: 0,
1874
+ target: conf.target,
1875
+ listener: conf.listener,
1876
+ remove: function() {
1877
+ conf.target[remove](type, onMouseWheel, false);
1878
+ }
1879
+ };
1880
+ // Tracking the events.
1881
+ var onMouseWheel = function(event) {
1882
+ event = event || window.event;
1883
+ self.state = count++ ? "change" : "start";
1884
+ self.wheelDelta = event.detail ? event.detail * -20 : event.wheelDelta;
1885
+ conf.listener(event, self);
1886
+ clearTimeout(interval);
1887
+ interval = setTimeout(function() {
1888
+ count = 0;
1889
+ self.state = "end";
1890
+ self.wheelDelta = 0;
1891
+ conf.listener(event, self);
1892
+ }, timeout);
1893
+ };
1894
+ // Attach events.
1895
+ var add = document.addEventListener ? "addEventListener" : "attachEvent";
1896
+ var remove = document.removeEventListener ? "removeEventListener" : "detachEvent";
1897
+ var type = Event.supports("mousewheel") ? "mousewheel" : "DOMMouseScroll";
1898
+ conf.target[add](type, onMouseWheel, false);
1899
+ // Return this object.
1900
+ return self;
1901
+ };
1902
+
1903
+ Event.Gesture = Event.Gesture || {};
1904
+ Event.Gesture._gestureHandlers = Event.Gesture._gestureHandlers || {};
1905
+ Event.Gesture._gestureHandlers.wheel = root.wheel;
1906
+
1907
+ return root;
1908
+
1909
+ })(Event.proxy);