PageSourceSearch

https://omotobreast.com/wp/wp-content/themes/system-template/js/plugin.js

js omotobreast.com collected 2026-10-06 08:03:26 UTC 61,394 bytes, 2,196 lines download raw bytes

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