PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / trunk
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF vtrunk
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
← All changes | assets/js/jquery.event.move.js +346 -348 1.3.6.1 → trunk View file →
@@ -1,7 +1,7 @@
1 -// jquery.event.move
1 +// DOM.event.move
2 2 //
3 -// 1.3.6
3 +// 2.0.1
4 4 //
5 5 // Stephen Band
6 6 //
7 7 // Triggers 'movestart', 'move' and 'moveend' events after
@@ -10,87 +10,143 @@
10 10 // Move events are throttled to animation frames. Move event objects
11 11 // have the properties:
12 12 //
13 13 // pageX:
14 -// pageY: Page coordinates of pointer.
14 +// pageY: Page coordinates of pointer.
15 15 // startX:
16 -// startY: Page coordinates of pointer at movestart.
16 +// startY: Page coordinates of pointer at movestart.
17 17 // distX:
18 -// distY: Distance the pointer has moved since movestart.
18 +// distY: Distance the pointer has moved since movestart.
19 19 // deltaX:
20 -// deltaY: Distance the finger has moved since last event.
20 +// deltaY: Distance the finger has moved since last event.
21 21 // velocityX:
22 -// velocityY: Average velocity over last few events.
22 +// velocityY: Average velocity over last few events.
23 23
24 24
25 -(function (module) {
25 +(function(fn) {
26 26 if (typeof define === 'function' && define.amd) {
27 - // AMD. Register as an anonymous module.
28 - define(['jquery'], module);
27 + define([], fn);
28 + } else if ((typeof module !== "undefined" && module !== null) && module.exports) {
29 + module.exports = fn;
29 30 } else {
30 - // Browser globals
31 - module(jQuery);
31 + fn();
32 32 }
33 -})(function(jQuery, undefined){
33 +})(function(){
34 + var assign = Object.assign || window.jQuery && jQuery.extend;
34 35
35 - var // Number of pixels a pressed pointer travels before movestart
36 - // event is fired.
37 - threshold = 6,
38 -
39 - add = jQuery.event.add,
40 -
41 - remove = jQuery.event.remove,
36 + // Number of pixels a pressed pointer travels before movestart
37 + // event is fired.
38 + var threshold = 8;
42 39
43 - // Just sugar, so we can have arguments in the same order as
44 - // add and remove.
45 - trigger = function(node, type, data) {
46 - jQuery.event.trigger(type, data, node);
47 - },
40 + // Shim for requestAnimationFrame, falling back to timer. See:
41 + // see http://paulirish.com/2011/requestanimationframe-for-smart-animating/
42 + var requestFrame = (function(){
43 + return (
44 + window.requestAnimationFrame ||
45 + window.webkitRequestAnimationFrame ||
46 + window.mozRequestAnimationFrame ||
47 + window.oRequestAnimationFrame ||
48 + window.msRequestAnimationFrame ||
49 + function(fn, element){
50 + return window.setTimeout(function(){
51 + fn();
52 + }, 25);
53 + }
54 + );
55 + })();
48 56
49 - // Shim for requestAnimationFrame, falling back to timer. See:
50 - // see http://paulirish.com/2011/requestanimationframe-for-smart-animating/
51 - requestFrame = (function(){
52 - return (
53 - window.requestAnimationFrame ||
54 - window.webkitRequestAnimationFrame ||
55 - window.mozRequestAnimationFrame ||
56 - window.oRequestAnimationFrame ||
57 - window.msRequestAnimationFrame ||
58 - function(fn, element){
59 - return window.setTimeout(function(){
60 - fn();
61 - }, 25);
62 - }
63 - );
64 - })(),
65 -
66 - ignoreTags = {
67 - textarea: true,
68 - input: true,
69 - select: true,
70 - button: true
71 - },
72 -
73 - mouseevents = {
74 - move: 'mousemove',
75 - cancel: 'mouseup dragstart',
76 - end: 'mouseup'
77 - },
78 -
79 - touchevents = {
80 - move: 'touchmove',
81 - cancel: 'touchend',
82 - end: 'touchend'
83 - };
57 + var ignoreTags = {
58 + textarea: true,
59 + input: true,
60 + select: true,
61 + button: true
62 + };
84 63
64 + var mouseevents = {
65 + move: 'mousemove',
66 + cancel: 'mouseup dragstart',
67 + end: 'mouseup'
68 + };
85 69
70 + var touchevents = {
71 + move: 'touchmove',
72 + cancel: 'touchend',
73 + end: 'touchend'
74 + };
75 +
76 + var rspaces = /\s+/;
77 +
78 +
79 + // DOM Events
80 +
81 + var eventOptions = { bubbles: true, cancelable: true };
82 +
83 + var eventsSymbol = Symbol('events');
84 +
85 + function createEvent(type) {
86 + return new CustomEvent(type, eventOptions);
87 + }
88 +
89 + function getEvents(node) {
90 + return node[eventsSymbol] || (node[eventsSymbol] = {});
91 + }
92 +
93 + function on(node, types, fn, data, selector) {
94 + types = types.split(rspaces);
95 +
96 + var events = getEvents(node);
97 + var i = types.length;
98 + var handlers, type;
99 +
100 + function handler(e) { fn(e, data); }
101 +
102 + while (i--) {
103 + type = types[i];
104 + handlers = events[type] || (events[type] = []);
105 + handlers.push([fn, handler]);
106 + node.addEventListener(type, handler);
107 + }
108 + }
109 +
110 + function off(node, types, fn, selector) {
111 + types = types.split(rspaces);
112 +
113 + var events = getEvents(node);
114 + var i = types.length;
115 + var type, handlers, k;
116 +
117 + if (!events) { return; }
118 +
119 + while (i--) {
120 + type = types[i];
121 + handlers = events[type];
122 + if (!handlers) { continue; }
123 + k = handlers.length;
124 + while (k--) {
125 + if (handlers[k][0] === fn) {
126 + node.removeEventListener(type, handlers[k][1]);
127 + handlers.splice(k, 1);
128 + }
129 + }
130 + }
131 + }
132 +
133 + function trigger(node, type, properties) {
134 + // Don't cache events. It prevents you from triggering an event of a
135 + // given type from inside the handler of another event of that type.
136 + var event = createEvent(type);
137 + if (properties) { assign(event, properties); }
138 + node.dispatchEvent(event);
139 + }
140 +
141 +
86 142 // Constructors
87 -
143 +
88 144 function Timer(fn){
89 145 var callback = fn,
90 146 active = false,
91 147 running = false;
92 -
148 +
93 149 function trigger(time) {
94 150 if (active){
95 151 callback();
96 152 requestFrame(trigger);
@@ -100,19 +156,19 @@
100 156 else {
101 157 running = false;
102 158 }
103 159 }
104 -
160 +
105 161 this.kick = function(fn) {
106 162 active = true;
107 163 if (!running) { trigger(); }
108 164 };
109 -
165 +
110 166 this.end = function(fn) {
111 167 var cb = callback;
112 -
168 +
113 169 if (!fn) { return; }
114 -
170 +
115 171 // If the timer is not running, simply call the end callback.
116 172 if (!running) {
117 173 fn();
118 174 }
@@ -120,11 +176,11 @@
120 176 // queue up the current callback and the end callback, otherwise
121 177 // just the end callback.
122 178 else {
123 179 callback = active ?
124 - function(){ cb(); fn(); } :
180 + function(){ cb(); fn(); } :
125 181 fn ;
126 -
182 +
127 183 active = true;
128 184 }
129 185 };
130 186 }
@@ -130,29 +186,20 @@
130 186 }
131 187
132 188
133 189 // Functions
134 -
135 - function returnTrue() {
136 - return true;
137 - }
138 -
139 - function returnFalse() {
140 - return false;
141 - }
142 -
190 +
191 + function noop() {}
192 +
143 193 function preventDefault(e) {
144 194 e.preventDefault();
145 195 }
146 -
147 - function preventIgnoreTags(e) {
148 - // Don't prevent interaction with form elements.
149 - if (ignoreTags[ e.target.tagName.toLowerCase() ]) { return; }
150 -
151 - e.preventDefault();
196 +
197 + function isIgnoreTag(e) {
198 + return !!ignoreTags[e.target.tagName.toLowerCase()];
152 199 }
153 200
154 - function isLeftButton(e) {
201 + function isPrimaryButton(e) {
155 202 // Ignore mousedowns on any button other than the left (or primary)
156 203 // mouse button, or when a modifier key is pressed.
157 204 return (e.which === 1 && !e.ctrlKey && !e.altKey);
158 205 }
@@ -162,15 +209,15 @@
162 209
163 210 if (touchList.identifiedTouch) {
164 211 return touchList.identifiedTouch(id);
165 212 }
166 -
213 +
167 214 // touchList.identifiedTouch() does not exist in
168 215 // webkit yet… we must do the search ourselves...
169 -
216 +
170 217 i = -1;
171 218 l = touchList.length;
172 -
219 +
173 220 while (++i < l) {
174 221 if (touchList[i].identifier === id) {
175 222 return touchList[i];
176 223 }
@@ -176,10 +223,10 @@
176 223 }
177 224 }
178 225 }
179 226
180 - function changedTouch(e, event) {
181 - var touch = identifiedTouch(e.changedTouches, event.identifier);
227 + function changedTouch(e, data) {
228 + var touch = identifiedTouch(e.changedTouches, data.identifier);
182 229
183 230 // This isn't the touch you're looking for.
184 231 if (!touch) { return; }
185 232
@@ -185,9 +232,9 @@
185 232
186 233 // Chrome Android (at least) includes touches that have not
187 234 // changed in e.changedTouches. That's a bit annoying. Check
188 235 // that this touch has changed.
189 - if (touch.pageX === event.pageX && touch.pageY === event.pageY) { return; }
236 + if (touch.pageX === data.pageX && touch.pageY === data.pageY) { return; }
190 237
191 238 return touch;
192 239 }
193 240
@@ -192,187 +239,159 @@
192 239 }
193 240
194 241
195 242 // Handlers that decide when the first movestart is triggered
196 -
243 +
197 244 function mousedown(e){
198 - var data;
245 + // Ignore non-primary buttons
246 + if (!isPrimaryButton(e)) { return; }
199 247
200 - if (!isLeftButton(e)) { return; }
248 + // Ignore form and interactive elements
249 + if (isIgnoreTag(e)) { return; }
201 250
202 - data = {
203 - target: e.target,
204 - startX: e.pageX,
205 - startY: e.pageY,
206 - timeStamp: e.timeStamp
207 - };
208 -
209 - add(document, mouseevents.move, mousemove, data);
210 - add(document, mouseevents.cancel, mouseend, data);
251 + on(document, mouseevents.move, mousemove, e);
252 + on(document, mouseevents.cancel, mouseend, e);
211 253 }
212 254
213 - function mousemove(e){
214 - var data = e.data;
215 -
255 + function mousemove(e, data){
216 256 checkThreshold(e, data, e, removeMouse);
217 257 }
218 258
219 - function mouseend(e) {
259 + function mouseend(e, data) {
220 260 removeMouse();
221 261 }
222 262
223 263 function removeMouse() {
224 - remove(document, mouseevents.move, mousemove);
225 - remove(document, mouseevents.cancel, mouseend);
264 + off(document, mouseevents.move, mousemove);
265 + off(document, mouseevents.cancel, mouseend);
226 266 }
227 267
228 268 function touchstart(e) {
229 - var touch, template;
269 + // Don't get in the way of interaction with form elements
270 + if (ignoreTags[e.target.tagName.toLowerCase()]) { return; }
230 271
231 - // Don't get in the way of interaction with form elements.
232 - if (ignoreTags[ e.target.tagName.toLowerCase() ]) { return; }
272 + var touch = e.changedTouches[0];
233 273
234 - touch = e.changedTouches[0];
235 -
236 274 // iOS live updates the touch objects whereas Android gives us copies.
237 275 // That means we can't trust the touchstart object to stay the same,
238 276 // so we must copy the data. This object acts as a template for
239 277 // movestart, move and moveend event objects.
240 - template = {
241 - target: touch.target,
242 - startX: touch.pageX,
243 - startY: touch.pageY,
244 - timeStamp: e.timeStamp,
245 - identifier: touch.identifier
278 + var data = {
279 + target: touch.target,
280 + pageX: touch.pageX,
281 + pageY: touch.pageY,
282 + identifier: touch.identifier,
283 +
284 + // The only way to make handlers individually unbindable is by
285 + // making them unique.
286 + touchmove: function(e, data) { touchmove(e, data); },
287 + touchend: function(e, data) { touchend(e, data); }
246 288 };
247 289
248 - // Use the touch identifier as a namespace, so that we can later
249 - // remove handlers pertaining only to this touch.
250 - add(document, touchevents.move + '.' + touch.identifier, touchmove, template);
251 - add(document, touchevents.cancel + '.' + touch.identifier, touchend, template);
290 + on(document, touchevents.move, data.touchmove, data);
291 + on(document, touchevents.cancel, data.touchend, data);
252 292 }
253 293
254 - function touchmove(e){
255 - var data = e.data,
256 - touch = changedTouch(e, data);
257 -
294 + function touchmove(e, data) {
295 + var touch = changedTouch(e, data);
258 296 if (!touch) { return; }
259 -
260 297 checkThreshold(e, data, touch, removeTouch);
261 298 }
262 299
263 - function touchend(e) {
264 - var template = e.data,
265 - touch = identifiedTouch(e.changedTouches, template.identifier);
266 -
300 + function touchend(e, data) {
301 + var touch = identifiedTouch(e.changedTouches, data.identifier);
267 302 if (!touch) { return; }
268 -
269 - removeTouch(template.identifier);
303 + removeTouch(data);
270 304 }
271 305
272 - function removeTouch(identifier) {
273 - remove(document, '.' + identifier, touchmove);
274 - remove(document, '.' + identifier, touchend);
306 + function removeTouch(data) {
307 + off(document, touchevents.move, data.touchmove);
308 + off(document, touchevents.cancel, data.touchend);
275 309 }
276 310
311 + function checkThreshold(e, data, touch, fn) {
312 + var distX = touch.pageX - data.pageX;
313 + var distY = touch.pageY - data.pageY;
277 314
278 - // Logic for deciding when to trigger a movestart.
279 -
280 - function checkThreshold(e, template, touch, fn) {
281 - var distX = touch.pageX - template.startX,
282 - distY = touch.pageY - template.startY;
283 -
284 315 // Do nothing if the threshold has not been crossed.
285 316 if ((distX * distX) + (distY * distY) < (threshold * threshold)) { return; }
286 317
287 - triggerStart(e, template, touch, distX, distY, fn);
318 + triggerStart(e, data, touch, distX, distY, fn);
288 319 }
289 320
290 - function handled() {
291 - // this._handled should return false once, and after return true.
292 - this._handled = returnTrue;
293 - return false;
294 - }
321 + function triggerStart(e, data, touch, distX, distY, fn) {
322 + var touches = e.targetTouches;
323 + var time = e.timeStamp - data.timeStamp;
295 324
296 - function flagAsHandled(e) {
297 - e._handled();
298 - }
299 -
300 - function triggerStart(e, template, touch, distX, distY, fn) {
301 - var node = template.target,
302 - touches, time;
303 -
304 - touches = e.targetTouches;
305 - time = e.timeStamp - template.timeStamp;
306 -
307 325 // Create a movestart object with some special properties that
308 326 // are passed only to the movestart handlers.
309 - template.type = 'movestart';
310 - template.distX = distX;
311 - template.distY = distY;
312 - template.deltaX = distX;
313 - template.deltaY = distY;
314 - template.pageX = touch.pageX;
315 - template.pageY = touch.pageY;
316 - template.velocityX = distX / time;
317 - template.velocityY = distY / time;
318 - template.targetTouches = touches;
319 - template.finger = touches ?
320 - touches.length :
321 - 1 ;
322 -
323 - // The _handled method is fired to tell the default movestart
324 - // handler that one of the move events is bound.
325 - template._handled = handled;
326 -
327 - // Pass the touchmove event so it can be prevented if or when
328 - // movestart is handled.
329 - template._preventTouchmoveDefault = function() {
330 - e.preventDefault();
327 + var template = {
328 + altKey: e.altKey,
329 + ctrlKey: e.ctrlKey,
330 + shiftKey: e.shiftKey,
331 + startX: data.pageX,
332 + startY: data.pageY,
333 + distX: distX,
334 + distY: distY,
335 + deltaX: distX,
336 + deltaY: distY,
337 + pageX: touch.pageX,
338 + pageY: touch.pageY,
339 + velocityX: distX / time,
340 + velocityY: distY / time,
341 + identifier: data.identifier,
342 + targetTouches: touches,
343 + finger: touches ? touches.length : 1,
344 + enableMove: function() {
345 + this.moveEnabled = true;
346 + this.enableMove = noop;
347 + e.preventDefault();
348 + }
331 349 };
332 350
333 351 // Trigger the movestart event.
334 - trigger(template.target, template);
352 + trigger(data.target, 'movestart', template);
335 353
336 354 // Unbind handlers that tracked the touch or mouse up till now.
337 - fn(template.identifier);
355 + fn(data);
338 356 }
339 357
340 358
341 359 // Handlers that control what happens following a movestart
342 360
343 - function activeMousemove(e) {
344 - var timer = e.data.timer;
361 + function activeMousemove(e, data) {
362 + var timer = data.timer;
345 363
346 - e.data.touch = e;
347 - e.data.timeStamp = e.timeStamp;
364 + data.touch = e;
365 + data.timeStamp = e.timeStamp;
348 366 timer.kick();
349 367 }
350 368
351 - function activeMouseend(e) {
352 - var event = e.data.event,
353 - timer = e.data.timer;
354 -
369 + function activeMouseend(e, data) {
370 + var target = data.target;
371 + var event = data.event;
372 + var timer = data.timer;
373 +
355 374 removeActiveMouse();
356 375
357 - endEvent(event, timer, function() {
376 + endEvent(target, event, timer, function() {
358 377 // Unbind the click suppressor, waiting until after mouseup
359 378 // has been handled.
360 379 setTimeout(function(){
361 - remove(event.target, 'click', returnFalse);
380 + off(target, 'click', preventDefault);
362 381 }, 0);
363 382 });
364 383 }
365 384
366 - function removeActiveMouse(event) {
367 - remove(document, mouseevents.move, activeMousemove);
368 - remove(document, mouseevents.end, activeMouseend);
385 + function removeActiveMouse() {
386 + off(document, mouseevents.move, activeMousemove);
387 + off(document, mouseevents.end, activeMouseend);
369 388 }
370 389
371 - function activeTouchmove(e) {
372 - var event = e.data.event,
373 - timer = e.data.timer,
374 - touch = changedTouch(e, event);
390 + function activeTouchmove(e, data) {
391 + var event = data.event;
392 + var timer = data.timer;
393 + var touch = changedTouch(e, event);
375 394
376 395 if (!touch) { return; }
377 396
378 397 // Stop the interface from gesturing
@@ -378,42 +397,43 @@
378 397 // Stop the interface from gesturing
379 398 e.preventDefault();
380 399
381 400 event.targetTouches = e.targetTouches;
382 - e.data.touch = touch;
383 - e.data.timeStamp = e.timeStamp;
401 + data.touch = touch;
402 + data.timeStamp = e.timeStamp;
403 +
384 404 timer.kick();
385 405 }
386 406
387 - function activeTouchend(e) {
388 - var event = e.data.event,
389 - timer = e.data.timer,
390 - touch = identifiedTouch(e.changedTouches, event.identifier);
407 + function activeTouchend(e, data) {
408 + var target = data.target;
409 + var event = data.event;
410 + var timer = data.timer;
411 + var touch = identifiedTouch(e.changedTouches, event.identifier);
391 412
392 413 // This isn't the touch you're looking for.
393 414 if (!touch) { return; }
394 415
395 - removeActiveTouch(event);
396 - endEvent(event, timer);
416 + removeActiveTouch(data);
417 + endEvent(target, event, timer);
397 418 }
398 419
399 - function removeActiveTouch(event) {
400 - remove(document, '.' + event.identifier, activeTouchmove);
401 - remove(document, '.' + event.identifier, activeTouchend);
420 + function removeActiveTouch(data) {
421 + off(document, touchevents.move, data.activeTouchmove);
422 + off(document, touchevents.end, data.activeTouchend);
402 423 }
403 424
404 425
405 426 // Logic for triggering move and moveend events
406 427
407 - function updateEvent(event, touch, timeStamp, timer) {
428 + function updateEvent(event, touch, timeStamp) {
408 429 var time = timeStamp - event.timeStamp;
409 430
410 - event.type = 'move';
411 431 event.distX = touch.pageX - event.startX;
412 432 event.distY = touch.pageY - event.startY;
413 433 event.deltaX = touch.pageX - event.pageX;
414 434 event.deltaY = touch.pageY - event.pageY;
415 -
435 +
416 436 // Average the velocity of the last few events using a decay
417 437 // curve to even out spurious jumps in values.
418 438 event.velocityX = 0.3 * event.velocityX + 0.7 * event.deltaX / time;
419 439 event.velocityY = 0.3 * event.velocityY + 0.7 * event.deltaY / time;
@@ -420,167 +440,145 @@
420 440 event.pageX = touch.pageX;
421 441 event.pageY = touch.pageY;
422 442 }
423 443
424 - function endEvent(event, timer, fn) {
444 + function endEvent(target, event, timer, fn) {
425 445 timer.end(function(){
426 - event.type = 'moveend';
427 -
428 - trigger(event.target, event);
429 -
446 + trigger(target, 'moveend', event);
430 447 return fn && fn();
431 448 });
432 449 }
433 450
434 451
435 - // jQuery special event definition
452 + // Set up the DOM
436 453
437 - function setup(data, namespaces, eventHandle) {
438 - // Stop the node from being dragged
439 - //add(this, 'dragstart.move drag.move', preventDefault);
440 -
441 - // Prevent text selection and touch interface scrolling
442 - //add(this, 'mousedown.move', preventIgnoreTags);
443 -
444 - // Tell movestart default handler that we've handled this
445 - add(this, 'movestart.move', flagAsHandled);
454 + function movestart(e) {
455 + if (e.defaultPrevented) { return; }
456 + if (!e.moveEnabled) { return; }
446 457
447 - // Don't bind to the DOM. For speed.
448 - return true;
449 - }
450 -
451 - function teardown(namespaces) {
452 - remove(this, 'dragstart drag', preventDefault);
453 - remove(this, 'mousedown touchstart', preventIgnoreTags);
454 - remove(this, 'movestart', flagAsHandled);
455 -
456 - // Don't bind to the DOM. For speed.
457 - return true;
458 - }
459 -
460 - function addMethod(handleObj) {
461 - // We're not interested in preventing defaults for handlers that
462 - // come from internal move or moveend bindings
463 - if (handleObj.namespace === "move" || handleObj.namespace === "moveend") {
464 - return;
458 + var event = {
459 + startX: e.startX,
460 + startY: e.startY,
461 + pageX: e.pageX,
462 + pageY: e.pageY,
463 + distX: e.distX,
464 + distY: e.distY,
465 + deltaX: e.deltaX,
466 + deltaY: e.deltaY,
467 + velocityX: e.velocityX,
468 + velocityY: e.velocityY,
469 + identifier: e.identifier,
470 + targetTouches: e.targetTouches,
471 + finger: e.finger
472 + };
473 +
474 + var data = {
475 + target: e.target,
476 + event: event,
477 + timer: new Timer(update),
478 + touch: undefined,
479 + timeStamp: e.timeStamp
480 + };
481 +
482 + function update(time) {
483 + updateEvent(event, data.touch, data.timeStamp);
484 + trigger(data.target, 'move', event);
465 485 }
466 -
467 - // Stop the node from being dragged
468 - add(this, 'dragstart.' + handleObj.guid + ' drag.' + handleObj.guid, preventDefault, undefined, handleObj.selector);
469 -
470 - // Prevent text selection and touch interface scrolling
471 - add(this, 'mousedown.' + handleObj.guid, preventIgnoreTags, undefined, handleObj.selector);
472 - }
473 -
474 - function removeMethod(handleObj) {
475 - if (handleObj.namespace === "move" || handleObj.namespace === "moveend") {
476 - return;
486 +
487 + if (e.identifier === undefined) {
488 + // We're dealing with a mouse event.
489 + // Stop clicks from propagating during a move
490 + on(e.target, 'click', preventDefault);
491 + on(document, mouseevents.move, activeMousemove, data);
492 + on(document, mouseevents.end, activeMouseend, data);
477 493 }
478 -
479 - remove(this, 'dragstart.' + handleObj.guid + ' drag.' + handleObj.guid);
480 - remove(this, 'mousedown.' + handleObj.guid);
494 + else {
495 + // In order to unbind correct handlers they have to be unique
496 + data.activeTouchmove = function(e, data) { activeTouchmove(e, data); };
497 + data.activeTouchend = function(e, data) { activeTouchend(e, data); };
498 +
499 + // We're dealing with a touch.
500 + on(document, touchevents.move, data.activeTouchmove, data);
501 + on(document, touchevents.end, data.activeTouchend, data);
502 + }
481 503 }
482 -
483 - jQuery.event.special.movestart = {
484 - setup: setup,
485 - teardown: teardown,
486 - add: addMethod,
487 - remove: removeMethod,
488 504
489 - _default: function(e) {
490 - var event, data;
491 -
492 - // If no move events were bound to any ancestors of this
493 - // target, high tail it out of here.
494 - if (!e._handled()) { return; }
505 + on(document, 'mousedown', mousedown);
506 + on(document, 'touchstart', touchstart);
507 + on(document, 'movestart', movestart);
495 508
496 - function update(time) {
497 - updateEvent(event, data.touch, data.timeStamp);
498 - trigger(e.target, event);
509 +
510 + // jQuery special events
511 + //
512 + // jQuery event objects are copies of DOM event objects. They need
513 + // a little help copying the move properties across.
514 +
515 + if (!window.jQuery) { return; }
516 +
517 + var properties = ("startX startY pageX pageY distX distY deltaX deltaY velocityX velocityY").split(' ');
518 +
519 + function enableMove1(e) { e.enableMove(); }
520 + function enableMove2(e) { e.enableMove(); }
521 + function enableMove3(e) { e.enableMove(); }
522 +
523 + function add(handleObj) {
524 + var handler = handleObj.handler;
525 +
526 + handleObj.handler = function(e) {
527 + // Copy move properties across from originalEvent
528 + var i = properties.length;
529 + var property;
530 +
531 + while(i--) {
532 + property = properties[i];
533 + e[property] = e.originalEvent[property];
499 534 }
500 535
501 - event = {
502 - target: e.target,
503 - startX: e.startX,
504 - startY: e.startY,
505 - pageX: e.pageX,
506 - pageY: e.pageY,
507 - distX: e.distX,
508 - distY: e.distY,
509 - deltaX: e.deltaX,
510 - deltaY: e.deltaY,
511 - velocityX: e.velocityX,
512 - velocityY: e.velocityY,
513 - timeStamp: e.timeStamp,
514 - identifier: e.identifier,
515 - targetTouches: e.targetTouches,
516 - finger: e.finger
517 - };
536 + handler.apply(this, arguments);
537 + };
538 + }
518 539
519 - data = {
520 - event: event,
521 - timer: new Timer(update),
522 - touch: undefined,
523 - timeStamp: undefined
524 - };
525 -
526 - if (e.identifier === undefined) {
527 - // We're dealing with a mouse
528 - // Stop clicks from propagating during a move
529 - add(e.target, 'click', returnFalse);
530 - add(document, mouseevents.move, activeMousemove, data);
531 - add(document, mouseevents.end, activeMouseend, data);
532 - }
533 - else {
534 - // We're dealing with a touch. Stop touchmove doing
535 - // anything defaulty.
536 - e._preventTouchmoveDefault();
537 - add(document, touchevents.move + '.' + e.identifier, activeTouchmove, data);
538 - add(document, touchevents.end + '.' + e.identifier, activeTouchend, data);
539 - }
540 - }
540 + jQuery.event.special.movestart = {
541 + setup: function() {
542 + // Movestart must be enabled to allow other move events
543 + on(this, 'movestart', enableMove1);
544 +
545 + // Do listen to DOM events
546 + return false;
547 + },
548 +
549 + teardown: function() {
550 + off(this, 'movestart', enableMove1);
551 + return false;
552 + },
553 +
554 + add: add
541 555 };
542 556
543 557 jQuery.event.special.move = {
544 558 setup: function() {
545 - // Bind a noop to movestart. Why? It's the movestart
546 - // setup that decides whether other move events are fired.
547 - add(this, 'movestart.move', jQuery.noop);
559 + on(this, 'movestart', enableMove2);
560 + return false;
548 561 },
549 -
562 +
550 563 teardown: function() {
551 - remove(this, 'movestart.move', jQuery.noop);
552 - }
564 + off(this, 'movestart', enableMove2);
565 + return false;
566 + },
567 +
568 + add: add
553 569 };
554 -
570 +
555 571 jQuery.event.special.moveend = {
556 572 setup: function() {
557 - // Bind a noop to movestart. Why? It's the movestart
558 - // setup that decides whether other move events are fired.
559 - add(this, 'movestart.moveend', jQuery.noop);
573 + on(this, 'movestart', enableMove3);
574 + return false;
560 575 },
561 -
576 +
562 577 teardown: function() {
563 - remove(this, 'movestart.moveend', jQuery.noop);
564 - }
565 - };
578 + off(this, 'movestart', enableMove3);
579 + return false;
580 + },
566 581
567 - add(document, 'mousedown.move', mousedown);
568 - add(document, 'touchstart.move', touchstart);
569 -
570 - // Make jQuery copy touch event properties over to the jQuery event
571 - // object, if they are not already listed. But only do the ones we
572 - // really need. IE7/8 do not have Array#indexOf(), but nor do they
573 - // have touch events, so let's assume we can ignore them.
574 - if (typeof Array.prototype.indexOf === 'function') {
575 - (function(jQuery, undefined){
576 - var props = ["changedTouches", "targetTouches"],
577 - l = props.length;
578 -
579 - while (l--) {
580 - if (jQuery.event.props.indexOf(props[l]) === -1) {
581 - jQuery.event.props.push(props[l]);
582 - }
583 - }
584 - })(jQuery);
582 + add: add
585 583 };
586 584 });