PageSourceSearch

https://sso-mil.ru/local/templates/base/plugins/CustomScrollbarr/jquery.mCustomScrollbar.js

js sso-mil.ru collected 2026-10-04 00:05:36 UTC 91,179 bytes, 2,425 lines download raw bytes

1/*
2== malihu jquery custom scrollbar plugin == 
3Version: 3.1.3 
4Plugin URI: http://manos.malihu.gr/jquery-custom-content-scroller 
5Author: malihu
6Author URI: http://manos.malihu.gr
7License: MIT License (MIT)
8*/
9
10/*
11Copyright Manos Malihutsakis (email: [email protected])
12
13Permission is hereby granted, free of charge, to any person obtaining a copy
14of this software and associated documentation files (the "Software"), to deal
15in the Software without restriction, including without limitation the rights
16to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17copies of the Software, and to permit persons to whom the Software is
18furnished to do so, subject to the following conditions:
19
20The above copyright notice and this permission notice shall be included in
21all copies or substantial portions of the Software.
22
23THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29THE SOFTWARE.
30*/
31
32/*
33The code below is fairly long, fully commented and should be normally used in development. 
34For production, use either the minified jquery.mCustomScrollbar.min.js script or 
35the production-ready jquery.mCustomScrollbar.concat.min.js which contains the plugin 
36and dependencies (minified). 
37*/
38
39(function(factory){
40	
vendor: 27,831 bytes, lines 40-863
40if(typeof module!=="undefined" && module.exports){
41		module.exports=factory;
42	}else{
43		factory(jQuery,window,document);
44	}
45}(function($){
46(function(init){
47	var _rjs=typeof define==="function" && define.amd, /* RequireJS */
48		_njs=typeof module !== "undefined" && module.exports, /* NodeJS */
49		_dlp=("https:"==document.location.protocol) ? "https:" : "http:", /* location protocol */
50		_url="cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js";
51	if(!_rjs){
52		if(_njs){
53			require("jquery-mousewheel")($);
54		}else{
55			/* load jquery-mousewheel plugin (via CDN) if it's not present or not loaded via RequireJS 
56			(works when mCustomScrollbar fn is called on window load) */
57			$.event.special.mousewheel || $("head").append(decodeURI("%3Cscript src="+_dlp+"//"+_url+"%3E%3C/script%3E"));
58		}
59	}
60	init();
61}(function(){
62	
63	/* 
64	----------------------------------------
65	PLUGIN NAMESPACE, PREFIX, DEFAULT SELECTOR(S) 
66	----------------------------------------
67	*/
68	
69	var pluginNS="mCustomScrollbar",
70		pluginPfx="mCS",
71		defaultSelector=".mCustomScrollbar",
72	
73	
74		
75	
76	
77	/* 
78	----------------------------------------
79	DEFAULT OPTIONS 
80	----------------------------------------
81	*/
82	
83		defaults={
84			/*
85			set element/content width/height programmatically 
86			values: boolean, pixels, percentage 
87				option						default
88				-------------------------------------
89				setWidth					false
90				setHeight					false
91			*/
92			/*
93			set the initial css top property of content  
94			values: string (e.g. "-100px", "10%" etc.)
95			*/
96			setTop:0,
97			/*
98			set the initial css left property of content  
99			values: string (e.g. "-100px", "10%" etc.)
100			*/
101			setLeft:0,
102			/* 
103			scrollbar axis (vertical and/or horizontal scrollbars) 
104			values (string): "y", "x", "yx"
105			*/
106			axis:"y",
107			/*
108			position of scrollbar relative to content  
109			values (string): "inside", "outside" ("outside" requires elements with position:relative)
110			*/
111			scrollbarPosition:"inside",
112			/*
113			scrolling inertia
114			values: integer (milliseconds)
115			*/
116			scrollInertia:950,
117			/* 
118			auto-adjust scrollbar dragger length
119			values: boolean
120			*/
121			autoDraggerLength:true,
122			/*
123			auto-hide scrollbar when idle 
124			values: boolean
125				option						default
126				-------------------------------------
127				autoHideScrollbar			false
128			*/
129			/*
130			auto-expands scrollbar on mouse-over and dragging
131			values: boolean
132				option						default
133				-------------------------------------
134				autoExpandScrollbar			false
135			*/
136			/*
137			always show scrollbar, even when there's nothing to scroll 
138			values: integer (0=disable, 1=always show dragger rail and buttons, 2=always show dragger rail, dragger and buttons), boolean
139			*/
140			alwaysShowScrollbar:0,
141			/*
142			scrolling always snaps to a multiple of this number in pixels
143			values: integer, array ([y,x])
144				option						default
145				-------------------------------------
146				snapAmount					null
147			*/
148			/*
149			when snapping, snap with this number in pixels as an offset 
150			values: integer
151			*/
152			snapOffset:0,
153			/* 
154			mouse-wheel scrolling
155			*/
156			mouseWheel:{
157				/* 
158				enable mouse-wheel scrolling
159				values: boolean
160				*/
161				enable:true,
162				/* 
163				scrolling amount in pixels
164				values: "auto", integer 
165				*/
166				scrollAmount:"auto",
167				/* 
168				mouse-wheel scrolling axis 
169				the default scrolling direction when both vertical and horizontal scrollbars are present 
170				values (string): "y", "x" 
171				*/
172				axis:"y",
173				/* 
174				prevent the default behaviour which automatically scrolls the parent element(s) when end of scrolling is reached 
175				values: boolean
176					option						default
177					-------------------------------------
178					preventDefault				null
179				*/
180				/*
181				the reported mouse-wheel delta value. The number of lines (translated to pixels) one wheel notch scrolls.  
182				values: "auto", integer 
183				"auto" uses the default OS/browser value 
184				*/
185				deltaFactor:"auto",
186				/*
187				normalize mouse-wheel delta to -1 or 1 (disables mouse-wheel acceleration) 
188				values: boolean
189					option						default
190					-------------------------------------
191					normalizeDelta				null
192				*/
193				/*
194				invert mouse-wheel scrolling direction 
195				values: boolean
196					option						default
197					-------------------------------------
198					invert						null
199				*/
200				/*
201				the tags that disable mouse-wheel when cursor is over them
202				*/
203				disableOver:["select","option","keygen","datalist","textarea"]
204			},
205			/* 
206			scrollbar buttons
207			*/
208			scrollButtons:{ 
209				/*
210				enable scrollbar buttons
211				values: boolean
212					option						default
213					-------------------------------------
214					enable						null
215				*/
216				/*
217				scrollbar buttons scrolling type 
218				values (string): "stepless", "stepped"
219				*/
220				scrollType:"stepless",
221				/*
222				scrolling amount in pixels
223				values: "auto", integer 
224				*/
225				scrollAmount:"auto"
226				/*
227				tabindex of the scrollbar buttons
228				values: false, integer
229					option						default
230					-------------------------------------
231					tabindex					null
232				*/
233			},
234			/* 
235			keyboard scrolling
236			*/
237			keyboard:{ 
238				/*
239				enable scrolling via keyboard
240				values: boolean
241				*/
242				enable:true,
243				/*
244				keyboard scrolling type 
245				values (string): "stepless", "stepped"
246				*/
247				scrollType:"stepless",
248				/*
249				scrolling amount in pixels
250				values: "auto", integer 
251				*/
252				scrollAmount:"auto"
253			},
254			/*
255			enable content touch-swipe scrolling 
256			values: boolean, integer, string (number)
257			integer values define the axis-specific minimum amount required for scrolling momentum
258			*/
259			contentTouchScroll:25,
260			/*
261			enable/disable document (default) touch-swipe scrolling 
262			*/
263			documentTouchScroll:true,
264			/*
265			advanced option parameters
266			*/
267			advanced:{
268				/*
269				auto-expand content horizontally (for "x" or "yx" axis) 
270				values: boolean, integer (the value 2 forces the non scrollHeight/scrollWidth method, the value 3 forces the scrollHeight/scrollWidth method)
271					option						default
272					-------------------------------------
273					autoExpandHorizontalScroll	null
274				*/
275				/*
276				auto-scroll to elements with focus
277				*/
278				autoScrollOnFocus:"input,textarea,select,button,datalist,keygen,a[tabindex],area,object,[contenteditable='true']",
279				/*
280				auto-update scrollbars on content, element or viewport resize 
281				should be true for fluid layouts/elements, adding/removing content dynamically, hiding/showing elements, content with images etc. 
282				values: boolean
283				*/
284				updateOnContentResize:true,
285				/*
286				auto-update scrollbars each time each image inside the element is fully loaded 
287				values: "auto", boolean
288				*/
289				updateOnImageLoad:"auto",
290				/*
291				auto-update scrollbars based on the amount and size changes of specific selectors 
292				useful when you need to update the scrollbar(s) automatically, each time a type of element is added, removed or changes its size 
293				values: boolean, string (e.g. "ul li" will auto-update scrollbars each time list-items inside the element are changed) 
294				a value of true (boolean) will auto-update scrollbars each time any element is changed
295					option						default
296					-------------------------------------
297					updateOnSelectorChange		null
298				*/
299				/*
300				extra selectors that'll allow scrollbar dragging upon mousemove/up, pointermove/up, touchend etc. (e.g. "selector-1, selector-2")
301					option						default
302					-------------------------------------
303					extraDraggableSelectors		null
304				*/
305				/*
306				extra selectors that'll release scrollbar dragging upon mouseup, pointerup, touchend etc. (e.g. "selector-1, selector-2")
307					option						default
308					-------------------------------------
309					releaseDraggableSelectors	null
310				*/
311				/*
312				auto-update timeout 
313				values: integer (milliseconds)
314				*/
315				autoUpdateTimeout:60
316			},
317			/* 
318			scrollbar theme 
319			values: string (see CSS/plugin URI for a list of ready-to-use themes)
320			*/
321			theme:"light",
322			/*
323			user defined callback functions
324			*/
325			callbacks:{
326				/*
327				Available callbacks: 
328					callback					default
329					-------------------------------------
330					onCreate					null
331					onInit						null
332					onScrollStart				null
333					onScroll					null
334					onTotalScroll				null
335					onTotalScrollBack			null
336					whileScrolling				null
337					onOverflowY					null
338					onOverflowX					null
339					onOverflowYNone				null
340					onOverflowXNone				null
341					onImageLoad					null
342					onSelectorChange			null
343					onBeforeUpdate				null
344					onUpdate					null
345				*/
346				onTotalScrollOffset:0,
347				onTotalScrollBackOffset:0,
348				alwaysTriggerOffsets:true
349			}
350			/*
351			add scrollbar(s) on all elements matching the current selector, now and in the future 
352			values: boolean, string 
353			string values: "on" (enable), "once" (disable after first invocation), "off" (disable)
354			liveSelector values: string (selector)
355				option						default
356				-------------------------------------
357				live						false
358				liveSelector				null
359			*/
360		},
361	
362	
363	
364	
365	
366	/* 
367	----------------------------------------
368	VARS, CONSTANTS 
369	----------------------------------------
370	*/
371	
372		totalInstances=0, /* plugin instances amount */
373		liveTimers={}, /* live option timers */
374		oldIE=(window.attachEvent && !window.addEventListener) ? 1 : 0, /* detect IE < 9 */
375		touchActive=false,touchable, /* global touch vars (for touch and pointer events) */
376		/* general plugin classes */
377		classes=[
378			"mCSB_dragger_onDrag","mCSB_scrollTools_onDrag","mCS_img_loaded","mCS_disabled","mCS_destroyed","mCS_no_scrollbar",
379			"mCS-autoHide","mCS-dir-rtl","mCS_no_scrollbar_y","mCS_no_scrollbar_x","mCS_y_hidden","mCS_x_hidden","mCSB_draggerContainer",
380			"mCSB_buttonUp","mCSB_buttonDown","mCSB_buttonLeft","mCSB_buttonRight"
381		],
382		
383	
384	
385	
386	
387	/* 
388	----------------------------------------
389	METHODS 
390	----------------------------------------
391	*/
392	
393		methods={
394			
395			/* 
396			plugin initialization method 
397			creates the scrollbar(s), plugin data object and options
398			----------------------------------------
399			*/
400			
401			init:function(options){
402				
403				var options=$.extend(true,{},defaults,options),
404					selector=_selector.call(this); /* validate selector */
405				
406				/* 
407				if live option is enabled, monitor for elements matching the current selector and 
408				apply scrollbar(s) when found (now and in the future) 
409				*/
410				if(options.live){
411					var liveSelector=options.liveSelector || this.selector || defaultSelector, /* live selector(s) */
412						$liveSelector=$(liveSelector); /* live selector(s) as jquery object */
413					if(options.live==="off"){
414						/* 
415						disable live if requested 
416						usage: $(selector).mCustomScrollbar({live:"off"}); 
417						*/
418						removeLiveTimers(liveSelector);
419						return;
420					}
421					liveTimers[liveSelector]=setTimeout(function(){
422						/* call mCustomScrollbar fn on live selector(s) every half-second */
423						$liveSelector.mCustomScrollbar(options);
424						if(options.live==="once" && $liveSelector.length){
425							/* disable live after first invocation */
426							removeLiveTimers(liveSelector);
427						}
428					},500);
429				}else{
430					removeLiveTimers(liveSelector);
431				}
432				
433				/* options backward compatibility (for versions < 3.0.0) and normalization */
434				options.setWidth=(options.set_width) ? options.set_width : options.setWidth;
435				options.setHeight=(options.set_height) ? options.set_height : options.setHeight;
436				options.axis=(options.horizontalScroll) ? "x" : _findAxis(options.axis);
437				options.scrollInertia=options.scrollInertia>0 && options.scrollInertia<17 ? 17 : options.scrollInertia;
438				if(typeof options.mouseWheel!=="object" &&  options.mouseWheel==true){ /* old school mouseWheel option (non-object) */
439					options.mouseWheel={enable:true,scrollAmount:"auto",axis:"y",preventDefault:false,deltaFactor:"auto",normalizeDelta:false,invert:false}
440				}
441				options.mouseWheel.scrollAmount=!options.mouseWheelPixels ? options.mouseWheel.scrollAmount : options.mouseWheelPixels;
442				options.mouseWheel.normalizeDelta=!options.advanced.normalizeMouseWheelDelta ? options.mouseWheel.normalizeDelta : options.advanced.normalizeMouseWheelDelta;
443				options.scrollButtons.scrollType=_findScrollButtonsType(options.scrollButtons.scrollType); 
444				
445				_theme(options); /* theme-specific options */
446				
447				/* plugin constructor */
448				return $(selector).each(function(){
449					
450					var $this=$(this);
451					
452					if(!$this.data(pluginPfx)){ /* prevent multiple instantiations */
453					
454						/* store options and create objects in jquery data */
455						$this.data(pluginPfx,{
456							idx:++totalInstances, /* instance index */
457							opt:options, /* options */
458							scrollRatio:{y:null,x:null}, /* scrollbar to content ratio */
459							overflowed:null, /* overflowed axis */
460							contentReset:{y:null,x:null}, /* object to check when content resets */
461							bindEvents:false, /* object to check if events are bound */
462							tweenRunning:false, /* object to check if tween is running */
463							sequential:{}, /* sequential scrolling object */
464							langDir:$this.css("direction"), /* detect/store direction (ltr or rtl) */
465							cbOffsets:null, /* object to check whether callback offsets always trigger */
466							/* 
467							object to check how scrolling events where last triggered 
468							"internal" (default - triggered by this script), "external" (triggered by other scripts, e.g. via scrollTo method) 
469							usage: object.data("mCS").trigger
470							*/
471							trigger:null,
472							/* 
473							object to check for changes in elements in order to call the update method automatically 
474							*/
475							poll:{size:{o:0,n:0},img:{o:0,n:0},change:{o:0,n:0}}
476						});
477						
478						var d=$this.data(pluginPfx),o=d.opt,
479							/* HTML data attributes */
480							htmlDataAxis=$this.data("mcs-axis"),htmlDataSbPos=$this.data("mcs-scrollbar-position"),htmlDataTheme=$this.data("mcs-theme");
481						 
482						if(htmlDataAxis){o.axis=htmlDataAxis;} /* usage example: data-mcs-axis="y" */
483						if(htmlDataSbPos){o.scrollbarPosition=htmlDataSbPos;} /* usage example: data-mcs-scrollbar-position="outside" */
484						if(htmlDataTheme){ /* usage example: data-mcs-theme="minimal" */
485							o.theme=htmlDataTheme;
486							_theme(o); /* theme-specific options */
487						}
488						
489						_pluginMarkup.call(this); /* add plugin markup */
490						
491						if(d && o.callbacks.onCreate && typeof o.callbacks.onCreate==="function"){o.callbacks.onCreate.call(this);} /* callbacks: onCreate */
492						
493						$("#mCSB_"+d.idx+"_container img:not(."+classes[2]+")").addClass(classes[2]); /* flag loaded images */
494						
495						methods.update.call(null,$this); /* call the update method */
496					
497					}
498					
499				});
500				
501			},
502			/* ---------------------------------------- */
503			
504			
505			
506			/* 
507			plugin update method 
508			updates content and scrollbar(s) values, events and status 
509			----------------------------------------
510			usage: $(selector).mCustomScrollbar("update");
511			*/
512			
513			update:function(el,cb){
514				
515				var selector=el || _selector.call(this); /* validate selector */
516				
517				return $(selector).each(function(){
518					
519					var $this=$(this);
520					
521					if($this.data(pluginPfx)){ /* check if plugin has initialized */
522						
523						var d=$this.data(pluginPfx),o=d.opt,
524							mCSB_container=$("#mCSB_"+d.idx+"_container"),
525							mCustomScrollBox=$("#mCSB_"+d.idx),
526							mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")];
527						
528						if(!mCSB_container.length){return;}
529						
530						if(d.tweenRunning){_stop($this);} /* stop any running tweens while updating */
531						
532						if(cb && d && o.callbacks.onBeforeUpdate && typeof o.callbacks.onBeforeUpdate==="function"){o.callbacks.onBeforeUpdate.call(this);} /* callbacks: onBeforeUpdate */
533						
534						/* if element was disabled or destroyed, remove class(es) */
535						if($this.hasClass(classes[3])){$this.removeClass(classes[3]);}
536						if($this.hasClass(classes[4])){$this.removeClass(classes[4]);}
537						
538						/* css flexbox fix, detect/set max-height */
539						mCustomScrollBox.css("max-height","none");
540						if(mCustomScrollBox.height()!==$this.height()){mCustomScrollBox.css("max-height",$this.height());}
541						
542						_expandContentHorizontally.call(this); /* expand content horizontally */
543						
544						if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){
545							mCSB_container.css("width",_contentWidth(mCSB_container));
546						}
547						
548						d.overflowed=_overflowed.call(this); /* determine if scrolling is required */
549						
550						_scrollbarVisibility.call(this); /* show/hide scrollbar(s) */
551						
552						/* auto-adjust scrollbar dragger length analogous to content */
553						if(o.autoDraggerLength){_setDraggerLength.call(this);}
554						
555						_scrollRatio.call(this); /* calculate and store scrollbar to content ratio */
556						
557						_bindEvents.call(this); /* bind scrollbar events */
558						
559						/* reset scrolling position and/or events */
560						var to=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)];
561						if(o.axis!=="x"){ /* y/yx axis */
562							if(!d.overflowed[0]){ /* y scrolling is not required */
563								_resetContentPosition.call(this); /* reset content position */
564								if(o.axis==="y"){
565									_unbindEvents.call(this);
566								}else if(o.axis==="yx" && d.overflowed[1]){
567									_scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"});
568								}
569							}else if(mCSB_dragger[0].height()>mCSB_dragger[0].parent().height()){
570								_resetContentPosition.call(this); /* reset content position */
571							}else{ /* y scrolling is required */
572								_scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"});
573								d.contentReset.y=null;
574							}
575						}
576						if(o.axis!=="y"){ /* x/yx axis */
577							if(!d.overflowed[1]){ /* x scrolling is not required */
578								_resetContentPosition.call(this); /* reset content position */
579								if(o.axis==="x"){
580									_unbindEvents.call(this);
581								}else if(o.axis==="yx" && d.overflowed[0]){
582									_scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"});
583								}
584							}else if(mCSB_dragger[1].width()>mCSB_dragger[1].parent().width()){
585								_resetContentPosition.call(this); /* reset content position */
586							}else{ /* x scrolling is required */
587								_scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"});
588								d.contentReset.x=null;
589							}
590						}
591						
592						/* callbacks: onImageLoad, onSelectorChange, onUpdate */
593						if(cb && d){
594							if(cb===2 && o.callbacks.onImageLoad && typeof o.callbacks.onImageLoad==="function"){
595								o.callbacks.onImageLoad.call(this);
596							}else if(cb===3 && o.callbacks.onSelectorChange && typeof o.callbacks.onSelectorChange==="function"){
597								o.callbacks.onSelectorChange.call(this);
598							}else if(o.callbacks.onUpdate && typeof o.callbacks.onUpdate==="function"){
599								o.callbacks.onUpdate.call(this);
600							}
601						}
602						
603						_autoUpdate.call(this); /* initialize automatic updating (for dynamic content, fluid layouts etc.) */
604						
605					}
606					
607				});
608				
609			},
610			/* ---------------------------------------- */
611			
612			
613			
614			/* 
615			plugin scrollTo method 
616			triggers a scrolling event to a specific value
617			----------------------------------------
618			usage: $(selector).mCustomScrollbar("scrollTo",value,options);
619			*/
620		
621			scrollTo:function(val,options){
622				
623				/* prevent silly things like $(selector).mCustomScrollbar("scrollTo",undefined); */
624				if(typeof val=="undefined" || val==null){return;}
625				
626				var selector=_selector.call(this); /* validate selector */
627				
628				return $(selector).each(function(){
629					
630					var $this=$(this);
631					
632					if($this.data(pluginPfx)){ /* check if plugin has initialized */
633					
634						var d=$this.data(pluginPfx),o=d.opt,
635							/* method default options */
636							methodDefaults={
637								trigger:"external", /* method is by default triggered externally (e.g. from other scripts) */
638								scrollInertia:o.scrollInertia, /* scrolling inertia (animation duration) */
639								scrollEasing:"mcsEaseInOut", /* animation easing */
640								moveDragger:false, /* move dragger instead of content */
641								timeout:60, /* scroll-to delay */
642								callbacks:true, /* enable/disable callbacks */
643								onStart:true,
644								onUpdate:true,
645								onComplete:true
646							},
647							methodOptions=$.extend(true,{},methodDefaults,options),
648							to=_arr.call(this,val),dur=methodOptions.scrollInertia>0 && methodOptions.scrollInertia<17 ? 17 : methodOptions.scrollInertia;
649						
650						/* translate yx values to actual scroll-to positions */
651						to[0]=_to.call(this,to[0],"y");
652						to[1]=_to.call(this,to[1],"x");
653						
654						/* 
655						check if scroll-to value moves the dragger instead of content. 
656						Only pixel values apply on dragger (e.g. 100, "100px", "-=100" etc.) 
657						*/
658						if(methodOptions.moveDragger){
659							to[0]*=d.scrollRatio.y;
660							to[1]*=d.scrollRatio.x;
661						}
662						
663						methodOptions.dur=_isTabHidden() ? 0 : dur; //skip animations if browser tab is hidden
664						
665						setTimeout(function(){ 
666							/* do the scrolling */
667							if(to[0]!==null && typeof to[0]!=="undefined" && o.axis!=="x" && d.overflowed[0]){ /* scroll y */
668								methodOptions.dir="y";
669								methodOptions.overwrite="all";
670								_scrollTo($this,to[0].toString(),methodOptions);
671							}
672							if(to[1]!==null && typeof to[1]!=="undefined" && o.axis!=="y" && d.overflowed[1]){ /* scroll x */
673								methodOptions.dir="x";
674								methodOptions.overwrite="none";
675								_scrollTo($this,to[1].toString(),methodOptions);
676							}
677						},methodOptions.timeout);
678						
679					}
680					
681				});
682				
683			},
684			/* ---------------------------------------- */
685			
686			
687			
688			/*
689			plugin stop method 
690			stops scrolling animation
691			----------------------------------------
692			usage: $(selector).mCustomScrollbar("stop");
693			*/
694			stop:function(){
695				
696				var selector=_selector.call(this); /* validate selector */
697				
698				return $(selector).each(function(){
699					
700					var $this=$(this);
701					
702					if($this.data(pluginPfx)){ /* check if plugin has initialized */
703										
704						_stop($this);
705					
706					}
707					
708				});
709				
710			},
711			/* ---------------------------------------- */
712			
713			
714			
715			/*
716			plugin disable method 
717			temporarily disables the scrollbar(s) 
718			----------------------------------------
719			usage: $(selector).mCustomScrollbar("disable",reset); 
720			reset (boolean): resets content position to 0 
721			*/
722			disable:function(r){
723				
724				var selector=_selector.call(this); /* validate selector */
725				
726				return $(selector).each(function(){
727					
728					var $this=$(this);
729					
730					if($this.data(pluginPfx)){ /* check if plugin has initialized */
731						
732						var d=$this.data(pluginPfx);
733						
734						_autoUpdate.call(this,"remove"); /* remove automatic updating */
735						
736						_unbindEvents.call(this); /* unbind events */
737						
738						if(r){_resetContentPosition.call(this);} /* reset content position */
739						
740						_scrollbarVisibility.call(this,true); /* show/hide scrollbar(s) */
741						
742						$this.addClass(classes[3]); /* add disable class */
743					
744					}
745					
746				});
747				
748			},
749			/* ---------------------------------------- */
750			
751			
752			
753			/*
754			plugin destroy method 
755			completely removes the scrollbar(s) and returns the element to its original state
756			----------------------------------------
757			usage: $(selector).mCustomScrollbar("destroy"); 
758			*/
759			destroy:function(){
760				
761				var selector=_selector.call(this); /* validate selector */
762				
763				return $(selector).each(function(){
764					
765					var $this=$(this);
766					
767					if($this.data(pluginPfx)){ /* check if plugin has initialized */
768					
769						var d=$this.data(pluginPfx),o=d.opt,
770							mCustomScrollBox=$("#mCSB_"+d.idx),
771							mCSB_container=$("#mCSB_"+d.idx+"_container"),
772							scrollbar=$(".mCSB_"+d.idx+"_scrollbar");
773					
774						if(o.live){removeLiveTimers(o.liveSelector || $(selector).selector);} /* remove live timers */
775						
776						_autoUpdate.call(this,"remove"); /* remove automatic updating */
777						
778						_unbindEvents.call(this); /* unbind events */
779						
780						_resetContentPosition.call(this); /* reset content position */
781						
782						$this.removeData(pluginPfx); /* remove plugin data object */
783						
784						_delete(this,"mcs"); /* delete callbacks object */
785						
786						/* remove plugin markup */
787						scrollbar.remove(); /* remove scrollbar(s) first (those can be either inside or outside plugin's inner wrapper) */
788						mCSB_container.find("img."+classes[2]).removeClass(classes[2]); /* remove loaded images flag */
789						mCustomScrollBox.replaceWith(mCSB_container.contents()); /* replace plugin's inner wrapper with the original content */
790						/* remove plugin classes from the element and add destroy class */
791						$this.removeClass(pluginNS+" _"+pluginPfx+"_"+d.idx+" "+classes[6]+" "+classes[7]+" "+classes[5]+" "+classes[3]).addClass(classes[4]);
792					
793					}
794					
795				});
796				
797			}
798			/* ---------------------------------------- */
799			
800		},
801	
802	
803	
804	
805		
806	/* 
807	----------------------------------------
808	FUNCTIONS
809	----------------------------------------
810	*/
811	
812		/* validates selector (if selector is invalid or undefined uses the default one) */
813		_selector=function(){
814			return (typeof $(this)!=="object" || $(this).length<1) ? defaultSelector : this;
815		},
816		/* -------------------- */
817		
818		
819		/* changes options according to theme */
820		_theme=function(obj){
821			var fixedSizeScrollbarThemes=["rounded","rounded-dark","rounded-dots","rounded-dots-dark"],
822				nonExpandedScrollbarThemes=["rounded-dots","rounded-dots-dark","3d","3d-dark","3d-thick","3d-thick-dark","inset","inset-dark","inset-2","inset-2-dark","inset-3","inset-3-dark"],
823				disabledScrollButtonsThemes=["minimal","minimal-dark"],
824				enabledAutoHideScrollbarThemes=["minimal","minimal-dark"],
825				scrollbarPositionOutsideThemes=["minimal","minimal-dark"];
826			obj.autoDraggerLength=$.inArray(obj.theme,fixedSizeScrollbarThemes) > -1 ? false : obj.autoDraggerLength;
827			obj.autoExpandScrollbar=$.inArray(obj.theme,nonExpandedScrollbarThemes) > -1 ? false : obj.autoExpandScrollbar;
828			obj.scrollButtons.enable=$.inArray(obj.theme,disabledScrollButtonsThemes) > -1 ? false : obj.scrollButtons.enable;
829			obj.autoHideScrollbar=$.inArray(obj.theme,enabledAutoHideScrollbarThemes) > -1 ? true : obj.autoHideScrollbar;
830			obj.scrollbarPosition=$.inArray(obj.theme,scrollbarPositionOutsideThemes) > -1 ? "outside" : obj.scrollbarPosition;
831		},
832		/* -------------------- */
833		
834		
835		/* live option timers removal */
836		removeLiveTimers=function(selector){
837			if(liveTimers[selector]){
838				clearTimeout(liveTimers[selector]);
839				_delete(liveTimers,selector);
840			}
841		},
842		/* -------------------- */
843		
844		
845		/* normalizes axis option to valid values: "y", "x", "yx" */
846		_findAxis=function(val){
847			return (val==="yx" || val==="xy" || val==="auto") ? "yx" : (val==="x" || val==="horizontal") ? "x" : "y";
848		},
849		/* -------------------- */
850		
851		
852		/* normalizes scrollButtons.scrollType option to valid values: "stepless", "stepped" */
853		_findScrollButtonsType=function(val){
854			return (val==="stepped" || val==="pixels" || val==="step" || val==="click") ? "stepped" : "stepless";
855		},
856		/* -------------------- */
857		
858		
859		/* generates plugin markup */
860		_pluginMarkup=function(){
861			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
862				expandClass=o.autoExpandScrollbar ? " "+classes[1]+"_expand" : "",
863				scrollbar=["<div id='mCSB_"+d.idx+"_scrollbar_vertical' class='mCSB_scrollTools mCSB_"+d.idx+"_scrollbar mCS-"+o.theme+" mCSB_scrollTools_vertical"+expandClass+"'><div class='"+classes[12]+"'><div id='mCSB_"+d.idx+"_dragger_vertical' class='mCSB_dragger' style='position:absolute;'
863 oncontextmenu='return false;'><div class='mCSB_dragger_bar' /></div><div class='mCSB_draggerRail' /></div></div>","<div id='mCSB_"+d.idx+"_scrollbar_horizontal' class='mCSB_scrollTools mCSB_"+d.idx+"_scrollbar mCS-"+o.theme+" mCSB_scrollTools_horizontal"+expandClass+"'><div class='"+classes[12]+"'><div id='mCSB_"+d.idx+"_dragger_horizontal' class='mCSB_dragger' style='position:absolute;' oncontextmenu='return false;'><div class='mCSB_dragger_bar' /></div><div class='mCSB_draggerRail' /></div></div>"],
864				wrapperClass=o.axis==="yx" ? "mCSB_vertical_horizontal" : o.axis==="x" ? "mCSB_horizontal" : "mCSB_vertical",
865				scrollbars=o.axis==="yx" ? scrollbar[0]+scrollbar[1] : o.axis==="x" ? scrollbar[1] : scrollbar[0],
866				contentWrapper=o.axis==="yx" ? "<div id='mCSB_"+d.idx+"_container_wrapper' class='mCSB_container_wrapper' />" : "",
867				autoHideClass=o.autoHideScrollbar ? " "+classes[6] : "",
868				scrollbarDirClass=(o.axis!=="x" && d.langDir==="rtl") ? " "+classes[7] : "";
869			if(o.setWidth){$this.css("width",o.setWidth);} /* set element width */
870			if(o.setHeight){$this.css("height",o.setHeight);} /* set element height */
871			o.setLeft=(o.axis!=="y" && d.langDir==="rtl") ? "989999px" : o.setLeft; /* adjust left position for rtl direction */
872			$this.addClass(pluginNS+" _"+pluginPfx+"_"+d.idx+autoHideClass+scrollbarDirClass).wrapInner("<div id='m
vendor: 9,917 bytes, lines 872-1098
872CSB_"+d.idx+"' class='mCustomScrollBox mCS-"+o.theme+" "+wrapperClass+"'><div id='mCSB_"+d.idx+"_container' class='mCSB_container' style='position:relative; top:"+o.setTop+"; left:"+o.setLeft+";' dir="+d.langDir+" /></div>");
873			var mCustomScrollBox=$("#mCSB_"+d.idx),
874				mCSB_container=$("#mCSB_"+d.idx+"_container");
875			if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){
876				mCSB_container.css("width",_contentWidth(mCSB_container));
877			}
878			if(o.scrollbarPosition==="outside"){
879				if($this.css("position")==="static"){ /* requires elements with non-static position */
880					$this.css("position","relative");
881				}
882				$this.css("overflow","visible");
883				mCustomScrollBox.addClass("mCSB_outside").after(scrollbars);
884			}else{
885				mCustomScrollBox.addClass("mCSB_inside").append(scrollbars);
886				mCSB_container.wrap(contentWrapper);
887			}
888			_scrollButtons.call(this); /* add scrollbar buttons */
889			/* minimum dragger length */
890			var mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")];
891			mCSB_dragger[0].css("min-height",mCSB_dragger[0].height());
892			mCSB_dragger[1].css("min-width",mCSB_dragger[1].width());
893		},
894		/* -------------------- */
895		
896		
897		/* calculates content width */
898		_contentWidth=function(el){
899			var val=[el[0].scrollWidth,Math.max.apply(Math,el.children().map(function(){return $(this).outerWidth(true);}).get())],w=el.parent().width();
900			return val[0]>w ? val[0] : val[1]>w ? val[1] : "100%";
901		},
902		/* -------------------- */
903		
904		
905		/* expands content horizontally */
906		_expandContentHorizontally=function(){
907			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
908				mCSB_container=$("#mCSB_"+d.idx+"_container");
909			if(o.advanced.autoExpandHorizontalScroll && o.axis!=="y"){
910				/* calculate scrollWidth */
911				mCSB_container.css({"width":"auto","min-width":0,"overflow-x":"scroll"});
912				var w=Math.ceil(mCSB_container[0].scrollWidth);
913				if(o.advanced.autoExpandHorizontalScroll===3 || (o.advanced.autoExpandHorizontalScroll!==2 && w>mCSB_container.parent().width())){
914					mCSB_container.css({"width":w,"min-width":"100%","overflow-x":"inherit"});
915				}else{
916					/* 
917					wrap content with an infinite width div and set its position to absolute and width to auto. 
918					Setting width to auto before calculating the actual width is important! 
919					We must let the browser set the width as browser zoom values are impossible to calculate.
920					*/
921					mCSB_container.css({"overflow-x":"inherit","position":"absolute"})
922						.wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />")
923						.css({ /* set actual width, original position and un-wrap */
924							/* 
925							get the exact width (with decimals) and then round-up. 
926							Using jquery outerWidth() will round the width value which will mess up with inner elements that have non-integer width
927							*/
928							"width":(Math.ceil(mCSB_container[0].getBoundingClientRect().right+0.4)-Math.floor(mCSB_container[0].getBoundingClientRect().left)),
929							"min-width":"100%",
930							"position":"relative"
931						}).unwrap();
932				}
933			}
934		},
935		/* -------------------- */
936		
937		
938		/* adds scrollbar buttons */
939		_scrollButtons=function(){
940			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
941				mCSB_scrollTools=$(".mCSB_"+d.idx+"_scrollbar:first"),
942				tabindex=!_isNumeric(o.scrollButtons.tabindex) ? "" : "tabindex='"+o.scrollButtons.tabindex+"'",
943				btnHTML=[
944					"<a href='#' class='"+classes[13]+"' oncontextmenu='return false;' "+tabindex+" />",
945					"<a href='#' class='"+classes[14]+"' oncontextmenu='return false;' "+tabindex+" />",
946					"<a href='#' class='"+classes[15]+"' oncontextmenu='return false;' "+tabindex+" />",
947					"<a href='#' class='"+classes[16]+"' oncontextmenu='return false;' "+tabindex+" />"
948				],
949				btn=[(o.axis==="x" ? btnHTML[2] : btnHTML[0]),(o.axis==="x" ? btnHTML[3] : btnHTML[1]),btnHTML[2],btnHTML[3]];
950			if(o.scrollButtons.enable){
951				mCSB_scrollTools.prepend(btn[0]).append(btn[1]).next(".mCSB_scrollTools").prepend(btn[2]).append(btn[3]);
952			}
953		},
954		/* -------------------- */
955		
956		
957		/* auto-adjusts scrollbar dragger length */
958		_setDraggerLength=function(){
959			var $this=$(this),d=$this.data(pluginPfx),
960				mCustomScrollBox=$("#mCSB_"+d.idx),
961				mCSB_container=$("#mCSB_"+d.idx+"_container"),
962				mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")],
963				ratio=[mCustomScrollBox.height()/mCSB_container.outerHeight(false),mCustomScrollBox.width()/mCSB_container.outerWidth(false)],
964				l=[
965					parseInt(mCSB_dragger[0].css("min-height")),Math.round(ratio[0]*mCSB_dragger[0].parent().height()),
966					parseInt(mCSB_dragger[1].css("min-width")),Math.round(ratio[1]*mCSB_dragger[1].parent().width())
967				],
968				h=oldIE && (l[1]<l[0]) ? l[0] : l[1],w=oldIE && (l[3]<l[2]) ? l[2] : l[3];
969			mCSB_dragger[0].css({
970				"height":h,"max-height":(mCSB_dragger[0].parent().height()-10)
971			}).find(".mCSB_dragger_bar").css({"line-height":l[0]+"px"});
972			mCSB_dragger[1].css({
973				"width":w,"max-width":(mCSB_dragger[1].parent().width()-10)
974			});
975		},
976		/* -------------------- */
977		
978		
979		/* calculates scrollbar to content ratio */
980		_scrollRatio=function(){
981			var $this=$(this),d=$this.data(pluginPfx),
982				mCustomScrollBox=$("#mCSB_"+d.idx),
983				mCSB_container=$("#mCSB_"+d.idx+"_container"),
984				mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")],
985				scrollAmount=[mCSB_container.outerHeight(false)-mCustomScrollBox.height(),mCSB_container.outerWidth(false)-mCustomScrollBox.width()],
986				ratio=[
987					scrollAmount[0]/(mCSB_dragger[0].parent().height()-mCSB_dragger[0].height()),
988					scrollAmount[1]/(mCSB_dragger[1].parent().width()-mCSB_dragger[1].width())
989				];
990			d.scrollRatio={y:ratio[0],x:ratio[1]};
991		},
992		/* -------------------- */
993		
994		
995		/* toggles scrolling classes */
996		_onDragClasses=function(el,action,xpnd){
997			var expandClass=xpnd ? classes[0]+"_expanded" : "",
998				scrollbar=el.closest(".mCSB_scrollTools");
999			if(action==="active"){
1000				el.toggleClass(classes[0]+" "+expandClass); scrollbar.toggleClass(classes[1]); 
1001				el[0]._draggable=el[0]._draggable ? 0 : 1;
1002			}else{
1003				if(!el[0]._draggable){
1004					if(action==="hide"){
1005						el.removeClass(classes[0]); scrollbar.removeClass(classes[1]);
1006					}else{
1007						el.addClass(classes[0]); scrollbar.addClass(classes[1]);
1008					}
1009				}
1010			}
1011		},
1012		/* -------------------- */
1013		
1014		
1015		/* checks if content overflows its container to determine if scrolling is required */
1016		_overflowed=function(){
1017			var $this=$(this),d=$this.data(pluginPfx),
1018				mCustomScrollBox=$("#mCSB_"+d.idx),
1019				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1020				contentHeight=d.overflowed==null ? mCSB_container.height() : mCSB_container.outerHeight(false),
1021				contentWidth=d.overflowed==null ? mCSB_container.width() : mCSB_container.outerWidth(false),
1022				h=mCSB_container[0].scrollHeight,w=mCSB_container[0].scrollWidth;
1023			if(h>contentHeight){contentHeight=h;}
1024			if(w>contentWidth){contentWidth=w;}
1025			return [contentHeight>mCustomScrollBox.height(),contentWidth>mCustomScrollBox.width()];
1026		},
1027		/* -------------------- */
1028		
1029		
1030		/* resets content position to 0 */
1031		_resetContentPosition=function(){
1032			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1033				mCustomScrollBox=$("#mCSB_"+d.idx),
1034				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1035				mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")];
1036			_stop($this); /* stop any current scrolling before resetting */
1037			if((o.axis!=="x" && !d.overflowed[0]) || (o.axis==="y" && d.overflowed[0])){ /* reset y */
1038				mCSB_dragger[0].add(mCSB_container).css("top",0);
1039				_scrollTo($this,"_resetY");
1040			}
1041			if((o.axis!=="y" && !d.overflowed[1]) || (o.axis==="x" && d.overflowed[1])){ /* reset x */
1042				var cx=dx=0;
1043				if(d.langDir==="rtl"){ /* adjust left position for rtl direction */
1044					cx=mCustomScrollBox.width()-mCSB_container.outerWidth(false);
1045					dx=Math.abs(cx/d.scrollRatio.x);
1046				}
1047				mCSB_container.css("left",cx);
1048				mCSB_dragger[1].css("left",dx);
1049				_scrollTo($this,"_resetX");
1050			}
1051		},
1052		/* -------------------- */
1053		
1054		
1055		/* binds scrollbar events */
1056		_bindEvents=function(){
1057			var $this=$(this),d=$this.data(pluginPfx),o=d.opt;
1058			if(!d.bindEvents){ /* check if events are already bound */
1059				_draggable.call(this);
1060				if(o.contentTouchScroll){_contentDraggable.call(this);}
1061				_selectable.call(this);
1062				if(o.mouseWheel.enable){ /* bind mousewheel fn when plugin is available */
1063					function _mwt(){
1064						mousewheelTimeout=setTimeout(function(){
1065							if(!$.event.special.mousewheel){
1066								_mwt();
1067							}else{
1068								clearTimeout(mousewheelTimeout);
1069								_mousewheel.call($this[0]);
1070							}
1071						},100);
1072					}
1073					var mousewheelTimeout;
1074					_mwt();
1075				}
1076				_draggerRail.call(this);
1077				_wrapperScroll.call(this);
1078				if(o.advanced.autoScrollOnFocus){_focus.call(this);}
1079				if(o.scrollButtons.enable){_buttons.call(this);}
1080				if(o.keyboard.enable){_keyboard.call(this);}
1081				d.bindEvents=true;
1082			}
1083		},
1084		/* -------------------- */
1085		
1086		
1087		/* unbinds scrollbar events */
1088		_unbindEvents=function(){
1089			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1090				namespace=pluginPfx+"_"+d.idx,
1091				sb=".mCSB_"+d.idx+"_scrollbar",
1092				sel=$("#mCSB_"+d.idx+",#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,"+sb+" ."+classes[12]+",#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal,"+sb+">a"),
1093				mCSB_container=$("#mCSB_"+d.idx+"_container");
1094			if(o.advanced.releaseDraggableSelectors){sel.add($(o.advanced.releaseDraggableSelectors));}
1095			if(o.advanced.extraDraggableSelectors){sel.add($(o.advanced.extraDraggableSelectors));}
1096			if(d.bindEvents){ /* check if events are bound */
1097				/* unbind namespaced events from document/selectors */
1098				$(document).add($(!_canAccessIFrame() || top.document
vendor: 2,283 bytes, lines 1098-1160
1098)).unbind("."+namespace);
1099				sel.each(function(){
1100					$(this).unbind("."+namespace);
1101				});
1102				/* clear and delete timeouts/objects */
1103				clearTimeout($this[0]._focusTimeout); _delete($this[0],"_focusTimeout");
1104				clearTimeout(d.sequential.step); _delete(d.sequential,"step");
1105				clearTimeout(mCSB_container[0].onCompleteTimeout); _delete(mCSB_container[0],"onCompleteTimeout");
1106				d.bindEvents=false;
1107			}
1108		},
1109		/* -------------------- */
1110		
1111		
1112		/* toggles scrollbar visibility */
1113		_scrollbarVisibility=function(disabled){
1114			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1115				contentWrapper=$("#mCSB_"+d.idx+"_container_wrapper"),
1116				content=contentWrapper.length ? contentWrapper : $("#mCSB_"+d.idx+"_container"),
1117				scrollbar=[$("#mCSB_"+d.idx+"_scrollbar_vertical"),$("#mCSB_"+d.idx+"_scrollbar_horizontal")],
1118				mCSB_dragger=[scrollbar[0].find(".mCSB_dragger"),scrollbar[1].find(".mCSB_dragger")];
1119			if(o.axis!=="x"){
1120				if(d.overflowed[0] && !disabled){
1121					scrollbar[0].add(mCSB_dragger[0]).add(scrollbar[0].children("a")).css("display","block");
1122					content.removeClass(classes[8]+" "+classes[10]);
1123				}else{
1124					if(o.alwaysShowScrollbar){
1125						if(o.alwaysShowScrollbar!==2){mCSB_dragger[0].css("display","none");}
1126						content.removeClass(classes[10]);
1127					}else{
1128						scrollbar[0].css("display","none");
1129						content.addClass(classes[10]);
1130					}
1131					content.addClass(classes[8]);
1132				}
1133			}
1134			if(o.axis!=="y"){
1135				if(d.overflowed[1] && !disabled){
1136					scrollbar[1].add(mCSB_dragger[1]).add(scrollbar[1].children("a")).css("display","block");
1137					content.removeClass(classes[9]+" "+classes[11]);
1138				}else{
1139					if(o.alwaysShowScrollbar){
1140						if(o.alwaysShowScrollbar!==2){mCSB_dragger[1].css("display","none");}
1141						content.removeClass(classes[11]);
1142					}else{
1143						scrollbar[1].css("display","none");
1144						content.addClass(classes[11]);
1145					}
1146					content.addClass(classes[9]);
1147				}
1148			}
1149			if(!d.overflowed[0] && !d.overflowed[1]){
1150				$this.addClass(classes[5]);
1151			}else{
1152				$this.removeClass(classes[5]);
1153			}
1154		},
1155		/* -------------------- */
1156		
1157		
1158		/* returns input coordinates of pointer, touch and mouse events (relative to document) */
1159		_coordinates=function(e){
1160			var t=e.type,o=e.target.ownerDocument!==document 
vendor: 28,345 bytes, lines 1160-1856
1160? [$(frameElement).offset().top,$(frameElement).offset().left] : null,
1161				io=_canAccessIFrame() && e.target.ownerDocument!==top.document ? [$(e.view.frameElement).offset().top,$(e.view.frameElement).offset().left] : [0,0];
1162			switch(t){
1163				case "pointerdown": case "MSPointerDown": case "pointermove": case "MSPointerMove": case "pointerup": case "MSPointerUp":
1164					return o ? [e.originalEvent.pageY-o[0]+io[0],e.originalEvent.pageX-o[1]+io[1],false] : [e.originalEvent.pageY,e.originalEvent.pageX,false];
1165					break;
1166				case "touchstart": case "touchmove": case "touchend":
1167					var touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0],
1168						touches=e.originalEvent.touches.length || e.originalEvent.changedTouches.length;
1169					return e.target.ownerDocument!==document ? [touch.screenY,touch.screenX,touches>1] : [touch.pageY,touch.pageX,touches>1];
1170					break;
1171				default:
1172					return o ? [e.pageY-o[0]+io[0],e.pageX-o[1]+io[1],false] : [e.pageY,e.pageX,false];
1173			}
1174		},
1175		/* -------------------- */
1176		
1177		
1178		/* 
1179		SCROLLBAR DRAG EVENTS
1180		scrolls content via scrollbar dragging 
1181		*/
1182		_draggable=function(){
1183			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1184				namespace=pluginPfx+"_"+d.idx,
1185				draggerId=["mCSB_"+d.idx+"_dragger_vertical","mCSB_"+d.idx+"_dragger_horizontal"],
1186				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1187				mCSB_dragger=$("#"+draggerId[0]+",#"+draggerId[1]),
1188				draggable,dragY,dragX,
1189				rds=o.advanced.releaseDraggableSelectors ? mCSB_dragger.add($(o.advanced.releaseDraggableSelectors)) : mCSB_dragger,
1190				eds=o.advanced.extraDraggableSelectors ? $(!_canAccessIFrame() || top.document).add($(o.advanced.extraDraggableSelectors)) : $(!_canAccessIFrame() || top.document);
1191			mCSB_dragger.bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){
1192				e.stopImmediatePropagation();
1193				e.preventDefault();
1194				if(!_mouseBtnLeft(e)){return;} /* left mouse button only */
1195				touchActive=true;
1196				if(oldIE){document.onselectstart=function(){return false;}} /* disable text selection for IE < 9 */
1197				_iframe(false); /* enable scrollbar dragging over iframes by disabling their events */
1198				_stop($this);
1199				draggable=$(this);
1200				var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left,
1201					h=draggable.height()+offset.top,w=draggable.width()+offset.left;
1202				if(y<h && y>0 && x<w && x>0){
1203					dragY=y; 
1204					dragX=x;
1205				}
1206				_onDragClasses(draggable,"active",o.autoExpandScrollbar); 
1207			}).bind("touchmove."+namespace,function(e){
1208				e.stopImmediatePropagation();
1209				e.preventDefault();
1210				var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left;
1211				_drag(dragY,dragX,y,x);
1212			});
1213			$(document).add(eds).bind("mousemove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace,function(e){
1214				if(draggable){
1215					var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left;
1216					if(dragY===y && dragX===x){return;} /* has it really moved? */
1217					_drag(dragY,dragX,y,x);
1218				}
1219			}).add(rds).bind("mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){
1220				if(draggable){
1221					_onDragClasses(draggable,"active",o.autoExpandScrollbar); 
1222					draggable=null;
1223				}
1224				touchActive=false;
1225				if(oldIE){document.onselectstart=null;} /* enable text selection for IE < 9 */
1226				_iframe(true); /* enable iframes events */
1227			});
1228			function _iframe(evt){
1229				var el=mCSB_container.find("iframe");
1230				if(!el.length){return;} /* check if content contains iframes */
1231				var val=!evt ? "none" : "auto";
1232				el.css("pointer-events",val); /* for IE11, iframe's display property should not be "block" */
1233			}
1234			function _drag(dragY,dragX,y,x){
1235				mCSB_container[0].idleTimer=o.scrollInertia<233 ? 250 : 0;
1236				if(draggable.attr("id")===draggerId[1]){
1237					var dir="x",to=((draggable[0].offsetLeft-dragX)+x)*d.scrollRatio.x;
1238				}else{
1239					var dir="y",to=((draggable[0].offsetTop-dragY)+y)*d.scrollRatio.y;
1240				}
1241				_scrollTo($this,to.toString(),{dir:dir,drag:true});
1242			}
1243		},
1244		/* -------------------- */
1245		
1246		
1247		/* 
1248		TOUCH SWIPE EVENTS
1249		scrolls content via touch swipe 
1250		Emulates the native touch-swipe scrolling with momentum found in iOS, Android and WP devices 
1251		*/
1252		_contentDraggable=function(){
1253			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1254				namespace=pluginPfx+"_"+d.idx,
1255				mCustomScrollBox=$("#mCSB_"+d.idx),
1256				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1257				mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")],
1258				draggable,dragY,dragX,touchStartY,touchStartX,touchMoveY=[],touchMoveX=[],startTime,runningTime,endTime,distance,speed,amount,
1259				durA=0,durB,overwrite=o.axis==="yx" ? "none" : "all",touchIntent=[],touchDrag,docDrag,
1260				iframe=mCSB_container.find("iframe"),
1261				events=[
1262					"touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace, //start
1263					"touchmove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace, //move
1264					"touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace //end
1265				],
1266				touchAction=document.body.style.touchAction!==undefined;
1267			mCSB_container.bind(events[0],function(e){
1268				_onTouchstart(e);
1269			}).bind(events[1],function(e){
1270				_onTouchmove(e);
1271			});
1272			mCustomScrollBox.bind(events[0],function(e){
1273				_onTouchstart2(e);
1274			}).bind(events[2],function(e){
1275				_onTouchend(e);
1276			});
1277			if(iframe.length){
1278				iframe.each(function(){
1279					$(this).load(function(){
1280						/* bind events on accessible iframes */
1281						if(_canAccessIFrame(this)){
1282							$(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){
1283								_onTouchstart(e);
1284								_onTouchstart2(e);
1285							}).bind(events[1],function(e){
1286								_onTouchmove(e);
1287							}).bind(events[2],function(e){
1288								_onTouchend(e);
1289							});
1290						}
1291					});
1292				});
1293			}
1294			function _onTouchstart(e){
1295				if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){touchable=0; return;}
1296				touchable=1; touchDrag=0; docDrag=0; draggable=1;
1297				$this.removeClass("mCS_touch_action");
1298				var offset=mCSB_container.offset();
1299				dragY=_coordinates(e)[0]-offset.top;
1300				dragX=_coordinates(e)[1]-offset.left;
1301				touchIntent=[_coordinates(e)[0],_coordinates(e)[1]];
1302			}
1303			function _onTouchmove(e){
1304				if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){return;}
1305				if(!o.documentTouchScroll){e.preventDefault();} 
1306				e.stopImmediatePropagation();
1307				if(docDrag && !touchDrag){return;}
1308				if(draggable){
1309					runningTime=_getTime();
1310					var offset=mCustomScrollBox.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left,
1311						easing="mcsLinearOut";
1312					touchMoveY.push(y);
1313					touchMoveX.push(x);
1314					touchIntent[2]=Math.abs(_coordinates(e)[0]-touchIntent[0]); touchIntent[3]=Math.abs(_coordinates(e)[1]-touchIntent[1]);
1315					if(d.overflowed[0]){
1316						var limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(),
1317							prevent=((dragY-y)>0 && (y-dragY)>-(limit*d.scrollRatio.y) && (touchIntent[3]*2<touchIntent[2] || o.axis==="yx"));
1318					}
1319					if(d.overflowed[1]){
1320						var limitX=mCSB_dragger[1].parent().width()-mCSB_dragger[1].width(),
1321							preventX=((dragX-x)>0 && (x-dragX)>-(limitX*d.scrollRatio.x) && (touchIntent[2]*2<touchIntent[3] || o.axis==="yx"));
1322					}
1323					if(prevent || preventX){ /* prevent native document scrolling */
1324						if(!touchAction){e.preventDefault();} 
1325						touchDrag=1;
1326					}else{
1327						docDrag=1;
1328						$this.addClass("mCS_touch_action");
1329					}
1330					if(touchAction){e.preventDefault();} 
1331					amount=o.axis==="yx" ? [(dragY-y),(dragX-x)] : o.axis==="x" ? [null,(dragX-x)] : [(dragY-y),null];
1332					mCSB_container[0].idleTimer=250;
1333					if(d.overflowed[0]){_drag(amount[0],durA,easing,"y","all",true);}
1334					if(d.overflowed[1]){_drag(amount[1],durA,easing,"x",overwrite,true);}
1335				}
1336			}
1337			function _onTouchstart2(e){
1338				if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){touchable=0; return;}
1339				touchable=1;
1340				e.stopImmediatePropagation();
1341				_stop($this);
1342				startTime=_getTime();
1343				var offset=mCustomScrollBox.offset();
1344				touchStartY=_coordinates(e)[0]-offset.top;
1345				touchStartX=_coordinates(e)[1]-offset.left;
1346				touchMoveY=[]; touchMoveX=[];
1347			}
1348			function _onTouchend(e){
1349				if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){return;}
1350				draggable=0;
1351				e.stopImmediatePropagation();
1352				touchDrag=0; docDrag=0;
1353				endTime=_getTime();
1354				var offset=mCustomScrollBox.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left;
1355				if((endTime-runningTime)>30){return;}
1356				speed=1000/(endTime-startTime);
1357				var easing="mcsEaseOut",slow=speed<2.5,
1358					diff=slow ? [touchMoveY[touchMoveY.length-2],touchMoveX[touchMoveX.length-2]] : [0,0];
1359				distance=slow ? [(y-diff[0]),(x-diff[1])] : [y-touchStartY,x-touchStartX];
1360				var absDistance=[Math.abs(distance[0]),Math.abs(distance[1])];
1361				speed=slow ? [Math.abs(distance[0]/4),Math.abs(distance[1]/4)] : [speed,speed];
1362				var a=[
1363					Math.abs(mCSB_container[0].offsetTop)-(distance[0]*_m((absDistance[0]/speed[0]),speed[0])),
1364					Math.abs(mCSB_container[0].offsetLeft)-(distance[1]*_m((absDistance[1]/speed[1]),speed[1]))
1365				];
1366				amount=o.axis==="yx" ? [a[0],a[1]] : o.axis==="x" ? [null,a[1]] : [a[0],null];
1367				durB=[(absDistance[0]*4)+o.scrollInertia,(absDistance[1]*4)+o.scrollInertia];
1368				var md=parseInt(o.contentTouchScroll) || 0; /* absolute minimum distance required */
1369				amount[0]=absDistance[0]>md ? amount[0] : 0;
1370				amount[1]=absDistance[1]>md ? amount[1] : 0;
1371				if(d.overflowed[0]){_drag(amount[0],durB[0],easing,"y",overwrite,false);}
1372				if(d.overflowed[1]){_drag(amount[1],durB[1],easing,"x",overwrite,false);}
1373			}
1374			function _m(ds,s){
1375				var r=[s*1.5,s*2,s/1.5,s/2];
1376				if(ds>90){
1377					return s>4 ? r[0] : r[3];
1378				}else if(ds>60){
1379					return s>3 ? r[3] : r[2];
1380				}else if(ds>30){
1381					return s>8 ? r[1] : s>6 ? r[0] : s>4 ? s : r[2];
1382				}else{
1383					return s>8 ? s : r[3];
1384				}
1385			}
1386			function _drag(amount,dur,easing,dir,overwrite,drag){
1387				if(!amount){return;}
1388				_scrollTo($this,amount.toString(),{dur:dur,scrollEasing:easing,dir:dir,overwrite:overwrite,drag:drag});
1389			}
1390		},
1391		/* -------------------- */
1392		
1393		
1394		/* 
1395		SELECT TEXT EVENTS 
1396		scrolls content when text is selected 
1397		*/
1398		_selectable=function(){
1399			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential,
1400				namespace=pluginPfx+"_"+d.idx,
1401				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1402				wrapper=mCSB_container.parent(),
1403				action;
1404			mCSB_container.bind("mousedown."+namespace,function(e){
1405				if(touchable){return;}
1406				if(!action){action=1; touchActive=true;}
1407			}).add(document).bind("mousemove."+namespace,function(e){
1408				if(!touchable && action && _sel()){
1409					var offset=mCSB_container.offset(),
1410						y=_coordinates(e)[0]-offset.top+mCSB_container[0].offsetTop,x=_coordinates(e)[1]-offset.left+mCSB_container[0].offsetLeft;
1411					if(y>0 && y<wrapper.height() && x>0 && x<wrapper.width()){
1412						if(seq.step){_seq("off",null,"stepped");}
1413					}else{
1414						if(o.axis!=="x" && d.overflowed[0]){
1415							if(y<0){
1416								_seq("on",38);
1417							}else if(y>wrapper.height()){
1418								_seq("on",40);
1419							}
1420						}
1421						if(o.axis!=="y" && d.overflowed[1]){
1422							if(x<0){
1423								_seq("on",37);
1424							}else if(x>wrapper.width()){
1425								_seq("on",39);
1426							}
1427						}
1428					}
1429				}
1430			}).bind("mouseup."+namespace+" dragend."+namespace,function(e){
1431				if(touchable){return;}
1432				if(action){action=0; _seq("off",null);}
1433				touchActive=false;
1434			});
1435			function _sel(){
1436				return 	window.getSelection ? window.getSelection().toString() : 
1437						document.selection && document.selection.type!="Control" ? document.selection.createRange().text : 0;
1438			}
1439			function _seq(a,c,s){
1440				seq.type=s && action ? "stepped" : "stepless";
1441				seq.scrollAmount=10;
1442				_sequentialScroll($this,a,c,"mcsLinearOut",s ? 60 : null);
1443			}
1444		},
1445		/* -------------------- */
1446		
1447		
1448		/* 
1449		MOUSE WHEEL EVENT
1450		scrolls content via mouse-wheel 
1451		via mouse-wheel plugin (https://github.com/brandonaaron/jquery-mousewheel)
1452		*/
1453		_mousewheel=function(){
1454			if(!$(this).data(pluginPfx)){return;} /* Check if the scrollbar is ready to use mousewheel events (issue: #185) */
1455			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1456				namespace=pluginPfx+"_"+d.idx,
1457				mCustomScrollBox=$("#mCSB_"+d.idx),
1458				mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")],
1459				iframe=$("#mCSB_"+d.idx+"_container").find("iframe");
1460			if(iframe.length){
1461				iframe.each(function(){
1462					$(this).load(function(){
1463						/* bind events on accessible iframes */
1464						if(_canAccessIFrame(this)){
1465							$(this.contentDocument || this.contentWindow.document).bind("mousewheel."+namespace,function(e,delta){
1466								_onMousewheel(e,delta);
1467							});
1468						}
1469					});
1470				});
1471			}
1472			mCustomScrollBox.bind("mousewheel."+namespace,function(e,delta){
1473				_onMousewheel(e,delta);
1474			});
1475			function _onMousewheel(e,delta){
1476				_stop($this);
1477				if(_disableMousewheel($this,e.target)){return;} /* disables mouse-wheel when hovering specific elements */
1478				var deltaFactor=o.mouseWheel.deltaFactor!=="auto" ? parseInt(o.mouseWheel.deltaFactor) : (oldIE && e.deltaFactor<100) ? 100 : e.deltaFactor || 100,
1479					dur=o.scrollInertia;
1480				if(o.axis==="x" || o.mouseWheel.axis==="x"){
1481					var dir="x",
1482						px=[Math.round(deltaFactor*d.scrollRatio.x),parseInt(o.mouseWheel.scrollAmount)],
1483						amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.width() ? mCustomScrollBox.width()*0.9 : px[0],
1484						contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetLeft),
1485						draggerPos=mCSB_dragger[1][0].offsetLeft,
1486						limit=mCSB_dragger[1].parent().width()-mCSB_dragger[1].width(),
1487						dlt=e.deltaX || e.deltaY || delta;
1488				}else{
1489					var dir="y",
1490						px=[Math.round(deltaFactor*d.scrollRatio.y),parseInt(o.mouseWheel.scrollAmount)],
1491						amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.height() ? mCustomScrollBox.height()*0.9 : px[0],
1492						contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetTop),
1493						draggerPos=mCSB_dragger[0][0].offsetTop,
1494						limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(),
1495						dlt=e.deltaY || delta;
1496				}
1497				if((dir==="y" && !d.overflowed[0]) || (dir==="x" && !d.overflowed[1])){return;}
1498				if(o.mouseWheel.invert || e.webkitDirectionInvertedFromDevice){dlt=-dlt;}
1499				if(o.mouseWheel.normalizeDelta){dlt=dlt<0 ? -1 : 1;}
1500				if((dlt>0 && draggerPos!==0) || (dlt<0 && draggerPos!==limit) || o.mouseWheel.preventDefault){
1501					e.stopImmediatePropagation();
1502					e.preventDefault();
1503				}
1504				if(e.deltaFactor<2 && !o.mouseWheel.normalizeDelta){
1505					//very low deltaFactor values mean some kind of delta acceleration (e.g. osx trackpad), so adjusting scrolling accordingly
1506					amount=e.deltaFactor; dur=17;
1507				}
1508				_scrollTo($this,(contentPos-(dlt*amount)).toString(),{dir:dir,dur:dur});
1509			}
1510		},
1511		/* -------------------- */
1512		
1513		
1514		/* checks if iframe can be accessed */
1515		_canAccessIFrame=function(iframe){
1516			var html=null;
1517			if(!iframe){
1518				try{
1519					var doc=top.document;
1520					html=doc.body.innerHTML;
1521				}catch(err){/* do nothing */}
1522				return(html!==null);
1523			}else{
1524				try{
1525					var doc=iframe.contentDocument || iframe.contentWindow.document;
1526					html=doc.body.innerHTML;
1527				}catch(err){/* do nothing */}
1528				return(html!==null);
1529			}
1530		},
1531		/* -------------------- */
1532		
1533		
1534		/* disables mouse-wheel when hovering specific elements like select, datalist etc. */
1535		_disableMousewheel=function(el,target){
1536			var tag=target.nodeName.toLowerCase(),
1537				tags=el.data(pluginPfx).opt.mouseWheel.disableOver,
1538				/* elements that require focus */
1539				focusTags=["select","textarea"];
1540			return $.inArray(tag,tags) > -1 && !($.inArray(tag,focusTags) > -1 && !$(target).is(":focus"));
1541		},
1542		/* -------------------- */
1543		
1544		
1545		/* 
1546		DRAGGER RAIL CLICK EVENT
1547		scrolls content via dragger rail 
1548		*/
1549		_draggerRail=function(){
1550			var $this=$(this),d=$this.data(pluginPfx),
1551				namespace=pluginPfx+"_"+d.idx,
1552				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1553				wrapper=mCSB_container.parent(),
1554				mCSB_draggerContainer=$(".mCSB_"+d.idx+"_scrollbar ."+classes[12]),
1555				clickable;
1556			mCSB_draggerContainer.bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){
1557				touchActive=true;
1558				if(!$(e.target).hasClass("mCSB_dragger")){clickable=1;}
1559			}).bind("touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){
1560				touchActive=false;
1561			}).bind("click."+namespace,function(e){
1562				if(!clickable){return;}
1563				clickable=0;
1564				if($(e.target).hasClass(classes[12]) || $(e.target).hasClass("mCSB_draggerRail")){
1565					_stop($this);
1566					var el=$(this),mCSB_dragger=el.find(".mCSB_dragger");
1567					if(el.parent(".mCSB_scrollTools_horizontal").length>0){
1568						if(!d.overflowed[1]){return;}
1569						var dir="x",
1570							clickDir=e.pageX>mCSB_dragger.offset().left ? -1 : 1,
1571							to=Math.abs(mCSB_container[0].offsetLeft)-(clickDir*(wrapper.width()*0.9));
1572					}else{
1573						if(!d.overflowed[0]){return;}
1574						var dir="y",
1575							clickDir=e.pageY>mCSB_dragger.offset().top ? -1 : 1,
1576							to=Math.abs(mCSB_container[0].offsetTop)-(clickDir*(wrapper.height()*0.9));
1577					}
1578					_scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"});
1579				}
1580			});
1581		},
1582		/* -------------------- */
1583		
1584		
1585		/* 
1586		FOCUS EVENT
1587		scrolls content via element focus (e.g. clicking an input, pressing TAB key etc.)
1588		*/
1589		_focus=function(){
1590			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1591				namespace=pluginPfx+"_"+d.idx,
1592				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1593				wrapper=mCSB_container.parent();
1594			mCSB_container.bind("focusin."+namespace,function(e){
1595				var el=$(document.activeElement),
1596					nested=mCSB_container.find(".mCustomScrollBox").length,
1597					dur=0;
1598				if(!el.is(o.advanced.autoScrollOnFocus)){return;}
1599				_stop($this);
1600				clearTimeout($this[0]._focusTimeout);
1601				$this[0]._focusTimer=nested ? (dur+17)*nested : 0;
1602				$this[0]._focusTimeout=setTimeout(function(){
1603					var	to=[_childPos(el)[0],_childPos(el)[1]],
1604						contentPos=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft],
1605						isVisible=[
1606							(contentPos[0]+to[0]>=0 && contentPos[0]+to[0]<wrapper.height()-el.outerHeight(false)),
1607							(contentPos[1]+to[1]>=0 && contentPos[0]+to[1]<wrapper.width()-el.outerWidth(false))
1608						],
1609						overwrite=(o.axis==="yx" && !isVisible[0] && !isVisible[1]) ? "none" : "all";
1610					if(o.axis!=="x" && !isVisible[0]){
1611						_scrollTo($this,to[0].toString(),{dir:"y",scrollEasing:"mcsEaseInOut",overwrite:overwrite,dur:dur});
1612					}
1613					if(o.axis!=="y" && !isVisible[1]){
1614						_scrollTo($this,to[1].toString(),{dir:"x",scrollEasing:"mcsEaseInOut",overwrite:overwrite,dur:dur});
1615					}
1616				},$this[0]._focusTimer);
1617			});
1618		},
1619		/* -------------------- */
1620		
1621		
1622		/* sets content wrapper scrollTop/scrollLeft always to 0 */
1623		_wrapperScroll=function(){
1624			var $this=$(this),d=$this.data(pluginPfx),
1625				namespace=pluginPfx+"_"+d.idx,
1626				wrapper=$("#mCSB_"+d.idx+"_container").parent();
1627			wrapper.bind("scroll."+namespace,function(e){
1628				if(wrapper.scrollTop()!==0 || wrapper.scrollLeft()!==0){
1629					$(".mCSB_"+d.idx+"_scrollbar").css("visibility","hidden"); /* hide scrollbar(s) */
1630				}
1631			});
1632		},
1633		/* -------------------- */
1634		
1635		
1636		/* 
1637		BUTTONS EVENTS
1638		scrolls content via up, down, left and right buttons 
1639		*/
1640		_buttons=function(){
1641			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential,
1642				namespace=pluginPfx+"_"+d.idx,
1643				sel=".mCSB_"+d.idx+"_scrollbar",
1644				btn=$(sel+">a");
1645			btn.bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace+" mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace+" mouseout."+namespace+" pointerout."+namespace+" MSPointerOut."+namespace+" click."+namespace,function(e){
1646				e.preventDefault();
1647				if(!_mouseBtnLeft(e)){return;} /* left mouse button only */
1648				var btnClass=$(this).attr("class");
1649				seq.type=o.scrollButtons.scrollType;
1650				switch(e.type){
1651					case "mousedown": case "touchstart": case "pointerdown": case "MSPointerDown":
1652						if(seq.type==="stepped"){return;}
1653						touchActive=true;
1654						d.tweenRunning=false;
1655						_seq("on",btnClass);
1656						break;
1657					case "mouseup": case "touchend": case "pointerup": case "MSPointerUp":
1658					case "mouseout": case "pointerout": case "MSPointerOut":
1659						if(seq.type==="stepped"){return;}
1660						touchActive=false;
1661						if(seq.dir){_seq("off",btnClass);}
1662						break;
1663					case "click":
1664						if(seq.type!=="stepped" || d.tweenRunning){return;}
1665						_seq("on",btnClass);
1666						break;
1667				}
1668				function _seq(a,c){
1669					seq.scrollAmount=o.scrollButtons.scrollAmount;
1670					_sequentialScroll($this,a,c);
1671				}
1672			});
1673		},
1674		/* -------------------- */
1675		
1676		
1677		/* 
1678		KEYBOARD EVENTS
1679		scrolls content via keyboard 
1680		Keys: up arrow, down arrow, left arrow, right arrow, PgUp, PgDn, Home, End
1681		*/
1682		_keyboard=function(){
1683			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential,
1684				namespace=pluginPfx+"_"+d.idx,
1685				mCustomScrollBox=$("#mCSB_"+d.idx),
1686				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1687				wrapper=mCSB_container.parent(),
1688				editables="input,textarea,select,datalist,keygen,[contenteditable='true']",
1689				iframe=mCSB_container.find("iframe"),
1690				events=["blur."+namespace+" keydown."+namespace+" keyup."+namespace];
1691			if(iframe.length){
1692				iframe.each(function(){
1693					$(this).load(function(){
1694						/* bind events on accessible iframes */
1695						if(_canAccessIFrame(this)){
1696							$(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){
1697								_onKeyboard(e);
1698							});
1699						}
1700					});
1701				});
1702			}
1703			mCustomScrollBox.attr("tabindex","0").bind(events[0],function(e){
1704				_onKeyboard(e);
1705			});
1706			function _onKeyboard(e){
1707				switch(e.type){
1708					case "blur":
1709						if(d.tweenRunning && seq.dir){_seq("off",null);}
1710						break;
1711					case "keydown": case "keyup":
1712						var code=e.keyCode ? e.keyCode : e.which,action="on";
1713						if((o.axis!=="x" && (code===38 || code===40)) || (o.axis!=="y" && (code===37 || code===39))){
1714							/* up (38), down (40), left (37), right (39) arrows */
1715							if(((code===38 || code===40) && !d.overflowed[0]) || ((code===37 || code===39) && !d.overflowed[1])){return;}
1716							if(e.type==="keyup"){action="off";}
1717							if(!$(document.activeElement).is(editables)){
1718								e.preventDefault();
1719								e.stopImmediatePropagation();
1720								_seq(action,code);
1721							}
1722						}else if(code===33 || code===34){
1723							/* PgUp (33), PgDn (34) */
1724							if(d.overflowed[0] || d.overflowed[1]){
1725								e.preventDefault();
1726								e.stopImmediatePropagation();
1727							}
1728							if(e.type==="keyup"){
1729								_stop($this);
1730								var keyboardDir=code===34 ? -1 : 1;
1731								if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){
1732									var dir="x",to=Math.abs(mCSB_container[0].offsetLeft)-(keyboardDir*(wrapper.width()*0.9));
1733								}else{
1734									var dir="y",to=Math.abs(mCSB_container[0].offsetTop)-(keyboardDir*(wrapper.height()*0.9));
1735								}
1736								_scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"});
1737							}
1738						}else if(code===35 || code===36){
1739							/* End (35), Home (36) */
1740							if(!$(document.activeElement).is(editables)){
1741								if(d.overflowed[0] || d.overflowed[1]){
1742									e.preventDefault();
1743									e.stopImmediatePropagation();
1744								}
1745								if(e.type==="keyup"){
1746									if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){
1747										var dir="x",to=code===35 ? Math.abs(wrapper.width()-mCSB_container.outerWidth(false)) : 0;
1748									}else{
1749										var dir="y",to=code===35 ? Math.abs(wrapper.height()-mCSB_container.outerHeight(false)) : 0;
1750									}
1751									_scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"});
1752								}
1753							}
1754						}
1755						break;
1756				}
1757				function _seq(a,c){
1758					seq.type=o.keyboard.scrollType;
1759					seq.scrollAmount=o.keyboard.scrollAmount;
1760					if(seq.type==="stepped" && d.tweenRunning){return;}
1761					_sequentialScroll($this,a,c);
1762				}
1763			}
1764		},
1765		/* -------------------- */
1766		
1767		
1768		/* scrolls content sequentially (used when scrolling via buttons, keyboard arrows etc.) */
1769		_sequentialScroll=function(el,action,trigger,e,s){
1770			var d=el.data(pluginPfx),o=d.opt,seq=d.sequential,
1771				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1772				once=seq.type==="stepped" ? true : false,
1773				steplessSpeed=o.scrollInertia < 26 ? 26 : o.scrollInertia, /* 26/1.5=17 */
1774				steppedSpeed=o.scrollInertia < 1 ? 17 : o.scrollInertia;
1775			switch(action){
1776				case "on":
1777					seq.dir=[
1778						(trigger===classes[16] || trigger===classes[15] || trigger===39 || trigger===37 ? "x" : "y"),
1779						(trigger===classes[13] || trigger===classes[15] || trigger===38 || trigger===37 ? -1 : 1)
1780					];
1781					_stop(el);
1782					if(_isNumeric(trigger) && seq.type==="stepped"){return;}
1783					_on(once);
1784					break;
1785				case "off":
1786					_off();
1787					if(once || (d.tweenRunning && seq.dir)){
1788						_on(true);
1789					}
1790					break;
1791			}
1792			
1793			/* starts sequence */
1794			function _on(once){
1795				if(o.snapAmount){seq.scrollAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : seq.dir[0]==="x" ? o.snapAmount[1] : o.snapAmount[0];} /* scrolling snapping */
1796				var c=seq.type!=="stepped", /* continuous scrolling */
1797					t=s ? s : !once ? 1000/60 : c ? steplessSpeed/1.5 : steppedSpeed, /* timer */
1798					m=!once ? 2.5 : c ? 7.5 : 40, /* multiplier */
1799					contentPos=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)],
1800					ratio=[d.scrollRatio.y>10 ? 10 : d.scrollRatio.y,d.scrollRatio.x>10 ? 10 : d.scrollRatio.x],
1801					amount=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*(ratio[1]*m)) : contentPos[0]+(seq.dir[1]*(ratio[0]*m)),
1802					px=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*parseInt(seq.scrollAmount)) : contentPos[0]+(seq.dir[1]*parseInt(seq.scrollAmount)),
1803					to=seq.scrollAmount!=="auto" ? px : amount,
1804					easing=e ? e : !once ? "mcsLinear" : c ? "mcsLinearOut" : "mcsEaseInOut",
1805					onComplete=!once ? false : true;
1806				if(once && t<17){
1807					to=seq.dir[0]==="x" ? contentPos[1] : contentPos[0];
1808				}
1809				_scrollTo(el,to.toString(),{dir:seq.dir[0],scrollEasing:easing,dur:t,onComplete:onComplete});
1810				if(once){
1811					seq.dir=false;
1812					return;
1813				}
1814				clearTimeout(seq.step);
1815				seq.step=setTimeout(function(){
1816					_on();
1817				},t);
1818			}
1819			/* stops sequence */
1820			function _off(){
1821				clearTimeout(seq.step);
1822				_delete(seq,"step");
1823				_stop(el);
1824			}
1825		},
1826		/* -------------------- */
1827		
1828		
1829		/* returns a yx array from value */
1830		_arr=function(val){
1831			var o=$(this).data(pluginPfx).opt,vals=[];
1832			if(typeof val==="function"){val=val();} /* check if the value is a single anonymous function */
1833			/* check if value is object or array, its length and create an array with yx values */
1834			if(!(val instanceof Array)){ /* object value (e.g. {y:"100",x:"100"}, 100 etc.) */
1835				vals[0]=val.y ? val.y : val.x || o.axis==="x" ? null : val;
1836				vals[1]=val.x ? val.x : val.y || o.axis==="y" ? null : val;
1837			}else{ /* array value (e.g. [100,100]) */
1838				vals=val.length>1 ? [val[0],val[1]] : o.axis==="x" ? [null,val[0]] : [val[0],null];
1839			}
1840			/* check if array values are anonymous functions */
1841			if(typeof vals[0]==="function"){vals[0]=vals[0]();}
1842			if(typeof vals[1]==="function"){vals[1]=vals[1]();}
1843			return vals;
1844		},
1845		/* -------------------- */
1846		
1847		
1848		/* translates values (e.g. "top", 100, "100px", "#id") to actual scroll-to positions */
1849		_to=function(val,dir){
1850			if(val==null || typeof val=="undefined"){return;}
1851			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1852				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1853				wrapper=mCSB_container.parent(),
1854				t=typeof val;
1855			if(!dir){dir=o.axis==="x" ? "x" : "y";}
1856			var contentLength=dir==="x" ? mCSB_container.outerWidth(false) : mCSB_container.outerHeight(false
vendor: 18,880 bytes, lines 1856-2400
1856),
1857				contentPos=dir==="x" ? mCSB_container[0].offsetLeft : mCSB_container[0].offsetTop,
1858				cssProp=dir==="x" ? "left" : "top";
1859			switch(t){
1860				case "function": /* this currently is not used. Consider removing it */
1861					return val();
1862					break;
1863				case "object": /* js/jquery object */
1864					var obj=val.jquery ? val : $(val);
1865					if(!obj.length){return;}
1866					return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0];
1867					break;
1868				case "string": case "number":
1869					if(_isNumeric(val)){ /* numeric value */
1870						return Math.abs(val);
1871					}else if(val.indexOf("%")!==-1){ /* percentage value */
1872						return Math.abs(contentLength*parseInt(val)/100);
1873					}else if(val.indexOf("-=")!==-1){ /* decrease value */
1874						return Math.abs(contentPos-parseInt(val.split("-=")[1]));
1875					}else if(val.indexOf("+=")!==-1){ /* inrease value */
1876						var p=(contentPos+parseInt(val.split("+=")[1]));
1877						return p>=0 ? 0 : Math.abs(p);
1878					}else if(val.indexOf("px")!==-1 && _isNumeric(val.split("px")[0])){ /* pixels string value (e.g. "100px") */
1879						return Math.abs(val.split("px")[0]);
1880					}else{
1881						if(val==="top" || val==="left"){ /* special strings */
1882							return 0;
1883						}else if(val==="bottom"){
1884							return Math.abs(wrapper.height()-mCSB_container.outerHeight(false));
1885						}else if(val==="right"){
1886							return Math.abs(wrapper.width()-mCSB_container.outerWidth(false));
1887						}else if(val==="first" || val==="last"){
1888							var obj=mCSB_container.find(":"+val);
1889							return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0];
1890						}else{
1891							if($(val).length){ /* jquery selector */
1892								return dir==="x" ? _childPos($(val))[1] : _childPos($(val))[0];
1893							}else{ /* other values (e.g. "100em") */
1894								mCSB_container.css(cssProp,val);
1895								methods.update.call(null,$this[0]);
1896								return;
1897							}
1898						}
1899					}
1900					break;
1901			}
1902		},
1903		/* -------------------- */
1904		
1905		
1906		/* calls the update method automatically */
1907		_autoUpdate=function(rem){
1908			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1909				mCSB_container=$("#mCSB_"+d.idx+"_container");
1910			if(rem){
1911				/* 
1912				removes autoUpdate timer 
1913				usage: _autoUpdate.call(this,"remove");
1914				*/
1915				clearTimeout(mCSB_container[0].autoUpdate);
1916				_delete(mCSB_container[0],"autoUpdate");
1917				return;
1918			}
1919			upd();
1920			function upd(){
1921				clearTimeout(mCSB_container[0].autoUpdate);
1922				if($this.parents("html").length===0){
1923					/* check element in dom tree */
1924					$this=null;
1925					return;
1926				}
1927				mCSB_container[0].autoUpdate=setTimeout(function(){
1928					/* update on specific selector(s) length and size change */
1929					if(o.advanced.updateOnSelectorChange){
1930						d.poll.change.n=sizesSum();
1931						if(d.poll.change.n!==d.poll.change.o){
1932							d.poll.change.o=d.poll.change.n;
1933							doUpd(3);
1934							return;
1935						}
1936					}
1937					/* update on main element and scrollbar size changes */
1938					if(o.advanced.updateOnContentResize){
1939						d.poll.size.n=$this[0].scrollHeight+$this[0].scrollWidth+mCSB_container[0].offsetHeight+$this[0].offsetHeight+$this[0].offsetWidth;
1940						if(d.poll.size.n!==d.poll.size.o){
1941							d.poll.size.o=d.poll.size.n;
1942							doUpd(1);
1943							return;
1944						}
1945					}
1946					/* update on image load */
1947					if(o.advanced.updateOnImageLoad){
1948						if(!(o.advanced.updateOnImageLoad==="auto" && o.axis==="y")){ //by default, it doesn't run on vertical content
1949							d.poll.img.n=mCSB_container.find("img").length;
1950							if(d.poll.img.n!==d.poll.img.o){
1951								d.poll.img.o=d.poll.img.n;
1952								mCSB_container.find("img").each(function(){
1953									imgLoader(this);
1954								});
1955								return;
1956							}
1957						}
1958					}
1959					if(o.advanced.updateOnSelectorChange || o.advanced.updateOnContentResize || o.advanced.updateOnImageLoad){upd();}
1960				},o.advanced.autoUpdateTimeout);
1961			}
1962			/* a tiny image loader */
1963			function imgLoader(el){
1964				if($(el).hasClass(classes[2])){doUpd(); return;}
1965				var img=new Image();
1966				function createDelegate(contextObject,delegateMethod){
1967					return function(){return delegateMethod.apply(contextObject,arguments);}
1968				}
1969				function imgOnLoad(){
1970					this.onload=null;
1971					$(el).addClass(classes[2]);
1972					doUpd(2);
1973				}
1974				img.onload=createDelegate(img,imgOnLoad);
1975				img.src=el.src;
1976			}
1977			/* returns the total height and width sum of all elements matching the selector */
1978			function sizesSum(){
1979				if(o.advanced.updateOnSelectorChange===true){o.advanced.updateOnSelectorChange="*";}
1980				var total=0,sel=mCSB_container.find(o.advanced.updateOnSelectorChange);
1981				if(o.advanced.updateOnSelectorChange && sel.length>0){sel.each(function(){total+=this.offsetHeight+this.offsetWidth;});}
1982				return total;
1983			}
1984			/* calls the update method */
1985			function doUpd(cb){
1986				clearTimeout(mCSB_container[0].autoUpdate);
1987				methods.update.call(null,$this[0],cb);
1988			}
1989		},
1990		/* -------------------- */
1991		
1992		
1993		/* snaps scrolling to a multiple of a pixels number */
1994		_snapAmount=function(to,amount,offset){
1995			return (Math.round(to/amount)*amount-offset); 
1996		},
1997		/* -------------------- */
1998		
1999		
2000		/* stops content and scrollbar animations */
2001		_stop=function(el){
2002			var d=el.data(pluginPfx),
2003				sel=$("#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal");
2004			sel.each(function(){
2005				_stopTween.call(this);
2006			});
2007		},
2008		/* -------------------- */
2009		
2010		
2011		/* 
2012		ANIMATES CONTENT 
2013		This is where the actual scrolling happens
2014		*/
2015		_scrollTo=function(el,to,options){
2016			var d=el.data(pluginPfx),o=d.opt,
2017				defaults={
2018					trigger:"internal",
2019					dir:"y",
2020					scrollEasing:"mcsEaseOut",
2021					drag:false,
2022					dur:o.scrollInertia,
2023					overwrite:"all",
2024					callbacks:true,
2025					onStart:true,
2026					onUpdate:true,
2027					onComplete:true
2028				},
2029				options=$.extend(defaults,options),
2030				dur=[options.dur,(options.drag ? 0 : options.dur)],
2031				mCustomScrollBox=$("#mCSB_"+d.idx),
2032				mCSB_container=$("#mCSB_"+d.idx+"_container"),
2033				wrapper=mCSB_container.parent(),
2034				totalScrollOffsets=o.callbacks.onTotalScrollOffset ? _arr.call(el,o.callbacks.onTotalScrollOffset) : [0,0],
2035				totalScrollBackOffsets=o.callbacks.onTotalScrollBackOffset ? _arr.call(el,o.callbacks.onTotalScrollBackOffset) : [0,0];
2036			d.trigger=options.trigger;
2037			if(wrapper.scrollTop()!==0 || wrapper.scrollLeft()!==0){ /* always reset scrollTop/Left */
2038				$(".mCSB_"+d.idx+"_scrollbar").css("visibility","visible");
2039				wrapper.scrollTop(0).scrollLeft(0);
2040			}
2041			if(to==="_resetY" && !d.contentReset.y){
2042				/* callbacks: onOverflowYNone */
2043				if(_cb("onOverflowYNone")){o.callbacks.onOverflowYNone.call(el[0]);}
2044				d.contentReset.y=1;
2045			}
2046			if(to==="_resetX" && !d.contentReset.x){
2047				/* callbacks: onOverflowXNone */
2048				if(_cb("onOverflowXNone")){o.callbacks.onOverflowXNone.call(el[0]);}
2049				d.contentReset.x=1;
2050			}
2051			if(to==="_resetY" || to==="_resetX"){return;}
2052			if((d.contentReset.y || !el[0].mcs) && d.overflowed[0]){
2053				/* callbacks: onOverflowY */
2054				if(_cb("onOverflowY")){o.callbacks.onOverflowY.call(el[0]);}
2055				d.contentReset.x=null;
2056			}
2057			if((d.contentReset.x || !el[0].mcs) && d.overflowed[1]){
2058				/* callbacks: onOverflowX */
2059				if(_cb("onOverflowX")){o.callbacks.onOverflowX.call(el[0]);}
2060				d.contentReset.x=null;
2061			}
2062			if(o.snapAmount){ /* scrolling snapping */
2063				var snapAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : options.dir==="x" ? o.snapAmount[1] : o.snapAmount[0];
2064				to=_snapAmount(to,snapAmount,o.snapOffset);
2065			}
2066			switch(options.dir){
2067				case "x":
2068					var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_horizontal"),
2069						property="left",
2070						contentPos=mCSB_container[0].offsetLeft,
2071						limit=[
2072							mCustomScrollBox.width()-mCSB_container.outerWidth(false),
2073							mCSB_dragger.parent().width()-mCSB_dragger.width()
2074						],
2075						scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.x)],
2076						tso=totalScrollOffsets[1],
2077						tsbo=totalScrollBackOffsets[1],
2078						totalScrollOffset=tso>0 ? tso/d.scrollRatio.x : 0,
2079						totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.x : 0;
2080					break;
2081				case "y":
2082					var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_vertical"),
2083						property="top",
2084						contentPos=mCSB_container[0].offsetTop,
2085						limit=[
2086							mCustomScrollBox.height()-mCSB_container.outerHeight(false),
2087							mCSB_dragger.parent().height()-mCSB_dragger.height()
2088						],
2089						scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.y)],
2090						tso=totalScrollOffsets[0],
2091						tsbo=totalScrollBackOffsets[0],
2092						totalScrollOffset=tso>0 ? tso/d.scrollRatio.y : 0,
2093						totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.y : 0;
2094					break;
2095			}
2096			if(scrollTo[1]<0 || (scrollTo[0]===0 && scrollTo[1]===0)){
2097				scrollTo=[0,0];
2098			}else if(scrollTo[1]>=limit[1]){
2099				scrollTo=[limit[0],limit[1]];
2100			}else{
2101				scrollTo[0]=-scrollTo[0];
2102			}
2103			if(!el[0].mcs){
2104				_mcs();  /* init mcs object (once) to make it available before callbacks */
2105				if(_cb("onInit")){o.callbacks.onInit.call(el[0]);} /* callbacks: onInit */
2106			}
2107			clearTimeout(mCSB_container[0].onCompleteTimeout);
2108			_tweenTo(mCSB_dragger[0],property,Math.round(scrollTo[1]),dur[1],options.scrollEasing);
2109			if(!d.tweenRunning && ((contentPos===0 && scrollTo[0]>=0) || (contentPos===limit[0] && scrollTo[0]<=limit[0]))){return;}
2110			_tweenTo(mCSB_container[0],property,Math.round(scrollTo[0]),dur[0],options.scrollEasing,options.overwrite,{
2111				onStart:function(){
2112					if(options.callbacks && options.onStart && !d.tweenRunning){
2113						/* callbacks: onScrollStart */
2114						if(_cb("onScrollStart")){_mcs(); o.callbacks.onScrollStart.call(el[0]);}
2115						d.tweenRunning=true;
2116						_onDragClasses(mCSB_dragger);
2117						d.cbOffsets=_cbOffsets();
2118					}
2119				},onUpdate:function(){
2120					if(options.callbacks && options.onUpdate){
2121						/* callbacks: whileScrolling */
2122						if(_cb("whileScrolling")){_mcs(); o.callbacks.whileScrolling.call(el[0]);}
2123					}
2124				},onComplete:function(){
2125					if(options.callbacks && options.onComplete){
2126						if(o.axis==="yx"){clearTimeout(mCSB_container[0].onCompleteTimeout);}
2127						var t=mCSB_container[0].idleTimer || 0;
2128						mCSB_container[0].onCompleteTimeout=setTimeout(function(){
2129							/* callbacks: onScroll, onTotalScroll, onTotalScrollBack */
2130							if(_cb("onScroll")){_mcs(); o.callbacks.onScroll.call(el[0]);}
2131							if(_cb("onTotalScroll") && scrollTo[1]>=limit[1]-totalScrollOffset && d.cbOffsets[0]){_mcs(); o.callbacks.onTotalScroll.call(el[0]);}
2132							if(_cb("onTotalScrollBack") && scrollTo[1]<=totalScrollBackOffset && d.cbOffsets[1]){_mcs(); o.callbacks.onTotalScrollBack.call(el[0]);}
2133							d.tweenRunning=false;
2134							mCSB_container[0].idleTimer=0;
2135							_onDragClasses(mCSB_dragger,"hide");
2136						},t);
2137					}
2138				}
2139			});
2140			/* checks if callback function exists */
2141			function _cb(cb){
2142				return d && o.callbacks[cb] && typeof o.callbacks[cb]==="function";
2143			}
2144			/* checks whether callback offsets always trigger */
2145			function _cbOffsets(){
2146				return [o.callbacks.alwaysTriggerOffsets || contentPos>=limit[0]+tso,o.callbacks.alwaysTriggerOffsets || contentPos<=-tsbo];
2147			}
2148			/* 
2149			populates object with useful values for the user 
2150			values: 
2151				content: this.mcs.content
2152				content top position: this.mcs.top 
2153				content left position: this.mcs.left 
2154				dragger top position: this.mcs.draggerTop 
2155				dragger left position: this.mcs.draggerLeft 
2156				scrolling y percentage: this.mcs.topPct 
2157				scrolling x percentage: this.mcs.leftPct 
2158				scrolling direction: this.mcs.direction
2159			*/
2160			function _mcs(){
2161				var cp=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft], /* content position */
2162					dp=[mCSB_dragger[0].offsetTop,mCSB_dragger[0].offsetLeft], /* dragger position */
2163					cl=[mCSB_container.outerHeight(false),mCSB_container.outerWidth(false)], /* content length */
2164					pl=[mCustomScrollBox.height(),mCustomScrollBox.width()]; /* content parent length */
2165				el[0].mcs={
2166					content:mCSB_container, /* original content wrapper as jquery object */
2167					top:cp[0],left:cp[1],draggerTop:dp[0],draggerLeft:dp[1],
2168					topPct:Math.round((100*Math.abs(cp[0]))/(Math.abs(cl[0])-pl[0])),leftPct:Math.round((100*Math.abs(cp[1]))/(Math.abs(cl[1])-pl[1])),
2169					direction:options.dir
2170				};
2171				/* 
2172				this refers to the original element containing the scrollbar(s)
2173				usage: this.mcs.top, this.mcs.leftPct etc. 
2174				*/
2175			}
2176		},
2177		/* -------------------- */
2178		
2179		
2180		/* 
2181		CUSTOM JAVASCRIPT ANIMATION TWEEN 
2182		Lighter and faster than jquery animate() and css transitions 
2183		Animates top/left properties and includes easings 
2184		*/
2185		_tweenTo=function(el,prop,to,duration,easing,overwrite,callbacks){
2186			if(!el._mTween){el._mTween={top:{},left:{}};}
2187			var callbacks=callbacks || {},
2188				onStart=callbacks.onStart || function(){},onUpdate=callbacks.onUpdate || function(){},onComplete=callbacks.onComplete || function(){},
2189				startTime=_getTime(),_delay,progress=0,from=el.offsetTop,elStyle=el.style,_request,tobj=el._mTween[prop];
2190			if(prop==="left"){from=el.offsetLeft;}
2191			var diff=to-from;
2192			tobj.stop=0;
2193			if(overwrite!=="none"){_cancelTween();}
2194			_startTween();
2195			function _step(){
2196				if(tobj.stop){return;}
2197				if(!progress){onStart.call();}
2198				progress=_getTime()-startTime;
2199				_tween();
2200				if(progress>=tobj.time){
2201					tobj.time=(progress>tobj.time) ? progress+_delay-(progress-tobj.time) : progress+_delay-1;
2202					if(tobj.time<progress+1){tobj.time=progress+1;}
2203				}
2204				if(tobj.time<duration){tobj.id=_request(_step);}else{onComplete.call();}
2205			}
2206			function _tween(){
2207				if(duration>0){
2208					tobj.currVal=_ease(tobj.time,from,diff,duration,easing);
2209					elStyle[prop]=Math.round(tobj.currVal)+"px";
2210				}else{
2211					elStyle[prop]=to+"px";
2212				}
2213				onUpdate.call();
2214			}
2215			function _startTween(){
2216				_delay=1000/60;
2217				tobj.time=progress+_delay;
2218				_request=(!window.requestAnimationFrame) ? function(f){_tween(); return setTimeout(f,0.01);} : window.requestAnimationFrame;
2219				tobj.id=_request(_step);
2220			}
2221			function _cancelTween(){
2222				if(tobj.id==null){return;}
2223				if(!window.requestAnimationFrame){clearTimeout(tobj.id);
2224				}else{window.cancelAnimationFrame(tobj.id);}
2225				tobj.id=null;
2226			}
2227			function _ease(t,b,c,d,type){
2228				switch(type){
2229					case "linear": case "mcsLinear":
2230						return c*t/d + b;
2231						break;
2232					case "mcsLinearOut":
2233						t/=d; t--; return c * Math.sqrt(1 - t*t) + b;
2234						break;
2235					case "easeInOutSmooth":
2236						t/=d/2;
2237						if(t<1) return c/2*t*t + b;
2238						t--;
2239						return -c/2 * (t*(t-2) - 1) + b;
2240						break;
2241					case "easeInOutStrong":
2242						t/=d/2;
2243						if(t<1) return c/2 * Math.pow( 2, 10 * (t - 1) ) + b;
2244						t--;
2245						return c/2 * ( -Math.pow( 2, -10 * t) + 2 ) + b;
2246						break;
2247					case "easeInOut": case "mcsEaseInOut":
2248						t/=d/2;
2249						if(t<1) return c/2*t*t*t + b;
2250						t-=2;
2251						return c/2*(t*t*t + 2) + b;
2252						break;
2253					case "easeOutSmooth":
2254						t/=d; t--;
2255						return -c * (t*t*t*t - 1) + b;
2256						break;
2257					case "easeOutStrong":
2258						return c * ( -Math.pow( 2, -10 * t/d ) + 1 ) + b;
2259						break;
2260					case "easeOut": case "mcsEaseOut": default:
2261						var ts=(t/=d)*t,tc=ts*t;
2262						return b+c*(0.499999999999997*tc*ts + -2.5*ts*ts + 5.5*tc + -6.5*ts + 4*t);
2263				}
2264			}
2265		},
2266		/* -------------------- */
2267		
2268		
2269		/* returns current time */
2270		_getTime=function(){
2271			if(window.performance && window.performance.now){
2272				return window.performance.now();
2273			}else{
2274				if(window.performance && window.performance.webkitNow){
2275					return window.performance.webkitNow();
2276				}else{
2277					if(Date.now){return Date.now();}else{return new Date().getTime();}
2278				}
2279			}
2280		},
2281		/* -------------------- */
2282		
2283		
2284		/* stops a tween */
2285		_stopTween=function(){
2286			var el=this;
2287			if(!el._mTween){el._mTween={top:{},left:{}};}
2288			var props=["top","left"];
2289			for(var i=0; i<props.length; i++){
2290				var prop=props[i];
2291				if(el._mTween[prop].id){
2292					if(!window.requestAnimationFrame){clearTimeout(el._mTween[prop].id);
2293					}else{window.cancelAnimationFrame(el._mTween[prop].id);}
2294					el._mTween[prop].id=null;
2295					el._mTween[prop].stop=1;
2296				}
2297			}
2298		},
2299		/* -------------------- */
2300		
2301		
2302		/* deletes a property (avoiding the exception thrown by IE) */
2303		_delete=function(c,m){
2304			try{delete c[m];}catch(e){c[m]=null;}
2305		},
2306		/* -------------------- */
2307		
2308		
2309		/* detects left mouse button */
2310		_mouseBtnLeft=function(e){
2311			return !(e.which && e.which!==1);
2312		},
2313		/* -------------------- */
2314		
2315		
2316		/* detects if pointer type event is touch */
2317		_pointerTouch=function(e){
2318			var t=e.originalEvent.pointerType;
2319			return !(t && t!=="touch" && t!==2);
2320		},
2321		/* -------------------- */
2322		
2323		
2324		/* checks if value is numeric */
2325		_isNumeric=function(val){
2326			return !isNaN(parseFloat(val)) && isFinite(val);
2327		},
2328		/* -------------------- */
2329		
2330		
2331		/* returns element position according to content */
2332		_childPos=function(el){
2333			var p=el.parents(".mCSB_container");
2334			return [el.offset().top-p.offset().top,el.offset().left-p.offset().left];
2335		},
2336		/* -------------------- */
2337		
2338		
2339		/* checks if browser tab is hidden/inactive via Page Visibility API */
2340		_isTabHidden=function(){
2341			var prop=_getHiddenProp();
2342			if(!prop) return false;
2343			return document[prop];
2344			function _getHiddenProp(){
2345				var pfx=["webkit","moz","ms","o"];
2346				if("hidden" in document) return "hidden"; //natively supported
2347				for(var i=0; i<pfx.length; i++){ //prefixed
2348				    if((pfx[i]+"Hidden") in document) 
2349				        return pfx[i]+"Hidden";
2350				}
2351				return null; //not supported
2352			}
2353		};
2354		/* -------------------- */
2355		
2356	
2357	
2358	
2359	
2360	/* 
2361	----------------------------------------
2362	PLUGIN SETUP 
2363	----------------------------------------
2364	*/
2365	
2366	/* plugin constructor functions */
2367	$.fn[pluginNS]=function(method){ /* usage: $(selector).mCustomScrollbar(); */
2368		if(methods[method]){
2369			return methods[method].apply(this,Array.prototype.slice.call(arguments,1));
2370		}else if(typeof method==="object" || !method){
2371			return methods.init.apply(this,arguments);
2372		}else{
2373			$.error("Method "+method+" does not exist");
2374		}
2375	};
2376	$[pluginNS]=function(method){ /* usage: $.mCustomScrollbar(); */
2377		if(methods[method]){
2378			return methods[method].apply(this,Array.prototype.slice.call(arguments,1));
2379		}else if(typeof method==="object" || !method){
2380			return methods.init.apply(this,arguments);
2381		}else{
2382			$.error("Method "+method+" does not exist");
2383		}
2384	};
2385	
2386	/* 
2387	allow setting plugin default options. 
2388	usage: $.mCustomScrollbar.defaults.scrollInertia=500; 
2389	to apply any changed default options on default selectors (below), use inside document ready fn 
2390	e.g.: $(document).ready(function(){ $.mCustomScrollbar.defaults.scrollInertia=500; });
2391	*/
2392	$[pluginNS].defaults=defaults;
2393	
2394	/* 
2395	add window object (window.mCustomScrollbar) 
2396	usage: if(window.mCustomScrollbar){console.log("custom scrollbar plugin loaded");}
2397	*/
2398	window[pluginNS]=true;
2399	
2400	$(window).
vendor: 943 bytes, lines 2400-2425
2400load(function(){
2401		
2402		$(defaultSelector)[pluginNS](); /* add scrollbars automatically on default selector */
2403		
2404		/* extend jQuery expressions */
2405		$.extend($.expr[":"],{
2406			/* checks if element is within scrollable viewport */
2407			mcsInView:$.expr[":"].mcsInView || function(el){
2408				var $el=$(el),content=$el.parents(".mCSB_container"),wrapper,cPos;
2409				if(!content.length){return;}
2410				wrapper=content.parent();
2411				cPos=[content[0].offsetTop,content[0].offsetLeft];
2412				return 	cPos[0]+_childPos($el)[0]>=0 && cPos[0]+_childPos($el)[0]<wrapper.height()-$el.outerHeight(false) && 
2413						cPos[1]+_childPos($el)[1]>=0 && cPos[1]+_childPos($el)[1]<wrapper.width()-$el.outerWidth(false);
2414			},
2415			/* checks if element is overflowed having visible scrollbar(s) */
2416			mcsOverflow:$.expr[":"].mcsOverflow || function(el){
2417				var d=$(el).data(pluginPfx);
2418				if(!d){return;}
2419				return d.overflowed[0] || d.overflowed[1];
2420			}
2421		});
2422	
2423	});
2424
2425}))}));

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.