PageSourceSearch

https://rsez.lv/wp-content/plugins/codespacing-progress-map/assets…/jquery.mCustomScrollbar.js?ver=5.7.1

js rsez.lv collected 2026-10-02 19:10:59 UTC 95,464 bytes, 2,462 lines download raw bytes

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

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.