PageSourceSearch

https://parisandco.fr/wp-content/themes/estato/js/iscroll.js?ver=6.8.10

js parisandco.fr collected 2026-10-04 13:26:28 UTC 50,100 bytes, 2,012 lines download raw bytes

vendor: 4,204 bytes, lines 1-153
1'use strict';
2/*! iScroll v5.1.3 ~ (c) 2008-2014 Matteo Spinelli ~ http://cubiq.org/license */
3(function (window, document, Math) {
4var rAF = window.requestAnimationFrame	||
5	window.webkitRequestAnimationFrame	||
6	window.mozRequestAnimationFrame		||
7	window.oRequestAnimationFrame		||
8	window.msRequestAnimationFrame		||
9	function (callback) { window.setTimeout(callback, 1000 / 60); };
10
11var utils = (function () {
12	var me = {};
13
14	var _elementStyle = document.createElement('div').style;
15	var _vendor = (function () {
16		var vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],
17			transform,
18			i = 0,
19			l = vendors.length;
20
21		for ( ; i < l; i++ ) {
22			transform = vendors[i] + 'ransform';
23			if ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);
24		}
25
26		return false;
27	})();
28
29	function _prefixStyle (style) {
30		if ( _vendor === false ) return false;
31		if ( _vendor === '' ) return style;
32		return _vendor + style.charAt(0).toUpperCase() + style.substr(1);
33	}
34
35	me.getTime = Date.now || function getTime () { return new Date().getTime(); };
36
37	me.extend = function (target, obj) {
38		for ( var i in obj ) {
39			target[i] = obj[i];
40		}
41	};
42
43	me.addEvent = function (el, type, fn, capture) {
44		el.addEventListener(type, fn, !!capture);
45	};
46
47	me.removeEvent = function (el, type, fn, capture) {
48		el.removeEventListener(type, fn, !!capture);
49	};
50
51	me.prefixPointerEvent = function (pointerEvent) {
52		return window.MSPointerEvent ? 
53			'MSPointer' + pointerEvent.charAt(9).toUpperCase() + pointerEvent.substr(10):
54			pointerEvent;
55	};
56
57	me.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {
58		var distance = current - start,
59			speed = Math.abs(distance) / time,
60			destination,
61			duration;
62
63		deceleration = deceleration === undefined ? 0.0006 : deceleration;
64
65		destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
66		duration = speed / deceleration;
67
68		if ( destination < lowerMargin ) {
69			destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
70			distance = Math.abs(destination - current);
71			duration = distance / speed;
72		} else if ( destination > 0 ) {
73			destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
74			distance = Math.abs(current) + destination;
75			duration = distance / speed;
76		}
77
78		return {
79			destination: Math.round(destination),
80			duration: duration
81		};
82	};
83
84	var _transform = _prefixStyle('transform');
85
86	me.extend(me, {
87		hasTransform: _transform !== false,
88		hasPerspective: _prefixStyle('perspective') in _elementStyle,
89		hasTouch: 'ontouchstart' in window,
90		hasPointer: window.PointerEvent || window.MSPointerEvent, // IE10 is prefixed
91		hasTransition: _prefixStyle('transition') in _elementStyle
92	});
93
94	// This should find all Android browsers lower than build 535.19 (both stock browser and webview)
95	me.isBadAndroid = /Android /.test(window.navigator.appVersion) && !(/Chrome\/\d/.test(window.navigator.appVersion));
96
97	me.extend(me.style = {}, {
98		transform: _transform,
99		transitionTimingFunction: _prefixStyle('transitionTimingFunction'),
100		transitionDuration: _prefixStyle('transitionDuration'),
101		transitionDelay: _prefixStyle('transitionDelay'),
102		transformOrigin: _prefixStyle('transformOrigin')
103	});
104
105	me.hasClass = function (e, c) {
106		var re = new RegExp("(^|\\s)" + c + "(\\s|$)");
107		return re.test(e.className);
108	};
109
110	me.addClass = function (e, c) {
111		if ( me.hasClass(e, c) ) {
112			return;
113		}
114
115		var newclass = e.className.split(' ');
116		newclass.push(c);
117		e.className = newclass.join(' ');
118	};
119
120	me.removeClass = function (e, c) {
121		if ( !me.hasClass(e, c) ) {
122			return;
123		}
124
125		var re = new RegExp("(^|\\s)" + c + "(\\s|$)", 'g');
126		e.className = e.className.replace(re, ' ');
127	};
128
129	me.offset = function (el) {
130		var left = -el.offsetLeft,
131			top = -el.offsetTop;
132
133		// jshint -W084
134		while (el = el.offsetParent) {
135			left -= el.offsetLeft;
136			top -= el.offsetTop;
137		}
138		// jshint +W084
139
140		return {
141			left: left,
142			top: top
143		};
144	};
145
146	me.preventDefaultException = function (el, exceptions) {
147		for ( var i in exceptions ) {
148			if ( exceptions[i].test(el[i]) ) {
149				return true;
150			}
151		}
152
153		return false;
vendor: 4,146 bytes, lines 154-307
154	};
155
156	me.extend(me.eventType = {}, {
157		touchstart: 1,
158		touchmove: 1,
159		touchend: 1,
160
161		mousedown: 2,
162		mousemove: 2,
163		mouseup: 2,
164
165		pointerdown: 3,
166		pointermove: 3,
167		pointerup: 3,
168
169		MSPointerDown: 3,
170		MSPointerMove: 3,
171		MSPointerUp: 3
172	});
173
174	me.extend(me.ease = {}, {
175		quadratic: {
176			style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
177			fn: function (k) {
178				return k * ( 2 - k );
179			}
180		},
181		circular: {
182			style: 'cubic-bezier(0.1, 0.57, 0.1, 1)',	// Not properly "circular" but this looks better, it should be (0.075, 0.82, 0.165, 1)
183			fn: function (k) {
184				return Math.sqrt( 1 - ( --k * k ) );
185			}
186		},
187		back: {
188			style: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',
189			fn: function (k) {
190				var b = 4;
191				return ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;
192			}
193		},
194		bounce: {
195			style: '',
196			fn: function (k) {
197				if ( ( k /= 1 ) < ( 1 / 2.75 ) ) {
198					return 7.5625 * k * k;
199				} else if ( k < ( 2 / 2.75 ) ) {
200					return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;
201				} else if ( k < ( 2.5 / 2.75 ) ) {
202					return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;
203				} else {
204					return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;
205				}
206			}
207		},
208		elastic: {
209			style: '',
210			fn: function (k) {
211				var f = 0.22,
212					e = 0.4;
213
214				if ( k === 0 ) { return 0; }
215				if ( k == 1 ) { return 1; }
216
217				return ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );
218			}
219		}
220	});
221
222	me.tap = function (e, eventName) {
223		var ev = document.createEvent('Event');
224		ev.initEvent(eventName, true, true);
225		ev.pageX = e.pageX;
226		ev.pageY = e.pageY;
227		e.target.dispatchEvent(ev);
228	};
229
230	me.click = function (e) {
231		var target = e.target,
232			ev;
233
234		if ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {
235			ev = document.createEvent('MouseEvents');
236			ev.initMouseEvent('click', true, true, e.view, 1,
237				target.screenX, target.screenY, target.clientX, target.clientY,
238				e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
239				0, null);
240
241			ev._constructed = true;
242			target.dispatchEvent(ev);
243		}
244	};
245
246	return me;
247})();
248
249function IScroll (el, options) {
250	this.wrapper = typeof el == 'string' ? document.querySelector(el) : el;
251	this.scroller = this.wrapper.children[0];
252	this.scrollerStyle = this.scroller.style;		// cache style for better performance
253
254	this.options = {
255
256		resizeScrollbars: true,
257
258		mouseWheelSpeed: 20,
259
260		snapThreshold: 0.334,
261
262// INSERT POINT: OPTIONS 
263
264		startX: 0,
265		startY: 0,
266		scrollY: true,
267		directionLockThreshold: 5,
268		momentum: true,
269
270		bounce: true,
271		bounceTime: 600,
272		bounceEasing: '',
273
274		preventDefault: true,
275		preventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ },
276
277		HWCompositing: true,
278		useTransition: true,
279		useTransform: true
280	};
281
282	for ( var i in options ) {
283		this.options[i] = options[i];
284	}
285
286	// Normalize options
287	this.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';
288
289	this.options.useTransition = utils.hasTransition && this.options.useTransition;
290	this.options.useTransform = utils.hasTransform && this.options.useTransform;
291
292	this.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;
293	this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
294
295	// If you want eventPassthrough I have to lock one of the axes
296	this.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;
297	this.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;
298
299	// With eventPassthrough we also need lockDirection mechanism
300	this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
301	this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
302
303	this.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;
304
305	this.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;
306
307	if ( this.options.tap === true ) {
vendor: 4,198 bytes, lines 308-483
308		this.options.tap = 'tap';
309	}
310
311	if ( this.options.shrinkScrollbars == 'scale' ) {
312		this.options.useTransition = false;
313	}
314
315	this.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;
316
317// INSERT POINT: NORMALIZATION
318
319	// Some defaults	
320	this.x = 0;
321	this.y = 0;
322	this.directionX = 0;
323	this.directionY = 0;
324	this._events = {};
325
326// INSERT POINT: DEFAULTS
327
328	this._init();
329	this.refresh();
330
331	this.scrollTo(this.options.startX, this.options.startY);
332	this.enable();
333}
334
335IScroll.prototype = {
336	version: '5.1.3',
337
338	_init: function () {
339		this._initEvents();
340
341		if ( this.options.scrollbars || this.options.indicators ) {
342			this._initIndicators();
343		}
344
345		if ( this.options.mouseWheel ) {
346			this._initWheel();
347		}
348
349		if ( this.options.snap ) {
350			this._initSnap();
351		}
352
353		if ( this.options.keyBindings ) {
354			this._initKeys();
355		}
356
357// INSERT POINT: _init
358
359	},
360
361	destroy: function () {
362		this._initEvents(true);
363
364		this._execEvent('destroy');
365	},
366
367	_transitionEnd: function (e) {
368		if ( e.target != this.scroller || !this.isInTransition ) {
369			return;
370		}
371
372		this._transitionTime();
373		if ( !this.resetPosition(this.options.bounceTime) ) {
374			this.isInTransition = false;
375			this._execEvent('scrollEnd');
376		}
377	},
378
379	_start: function (e) {
380		// React to left mouse button only
381		if ( utils.eventType[e.type] != 1 ) {
382			if ( e.button !== 0 ) {
383				return;
384			}
385		}
386
387		if ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {
388			return;
389		}
390
391		if ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
392			e.preventDefault();
393		}
394
395		var point = e.touches ? e.touches[0] : e,
396			pos;
397
398		this.initiated	= utils.eventType[e.type];
399		this.moved		= false;
400		this.distX		= 0;
401		this.distY		= 0;
402		this.directionX = 0;
403		this.directionY = 0;
404		this.directionLocked = 0;
405
406		this._transitionTime();
407
408		this.startTime = utils.getTime();
409
410		if ( this.options.useTransition && this.isInTransition ) {
411			this.isInTransition = false;
412			pos = this.getComputedPosition();
413			this._translate(Math.round(pos.x), Math.round(pos.y));
414			this._execEvent('scrollEnd');
415		} else if ( !this.options.useTransition && this.isAnimating ) {
416			this.isAnimating = false;
417			this._execEvent('scrollEnd');
418		}
419
420		this.startX    = this.x;
421		this.startY    = this.y;
422		this.absStartX = this.x;
423		this.absStartY = this.y;
424		this.pointX    = point.pageX;
425		this.pointY    = point.pageY;
426
427		this._execEvent('beforeScrollStart');
428	},
429
430	_move: function (e) {
431		if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
432			return;
433		}
434
435		if ( this.options.preventDefault ) {	// increases performance on Android? TODO: check!
436			e.preventDefault();
437		}
438
439		var point		= e.touches ? e.touches[0] : e,
440			deltaX		= point.pageX - this.pointX,
441			deltaY		= point.pageY - this.pointY,
442			timestamp	= utils.getTime(),
443			newX, newY,
444			absDistX, absDistY;
445
446		this.pointX		= point.pageX;
447		this.pointY		= point.pageY;
448
449		this.distX		+= deltaX;
450		this.distY		+= deltaY;
451		absDistX		= Math.abs(this.distX);
452		absDistY		= Math.abs(this.distY);
453
454		// We need to move at least 10 pixels for the scrolling to initiate
455		if ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {
456			return;
457		}
458
459		// If you are scrolling in one direction lock the other
460		if ( !this.directionLocked && !this.options.freeScroll ) {
461			if ( absDistX > absDistY + this.options.directionLockThreshold ) {
462				this.directionLocked = 'h';		// lock horizontally
463			} else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {
464				this.directionLocked = 'v';		// lock vertically
465			} else {
466				this.directionLocked = 'n';		// no lock
467			}
468		}
469
470		if ( this.directionLocked == 'h' ) {
471			if ( this.options.eventPassthrough == 'vertical' ) {
472				e.preventDefault();
473			} else if ( this.options.eventPassthrough == 'horizontal' ) {
474				this.initiated = false;
475				return;
476			}
477
478			deltaY = 0;
479		} else if ( this.directionLocked == 'v' ) {
480			if ( this.options.eventPassthrough == 'horizontal' ) {
481				e.preventDefault();
482			} else if ( this.options.eventPassthrough == 'vertical' ) {
483				this.initiated = false;
vendor: 4,184 bytes, lines 484-648
484				return;
485			}
486
487			deltaX = 0;
488		}
489
490		deltaX = this.hasHorizontalScroll ? deltaX : 0;
491		deltaY = this.hasVerticalScroll ? deltaY : 0;
492
493		newX = this.x + deltaX;
494		newY = this.y + deltaY;
495
496		// Slow down if outside of the boundaries
497		if ( newX > 0 || newX < this.maxScrollX ) {
498			newX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;
499		}
500		if ( newY > 0 || newY < this.maxScrollY ) {
501			newY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;
502		}
503
504		this.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
505		this.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
506
507		if ( !this.moved ) {
508			this._execEvent('scrollStart');
509		}
510
511		this.moved = true;
512
513		this._translate(newX, newY);
514
515/* REPLACE START: _move */
516
517		if ( timestamp - this.startTime > 300 ) {
518			this.startTime = timestamp;
519			this.startX = this.x;
520			this.startY = this.y;
521		}
522
523/* REPLACE END: _move */
524
525	},
526
527	_end: function (e) {
528		if ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {
529			return;
530		}
531
532		if ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {
533			e.preventDefault();
534		}
535
536		var point = e.changedTouches ? e.changedTouches[0] : e,
537			momentumX,
538			momentumY,
539			duration = utils.getTime() - this.startTime,
540			newX = Math.round(this.x),
541			newY = Math.round(this.y),
542			distanceX = Math.abs(newX - this.startX),
543			distanceY = Math.abs(newY - this.startY),
544			time = 0,
545			easing = '';
546
547		this.isInTransition = 0;
548		this.initiated = 0;
549		this.endTime = utils.getTime();
550
551		// reset if we are outside of the boundaries
552		if ( this.resetPosition(this.options.bounceTime) ) {
553			return;
554		}
555
556		this.scrollTo(newX, newY);	// ensures that the last position is rounded
557
558		// we scrolled less than 10 pixels
559		if ( !this.moved ) {
560			if ( this.options.tap ) {
561				utils.tap(e, this.options.tap);
562			}
563
564			if ( this.options.click ) {
565				utils.click(e);
566			}
567
568			this._execEvent('scrollCancel');
569			return;
570		}
571
572		if ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {
573			this._execEvent('flick');
574			return;
575		}
576
577		// start momentum animation if needed
578		if ( this.options.momentum && duration < 300 ) {
579			momentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : { destination: newX, duration: 0 };
580			momentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : { destination: newY, duration: 0 };
581			newX = momentumX.destination;
582			newY = momentumY.destination;
583			time = Math.max(momentumX.duration, momentumY.duration);
584			this.isInTransition = 1;
585		}
586
587
588		if ( this.options.snap ) {
589			var snap = this._nearestSnap(newX, newY);
590			this.currentPage = snap;
591			time = this.options.snapSpeed || Math.max(
592					Math.max(
593						Math.min(Math.abs(newX - snap.x), 1000),
594						Math.min(Math.abs(newY - snap.y), 1000)
595					), 300);
596			newX = snap.x;
597			newY = snap.y;
598
599			this.directionX = 0;
600			this.directionY = 0;
601			easing = this.options.bounceEasing;
602		}
603
604// INSERT POINT: _end
605
606		if ( newX != this.x || newY != this.y ) {
607			// change easing function when scroller goes out of the boundaries
608			if ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {
609				easing = utils.ease.quadratic;
610			}
611
612			this.scrollTo(newX, newY, time, easing);
613			return;
614		}
615
616		this._execEvent('scrollEnd');
617	},
618
619	_resize: function () {
620		var that = this;
621
622		clearTimeout(this.resizeTimeout);
623
624		this.resizeTimeout = setTimeout(function () {
625			that.refresh();
626		}, this.options.resizePolling);
627	},
628
629	resetPosition: function (time) {
630		var x = this.x,
631			y = this.y;
632
633		time = time || 0;
634
635		if ( !this.hasHorizontalScroll || this.x > 0 ) {
636			x = 0;
637		} else if ( this.x < this.maxScrollX ) {
638			x = this.maxScrollX;
639		}
640
641		if ( !this.hasVerticalScroll || this.y > 0 ) {
642			y = 0;
643		} else if ( this.y < this.maxScrollY ) {
644			y = this.maxScrollY;
645		}
646
647		if ( x == this.x && y == this.y ) {
648			return false;
vendor: 11,242 bytes, lines 649-1120
649		}
650
651		this.scrollTo(x, y, time, this.options.bounceEasing);
652
653		return true;
654	},
655
656	disable: function () {
657		this.enabled = false;
658	},
659
660	enable: function () {
661		this.enabled = true;
662	},
663
664	refresh: function () {
665		var rf = this.wrapper.offsetHeight;		// Force reflow
666
667		this.wrapperWidth	= this.wrapper.clientWidth;
668		this.wrapperHeight	= this.wrapper.clientHeight;
669
670/* REPLACE START: refresh */
671
672		this.scrollerWidth	= this.scroller.offsetWidth;
673		this.scrollerHeight	= this.scroller.offsetHeight;
674
675		this.maxScrollX		= this.wrapperWidth - this.scrollerWidth;
676		this.maxScrollY		= this.wrapperHeight - this.scrollerHeight;
677
678/* REPLACE END: refresh */
679
680		this.hasHorizontalScroll	= this.options.scrollX && this.maxScrollX < 0;
681		this.hasVerticalScroll		= this.options.scrollY && this.maxScrollY < 0;
682
683		if ( !this.hasHorizontalScroll ) {
684			this.maxScrollX = 0;
685			this.scrollerWidth = this.wrapperWidth;
686		}
687
688		if ( !this.hasVerticalScroll ) {
689			this.maxScrollY = 0;
690			this.scrollerHeight = this.wrapperHeight;
691		}
692
693		this.endTime = 0;
694		this.directionX = 0;
695		this.directionY = 0;
696
697		this.wrapperOffset = utils.offset(this.wrapper);
698
699		this._execEvent('refresh');
700
701		this.resetPosition();
702
703// INSERT POINT: _refresh
704
705	},
706
707	on: function (type, fn) {
708		if ( !this._events[type] ) {
709			this._events[type] = [];
710		}
711
712		this._events[type].push(fn);
713	},
714
715	off: function (type, fn) {
716		if ( !this._events[type] ) {
717			return;
718		}
719
720		var index = this._events[type].indexOf(fn);
721
722		if ( index > -1 ) {
723			this._events[type].splice(index, 1);
724		}
725	},
726
727	_execEvent: function (type) {
728		if ( !this._events[type] ) {
729			return;
730		}
731
732		var i = 0,
733			l = this._events[type].length;
734
735		if ( !l ) {
736			return;
737		}
738
739		for ( ; i < l; i++ ) {
740			this._events[type][i].apply(this, [].slice.call(arguments, 1));
741		}
742	},
743
744	scrollBy: function (x, y, time, easing) {
745		x = this.x + x;
746		y = this.y + y;
747		time = time || 0;
748
749		this.scrollTo(x, y, time, easing);
750	},
751
752	scrollTo: function (x, y, time, easing) {
753		easing = easing || utils.ease.circular;
754
755		this.isInTransition = this.options.useTransition && time > 0;
756
757		if ( !time || (this.options.useTransition && easing.style) ) {
758			this._transitionTimingFunction(easing.style);
759			this._transitionTime(time);
760			this._translate(x, y);
761		} else {
762			this._animate(x, y, time, easing.fn);
763		}
764	},
765
766	scrollToElement: function (el, time, offsetX, offsetY, easing) {
767		el = el.nodeType ? el : this.scroller.querySelector(el);
768
769		if ( !el ) {
770			return;
771		}
772
773		var pos = utils.offset(el);
774
775		pos.left -= this.wrapperOffset.left;
776		pos.top  -= this.wrapperOffset.top;
777
778		// if offsetX/Y are true we center the element to the screen
779		if ( offsetX === true ) {
780			offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
781		}
782		if ( offsetY === true ) {
783			offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
784		}
785
786		pos.left -= offsetX || 0;
787		pos.top  -= offsetY || 0;
788
789		pos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
790		pos.top  = pos.top  > 0 ? 0 : pos.top  < this.maxScrollY ? this.maxScrollY : pos.top;
791
792		time = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;
793
794		this.scrollTo(pos.left, pos.top, time, easing);
795	},
796
797	_transitionTime: function (time) {
798		time = time || 0;
799
800		this.scrollerStyle[utils.style.transitionDuration] = time + 'ms';
801
802		if ( !time && utils.isBadAndroid ) {
803			this.scrollerStyle[utils.style.transitionDuration] = '0.001s';
804		}
805
806
807		if ( this.indicators ) {
808			for ( var i = this.indicators.length; i--; ) {
809				this.indicators[i].transitionTime(time);
810			}
811		}
812
813
814// INSERT POINT: _transitionTime
815
816	},
817
818	_transitionTimingFunction: function (easing) {
819		this.scrollerStyle[utils.style.transitionTimingFunction] = easing;
820
821
822		if ( this.indicators ) {
823			for ( var i = this.indicators.length; i--; ) {
824				this.indicators[i].transitionTimingFunction(easing);
825			}
826		}
827
828
829// INSERT POINT: _transitionTimingFunction
830
831	},
832
833	_translate: function (x, y) {
834		if ( this.options.useTransform ) {
835
836/* REPLACE START: _translate */
837
838			this.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;
839
840/* REPLACE END: _translate */
841
842		} else {
843			x = Math.round(x);
844			y = Math.round(y);
845			this.scrollerStyle.left = x + 'px';
846			this.scrollerStyle.top = y + 'px';
847		}
848
849		this.x = x;
850		this.y = y;
851
852
853	if ( this.indicators ) {
854		for ( var i = this.indicators.length; i--; ) {
855			this.indicators[i].updatePosition();
856		}
857	}
858
859
860// INSERT POINT: _translate
861
862	},
863
864	_initEvents: function (remove) {
865		var eventType = remove ? utils.removeEvent : utils.addEvent,
866			target = this.options.bindToWrapper ? this.wrapper : window;
867
868		eventType(window, 'orientationchange', this);
869		eventType(window, 'resize', this);
870
871		if ( this.options.click ) {
872			eventType(this.wrapper, 'click', this, true);
873		}
874
875		if ( !this.options.disableMouse ) {
876			eventType(this.wrapper, 'mousedown', this);
877			eventType(target, 'mousemove', this);
878			eventType(target, 'mousecancel', this);
879			eventType(target, 'mouseup', this);
880		}
881
882		if ( utils.hasPointer && !this.options.disablePointer ) {
883			eventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);
884			eventType(target, utils.prefixPointerEvent('pointermove'), this);
885			eventType(target, utils.prefixPointerEvent('pointercancel'), this);
886			eventType(target, utils.prefixPointerEvent('pointerup'), this);
887		}
888
889		if ( utils.hasTouch && !this.options.disableTouch ) {
890			eventType(this.wrapper, 'touchstart', this);
891			eventType(target, 'touchmove', this);
892			eventType(target, 'touchcancel', this);
893			eventType(target, 'touchend', this);
894		}
895
896		eventType(this.scroller, 'transitionend', this);
897		eventType(this.scroller, 'webkitTransitionEnd', this);
898		eventType(this.scroller, 'oTransitionEnd', this);
899		eventType(this.scroller, 'MSTransitionEnd', this);
900	},
901
902	getComputedPosition: function () {
903		var matrix = window.getComputedStyle(this.scroller, null),
904			x, y;
905
906		if ( this.options.useTransform ) {
907			matrix = matrix[utils.style.transform].split(')')[0].split(', ');
908			x = +(matrix[12] || matrix[4]);
909			y = +(matrix[13] || matrix[5]);
910		} else {
911			x = +matrix.left.replace(/[^-\d.]/g, '');
912			y = +matrix.top.replace(/[^-\d.]/g, '');
913		}
914
915		return { x: x, y: y };
916	},
917
918	_initIndicators: function () {
919		var interactive = this.options.interactiveScrollbars,
920			customStyle = typeof this.options.scrollbars != 'string',
921			indicators = [],
922			indicator;
923
924		var that = this;
925
926		this.indicators = [];
927
928		if ( this.options.scrollbars ) {
929			// Vertical scrollbar
930			if ( this.options.scrollY ) {
931				indicator = {
932					el: createDefaultScrollbar('v', interactive, this.options.scrollbars),
933					interactive: interactive,
934					defaultScrollbars: true,
935					customStyle: customStyle,
936					resize: this.options.resizeScrollbars,
937					shrink: this.options.shrinkScrollbars,
938					fade: this.options.fadeScrollbars,
939					listenX: false
940				};
941
942				this.wrapper.appendChild(indicator.el);
943				indicators.push(indicator);
944			}
945
946			// Horizontal scrollbar
947			if ( this.options.scrollX ) {
948				indicator = {
949					el: createDefaultScrollbar('h', interactive, this.options.scrollbars),
950					interactive: interactive,
951					defaultScrollbars: true,
952					customStyle: customStyle,
953					resize: this.options.resizeScrollbars,
954					shrink: this.options.shrinkScrollbars,
955					fade: this.options.fadeScrollbars,
956					listenY: false
957				};
958
959				this.wrapper.appendChild(indicator.el);
960				indicators.push(indicator);
961			}
962		}
963
964		if ( this.options.indicators ) {
965			// TODO: check concat compatibility
966			indicators = indicators.concat(this.options.indicators);
967		}
968
969		for ( var i = indicators.length; i--; ) {
970			this.indicators.push( new Indicator(this, indicators[i]) );
971		}
972
973		// TODO: check if we can use array.map (wide compatibility and performance issues)
974		function _indicatorsMap (fn) {
975			for ( var i = that.indicators.length; i--; ) {
976				fn.call(that.indicators[i]);
977			}
978		}
979
980		if ( this.options.fadeScrollbars ) {
981			this.on('scrollEnd', function () {
982				_indicatorsMap(function () {
983					this.fade();
984				});
985			});
986
987			this.on('scrollCancel', function () {
988				_indicatorsMap(function () {
989					this.fade();
990				});
991			});
992
993			this.on('scrollStart', function () {
994				_indicatorsMap(function () {
995					this.fade(1);
996				});
997			});
998
999			this.on('beforeScrollStart', function () {
1000				_indicatorsMap(function () {
1001					this.fade(1, true);
1002				});
1003			});
1004		}
1005
1006
1007		this.on('refresh', function () {
1008			_indicatorsMap(function () {
1009				this.refresh();
1010			});
1011		});
1012
1013		this.on('destroy', function () {
1014			_indicatorsMap(function () {
1015				this.destroy();
1016			});
1017
1018			delete this.indicators;
1019		});
1020	},
1021
1022	_initWheel: function () {
1023		utils.addEvent(this.wrapper, 'wheel', this);
1024		utils.addEvent(this.wrapper, 'mousewheel', this);
1025		utils.addEvent(this.wrapper, 'DOMMouseScroll', this);
1026
1027		this.on('destroy', function () {
1028			utils.removeEvent(this.wrapper, 'wheel', this);
1029			utils.removeEvent(this.wrapper, 'mousewheel', this);
1030			utils.removeEvent(this.wrapper, 'DOMMouseScroll', this);
1031		});
1032	},
1033
1034	_wheel: function (e) {
1035		if ( !this.enabled ) {
1036			return;
1037		}
1038
1039		e.preventDefault();
1040		e.stopPropagation();
1041
1042		var wheelDeltaX, wheelDeltaY,
1043			newX, newY,
1044			that = this;
1045
1046		if ( this.wheelTimeout === undefined ) {
1047			that._execEvent('scrollStart');
1048		}
1049
1050		// Execute the scrollEnd event after 400ms the wheel stopped scrolling
1051		clearTimeout(this.wheelTimeout);
1052		this.wheelTimeout = setTimeout(function () {
1053			that._execEvent('scrollEnd');
1054			that.wheelTimeout = undefined;
1055		}, 400);
1056
1057		if ( 'deltaX' in e ) {
1058			if (e.deltaMode === 1) {
1059				wheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;
1060				wheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;
1061			} else {
1062				wheelDeltaX = -e.deltaX;
1063				wheelDeltaY = -e.deltaY;
1064			}
1065		} else if ( 'wheelDeltaX' in e ) {
1066			wheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;
1067			wheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;
1068		} else if ( 'wheelDelta' in e ) {
1069			wheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;
1070		} else if ( 'detail' in e ) {
1071			wheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;
1072		} else {
1073			return;
1074		}
1075
1076		wheelDeltaX *= this.options.invertWheelDirection;
1077		wheelDeltaY *= this.options.invertWheelDirection;
1078
1079		if ( !this.hasVerticalScroll ) {
1080			wheelDeltaX = wheelDeltaY;
1081			wheelDeltaY = 0;
1082		}
1083
1084		if ( this.options.snap ) {
1085			newX = this.currentPage.pageX;
1086			newY = this.currentPage.pageY;
1087
1088			if ( wheelDeltaX > 0 ) {
1089				newX--;
1090			} else if ( wheelDeltaX < 0 ) {
1091				newX++;
1092			}
1093
1094			if ( wheelDeltaY > 0 ) {
1095				newY--;
1096			} else if ( wheelDeltaY < 0 ) {
1097				newY++;
1098			}
1099
1100			this.goToPage(newX, newY);
1101
1102			return;
1103		}
1104
1105		newX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);
1106		newY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);
1107
1108		if ( newX > 0 ) {
1109			newX = 0;
1110		} else if ( newX < this.maxScrollX ) {
1111			newX = this.maxScrollX;
1112		}
1113
1114		if ( newY > 0 ) {
1115			newY = 0;
1116		} else if ( newY < this.maxScrollY ) {
1117			newY = this.maxScrollY;
1118		}
1119
1120		this.scrollTo(newX, newY, 0);
vendor: 8,470 bytes, lines 1120-1509
1120
1121
1122// INSERT POINT: _wheel
1123	},
1124
1125	_initSnap: function () {
1126		this.currentPage = {};
1127
1128		if ( typeof this.options.snap == 'string' ) {
1129			this.options.snap = this.scroller.querySelectorAll(this.options.snap);
1130		}
1131
1132		this.on('refresh', function () {
1133			var i = 0, l,
1134				m = 0, n,
1135				cx, cy,
1136				x = 0, y,
1137				stepX = this.options.snapStepX || this.wrapperWidth,
1138				stepY = this.options.snapStepY || this.wrapperHeight,
1139				el;
1140
1141			this.pages = [];
1142
1143			if ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {
1144				return;
1145			}
1146
1147			if ( this.options.snap === true ) {
1148				cx = Math.round( stepX / 2 );
1149				cy = Math.round( stepY / 2 );
1150
1151				while ( x > -this.scrollerWidth ) {
1152					this.pages[i] = [];
1153					l = 0;
1154					y = 0;
1155
1156					while ( y > -this.scrollerHeight ) {
1157						this.pages[i][l] = {
1158							x: Math.max(x, this.maxScrollX),
1159							y: Math.max(y, this.maxScrollY),
1160							width: stepX,
1161							height: stepY,
1162							cx: x - cx,
1163							cy: y - cy
1164						};
1165
1166						y -= stepY;
1167						l++;
1168					}
1169
1170					x -= stepX;
1171					i++;
1172				}
1173			} else {
1174				el = this.options.snap;
1175				l = el.length;
1176				n = -1;
1177
1178				for ( ; i < l; i++ ) {
1179					if ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {
1180						m = 0;
1181						n++;
1182					}
1183
1184					if ( !this.pages[m] ) {
1185						this.pages[m] = [];
1186					}
1187
1188					x = Math.max(-el[i].offsetLeft, this.maxScrollX);
1189					y = Math.max(-el[i].offsetTop, this.maxScrollY);
1190					cx = x - Math.round(el[i].offsetWidth / 2);
1191					cy = y - Math.round(el[i].offsetHeight / 2);
1192
1193					this.pages[m][n] = {
1194						x: x,
1195						y: y,
1196						width: el[i].offsetWidth,
1197						height: el[i].offsetHeight,
1198						cx: cx,
1199						cy: cy
1200					};
1201
1202					if ( x > this.maxScrollX ) {
1203						m++;
1204					}
1205				}
1206			}
1207
1208			this.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);
1209
1210			// Update snap threshold if needed
1211			if ( this.options.snapThreshold % 1 === 0 ) {
1212				this.snapThresholdX = this.options.snapThreshold;
1213				this.snapThresholdY = this.options.snapThreshold;
1214			} else {
1215				this.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);
1216				this.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);
1217			}
1218		});
1219
1220		this.on('flick', function () {
1221			var time = this.options.snapSpeed || Math.max(
1222					Math.max(
1223						Math.min(Math.abs(this.x - this.startX), 1000),
1224						Math.min(Math.abs(this.y - this.startY), 1000)
1225					), 300);
1226
1227			this.goToPage(
1228				this.currentPage.pageX + this.directionX,
1229				this.currentPage.pageY + this.directionY,
1230				time
1231			);
1232		});
1233	},
1234
1235	_nearestSnap: function (x, y) {
1236		if ( !this.pages.length ) {
1237			return { x: 0, y: 0, pageX: 0, pageY: 0 };
1238		}
1239
1240		var i = 0,
1241			l = this.pages.length,
1242			m = 0;
1243
1244		// Check if we exceeded the snap threshold
1245		if ( Math.abs(x - this.absStartX) < this.snapThresholdX &&
1246			Math.abs(y - this.absStartY) < this.snapThresholdY ) {
1247			return this.currentPage;
1248		}
1249
1250		if ( x > 0 ) {
1251			x = 0;
1252		} else if ( x < this.maxScrollX ) {
1253			x = this.maxScrollX;
1254		}
1255
1256		if ( y > 0 ) {
1257			y = 0;
1258		} else if ( y < this.maxScrollY ) {
1259			y = this.maxScrollY;
1260		}
1261
1262		for ( ; i < l; i++ ) {
1263			if ( x >= this.pages[i][0].cx ) {
1264				x = this.pages[i][0].x;
1265				break;
1266			}
1267		}
1268
1269		l = this.pages[i].length;
1270
1271		for ( ; m < l; m++ ) {
1272			if ( y >= this.pages[0][m].cy ) {
1273				y = this.pages[0][m].y;
1274				break;
1275			}
1276		}
1277
1278		if ( i == this.currentPage.pageX ) {
1279			i += this.directionX;
1280
1281			if ( i < 0 ) {
1282				i = 0;
1283			} else if ( i >= this.pages.length ) {
1284				i = this.pages.length - 1;
1285			}
1286
1287			x = this.pages[i][0].x;
1288		}
1289
1290		if ( m == this.currentPage.pageY ) {
1291			m += this.directionY;
1292
1293			if ( m < 0 ) {
1294				m = 0;
1295			} else if ( m >= this.pages[0].length ) {
1296				m = this.pages[0].length - 1;
1297			}
1298
1299			y = this.pages[0][m].y;
1300		}
1301
1302		return {
1303			x: x,
1304			y: y,
1305			pageX: i,
1306			pageY: m
1307		};
1308	},
1309
1310	goToPage: function (x, y, time, easing) {
1311		easing = easing || this.options.bounceEasing;
1312
1313		if ( x >= this.pages.length ) {
1314			x = this.pages.length - 1;
1315		} else if ( x < 0 ) {
1316			x = 0;
1317		}
1318
1319		if ( y >= this.pages[x].length ) {
1320			y = this.pages[x].length - 1;
1321		} else if ( y < 0 ) {
1322			y = 0;
1323		}
1324
1325		var posX = this.pages[x][y].x,
1326			posY = this.pages[x][y].y;
1327
1328		time = time === undefined ? this.options.snapSpeed || Math.max(
1329			Math.max(
1330				Math.min(Math.abs(posX - this.x), 1000),
1331				Math.min(Math.abs(posY - this.y), 1000)
1332			), 300) : time;
1333
1334		this.currentPage = {
1335			x: posX,
1336			y: posY,
1337			pageX: x,
1338			pageY: y
1339		};
1340
1341		this.scrollTo(posX, posY, time, easing);
1342	},
1343
1344	next: function (time, easing) {
1345		var x = this.currentPage.pageX,
1346			y = this.currentPage.pageY;
1347
1348		x++;
1349
1350		if ( x >= this.pages.length && this.hasVerticalScroll ) {
1351			x = 0;
1352			y++;
1353		}
1354
1355		this.goToPage(x, y, time, easing);
1356	},
1357
1358	prev: function (time, easing) {
1359		var x = this.currentPage.pageX,
1360			y = this.currentPage.pageY;
1361
1362		x--;
1363
1364		if ( x < 0 && this.hasVerticalScroll ) {
1365			x = 0;
1366			y--;
1367		}
1368
1369		this.goToPage(x, y, time, easing);
1370	},
1371
1372	_initKeys: function (e) {
1373		// default key bindings
1374		var keys = {
1375			pageUp: 33,
1376			pageDown: 34,
1377			end: 35,
1378			home: 36,
1379			left: 37,
1380			up: 38,
1381			right: 39,
1382			down: 40
1383		};
1384		var i;
1385
1386		// if you give me characters I give you keycode
1387		if ( typeof this.options.keyBindings == 'object' ) {
1388			for ( i in this.options.keyBindings ) {
1389				if ( typeof this.options.keyBindings[i] == 'string' ) {
1390					this.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCodeAt(0);
1391				}
1392			}
1393		} else {
1394			this.options.keyBindings = {};
1395		}
1396
1397		for ( i in keys ) {
1398			this.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];
1399		}
1400
1401		utils.addEvent(window, 'keydown', this);
1402
1403		this.on('destroy', function () {
1404			utils.removeEvent(window, 'keydown', this);
1405		});
1406	},
1407
1408	_key: function (e) {
1409		if ( !this.enabled ) {
1410			return;
1411		}
1412
1413		var snap = this.options.snap,	// we are using this alot, better to cache it
1414			newX = snap ? this.currentPage.pageX : this.x,
1415			newY = snap ? this.currentPage.pageY : this.y,
1416			now = utils.getTime(),
1417			prevTime = this.keyTime || 0,
1418			acceleration = 0.250,
1419			pos;
1420
1421		if ( this.options.useTransition && this.isInTransition ) {
1422			pos = this.getComputedPosition();
1423
1424			this._translate(Math.round(pos.x), Math.round(pos.y));
1425			this.isInTransition = false;
1426		}
1427
1428		this.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;
1429
1430		switch ( e.keyCode ) {
1431			case this.options.keyBindings.pageUp:
1432				if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
1433					newX += snap ? 1 : this.wrapperWidth;
1434				} else {
1435					newY += snap ? 1 : this.wrapperHeight;
1436				}
1437				break;
1438			case this.options.keyBindings.pageDown:
1439				if ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {
1440					newX -= snap ? 1 : this.wrapperWidth;
1441				} else {
1442					newY -= snap ? 1 : this.wrapperHeight;
1443				}
1444				break;
1445			case this.options.keyBindings.end:
1446				newX = snap ? this.pages.length-1 : this.maxScrollX;
1447				newY = snap ? this.pages[0].length-1 : this.maxScrollY;
1448				break;
1449			case this.options.keyBindings.home:
1450				newX = 0;
1451				newY = 0;
1452				break;
1453			case this.options.keyBindings.left:
1454				newX += snap ? -1 : 5 + this.keyAcceleration>>0;
1455				break;
1456			case this.options.keyBindings.up:
1457				newY += snap ? 1 : 5 + this.keyAcceleration>>0;
1458				break;
1459			case this.options.keyBindings.right:
1460				newX -= snap ? -1 : 5 + this.keyAcceleration>>0;
1461				break;
1462			case this.options.keyBindings.down:
1463				newY -= snap ? 1 : 5 + this.keyAcceleration>>0;
1464				break;
1465			default:
1466				return;
1467		}
1468
1469		if ( snap ) {
1470			this.goToPage(newX, newY);
1471			return;
1472		}
1473
1474		if ( newX > 0 ) {
1475			newX = 0;
1476			this.keyAcceleration = 0;
1477		} else if ( newX < this.maxScrollX ) {
1478			newX = this.maxScrollX;
1479			this.keyAcceleration = 0;
1480		}
1481
1482		if ( newY > 0 ) {
1483			newY = 0;
1484			this.keyAcceleration = 0;
1485		} else if ( newY < this.maxScrollY ) {
1486			newY = this.maxScrollY;
1487			this.keyAcceleration = 0;
1488		}
1489
1490		this.scrollTo(newX, newY, 0);
1491
1492		this.keyTime = now;
1493	},
1494
1495	_animate: function (destX, destY, duration, easingFn) {
1496		var that = this,
1497			startX = this.x,
1498			startY = this.y,
1499			startTime = utils.getTime(),
1500			destTime = startTime + duration;
1501
1502		function step () {
1503			var now = utils.getTime(),
1504				newX, newY,
1505				easing;
1506
1507			if ( now >= destTime ) {
1508				that.isAnimating = false;
1509				that._translate(destX, destY);
vendor: 5,337 bytes, lines 1510-1726
1510
1511				if ( !that.resetPosition(that.options.bounceTime) ) {
1512					that._execEvent('scrollEnd');
1513				}
1514
1515				return;
1516			}
1517
1518			now = ( now - startTime ) / duration;
1519			easing = easingFn(now);
1520			newX = ( destX - startX ) * easing + startX;
1521			newY = ( destY - startY ) * easing + startY;
1522			that._translate(newX, newY);
1523
1524			if ( that.isAnimating ) {
1525				rAF(step);
1526			}
1527		}
1528
1529		this.isAnimating = true;
1530		step();
1531	},
1532	handleEvent: function (e) {
1533		switch ( e.type ) {
1534			case 'touchstart':
1535			case 'pointerdown':
1536			case 'MSPointerDown':
1537			case 'mousedown':
1538				this._start(e);
1539				break;
1540			case 'touchmove':
1541			case 'pointermove':
1542			case 'MSPointerMove':
1543			case 'mousemove':
1544				this._move(e);
1545				break;
1546			case 'touchend':
1547			case 'pointerup':
1548			case 'MSPointerUp':
1549			case 'mouseup':
1550			case 'touchcancel':
1551			case 'pointercancel':
1552			case 'MSPointerCancel':
1553			case 'mousecancel':
1554				this._end(e);
1555				break;
1556			case 'orientationchange':
1557			case 'resize':
1558				this._resize();
1559				break;
1560			case 'transitionend':
1561			case 'webkitTransitionEnd':
1562			case 'oTransitionEnd':
1563			case 'MSTransitionEnd':
1564				this._transitionEnd(e);
1565				break;
1566			case 'wheel':
1567			case 'DOMMouseScroll':
1568			case 'mousewheel':
1569				this._wheel(e);
1570				break;
1571			case 'keydown':
1572				this._key(e);
1573				break;
1574			case 'click':
1575				if ( !e._constructed ) {
1576					e.preventDefault();
1577					e.stopPropagation();
1578				}
1579				break;
1580		}
1581	}
1582};
1583function createDefaultScrollbar (direction, interactive, type) {
1584	var scrollbar = document.createElement('div'),
1585		indicator = document.createElement('div');
1586
1587	if ( type === true ) {
1588		scrollbar.style.cssText = 'position:absolute;z-index:9999';
1589		indicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px';
1590	}
1591
1592	indicator.className = 'iScrollIndicator';
1593
1594	if ( direction == 'h' ) {
1595		if ( type === true ) {
1596			scrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';
1597			indicator.style.height = '100%';
1598		}
1599		scrollbar.className = 'iScrollHorizontalScrollbar';
1600	} else {
1601		if ( type === true ) {
1602			scrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';
1603			indicator.style.width = '100%';
1604		}
1605		scrollbar.className = 'iScrollVerticalScrollbar';
1606	}
1607
1608	scrollbar.style.cssText += ';overflow:hidden';
1609
1610	if ( !interactive ) {
1611		scrollbar.style.pointerEvents = 'none';
1612	}
1613
1614	scrollbar.appendChild(indicator);
1615
1616	return scrollbar;
1617}
1618
1619function Indicator (scroller, options) {
1620	this.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;
1621	this.wrapperStyle = this.wrapper.style;
1622	this.indicator = this.wrapper.children[0];
1623	this.indicatorStyle = this.indicator.style;
1624	this.scroller = scroller;
1625
1626	this.options = {
1627		listenX: true,
1628		listenY: true,
1629		interactive: false,
1630		resize: true,
1631		defaultScrollbars: false,
1632		shrink: false,
1633		fade: false,
1634		speedRatioX: 0,
1635		speedRatioY: 0
1636	};
1637
1638	for ( var i in options ) {
1639		this.options[i] = options[i];
1640	}
1641
1642	this.sizeRatioX = 1;
1643	this.sizeRatioY = 1;
1644	this.maxPosX = 0;
1645	this.maxPosY = 0;
1646
1647	if ( this.options.interactive ) {
1648		if ( !this.options.disableTouch ) {
1649			utils.addEvent(this.indicator, 'touchstart', this);
1650			utils.addEvent(window, 'touchend', this);
1651		}
1652		if ( !this.options.disablePointer ) {
1653			utils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
1654			utils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);
1655		}
1656		if ( !this.options.disableMouse ) {
1657			utils.addEvent(this.indicator, 'mousedown', this);
1658			utils.addEvent(window, 'mouseup', this);
1659		}
1660	}
1661
1662	if ( this.options.fade ) {
1663		this.wrapperStyle[utils.style.transform] = this.scroller.translateZ;
1664		this.wrapperStyle[utils.style.transitionDuration] = utils.isBadAndroid ? '0.001s' : '0ms';
1665		this.wrapperStyle.opacity = '0';
1666	}
1667}
1668
1669Indicator.prototype = {
1670	handleEvent: function (e) {
1671		switch ( e.type ) {
1672			case 'touchstart':
1673			case 'pointerdown':
1674			case 'MSPointerDown':
1675			case 'mousedown':
1676				this._start(e);
1677				break;
1678			case 'touchmove':
1679			case 'pointermove':
1680			case 'MSPointerMove':
1681			case 'mousemove':
1682				this._move(e);
1683				break;
1684			case 'touchend':
1685			case 'pointerup':
1686			case 'MSPointerUp':
1687			case 'mouseup':
1688			case 'touchcancel':
1689			case 'pointercancel':
1690			case 'MSPointerCancel':
1691			case 'mousecancel':
1692				this._end(e);
1693				break;
1694		}
1695	},
1696
1697	destroy: function () {
1698		if ( this.options.interactive ) {
1699			utils.removeEvent(this.indicator, 'touchstart', this);
1700			utils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);
1701			utils.removeEvent(this.indicator, 'mousedown', this);
1702
1703			utils.removeEvent(window, 'touchmove', this);
1704			utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
1705			utils.removeEvent(window, 'mousemove', this);
1706
1707			utils.removeEvent(window, 'touchend', this);
1708			utils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);
1709			utils.removeEvent(window, 'mouseup', this);
1710		}
1711
1712		if ( this.options.defaultScrollbars ) {
1713			this.wrapper.parentNode.removeChild(this.wrapper);
1714		}
1715	},
1716
1717	_start: function (e) {
1718		var point = e.touches ? e.touches[0] : e;
1719
1720		e.preventDefault();
1721		e.stopPropagation();
1722
1723		this.transitionTime();
1724
1725		this.initiated = true;
1726		this.moved = false;
vendor: 8,319 bytes, lines 1727-2012
1727		this.lastPointX	= point.pageX;
1728		this.lastPointY	= point.pageY;
1729
1730		this.startTime	= utils.getTime();
1731
1732		if ( !this.options.disableTouch ) {
1733			utils.addEvent(window, 'touchmove', this);
1734		}
1735		if ( !this.options.disablePointer ) {
1736			utils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);
1737		}
1738		if ( !this.options.disableMouse ) {
1739			utils.addEvent(window, 'mousemove', this);
1740		}
1741
1742		this.scroller._execEvent('beforeScrollStart');
1743	},
1744
1745	_move: function (e) {
1746		var point = e.touches ? e.touches[0] : e,
1747			deltaX, deltaY,
1748			newX, newY,
1749			timestamp = utils.getTime();
1750
1751		if ( !this.moved ) {
1752			this.scroller._execEvent('scrollStart');
1753		}
1754
1755		this.moved = true;
1756
1757		deltaX = point.pageX - this.lastPointX;
1758		this.lastPointX = point.pageX;
1759
1760		deltaY = point.pageY - this.lastPointY;
1761		this.lastPointY = point.pageY;
1762
1763		newX = this.x + deltaX;
1764		newY = this.y + deltaY;
1765
1766		this._pos(newX, newY);
1767
1768// INSERT POINT: indicator._move
1769
1770		e.preventDefault();
1771		e.stopPropagation();
1772	},
1773
1774	_end: function (e) {
1775		if ( !this.initiated ) {
1776			return;
1777		}
1778
1779		this.initiated = false;
1780
1781		e.preventDefault();
1782		e.stopPropagation();
1783
1784		utils.removeEvent(window, 'touchmove', this);
1785		utils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);
1786		utils.removeEvent(window, 'mousemove', this);
1787
1788		if ( this.scroller.options.snap ) {
1789			var snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);
1790
1791			var time = this.options.snapSpeed || Math.max(
1792					Math.max(
1793						Math.min(Math.abs(this.scroller.x - snap.x), 1000),
1794						Math.min(Math.abs(this.scroller.y - snap.y), 1000)
1795					), 300);
1796
1797			if ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {
1798				this.scroller.directionX = 0;
1799				this.scroller.directionY = 0;
1800				this.scroller.currentPage = snap;
1801				this.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);
1802			}
1803		}
1804
1805		if ( this.moved ) {
1806			this.scroller._execEvent('scrollEnd');
1807		}
1808	},
1809
1810	transitionTime: function (time) {
1811		time = time || 0;
1812		this.indicatorStyle[utils.style.transitionDuration] = time + 'ms';
1813
1814		if ( !time && utils.isBadAndroid ) {
1815			this.indicatorStyle[utils.style.transitionDuration] = '0.001s';
1816		}
1817	},
1818
1819	transitionTimingFunction: function (easing) {
1820		this.indicatorStyle[utils.style.transitionTimingFunction] = easing;
1821	},
1822
1823	refresh: function () {
1824		this.transitionTime();
1825
1826		if ( this.options.listenX && !this.options.listenY ) {
1827			this.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';
1828		} else if ( this.options.listenY && !this.options.listenX ) {
1829			this.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';
1830		} else {
1831			this.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';
1832		}
1833
1834		if ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {
1835			utils.addClass(this.wrapper, 'iScrollBothScrollbars');
1836			utils.removeClass(this.wrapper, 'iScrollLoneScrollbar');
1837
1838			if ( this.options.defaultScrollbars && this.options.customStyle ) {
1839				if ( this.options.listenX ) {
1840					this.wrapper.style.right = '8px';
1841				} else {
1842					this.wrapper.style.bottom = '8px';
1843				}
1844			}
1845		} else {
1846			utils.removeClass(this.wrapper, 'iScrollBothScrollbars');
1847			utils.addClass(this.wrapper, 'iScrollLoneScrollbar');
1848
1849			if ( this.options.defaultScrollbars && this.options.customStyle ) {
1850				if ( this.options.listenX ) {
1851					this.wrapper.style.right = '2px';
1852				} else {
1853					this.wrapper.style.bottom = '2px';
1854				}
1855			}
1856		}
1857
1858		var r = this.wrapper.offsetHeight;	// force refresh
1859
1860		if ( this.options.listenX ) {
1861			this.wrapperWidth = this.wrapper.clientWidth;
1862			if ( this.options.resize ) {
1863				this.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);
1864				this.indicatorStyle.width = this.indicatorWidth + 'px';
1865			} else {
1866				this.indicatorWidth = this.indicator.clientWidth;
1867			}
1868
1869			this.maxPosX = this.wrapperWidth - this.indicatorWidth;
1870
1871			if ( this.options.shrink == 'clip' ) {
1872				this.minBoundaryX = -this.indicatorWidth + 8;
1873				this.maxBoundaryX = this.wrapperWidth - 8;
1874			} else {
1875				this.minBoundaryX = 0;
1876				this.maxBoundaryX = this.maxPosX;
1877			}
1878
1879			this.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));	
1880		}
1881
1882		if ( this.options.listenY ) {
1883			this.wrapperHeight = this.wrapper.clientHeight;
1884			if ( this.options.resize ) {
1885				this.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);
1886				this.indicatorStyle.height = this.indicatorHeight + 'px';
1887			} else {
1888				this.indicatorHeight = this.indicator.clientHeight;
1889			}
1890
1891			this.maxPosY = this.wrapperHeight - this.indicatorHeight;
1892
1893			if ( this.options.shrink == 'clip' ) {
1894				this.minBoundaryY = -this.indicatorHeight + 8;
1895				this.maxBoundaryY = this.wrapperHeight - 8;
1896			} else {
1897				this.minBoundaryY = 0;
1898				this.maxBoundaryY = this.maxPosY;
1899			}
1900
1901			this.maxPosY = this.wrapperHeight - this.indicatorHeight;
1902			this.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));
1903		}
1904
1905		this.updatePosition();
1906	},
1907
1908	updatePosition: function () {
1909		var x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,
1910			y = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;
1911
1912		if ( !this.options.ignoreBoundaries ) {
1913			if ( x < this.minBoundaryX ) {
1914				if ( this.options.shrink == 'scale' ) {
1915					this.width = Math.max(this.indicatorWidth + x, 8);
1916					this.indicatorStyle.width = this.width + 'px';
1917				}
1918				x = this.minBoundaryX;
1919			} else if ( x > this.maxBoundaryX ) {
1920				if ( this.options.shrink == 'scale' ) {
1921					this.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);
1922					this.indicatorStyle.width = this.width + 'px';
1923					x = this.maxPosX + this.indicatorWidth - this.width;
1924				} else {
1925					x = this.maxBoundaryX;
1926				}
1927			} else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {
1928				this.width = this.indicatorWidth;
1929				this.indicatorStyle.width = this.width + 'px';
1930			}
1931
1932			if ( y < this.minBoundaryY ) {
1933				if ( this.options.shrink == 'scale' ) {
1934					this.height = Math.max(this.indicatorHeight + y * 3, 8);
1935					this.indicatorStyle.height = this.height + 'px';
1936				}
1937				y = this.minBoundaryY;
1938			} else if ( y > this.maxBoundaryY ) {
1939				if ( this.options.shrink == 'scale' ) {
1940					this.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);
1941					this.indicatorStyle.height = this.height + 'px';
1942					y = this.maxPosY + this.indicatorHeight - this.height;
1943				} else {
1944					y = this.maxBoundaryY;
1945				}
1946			} else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {
1947				this.height = this.indicatorHeight;
1948				this.indicatorStyle.height = this.height + 'px';
1949			}
1950		}
1951
1952		this.x = x;
1953		this.y = y;
1954
1955		if ( this.scroller.options.useTransform ) {
1956			this.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;
1957		} else {
1958			this.indicatorStyle.left = x + 'px';
1959			this.indicatorStyle.top = y + 'px';
1960		}
1961	},
1962
1963	_pos: function (x, y) {
1964		if ( x < 0 ) {
1965			x = 0;
1966		} else if ( x > this.maxPosX ) {
1967			x = this.maxPosX;
1968		}
1969
1970		if ( y < 0 ) {
1971			y = 0;
1972		} else if ( y > this.maxPosY ) {
1973			y = this.maxPosY;
1974		}
1975
1976		x = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;
1977		y = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;
1978
1979		this.scroller.scrollTo(x, y);
1980	},
1981
1982	fade: function (val, hold) {
1983		if ( hold && !this.visible ) {
1984			return;
1985		}
1986
1987		clearTimeout(this.fadeTimeout);
1988		this.fadeTimeout = null;
1989
1990		var time = val ? 250 : 500,
1991			delay = val ? 0 : 300;
1992
1993		val = val ? '1' : '0';
1994
1995		this.wrapperStyle[utils.style.transitionDuration] = time + 'ms';
1996
1997		this.fadeTimeout = setTimeout((function (val) {
1998			this.wrapperStyle.opacity = val;
1999			this.visible = +val;
2000		}).bind(this, val), delay);
2001	}
2002};
2003
2004IScroll.utils = utils;
2005
2006if ( typeof module != 'undefined' && module.exports ) {
2007	module.exports = IScroll;
2008} else {
2009	window.IScroll = IScroll;
2010}
2011
2012})(window, document, Math);

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.