PageSourceSearch

https://valvesale.ru/catalog/view/javascript/mf/iscroll.js?v2.0.4.4.5.1

js valvesale.ru collected 2026-10-07 22:25:59 UTC 60,596 bytes, 2,384 lines download raw bytes

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

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.