PageSourceSearch

https://www.olympusat.com/wp-content/themes/olympusat/frontend-boi…/js/jquery.event.move.js?ver=1.0.3

js olympusat.com collected 2026-10-02 05:51:15 UTC 13,836 bytes, 576 lines download raw bytes

1// DOM.event.move
2//
3// 2.0.0
4//
5// Stephen Band
6//
7// Triggers 'movestart', 'move' and 'moveend' events after
8// mousemoves following a mousedown cross a distance threshold,
9// similar to the native 'dragstart', 'drag' and 'dragend' events.
10// Move events are throttled to animation frames. Move event objects
11// have the properties:
12//
13// pageX:
14// pageY:     Page coordinates of pointer.
15// startX:
16// startY:    Page coordinates of pointer at movestart.
17// distX:
18// distY:     Distance the pointer has moved since movestart.
19// deltaX:
20// deltaY:    Distance the finger has moved since last event.
21// velocityX:
22// velocityY: Average velocity over last few events.
23
24
25(function(fn) {
26	if (typeof define === 'function' && define.amd) {
27        define([], fn);
28    } else if ((typeof module !== "undefined" && module !== null) && module.exports) {
29        module.exports = fn;
30	} else {
31		fn();
32	}
33})(function(){
34	var assign = Object.assign || window.jQuery && jQuery.extend;
35
36	// Number of pixels a pressed pointer travels before movestart
37	// event is fired.
38	var threshold = 8;
39
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	})();
56
57	var ignoreTags = {
58			textarea: true,
59			input: true,
60			select: true,
61			button: true
62		};
63
64	var mouseevents = {
65		move:   'mousemove',
66		cancel: 'mouseup dragstart',
67		end:    'mouseup'
68	};
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 handlers, type;
98
99		function handler(e) { fn(e, data); }
100
101		for (type of types) {
102			handlers = events[type] || (events[type] = []);
103			handlers.push([fn, handler]);
104			node.addEventListener(type, handler);
105		}
106	}
107
108	function off(node, types, fn, selector) {
109		types = types.split(rspaces);
110
111		var events = getEvents(node);
112		var type, handlers, i;
113
114		if (!events) { return; }
115
116		for (type of types) {
117			handlers = events[type];
118			if (!handlers) { continue; }
119			i = handlers.length;
120			while (i--) {
121				if (handlers[i][0] === fn) {
122					node.removeEventListener(type, handlers[i][1]);
123					handlers.splice(i, 1);
124				}
125			}
126		}
127	}
128
129	function trigger(node, type, properties) {
130		// Don't cache events. It prevents you from triggering an event of a
131		// given type from inside the handler of another event of that type.
132		var event = createEvent(type);
133		if (properties) { assign(event, properties); }
134		node.dispatchEvent(event);
135	}
136
137
138	// Constructors
139	
140	function Timer(fn){
141		var callback = fn,
142		    active = false,
143		    running = false;
144		
145		function trigger(time) {
146			if (active){
147				callback();
148				requestFrame(trigger);
149				running = true;
150				active = false;
151			}
152			else {
153				running = false;
154			}
155		}
156		
157		this.kick = function(fn) {
158			active = true;
159			if (!running) { trigger(); }
160		};
161		
162		this.end = function(fn) {
163			var cb = callback;
164			
165			if (!fn) { return; }
166			
167			// If the timer is not running, simply call the end callback.
168			if (!running) {
169				fn();
170			}
171			// If the timer is running, and has been kicked lately, then
172			// queue up the current callback and the end callback, otherwise
173			// just the end callback.
174			else {
175				callback = active ?
176					function(){ cb(); fn(); } : 
177					fn ;
178				
179				active = true;
180			}
181		};
182	}
183
184
185	// Functions
186
187	function noop() {}
188	
189	function preventDefault(e) {
190		e.preventDefault();
191	}
192
193	function isIgnoreTag(e) {
194		return !!ignoreTags[e.target.tagName.toLowerCase()];
195	}
196
197	function isPrimaryButton(e) {
198		// Ignore mousedowns on any button other than the left (or primary)
199		// mouse button, or when a modifier key is pressed.
200		return (e.which === 1 && !e.ctrlKey && !e.altKey);
201	}
202
203	function identifiedTouch(touchList, id) {
204		var i, l;
205
206		if (touchList.identifiedTouch) {
207			return touchList.identifiedTouch(id);
208		}
209		
210		// touchList.identifiedTouch() does not exist in
211		// webkit yet… we must do the search ourselves...
212		
213		i = -1;
214		l = touchList.length;
215		
216		while (++i < l) {
217			if (touchList[i].identifier === id) {
218				return touchList[i];
219			}
220		}
221	}
222
223	function changedTouch(e, data) {
224		var touch = identifiedTouch(e.changedTouches, data.identifier);
225
226		// This isn't the touch you're looking for.
227		if (!touch) { return; }
228
229		// Chrome Android (at least) includes touches that have not
230		// changed in e.changedTouches. That's a bit annoying. Check
231		// that this touch has changed.
232		if (touch.pageX === data.pageX && touch.pageY === data.pageY) { return; }
233
234		return touch;
235	}
236
237
238	// Handlers that decide when the first movestart is triggered
239	
240	function mousedown(e){
241		// Ignore non-primary buttons
242		if (!isPrimaryButton(e)) { return; }
243
244		// Ignore form and interactive elements
245		if (isIgnoreTag(e)) { return; }
246
247		on(document, mouseevents.move, mousemove, e);
248		on(document, mouseevents.cancel, mouseend, e);
249	}
250
251	function mousemove(e, data){
252		checkThreshold(e, data, e, removeMouse);
253	}
254
255	function mouseend(e, data) {
256		removeMouse();
257	}
258
259	function removeMouse() {
260		off(document, mouseevents.move, mousemove);
261		off(document, mouseevents.cancel, mouseend);
262	}
263
264	function touchstart(e) {
265		// Don't get in the way of interaction with form elements
266		if (ignoreTags[e.target.tagName.toLowerCase()]) { return; }
267
268		var touch = e.changedTouches[0];
269
270		// iOS live updates the touch objects whereas Android gives us copies.
271		// That means we can't trust the touchstart object to stay the same,
272		// so we must copy the data. This object acts as a template for
273		// movestart, move and moveend event objects.
274		var data = {
275			target:     touch.target,
276			pageX:      touch.pageX,
277			pageY:      touch.pageY,
278			identifier: touch.identifier,
279
280			// The only way to make handlers individually unbindable is by
281			// making them unique.
282			touchmove:  function(e, data) { touchmove(e, data); },
283			touchend:   function(e, data) { touchend(e, data); }
284		};
285
286		on(document, touchevents.move, data.touchmove, data);
287		on(document, touchevents.cancel, data.touchend, data);
288	}
289
290	function touchmove(e, data) {
291		var touch = changedTouch(e, data);
292		if (!touch) { return; }
293		checkThreshold(e, data, touch, removeTouch);
294	}
295
296	function touchend(e, data) {
297		var touch = identifiedTouch(e.changedTouches, data.identifier);
298		if (!touch) { return; }
299		removeTouch(data);
300	}
301
302	function removeTouch(data) {
303		off(document, touchevents.move, data.touchmove);
304		off(document, touchevents.cancel, data.touchend);
305	}
306
307	function checkThreshold(e, data, touch, fn) {
308		var distX = touch.pageX - data.pageX;
309		var distY = touch.pageY - data.pageY;
310
311		// Do nothing if the threshold has not been crossed.
312		if ((distX * distX) + (distY * distY) < (threshold * threshold)) { return; }
313
314		triggerStart(e, data, touch, distX, distY, fn);
315	}
316
317	function triggerStart(e, data, touch, distX, distY, fn) {
318		var touches = e.targetTouches;
319		var time = e.timeStamp - data.timeStamp;
320
321		// Create a movestart object with some special properties that
322		// are passed only to the movestart handlers.
323		var template = {
324			altKey:     e.altKey,
325			ctrlKey:    e.ctrlKey,
326			shiftKey:   e.shiftKey,
327			startX:     data.pageX,
328			startY:     data.pageY,
329			distX:      distX,
330			distY:      distY,
331			deltaX:     distX,
332			deltaY:     distY,
333			pageX:      touch.pageX,
334			pageY:      touch.pageY,
335			velocityX:  distX / time,
336			velocityY:  distY / time,
337			identifier: data.identifier,
338			targetTouches: touches,
339			finger: touches ? touches.length : 1,
340			enableMove: function() {
341				this.moveEnabled = true;
342				this.enableMove = noop;
343				e.preventDefault();
344			}
345		};
346
347		// Trigger the movestart event.
348		trigger(data.target, 'movestart', template);
349
350		// Unbind handlers that tracked the touch or mouse up till now.
351		fn(data);
352	}
353
354
355	// Handlers that control what happens following a movestart
356
357	function activeMousemove(e, data) {
358		var timer  = data.timer;
359
360		data.touch = e;
361		data.timeStamp = e.timeStamp;
362		timer.kick();
363	}
364
365	function activeMouseend(e, data) {
366		var target = data.target;
367		var event  = data.event;
368		var timer  = data.timer;
369
370		removeActiveMouse();
371
372		endEvent(target, event, timer, function() {
373			// Unbind the click suppressor, waiting until after mouseup
374			// has been handled.
375			setTimeout(function(){
376				off(target, 'click', preventDefault);
377			}, 0);
378		});
379	}
380
381	function removeActiveMouse() {
382		off(document, mouseevents.move, activeMousemove);
383		off(document, mouseevents.end, activeMouseend);
384	}
385
386	function activeTouchmove(e, data) {
387		var event = data.event;
388		var timer = data.timer;
389		var touch = changedTouch(e, event);
390
391		if (!touch) { return; }
392
393		// Stop the interface from gesturing
394		e.preventDefault();
395
396		event.targetTouches = e.targetTouches;
397		data.touch = touch;
398		data.timeStamp = e.timeStamp;
399
400		timer.kick();
401	}
402
403	function activeTouchend(e, data) {
404		var target = data.target;
405		var event  = data.event;
406		var timer  = data.timer;
407		var touch  = identifiedTouch(e.changedTouches, event.identifier);
408
409		// This isn't the touch you're looking for.
410		if (!touch) { return; }
411
412		removeActiveTouch(data);
413		endEvent(target, event, timer);
414	}
415
416	function removeActiveTouch(data) {
417		off(document, touchevents.move, data.activeTouchmove);
418		off(document, touchevents.end, data.activeTouchend);
419	}
420
421
422	// Logic for triggering move and moveend events
423
424	function updateEvent(event, touch, timeStamp) {
425		var time = timeStamp - event.timeStamp;
426
427		event.distX =  touch.pageX - event.startX;
428		event.distY =  touch.pageY - event.startY;
429		event.deltaX = touch.pageX - event.pageX;
430		event.deltaY = touch.pageY - event.pageY;
431		
432		// Average the velocity of the last few events using a decay
433		// curve to even out spurious jumps in values.
434		event.velocityX = 0.3 * event.velocityX + 0.7 * event.deltaX / time;
435		event.velocityY = 0.3 * event.velocityY + 0.7 * event.deltaY / time;
436		event.pageX =  touch.pageX;
437		event.pageY =  touch.pageY;
438	}
439
440	function endEvent(target, event, timer, fn) {
441		timer.end(function(){
442			trigger(target, 'moveend', event);
443			return fn && fn();
444		});
445	}
446
447
448	// Set up the DOM
449
450	function movestart(e) {
451		if (e.defaultPrevented) { return; }
452		if (!e.moveEnabled) { return; }
453
454		var event = {
455			startX:        e.startX,
456			startY:        e.startY,
457			pageX:         e.pageX,
458			pageY:         e.pageY,
459			distX:         e.distX,
460			distY:         e.distY,
461			deltaX:        e.deltaX,
462			deltaY:        e.deltaY,
463			velocityX:     e.velocityX,
464			velocityY:     e.velocityY,
465			identifier:    e.identifier,
466			targetTouches: e.targetTouches,
467			finger:        e.finger
468		};
469
470		var data = {
471			target:    e.target,
472			event:     event,
473			timer:     new Timer(update),
474			touch:     undefined,
475			timeStamp: e.timeStamp
476		};
477
478		function update(time) {
479			updateEvent(event, data.touch, data.timeStamp);
480			trigger(data.target, 'move', event);
481		}
482
483		if (e.identifier === undefined) {
484			// We're dealing with a mouse event.
485			// Stop clicks from propagating during a move
486			on(e.target, 'click', preventDefault);
487			on(document, mouseevents.move, activeMousemove, data);
488			on(document, mouseevents.end, activeMouseend, data);
489		}
490		else {
491			// In order to unbind correct handlers they have to be unique
492			data.activeTouchmove = function(e, data) { activeTouchmove(e, data); };
493			data.activeTouchend = function(e, data) { activeTouchend(e, data); };
494
495			// We're dealing with a touch.
496			on(document, touchevents.move, data.activeTouchmove, data);
497			on(document, touchevents.end, data.activeTouchend, data);
498		}
499	}
500
501	on(document, 'mousedown', mousedown);
502	on(document, 'touchstart', touchstart);
503	on(document, 'movestart', movestart);
504
505
506	// jQuery special events
507	//
508	// jQuery event objects are copies of DOM event objects. They need
509	// a little help copying the move properties across.
510
511	if (!window.jQuery) { return; }
512
513	var properties = ("startX startY pageX pageY distX distY deltaX deltaY velocityX velocityY").split(' ');
514
515	function enableMove1(e) { e.enableMove(); }
516	function enableMove2(e) { e.enableMove(); }
517	function enableMove3(e) { e.enableMove(); }
518
519	function add(handleObj) {
520		var handler = handleObj.handler;
521
522		handleObj.handler = function(e) {
523			// Copy move properties across from originalEvent
524			var property;
525			for (property of properties) {
526				e[property] = e.originalEvent[property];
527			}
528			handler.apply(this, arguments);
529		};
530	}
531
532	jQuery.event.special.movestart = {
533		setup: function() {
534			// Movestart must be enabled to allow other move events
535			on(this, 'movestart', enableMove1);
536
537			// Do listen to DOM events
538			return false;
539		},
540
541		teardown: function() {
542			off(this, 'movestart', enableMove1);
543			return false;
544		},
545
546		add: add
547	};
548
549	jQuery.event.special.move = {
550		setup: function() {
551			on(this, 'movestart', enableMove2);
552			return false;
553		},
554
555		teardown: function() {
556			off(this, 'movestart', enableMove2);
557			return false;
558		},
559
560		add: add
561	};
562
563	jQuery.event.special.moveend = {
564		setup: function() {
565			on(this, 'movestart', enableMove3);
566			return false;
567		},
568
569		teardown: function() {
570			off(this, 'movestart', enableMove3);
571			return false;
572		},
573
574		add: add
575	};
576});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.