PageSourceSearch

https://www.hpmc.net.au/wp-content/themes/medicare/js/iscroll.js?ver=6.0.17

js hpmc.net.au collected 2026-10-08 02:21:47 UTC 50,086 bytes, 2,011 lines download raw bytes

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