PageSourceSearch

https://booksrus.fr/local/templates/aspro_max/js/jquery.mCustomScrollbar.js?165235570194214

js booksrus.fr collected 2026-09-30 02:36:52 UTC 94,214 bytes, 2,489 lines download raw bytes

vendor: 5,270 bytes, lines 1-176
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:100,
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
176(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 colored_theme_hover_text","mCSB_buttonRight colored_theme_hover_text"
383		],
384		touchOffCustom = false;
vendor: 22,935 bytes, lines 384-948
384
385		
386	
387	
388	
389	
390	/* 
391	----------------------------------------
392	METHODS 
393	----------------------------------------
394	*/
395	
396		methods={
397			
398			/* 
399			plugin initialization method 
400			creates the scrollbar(s), plugin data object and options
401			----------------------------------------
402			*/
403			
404			init:function(options){
405				
406				var options=$.extend(true,{},defaults,options),
407					selector=_selector.call(this); /* validate selector */
408				
409				/* 
410				if live option is enabled, monitor for elements matching the current selector and 
411				apply scrollbar(s) when found (now and in the future) 
412				*/
413				if(options.live){
414					var liveSelector=options.liveSelector || this.selector || defaultSelector, /* live selector(s) */
415						$liveSelector=$(liveSelector); /* live selector(s) as jquery object */
416					if(options.live==="off"){
417						/* 
418						disable live if requested 
419						usage: $(selector).mCustomScrollbar({live:"off"}); 
420						*/
421						removeLiveTimers(liveSelector);
422						return;
423					}
424					liveTimers[liveSelector]=setTimeout(function(){
425						/* call mCustomScrollbar fn on live selector(s) every half-second */
426						$liveSelector.mCustomScrollbar(options);
427						if(options.live==="once" && $liveSelector.length){
428							/* disable live after first invocation */
429							removeLiveTimers(liveSelector);
430						}
431					},500);
432				}else{
433					removeLiveTimers(liveSelector);
434				}
435				
436				/* options backward compatibility (for versions < 3.0.0) and normalization */
437				options.setWidth=(options.set_width) ? options.set_width : options.setWidth;
438				options.setHeight=(options.set_height) ? options.set_height : options.setHeight;
439				options.axis=(options.horizontalScroll) ? "x" : _findAxis(options.axis);
440				options.scrollInertia=options.scrollInertia>0 && options.scrollInertia<17 ? 17 : options.scrollInertia;
441				if(typeof options.mouseWheel!=="object" &&  options.mouseWheel==true){ /* old school mouseWheel option (non-object) */
442					options.mouseWheel={enable:true,scrollAmount:"auto",axis:"y",preventDefault:false,deltaFactor:"auto",normalizeDelta:false,invert:false}
443				}
444				options.mouseWheel.scrollAmount=!options.mouseWheelPixels ? options.mouseWheel.scrollAmount : options.mouseWheelPixels;
445				options.mouseWheel.normalizeDelta=!options.advanced.normalizeMouseWheelDelta ? options.mouseWheel.normalizeDelta : options.advanced.normalizeMouseWheelDelta;
446				options.scrollButtons.scrollType=_findScrollButtonsType(options.scrollButtons.scrollType); 
447				
448				_theme(options); /* theme-specific options */
449				
450				/* plugin constructor */
451				return $(selector).each(function(){
452					
453					var $this=$(this);
454					
455					if(!$this.data(pluginPfx)){ /* prevent multiple instantiations */
456					
457						/* store options and create objects in jquery data */
458						$this.data(pluginPfx,{
459							idx:++totalInstances, /* instance index */
460							opt:options, /* options */
461							scrollRatio:{y:null,x:null}, /* scrollbar to content ratio */
462							overflowed:null, /* overflowed axis */
463							contentReset:{y:null,x:null}, /* object to check when content resets */
464							bindEvents:false, /* object to check if events are bound */
465							tweenRunning:false, /* object to check if tween is running */
466							sequential:{}, /* sequential scrolling object */
467							langDir:$this.css("direction"), /* detect/store direction (ltr or rtl) */
468							cbOffsets:null, /* object to check whether callback offsets always trigger */
469							/* 
470							object to check how scrolling events where last triggered 
471							"internal" (default - triggered by this script), "external" (triggered by other scripts, e.g. via scrollTo method) 
472							usage: object.data("mCS").trigger
473							*/
474							trigger:null,
475							/* 
476							object to check for changes in elements in order to call the update method automatically 
477							*/
478							poll:{size:{o:0,n:0},img:{o:0,n:0},change:{o:0,n:0}}
479						});
480						
481						var d=$this.data(pluginPfx),o=d.opt,
482							/* HTML data attributes */
483							htmlDataAxis=$this.data("mcs-axis"),htmlDataSbPos=$this.data("mcs-scrollbar-position"),htmlDataTheme=$this.data("mcs-theme");
484						 
485						if(htmlDataAxis){o.axis=htmlDataAxis;} /* usage example: data-mcs-axis="y" */
486						if(htmlDataSbPos){o.scrollbarPosition=htmlDataSbPos;} /* usage example: data-mcs-scrollbar-position="outside" */
487						if(htmlDataTheme){ /* usage example: data-mcs-theme="minimal" */
488							o.theme=htmlDataTheme;
489							_theme(o); /* theme-specific options */
490						}
491						
492						_pluginMarkup.call(this); /* add plugin markup */
493						
494						if(d && o.callbacks.onCreate && typeof o.callbacks.onCreate==="function"){o.callbacks.onCreate.call(this);} /* callbacks: onCreate */
495						
496						$("#mCSB_"+d.idx+"_container img:not(."+classes[2]+")").addClass(classes[2]); /* flag loaded images */
497						
498						methods.update.call(null,$this); /* call the update method */
499					
500					}
501					
502				});
503				
504			},
505			/* ---------------------------------------- */
506			
507			
508			
509			/* 
510			plugin update method 
511			updates content and scrollbar(s) values, events and status 
512			----------------------------------------
513			usage: $(selector).mCustomScrollbar("update");
514			*/
515			
516			update:function(el,cb){
517				
518				var selector=el || _selector.call(this); /* validate selector */
519				
520				return $(selector).each(function(){
521					
522					var $this=$(this);
523					
524					if($this.data(pluginPfx)){ /* check if plugin has initialized */
525						
526						var d=$this.data(pluginPfx),o=d.opt,
527							mCSB_container=$("#mCSB_"+d.idx+"_container"),
528							mCustomScrollBox=$("#mCSB_"+d.idx),
529							mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")];
530						
531						if(!mCSB_container.length){return;}
532						
533						if(d.tweenRunning){_stop($this);} /* stop any running tweens while updating */
534						
535						if(cb && d && o.callbacks.onBeforeUpdate && typeof o.callbacks.onBeforeUpdate==="function"){o.callbacks.onBeforeUpdate.call(this);} /* callbacks: onBeforeUpdate */
536						
537						/* if element was disabled or destroyed, remove class(es) */
538						if($this.hasClass(classes[3])){$this.removeClass(classes[3]);}
539						if($this.hasClass(classes[4])){$this.removeClass(classes[4]);}
540						
541						/* css flexbox fix, detect/set max-height */
542						mCustomScrollBox.css("max-height","none");
543						if(mCustomScrollBox.height()!==$this.height()){mCustomScrollBox.css("max-height",$this.height());}
544						
545						_expandContentHorizontally.call(this); /* expand content horizontally */
546						
547						if(o.axis!=="y" && !o.advanced.autoExpandHorizontalScroll){
548							mCSB_container.css("width",_contentWidth(mCSB_container));
549						}
550						
551						d.overflowed=_overflowed.call(this); /* determine if scrolling is required */
552						
553						_scrollbarVisibility.call(this); /* show/hide scrollbar(s) */
554						
555						/* auto-adjust scrollbar dragger length analogous to content */
556						if(o.autoDraggerLength){_setDraggerLength.call(this);}
557						
558						_scrollRatio.call(this); /* calculate and store scrollbar to content ratio */
559						
560						_bindEvents.call(this); /* bind scrollbar events */
561						
562						/* reset scrolling position and/or events */
563						var to=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)];
564						if(o.axis!=="x"){ /* y/yx axis */
565							if(!d.overflowed[0]){ /* y scrolling is not required */
566								_resetContentPosition.call(this); /* reset content position */
567								if(o.axis==="y"){
568									_unbindEvents.call(this);
569								}else if(o.axis==="yx" && d.overflowed[1]){
570									_scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"});
571								}
572							}else if(mCSB_dragger[0].height()>mCSB_dragger[0].parent().height()){
573								_resetContentPosition.call(this); /* reset content position */
574							}else{ /* y scrolling is required */
575								_scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"});
576								d.contentReset.y=null;
577							}
578						}
579						if(o.axis!=="y"){ /* x/yx axis */
580							if(!d.overflowed[1]){ /* x scrolling is not required */
581								_resetContentPosition.call(this); /* reset content position */
582								if(o.axis==="x"){
583									_unbindEvents.call(this);
584								}else if(o.axis==="yx" && d.overflowed[0]){
585									_scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"});
586								}
587							}else if(mCSB_dragger[1].width()>mCSB_dragger[1].parent().width()){
588								_resetContentPosition.call(this); /* reset content position */
589							}else{ /* x scrolling is required */
590								_scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"});
591								d.contentReset.x=null;
592							}
593						}
594						
595						/* callbacks: onImageLoad, onSelectorChange, onUpdate */
596						if(cb && d){
597							if(cb===2 && o.callbacks.onImageLoad && typeof o.callbacks.onImageLoad==="function"){
598								o.callbacks.onImageLoad.call(this);
599							}else if(cb===3 && o.callbacks.onSelectorChange && typeof o.callbacks.onSelectorChange==="function"){
600								o.callbacks.onSelectorChange.call(this);
601							}else if(o.callbacks.onUpdate && typeof o.callbacks.onUpdate==="function"){
602								o.callbacks.onUpdate.call(this);
603							}
604						}
605						
606						_autoUpdate.call(this); /* initialize automatic updating (for dynamic content, fluid layouts etc.) */
607						
608					}
609					
610				});
611				
612			},
613			/* ---------------------------------------- */
614			
615			
616			
617			/* 
618			plugin scrollTo method 
619			triggers a scrolling event to a specific value
620			----------------------------------------
621			usage: $(selector).mCustomScrollbar("scrollTo",value,options);
622			*/
623		
624			scrollTo:function(val,options){
625				
626				/* prevent silly things like $(selector).mCustomScrollbar("scrollTo",undefined); */
627				if(typeof val=="undefined" || val==null){return;}
628				
629				var selector=_selector.call(this); /* validate selector */
630				
631				return $(selector).each(function(){
632					
633					var $this=$(this);
634					
635					if($this.data(pluginPfx)){ /* check if plugin has initialized */
636					
637						var d=$this.data(pluginPfx),o=d.opt,
638							/* method default options */
639							methodDefaults={
640								trigger:"external", /* method is by default triggered externally (e.g. from other scripts) */
641								scrollInertia:o.scrollInertia, /* scrolling inertia (animation duration) */
642								scrollEasing:"mcsEaseInOut", /* animation easing */
643								moveDragger:false, /* move dragger instead of content */
644								timeout:60, /* scroll-to delay */
645								callbacks:true, /* enable/disable callbacks */
646								onStart:true,
647								onUpdate:true,
648								onComplete:true
649							},
650							methodOptions=$.extend(true,{},methodDefaults,options),
651							to=_arr.call(this,val),dur=methodOptions.scrollInertia>0 && methodOptions.scrollInertia<17 ? 17 : methodOptions.scrollInertia;
652						
653						/* translate yx values to actual scroll-to positions */
654						to[0]=_to.call(this,to[0],"y");
655						to[1]=_to.call(this,to[1],"x");
656						
657						/* 
658						check if scroll-to value moves the dragger instead of content. 
659						Only pixel values apply on dragger (e.g. 100, "100px", "-=100" etc.) 
660						*/
661						if(methodOptions.moveDragger){
662							to[0]*=d.scrollRatio.y;
663							to[1]*=d.scrollRatio.x;
664						}
665						
666						methodOptions.dur=_isTabHidden() ? 0 : dur; //skip animations if browser tab is hidden
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' /></div><div class='mCSB_draggerRail' /></div></div>","<div id='mCSB_"+d.idx+"_scrollbar_horizontal' class='mCSB_scrollTools mCSB_"+d.idx+"_scrollbar mCS-"+o.theme+" mCSB_scrollTools_horizontal"+expandClass+"'><div class='"+classes[12]+"'><div id='mCSB_"+d.idx+"_dragger_horizontal' class='mCSB_dragger' style='position:absolute;'><div class='mCSB_dragger_bar' /></div><div class='mCSB_draggerRail' /></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' />" : "",
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>");
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			mCSB_dragger[0].css("min-height",mCSB_dragger[0].height());
894			mCSB_dragger[1].css("min-width",mCSB_dragger[1].width());
895		},
896		/* -------------------- */
897		
898		
899		/* calculates content width */
900		_contentWidth=function(el){
901			var val=[el[0].scrollWidth,Math.max.apply(Math,el.children().map(function(){return $(this).outerWidth(true);}).get())],w=el.parent().width();
902			return val[0]>w ? val[0] : val[1]>w ? val[1] : "100%";
903		},
904		/* -------------------- */
905		
906		
907		/* expands content horizontally */
908		_expandContentHorizontally=function(){
909			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
910				mCSB_container=$("#mCSB_"+d.idx+"_container");
911			if(o.advanced.autoExpandHorizontalScroll && o.axis!=="y"){
912				/* calculate scrollWidth */
913				mCSB_container.css({"width":"auto","min-width":0,"overflow-x":"scroll"});
914				var w=Math.ceil(mCSB_container[0].scrollWidth);
915				if(o.advanced.autoExpandHorizontalScroll===3 || (o.advanced.autoExpandHorizontalScroll!==2 && w>mCSB_container.parent().width())){
916					mCSB_container.css({"width":w,"min-width":"100%","overflow-x":"inherit"});
917				}else{
918					/* 
919					wrap content with an infinite width div and set its position to absolute and width to auto. 
920					Setting width to auto before calculating the actual width is important! 
921					We must let the browser set the width as browser zoom values are impossible to calculate.
922					*/
923					mCSB_container.css({"overflow-x":"inherit","position":"absolute"})
924						.wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />")
925						.css({ /* set actual width, original position and un-wrap */
926							/* 
927							get the exact width (with decimals) and then round-up. 
928							Using jquery outerWidth() will round the width value which will mess up with inner elements that have non-integer width
929							*/
930							"width":(Math.ceil(mCSB_container[0].getBoundingClientRect().right+0.4)-Math.floor(mCSB_container[0].getBoundingClientRect().left)),
931							"min-width":"100%",
932							"position":"relative"
933						}).unwrap();
934				}
935			}
936		},
937		/* -------------------- */
938		
939		
940		/* adds scrollbar buttons */
941		_scrollButtons=function(){
942			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
943				mCSB_scrollTools=$(".mCSB_"+d.idx+"_scrollbar:first"),
944				tabindex=!_isNumeric(o.scrollButtons.tabindex) ? "" : "tabindex='"+o.scrollButtons.tabindex+"'",
945				btnHTML=[
946					"<a href='#' class='"+classes[13]+"' "+tabindex+" />",
947					"<a href='#' class='"+classes[14]+"' "+tabindex+" />",
948					"<a href='#' class='"+classes[15]+"' "+tabindex+" 
948><i class='svg right'><svg width='12' height='6.969' viewBox='0 0 12 6.969'><path class='cls-1' d='M361.691,401.707a1,1,0,0,1-1.414,0L356,397.416l-4.306,4.291a1,1,0,0,1-1.414,0,0.991,0.991,0,0,1,0-1.406l5.016-5a1.006,1.006,0,0,1,1.415,0l4.984,5A0.989,0.989,0,0,1,361.691,401.707Z' transform='translate(-350 -395.031)'></path></svg></i></a>",
949					"<a href='#' class='"+classes[16]+"' "+tabindex+" ><i class='svg right'><svg width='12' height='6.969' viewBox='0 0 12 6.969'><path class='cls-1' d='M361.691,401.707a1,1,0,0,1-1.414,0L356,397.416l-4.306,4.291a1,1,0,0,1-1.414,0,0.99
vendor: 17,514 bytes, lines 949-1372
9491,0.991,0,0,1,0-1.406l5.016-5a1.006,1.006,0,0,1,1.415,0l4.984,5A0.989,0.989,0,0,1,361.691,401.707Z' transform='translate(-350 -395.031)'></path></svg></i></a>"
950				],
951				btn=[(o.axis==="x" ? btnHTML[2] : btnHTML[0]),(o.axis==="x" ? btnHTML[3] : btnHTML[1]),btnHTML[2],btnHTML[3]];
952			if(o.scrollButtons.enable){
953				mCSB_scrollTools.prepend(btn[0]).append(btn[1]).next(".mCSB_scrollTools").prepend(btn[2]).append(btn[3]);
954			}
955		},
956		/* -------------------- */
957		
958		
959		/* auto-adjusts scrollbar dragger length */
960		_setDraggerLength=function(){
961			var $this=$(this),d=$this.data(pluginPfx),
962				mCustomScrollBox=$("#mCSB_"+d.idx),
963				mCSB_container=$("#mCSB_"+d.idx+"_container"),
964				mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")],
965				ratio=[mCustomScrollBox.height()/mCSB_container.outerHeight(false),mCustomScrollBox.width()/mCSB_container.outerWidth(false)],
966				l=[
967					parseInt(mCSB_dragger[0].css("min-height")),Math.round(ratio[0]*mCSB_dragger[0].parent().height()),
968					parseInt(mCSB_dragger[1].css("min-width")),Math.round(ratio[1]*mCSB_dragger[1].parent().width())
969				],
970				h=oldIE && (l[1]<l[0]) ? l[0] : l[1],w=oldIE && (l[3]<l[2]) ? l[2] : l[3];
971			mCSB_dragger[0].css({
972				"height":h,"max-height":(mCSB_dragger[0].parent().height()-10)
973			}).find(".mCSB_dragger_bar").css({"line-height":l[0]+"px"});
974			mCSB_dragger[1].css({
975				"width":w,"max-width":(mCSB_dragger[1].parent().width()-10)
976			});
977		},
978		/* -------------------- */
979		
980		
981		/* calculates scrollbar to content ratio */
982		_scrollRatio=function(){
983			var $this=$(this),d=$this.data(pluginPfx),
984				mCustomScrollBox=$("#mCSB_"+d.idx),
985				mCSB_container=$("#mCSB_"+d.idx+"_container"),
986				mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")],
987				scrollAmount=[mCSB_container.outerHeight(false)-mCustomScrollBox.height(),mCSB_container.outerWidth(false)-mCustomScrollBox.width()],
988				ratio=[
989					scrollAmount[0]/(mCSB_dragger[0].parent().height()-mCSB_dragger[0].height()),
990					scrollAmount[1]/(mCSB_dragger[1].parent().width()-mCSB_dragger[1].width())
991				];
992			d.scrollRatio={y:ratio[0],x:ratio[1]};
993		},
994		/* -------------------- */
995		
996		
997		/* toggles scrolling classes */
998		_onDragClasses=function(el,action,xpnd){
999			var expandClass=xpnd ? classes[0]+"_expanded" : "",
1000				scrollbar=el.closest(".mCSB_scrollTools");
1001			if(action==="active"){
1002				el.toggleClass(classes[0]+" "+expandClass); scrollbar.toggleClass(classes[1]); 
1003				el[0]._draggable=el[0]._draggable ? 0 : 1;
1004			}else{
1005				if(!el[0]._draggable){
1006					if(action==="hide"){
1007						el.removeClass(classes[0]); scrollbar.removeClass(classes[1]);
1008					}else{
1009						el.addClass(classes[0]); scrollbar.addClass(classes[1]);
1010					}
1011				}
1012			}
1013		},
1014		/* -------------------- */
1015		
1016		
1017		/* checks if content overflows its container to determine if scrolling is required */
1018		_overflowed=function(){
1019			var $this=$(this),d=$this.data(pluginPfx),
1020				mCustomScrollBox=$("#mCSB_"+d.idx),
1021				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1022				contentHeight=d.overflowed==null ? mCSB_container.height() : mCSB_container.outerHeight(false),
1023				contentWidth=d.overflowed==null ? mCSB_container.width() : mCSB_container.outerWidth(false),
1024				h=mCSB_container[0].scrollHeight,w=mCSB_container[0].scrollWidth;
1025			if(h>contentHeight){contentHeight=h;}
1026			if(w>contentWidth){contentWidth=w;}
1027			return [contentHeight>mCustomScrollBox.height(),contentWidth>mCustomScrollBox.width()];
1028		},
1029		/* -------------------- */
1030		
1031		
1032		/* resets content position to 0 */
1033		_resetContentPosition=function(){
1034			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1035				mCustomScrollBox=$("#mCSB_"+d.idx),
1036				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1037				mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")];
1038			_stop($this); /* stop any current scrolling before resetting */
1039			if((o.axis!=="x" && !d.overflowed[0]) || (o.axis==="y" && d.overflowed[0])){ /* reset y */
1040				mCSB_dragger[0].add(mCSB_container).css("top",0);
1041				_scrollTo($this,"_resetY");
1042			}
1043			if((o.axis!=="y" && !d.overflowed[1]) || (o.axis==="x" && d.overflowed[1])){ /* reset x */
1044				var cx=dx=0;
1045				if(d.langDir==="rtl"){ /* adjust left position for rtl direction */
1046					cx=mCustomScrollBox.width()-mCSB_container.outerWidth(false);
1047					dx=Math.abs(cx/d.scrollRatio.x);
1048				}
1049				mCSB_container.css("left",cx);
1050				mCSB_dragger[1].css("left",dx);
1051				_scrollTo($this,"_resetX");
1052			}
1053		},
1054		/* -------------------- */
1055		
1056		
1057		/* binds scrollbar events */
1058		_bindEvents=function(){
1059			var $this=$(this),d=$this.data(pluginPfx),o=d.opt;
1060			if(!d.bindEvents){ /* check if events are already bound */
1061				_draggable.call(this);
1062				if(o.contentTouchScroll){_contentDraggable.call(this);}
1063				_selectable.call(this);
1064				if(o.mouseWheel.enable){ /* bind mousewheel fn when plugin is available */
1065					function _mwt(){
1066						mousewheelTimeout=setTimeout(function(){
1067							if(!$.event.special.mousewheel){
1068								_mwt();
1069							}else{
1070								clearTimeout(mousewheelTimeout);
1071								_mousewheel.call($this[0]);
1072							}
1073						},100);
1074					}
1075					var mousewheelTimeout;
1076					_mwt();
1077				}
1078				_draggerRail.call(this);
1079				_wrapperScroll.call(this);
1080				if(o.advanced.autoScrollOnFocus){_focus.call(this);}
1081				if(o.scrollButtons.enable){_buttons.call(this);}
1082				if(o.keyboard.enable){_keyboard.call(this);}
1083				d.bindEvents=true;
1084			}
1085		},
1086		/* -------------------- */
1087		
1088		
1089		/* unbinds scrollbar events */
1090		_unbindEvents=function(){
1091			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1092				namespace=pluginPfx+"_"+d.idx,
1093				sb=".mCSB_"+d.idx+"_scrollbar",
1094				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"),
1095				mCSB_container=$("#mCSB_"+d.idx+"_container");
1096			if(o.advanced.releaseDraggableSelectors){sel.add($(o.advanced.releaseDraggableSelectors));}
1097			if(o.advanced.extraDraggableSelectors){sel.add($(o.advanced.extraDraggableSelectors));}
1098			if(d.bindEvents){ /* check if events are bound */
1099				/* unbind namespaced events from document/selectors */
1100				$(document).add($(!_canAccessIFrame() || top.document)).unbind("."+namespace);
1101				sel.each(function(){
1102					$(this).unbind("."+namespace);
1103				});
1104				/* clear and delete timeouts/objects */
1105				clearTimeout($this[0]._focusTimeout); _delete($this[0],"_focusTimeout");
1106				clearTimeout(d.sequential.step); _delete(d.sequential,"step");
1107				clearTimeout(mCSB_container[0].onCompleteTimeout); _delete(mCSB_container[0],"onCompleteTimeout");
1108				d.bindEvents=false;
1109			}
1110		},
1111		/* -------------------- */
1112		
1113		
1114		/* toggles scrollbar visibility */
1115		_scrollbarVisibility=function(disabled){
1116			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1117				contentWrapper=$("#mCSB_"+d.idx+"_container_wrapper"),
1118				content=contentWrapper.length ? contentWrapper : $("#mCSB_"+d.idx+"_container"),
1119				scrollbar=[$("#mCSB_"+d.idx+"_scrollbar_vertical"),$("#mCSB_"+d.idx+"_scrollbar_horizontal")],
1120				mCSB_dragger=[scrollbar[0].find(".mCSB_dragger"),scrollbar[1].find(".mCSB_dragger")];
1121			if(o.axis!=="x"){
1122				if(d.overflowed[0] && !disabled){
1123					scrollbar[0].add(mCSB_dragger[0]).add(scrollbar[0].children("a")).css("display","block");
1124					content.removeClass(classes[8]+" "+classes[10]);
1125				}else{
1126					if(o.alwaysShowScrollbar){
1127						if(o.alwaysShowScrollbar!==2){mCSB_dragger[0].css("display","none");}
1128						content.removeClass(classes[10]);
1129					}else{
1130						scrollbar[0].css("display","none");
1131						content.addClass(classes[10]);
1132					}
1133					content.addClass(classes[8]);
1134				}
1135			}
1136			if(o.axis!=="y"){
1137				if(d.overflowed[1] && !disabled){
1138					scrollbar[1].add(mCSB_dragger[1]).add(scrollbar[1].children("a")).css("display","block");
1139					content.removeClass(classes[9]+" "+classes[11]);
1140				}else{
1141					if(o.alwaysShowScrollbar){
1142						if(o.alwaysShowScrollbar!==2){mCSB_dragger[1].css("display","none");}
1143						content.removeClass(classes[11]);
1144					}else{
1145						scrollbar[1].css("display","none");
1146						content.addClass(classes[11]);
1147					}
1148					content.addClass(classes[9]);
1149				}
1150			}
1151			if(!d.overflowed[0] && !d.overflowed[1]){
1152				$this.addClass(classes[5]);
1153			}else{
1154				$this.removeClass(classes[5]);
1155			}
1156		},
1157		/* -------------------- */
1158		
1159		
1160		/* returns input coordinates of pointer, touch and mouse events (relative to document) */
1161		_coordinates=function(e){
1162			var t=e.type,o=e.target.ownerDocument!==document && frameElement!==null ? [$(frameElement).offset().top,$(frameElement).offset().left] : null,
1163				io=_canAccessIFrame() && e.target.ownerDocument!==top.document && frameElement!==null ? [$(e.view.frameElement).offset().top,$(e.view.frameElement).offset().left] : [0,0];
1164			switch(t){
1165				case "pointerdown": case "MSPointerDown": case "pointermove": case "MSPointerMove": case "pointerup": case "MSPointerUp":
1166					return o ? [e.originalEvent.pageY-o[0]+io[0],e.originalEvent.pageX-o[1]+io[1],false] : [e.originalEvent.pageY,e.originalEvent.pageX,false];
1167					break;
1168				case "touchstart": case "touchmove": case "touchend":
1169					var touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0],
1170						touches=e.originalEvent.touches.length || e.originalEvent.changedTouches.length;
1171					return e.target.ownerDocument!==document ? [touch.screenY,touch.screenX,touches>1] : [touch.pageY,touch.pageX,touches>1];
1172					break;
1173				default:
1174					return o ? [e.pageY-o[0]+io[0],e.pageX-o[1]+io[1],false] : [e.pageY,e.pageX,false];
1175			}
1176		},
1177		/* -------------------- */
1178		
1179		
1180		/* 
1181		SCROLLBAR DRAG EVENTS
1182		scrolls content via scrollbar dragging 
1183		*/
1184		_draggable=function(){
1185			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1186				namespace=pluginPfx+"_"+d.idx,
1187				draggerId=["mCSB_"+d.idx+"_dragger_vertical","mCSB_"+d.idx+"_dragger_horizontal"],
1188				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1189				mCSB_dragger=$("#"+draggerId[0]+",#"+draggerId[1]),
1190				draggable,dragY,dragX,
1191				rds=o.advanced.releaseDraggableSelectors ? mCSB_dragger.add($(o.advanced.releaseDraggableSelectors)) : mCSB_dragger,
1192				eds=o.advanced.extraDraggableSelectors ? $(!_canAccessIFrame() || top.document).add($(o.advanced.extraDraggableSelectors)) : $(!_canAccessIFrame() || top.document);
1193			mCSB_dragger.bind("contextmenu."+namespace,function(e){
1194				e.preventDefault(); //prevent right click
1195			}).bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){
1196				e.stopImmediatePropagation();
1197				e.preventDefault();
1198				if(!_mouseBtnLeft(e)){return;} /* left mouse button only */
1199				touchActive=true;
1200				if(oldIE){document.onselectstart=function(){return false;}} /* disable text selection for IE < 9 */
1201				_iframe.call(mCSB_container,false); /* enable scrollbar dragging over iframes by disabling their events */
1202				_stop($this);
1203				draggable=$(this);
1204				var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left,
1205					h=draggable.height()+offset.top,w=draggable.width()+offset.left;
1206				if(y<h && y>0 && x<w && x>0){
1207					dragY=y; 
1208					dragX=x;
1209				}
1210				_onDragClasses(draggable,"active",o.autoExpandScrollbar); 
1211			}).bind("touchmove."+namespace,function(e){
1212				e.stopImmediatePropagation();
1213				e.preventDefault();
1214				var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left;
1215				_drag(dragY,dragX,y,x);
1216			});
1217			$(document).add(eds).bind("mousemove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace,function(e){
1218				if(draggable){
1219					var offset=draggable.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left;
1220					if(dragY===y && dragX===x){return;} /* has it really moved? */
1221					_drag(dragY,dragX,y,x);
1222				}
1223			}).add(rds).bind("mouseup."+namespace+" touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){
1224				if(draggable){
1225					_onDragClasses(draggable,"active",o.autoExpandScrollbar); 
1226					draggable=null;
1227				}
1228				touchActive=false;
1229				if(oldIE){document.onselectstart=null;} /* enable text selection for IE < 9 */
1230				_iframe.call(mCSB_container,true); /* enable iframes events */
1231			});
1232			function _drag(dragY,dragX,y,x){
1233				mCSB_container[0].idleTimer=o.scrollInertia<233 ? 250 : 0;
1234				if(draggable.attr("id")===draggerId[1]){
1235					var dir="x",to=((draggable[0].offsetLeft-dragX)+x)*d.scrollRatio.x;
1236				}else{
1237					var dir="y",to=((draggable[0].offsetTop-dragY)+y)*d.scrollRatio.y;
1238				}
1239				_scrollTo($this,to.toString(),{dir:dir,drag:true});
1240			}
1241		},
1242		/* -------------------- */
1243		
1244		
1245		/* 
1246		TOUCH SWIPE EVENTS
1247		scrolls content via touch swipe 
1248		Emulates the native touch-swipe scrolling with momentum found in iOS, Android and WP devices 
1249		*/
1250		_contentDraggable=function(){
1251			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1252				namespace=pluginPfx+"_"+d.idx,
1253				mCustomScrollBox=$("#mCSB_"+d.idx),
1254				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1255				mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")],
1256				draggable,dragY,dragX,touchStartY,touchStartX,touchMoveY=[],touchMoveX=[],startTime,runningTime,endTime,distance,speed,amount,
1257				durA=0,durB,overwrite=o.axis==="yx" ? "none" : "all",touchIntent=[],touchDrag,docDrag,
1258				iframe=mCSB_container.find("iframe"),
1259				events=[
1260					"touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace, //start
1261					"touchmove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace, //move
1262					"touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace //end
1263				],
1264				touchAction=document.body.style.touchAction!==undefined && document.body.style.touchAction!=="";
1265			mCSB_container.bind(events[0],function(e){
1266				_onTouchstart(e);
1267			}).bind(events[1],function(e){
1268				_onTouchmove(e);
1269			});
1270			mCustomScrollBox.bind(events[0],function(e){
1271				_onTouchstart2(e);
1272			}).bind(events[2],function(e){
1273				_onTouchend(e);
1274			});
1275			if(iframe.length){
1276				iframe.each(function(){
1277					$(this).bind("load",function(){
1278						/* bind events on accessible iframes */
1279						if(_canAccessIFrame(this)){
1280							$(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){
1281								_onTouchstart(e);
1282								_onTouchstart2(e);
1283							}).bind(events[1],function(e){
1284								_onTouchmove(e);
1285							}).bind(events[2],function(e){
1286								_onTouchend(e);
1287							});
1288						}
1289					});
1290				});
1291			}
1292			function _onTouchstart(e){
1293				if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){touchable=0; return;}
1294
1295				if($(e.target).closest('.bx_ui_slider_track').length){
1296					touchOffCustom = true;
1297					touchable=0; return;
1298				} else {
1299					touchOffCustom = false;
1300				}
1301
1302				touchable=1; touchDrag=0; docDrag=0; draggable=1;
1303				$this.removeClass("mCS_touch_action");
1304				var offset=mCSB_container.offset();
1305				dragY=_coordinates(e)[0]-offset.top;
1306				dragX=_coordinates(e)[1]-offset.left;
1307				touchIntent=[_coordinates(e)[0],_coordinates(e)[1]];
1308
1309			}
1310			function _onTouchmove(e){
1311				if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){return;}
1312
1313				if(touchOffCustom){
1314					touchable=0; return;
1315				}
1316
1317				if(!o.documentTouchScroll){e.preventDefault();} 
1318				e.stopImmediatePropagation();
1319				if(docDrag && !touchDrag){return;}
1320				if(draggable){
1321					runningTime=_getTime();
1322					var offset=mCustomScrollBox.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left,
1323						easing="mcsLinearOut";
1324					touchMoveY.push(y);
1325					touchMoveX.push(x);
1326					touchIntent[2]=Math.abs(_coordinates(e)[0]-touchIntent[0]); touchIntent[3]=Math.abs(_coordinates(e)[1]-touchIntent[1]);
1327					if(d.overflowed[0]){
1328						var limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(),
1329							prevent=((dragY-y)>0 && (y-dragY)>-(limit*d.scrollRatio.y) && (touchIntent[3]*2<touchIntent[2] || o.axis==="yx"));
1330					}
1331					if(d.overflowed[1]){
1332						var limitX=mCSB_dragger[1].parent().width()-mCSB_dragger[1].width(),
1333							preventX=((dragX-x)>0 && (x-dragX)>-(limitX*d.scrollRatio.x) && (touchIntent[2]*2<touchIntent[3] || o.axis==="yx"));
1334					}
1335					if(prevent || preventX){ /* prevent native document scrolling */
1336						if(!touchAction){e.preventDefault();} 
1337						touchDrag=1;
1338					}else{
1339						docDrag=1;
1340						$this.addClass("mCS_touch_action");
1341					}
1342					if(touchAction){e.preventDefault();} 
1343					amount=o.axis==="yx" ? [(dragY-y),(dragX-x)] : o.axis==="x" ? [null,(dragX-x)] : [(dragY-y),null];
1344					mCSB_container[0].idleTimer=250;
1345					if(d.overflowed[0]){_drag(amount[0],durA,easing,"y","all",true);}
1346					if(d.overflowed[1]){_drag(amount[1],durA,easing,"x",overwrite,true);}
1347				}
1348			}
1349			function _onTouchstart2(e){
1350				if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){touchable=0; return;}
1351
1352				if($(e.target).closest('.bx_ui_slider_track').length){
1353					touchOffCustom = true;
1354					touchable=0; return;
1355				} else {
1356					touchOffCustom = false;
1357				}
1358
1359				touchable=1;
1360				e.stopImmediatePropagation();
1361				_stop($this);
1362				startTime=_getTime();
1363				var offset=mCustomScrollBox.offset();
1364				touchStartY=_coordinates(e)[0]-offset.top;
1365				touchStartX=_coordinates(e)[1]-offset.left;
1366				touchMoveY=[]; touchMoveX=[];
1367			}
1368			function _onTouchend(e){				
1369				if(!_pointerTouch(e) || touchActive || _coordinates(e)[2]){return;}
1370
1371				if($(e.target).closest('.bx_ui_slider_track').length){
1372					touchOffCustom = false;
1373					touchable=0; return;
1374				}
vendor: 13,509 bytes, lines 1375-1718
1375
1376				draggable=0;
1377				e.stopImmediatePropagation();
1378				touchDrag=0; docDrag=0;
1379				endTime=_getTime();
1380				var offset=mCustomScrollBox.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left;
1381				if((endTime-runningTime)>30){return;}
1382				speed=1000/(endTime-startTime);
1383				var easing="mcsEaseOut",slow=speed<2.5,
1384					diff=slow ? [touchMoveY[touchMoveY.length-2],touchMoveX[touchMoveX.length-2]] : [0,0];
1385				distance=slow ? [(y-diff[0]),(x-diff[1])] : [y-touchStartY,x-touchStartX];
1386				var absDistance=[Math.abs(distance[0]),Math.abs(distance[1])];
1387				speed=slow ? [Math.abs(distance[0]/4),Math.abs(distance[1]/4)] : [speed,speed];
1388				var a=[
1389					Math.abs(mCSB_container[0].offsetTop)-(distance[0]*_m((absDistance[0]/speed[0]),speed[0])),
1390					Math.abs(mCSB_container[0].offsetLeft)-(distance[1]*_m((absDistance[1]/speed[1]),speed[1]))
1391				];
1392				amount=o.axis==="yx" ? [a[0],a[1]] : o.axis==="x" ? [null,a[1]] : [a[0],null];
1393				durB=[(absDistance[0]*4)+o.scrollInertia,(absDistance[1]*4)+o.scrollInertia];
1394				var md=parseInt(o.contentTouchScroll) || 0; /* absolute minimum distance required */
1395				amount[0]=absDistance[0]>md ? amount[0] : 0;
1396				amount[1]=absDistance[1]>md ? amount[1] : 0;
1397				if(d.overflowed[0]){_drag(amount[0],durB[0],easing,"y",overwrite,false);}
1398				if(d.overflowed[1]){_drag(amount[1],durB[1],easing,"x",overwrite,false);}
1399			}
1400			function _m(ds,s){
1401				var r=[s*1.5,s*2,s/1.5,s/2];
1402				if(ds>90){
1403					return s>4 ? r[0] : r[3];
1404				}else if(ds>60){
1405					return s>3 ? r[3] : r[2];
1406				}else if(ds>30){
1407					return s>8 ? r[1] : s>6 ? r[0] : s>4 ? s : r[2];
1408				}else{
1409					return s>8 ? s : r[3];
1410				}
1411			}
1412			function _drag(amount,dur,easing,dir,overwrite,drag){
1413				if(!amount){return;}
1414				_scrollTo($this,amount.toString(),{dur:dur,scrollEasing:easing,dir:dir,overwrite:overwrite,drag:drag});
1415			}
1416		},
1417		/* -------------------- */
1418		
1419		
1420		/* 
1421		SELECT TEXT EVENTS 
1422		scrolls content when text is selected 
1423		*/
1424		_selectable=function(){
1425			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential,
1426				namespace=pluginPfx+"_"+d.idx,
1427				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1428				wrapper=mCSB_container.parent(),
1429				action;
1430			mCSB_container.bind("mousedown."+namespace,function(e){
1431				if(touchable){return;}
1432				if(!action){action=1; touchActive=true;}
1433			}).add(document).bind("mousemove."+namespace,function(e){
1434				if(!touchable && action && _sel()){
1435					var offset=mCSB_container.offset(),
1436						y=_coordinates(e)[0]-offset.top+mCSB_container[0].offsetTop,x=_coordinates(e)[1]-offset.left+mCSB_container[0].offsetLeft;
1437					if(y>0 && y<wrapper.height() && x>0 && x<wrapper.width()){
1438						if(seq.step){_seq("off",null,"stepped");}
1439					}else{
1440						if(o.axis!=="x" && d.overflowed[0]){
1441							if(y<0){
1442								_seq("on",38);
1443							}else if(y>wrapper.height()){
1444								_seq("on",40);
1445							}
1446						}
1447						if(o.axis!=="y" && d.overflowed[1]){
1448							if(x<0){
1449								_seq("on",37);
1450							}else if(x>wrapper.width()){
1451								_seq("on",39);
1452							}
1453						}
1454					}
1455				}
1456			}).bind("mouseup."+namespace+" dragend."+namespace,function(e){
1457				if(touchable){return;}
1458				if(action){action=0; _seq("off",null);}
1459				touchActive=false;
1460			});
1461			function _sel(){
1462				return 	window.getSelection ? window.getSelection().toString() : 
1463						document.selection && document.selection.type!="Control" ? document.selection.createRange().text : 0;
1464			}
1465			function _seq(a,c,s){
1466				seq.type=s && action ? "stepped" : "stepless";
1467				seq.scrollAmount=10;
1468				_sequentialScroll($this,a,c,"mcsLinearOut",s ? 60 : null);
1469			}
1470		},
1471		/* -------------------- */
1472		
1473		
1474		/* 
1475		MOUSE WHEEL EVENT
1476		scrolls content via mouse-wheel 
1477		via mouse-wheel plugin (https://github.com/brandonaaron/jquery-mousewheel)
1478		*/
1479		_mousewheel=function(){
1480			if(!$(this).data(pluginPfx)){return;} /* Check if the scrollbar is ready to use mousewheel events (issue: #185) */
1481			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1482				namespace=pluginPfx+"_"+d.idx,
1483				mCustomScrollBox=$("#mCSB_"+d.idx),
1484				mCSB_dragger=[$("#mCSB_"+d.idx+"_dragger_vertical"),$("#mCSB_"+d.idx+"_dragger_horizontal")],
1485				iframe=$("#mCSB_"+d.idx+"_container").find("iframe");
1486			if(iframe.length){
1487				iframe.each(function(){
1488					$(this).bind("load",function(){
1489						/* bind events on accessible iframes */
1490						if(_canAccessIFrame(this)){
1491							$(this.contentDocument || this.contentWindow.document).bind("mousewheel."+namespace,function(e,delta){
1492								_onMousewheel(e,delta);
1493							});
1494						}
1495					});
1496				});
1497			}
1498			mCustomScrollBox.bind("mousewheel."+namespace,function(e,delta){
1499				_onMousewheel(e,delta);
1500			});
1501			function _onMousewheel(e,delta){
1502				_stop($this);
1503				if(_disableMousewheel($this,e.target)){return;} /* disables mouse-wheel when hovering specific elements */
1504				var deltaFactor=o.mouseWheel.deltaFactor!=="auto" ? parseInt(o.mouseWheel.deltaFactor) : (oldIE && e.deltaFactor<100) ? 100 : e.deltaFactor || 100,
1505					dur=o.scrollInertia;
1506				if(o.axis==="x" || o.mouseWheel.axis==="x"){
1507					var dir="x",
1508						px=[Math.round(deltaFactor*d.scrollRatio.x),parseInt(o.mouseWheel.scrollAmount)],
1509						amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.width() ? mCustomScrollBox.width()*0.9 : px[0],
1510						contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetLeft),
1511						draggerPos=mCSB_dragger[1][0].offsetLeft,
1512						limit=mCSB_dragger[1].parent().width()-mCSB_dragger[1].width(),
1513						dlt=o.mouseWheel.axis==="y" ? (e.deltaY || delta) : e.deltaX;
1514				}else{
1515					var dir="y",
1516						px=[Math.round(deltaFactor*d.scrollRatio.y),parseInt(o.mouseWheel.scrollAmount)],
1517						amount=o.mouseWheel.scrollAmount!=="auto" ? px[1] : px[0]>=mCustomScrollBox.height() ? mCustomScrollBox.height()*0.9 : px[0],
1518						contentPos=Math.abs($("#mCSB_"+d.idx+"_container")[0].offsetTop),
1519						draggerPos=mCSB_dragger[0][0].offsetTop,
1520						limit=mCSB_dragger[0].parent().height()-mCSB_dragger[0].height(),
1521						dlt=e.deltaY || delta;
1522				}
1523				if((dir==="y" && !d.overflowed[0]) || (dir==="x" && !d.overflowed[1])){return;}
1524				if(o.mouseWheel.invert || e.webkitDirectionInvertedFromDevice){dlt=-dlt;}
1525				if(o.mouseWheel.normalizeDelta){dlt=dlt<0 ? -1 : 1;}
1526				if((dlt>0 && draggerPos!==0) || (dlt<0 && draggerPos!==limit) || o.mouseWheel.preventDefault){
1527					e.stopImmediatePropagation();
1528					e.preventDefault();
1529				}
1530				if(e.deltaFactor<5 && !o.mouseWheel.normalizeDelta){
1531					//very low deltaFactor values mean some kind of delta acceleration (e.g. osx trackpad), so adjusting scrolling accordingly
1532					amount=e.deltaFactor; dur=17;
1533				}
1534				_scrollTo($this,(contentPos-(dlt*amount)).toString(),{dir:dir,dur:dur});
1535			}
1536		},
1537		/* -------------------- */
1538		
1539		
1540		/* checks if iframe can be accessed */
1541		_canAccessIFrameCache=new Object(),
1542		_canAccessIFrame=function(iframe){
1543		    var result=false,cacheKey=false,html=null;
1544		    if(iframe===undefined){
1545				cacheKey="#empty";
1546		    }else if($(iframe).attr("id")!==undefined){
1547				cacheKey=$(iframe).attr("id");
1548		    }
1549			if(cacheKey!==false && _canAccessIFrameCache[cacheKey]!==undefined){
1550				return _canAccessIFrameCache[cacheKey];
1551			}
1552			if(!iframe){
1553				try{
1554					var doc=top.document;
1555					html=doc.body.innerHTML;
1556				}catch(err){/* do nothing */}
1557				result=(html!==null);
1558			}else{
1559				try{
1560					var doc=iframe.contentDocument || iframe.contentWindow.document;
1561					html=doc.body.innerHTML;
1562				}catch(err){/* do nothing */}
1563				result=(html!==null);
1564			}
1565			if(cacheKey!==false){_canAccessIFrameCache[cacheKey]=result;}
1566			return result;
1567		},
1568		/* -------------------- */
1569		
1570		
1571		/* switches iframe's pointer-events property (drag, mousewheel etc. over cross-domain iframes) */
1572		_iframe=function(evt){
1573			var el=this.find("iframe");
1574			if(!el.length){return;} /* check if content contains iframes */
1575			var val=!evt ? "none" : "auto";
1576			el.css("pointer-events",val); /* for IE11, iframe's display property should not be "block" */
1577		},
1578		/* -------------------- */
1579		
1580		
1581		/* disables mouse-wheel when hovering specific elements like select, datalist etc. */
1582		_disableMousewheel=function(el,target){
1583			var tag=target.nodeName.toLowerCase(),
1584				tags=el.data(pluginPfx).opt.mouseWheel.disableOver,
1585				/* elements that require focus */
1586				focusTags=["select","textarea"];
1587			return $.inArray(tag,tags) > -1 && !($.inArray(tag,focusTags) > -1 && !$(target).is(":focus"));
1588		},
1589		/* -------------------- */
1590		
1591		
1592		/* 
1593		DRAGGER RAIL CLICK EVENT
1594		scrolls content via dragger rail 
1595		*/
1596		_draggerRail=function(){
1597			var $this=$(this),d=$this.data(pluginPfx),
1598				namespace=pluginPfx+"_"+d.idx,
1599				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1600				wrapper=mCSB_container.parent(),
1601				mCSB_draggerContainer=$(".mCSB_"+d.idx+"_scrollbar ."+classes[12]),
1602				clickable;
1603			mCSB_draggerContainer.bind("mousedown."+namespace+" touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){
1604				touchActive=true;
1605				if(!$(e.target).hasClass("mCSB_dragger")){clickable=1;}
1606			}).bind("touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){
1607				touchActive=false;
1608			}).bind("click."+namespace,function(e){
1609				if(!clickable){return;}
1610				clickable=0;
1611				if($(e.target).hasClass(classes[12]) || $(e.target).hasClass("mCSB_draggerRail")){
1612					_stop($this);
1613					var el=$(this),mCSB_dragger=el.find(".mCSB_dragger");
1614					if(el.parent(".mCSB_scrollTools_horizontal").length>0){
1615						if(!d.overflowed[1]){return;}
1616						var dir="x",
1617							clickDir=e.pageX>mCSB_dragger.offset().left ? -1 : 1,
1618							to=Math.abs(mCSB_container[0].offsetLeft)-(clickDir*(wrapper.width()*0.9));
1619					}else{
1620						if(!d.overflowed[0]){return;}
1621						var dir="y",
1622							clickDir=e.pageY>mCSB_dragger.offset().top ? -1 : 1,
1623							to=Math.abs(mCSB_container[0].offsetTop)-(clickDir*(wrapper.height()*0.9));
1624					}
1625					_scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"});
1626				}
1627			});
1628		},
1629		/* -------------------- */
1630		
1631		
1632		/* 
1633		FOCUS EVENT
1634		scrolls content via element focus (e.g. clicking an input, pressing TAB key etc.)
1635		*/
1636		_focus=function(){
1637			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1638				namespace=pluginPfx+"_"+d.idx,
1639				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1640				wrapper=mCSB_container.parent();
1641			mCSB_container.bind("focusin."+namespace,function(e){
1642				var el=$(document.activeElement),
1643					nested=mCSB_container.find(".mCustomScrollBox").length,
1644					dur=0;
1645				if(!el.is(o.advanced.autoScrollOnFocus)){return;}
1646				_stop($this);
1647				clearTimeout($this[0]._focusTimeout);
1648				$this[0]._focusTimer=nested ? (dur+17)*nested : 0;
1649				$this[0]._focusTimeout=setTimeout(function(){
1650					var	to=[_childPos(el)[0],_childPos(el)[1]],
1651						contentPos=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft],
1652						isVisible=[
1653							(contentPos[0]+to[0]>=0 && contentPos[0]+to[0]<wrapper.height()-el.outerHeight(false)),
1654							(contentPos[1]+to[1]>=0 && contentPos[0]+to[1]<wrapper.width()-el.outerWidth(false))
1655						],
1656						overwrite=(o.axis==="yx" && !isVisible[0] && !isVisible[1]) ? "none" : "all";
1657					if(o.axis!=="x" && !isVisible[0]){
1658						_scrollTo($this,to[0].toString(),{dir:"y",scrollEasing:"mcsEaseInOut",overwrite:overwrite,dur:dur});
1659					}
1660					if(o.axis!=="y" && !isVisible[1]){
1661						_scrollTo($this,to[1].toString(),{dir:"x",scrollEasing:"mcsEaseInOut",overwrite:overwrite,dur:dur});
1662					}
1663				},$this[0]._focusTimer);
1664			});
1665		},
1666		/* -------------------- */
1667		
1668		
1669		/* sets content wrapper scrollTop/scrollLeft always to 0 */
1670		_wrapperScroll=function(){
1671			var $this=$(this),d=$this.data(pluginPfx),
1672				namespace=pluginPfx+"_"+d.idx,
1673				wrapper=$("#mCSB_"+d.idx+"_container").parent();
1674			wrapper.bind("scroll."+namespace,function(e){
1675				if(wrapper.scrollTop()!==0 || wrapper.scrollLeft()!==0){
1676					$(".mCSB_"+d.idx+"_scrollbar").css("visibility","hidden"); /* hide scrollbar(s) */
1677				}
1678			});
1679		},
1680		/* -------------------- */
1681		
1682		
1683		/* 
1684		BUTTONS EVENTS
1685		scrolls content via up, down, left and right buttons 
1686		*/
1687		_buttons=function(){
1688			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential,
1689				namespace=pluginPfx+"_"+d.idx,
1690				sel=".mCSB_"+d.idx+"_scrollbar",
1691				btn=$(sel+">a");
1692			btn.bind("contextmenu."+namespace,function(e){
1693				e.preventDefault(); //prevent right click
1694			}).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){
1695				e.preventDefault();
1696				if(!_mouseBtnLeft(e)){return;} /* left mouse button only */
1697				var btnClass=$(this).attr("class");
1698				seq.type=o.scrollButtons.scrollType;
1699				switch(e.type){
1700					case "mousedown": case "touchstart": case "pointerdown": case "MSPointerDown":
1701						if(seq.type==="stepped"){return;}
1702						touchActive=true;
1703						d.tweenRunning=false;
1704						_seq("on",btnClass);
1705						break;
1706					case "mouseup": case "touchend": case "pointerup": case "MSPointerUp":
1707					case "mouseout": case "pointerout": case "MSPointerOut":
1708						if(seq.type==="stepped"){return;}
1709						touchActive=false;
1710						if(seq.dir){_seq("off",btnClass);}
1711						break;
1712					case "click":
1713						if(seq.type!=="stepped" || d.tweenRunning){return;}
1714						_seq("on",btnClass);
1715						break;
1716				}
1717				function _seq(a,c){
1718					
1718//seq.scrollAmount=o.scrollButtons.scrollAmount;
1719					_sequentialScroll($this,a,c);
1720				}
1721			});
1722		},
1723		/* -------------------- */
1724		
1725		
1726		/* 
1727		KEYBOARD EVENTS
1728		scrolls content via keyboard 
1729		Keys: up arrow, down arrow, left arrow, right arrow, PgUp, PgDn, Home, End
1730		*/
1731		_keyboard=function(){
1732			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,seq=d.sequential,
1733				namespace=pluginPfx+"_"+d.idx,
1734				mCustomScrollBox=$("#mCSB_"+d.idx),
1735				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1736				wrapper=mCSB_container.parent(),
1737				editables="input,textarea,select,datalist,keygen,[contenteditable='true']",
1738				iframe=mCSB_container.find("iframe"),
vendor: 19,307 bytes, lines 1739-2238
1739				events=["blur."+namespace+" keydown."+namespace+" keyup."+namespace];
1740			if(iframe.length){
1741				iframe.each(function(){
1742					$(this).bind("load",function(){
1743						/* bind events on accessible iframes */
1744						if(_canAccessIFrame(this)){
1745							$(this.contentDocument || this.contentWindow.document).bind(events[0],function(e){
1746								_onKeyboard(e);
1747							});
1748						}
1749					});
1750				});
1751			}
1752			mCustomScrollBox.attr("tabindex","0").bind(events[0],function(e){
1753				_onKeyboard(e);
1754			});
1755			function _onKeyboard(e){
1756				switch(e.type){
1757					case "blur":
1758						if(d.tweenRunning && seq.dir){_seq("off",null);}
1759						break;
1760					case "keydown": case "keyup":
1761						var code=e.keyCode ? e.keyCode : e.which,action="on";
1762						if((o.axis!=="x" && (code===38 || code===40)) || (o.axis!=="y" && (code===37 || code===39))){
1763							/* up (38), down (40), left (37), right (39) arrows */
1764							if(((code===38 || code===40) && !d.overflowed[0]) || ((code===37 || code===39) && !d.overflowed[1])){return;}
1765							if(e.type==="keyup"){action="off";}
1766							if(!$(document.activeElement).is(editables)){
1767								e.preventDefault();
1768								e.stopImmediatePropagation();
1769								_seq(action,code);
1770							}
1771						}else if(code===33 || code===34){
1772							/* PgUp (33), PgDn (34) */
1773							if(d.overflowed[0] || d.overflowed[1]){
1774								e.preventDefault();
1775								e.stopImmediatePropagation();
1776							}
1777							if(e.type==="keyup"){
1778								_stop($this);
1779								var keyboardDir=code===34 ? -1 : 1;
1780								if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){
1781									var dir="x",to=Math.abs(mCSB_container[0].offsetLeft)-(keyboardDir*(wrapper.width()*0.9));
1782								}else{
1783									var dir="y",to=Math.abs(mCSB_container[0].offsetTop)-(keyboardDir*(wrapper.height()*0.9));
1784								}
1785								_scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"});
1786							}
1787						}else if(code===35 || code===36){
1788							/* End (35), Home (36) */
1789							if(!$(document.activeElement).is(editables)){
1790								if(d.overflowed[0] || d.overflowed[1]){
1791									e.preventDefault();
1792									e.stopImmediatePropagation();
1793								}
1794								if(e.type==="keyup"){
1795									if(o.axis==="x" || (o.axis==="yx" && d.overflowed[1] && !d.overflowed[0])){
1796										var dir="x",to=code===35 ? Math.abs(wrapper.width()-mCSB_container.outerWidth(false)) : 0;
1797									}else{
1798										var dir="y",to=code===35 ? Math.abs(wrapper.height()-mCSB_container.outerHeight(false)) : 0;
1799									}
1800									_scrollTo($this,to.toString(),{dir:dir,scrollEasing:"mcsEaseInOut"});
1801								}
1802							}
1803						}
1804						break;
1805				}
1806				function _seq(a,c){
1807					seq.type=o.keyboard.scrollType;
1808					seq.scrollAmount=o.keyboard.scrollAmount;
1809					if(seq.type==="stepped" && d.tweenRunning){return;}
1810					_sequentialScroll($this,a,c);
1811				}
1812			}
1813		},
1814		/* -------------------- */
1815		
1816		
1817		/* scrolls content sequentially (used when scrolling via buttons, keyboard arrows etc.) */
1818		_sequentialScroll=function(el,action,trigger,e,s){
1819			var d=el.data(pluginPfx),o=d.opt,seq=d.sequential,
1820				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1821				once=seq.type==="stepped" ? true : false,
1822				steplessSpeed=o.scrollInertia < 26 ? 26 : o.scrollInertia, /* 26/1.5=17 */
1823				steppedSpeed=o.scrollInertia < 1 ? 17 : o.scrollInertia;
1824			switch(action){
1825				case "on":
1826					seq.dir=[
1827						(trigger===classes[16] || trigger===classes[15] || trigger===39 || trigger===37 ? "x" : "y"),
1828						(trigger===classes[13] || trigger===classes[15] || trigger===38 || trigger===37 ? -1 : 1)
1829					];
1830					_stop(el);
1831					if(_isNumeric(trigger) && seq.type==="stepped"){return;}
1832					_on(once);
1833					break;
1834				case "off":
1835					_off();
1836					if(once || (d.tweenRunning && seq.dir)){
1837						_on(true);
1838					}
1839					break;
1840			}
1841			
1842			/* starts sequence */
1843			function _on(once){
1844				if(o.snapAmount){seq.scrollAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : seq.dir[0]==="x" ? o.snapAmount[1] : o.snapAmount[0];} /* scrolling snapping */
1845				var c=seq.type!=="stepped", /* continuous scrolling */
1846					t=s ? s : !once ? 1000/60 : c ? steplessSpeed/1.5 : steppedSpeed, /* timer */
1847					m=!once ? 2.5 : c ? 7.5 : 40, /* multiplier */
1848					contentPos=[Math.abs(mCSB_container[0].offsetTop),Math.abs(mCSB_container[0].offsetLeft)],
1849					ratio=[d.scrollRatio.y>10 ? 10 : d.scrollRatio.y,d.scrollRatio.x>10 ? 10 : d.scrollRatio.x],
1850					amount=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*(ratio[1]*m)) : contentPos[0]+(seq.dir[1]*(ratio[0]*m)),
1851					px=seq.dir[0]==="x" ? contentPos[1]+(seq.dir[1]*parseInt(seq.scrollAmount)) : contentPos[0]+(seq.dir[1]*parseInt(seq.scrollAmount)),
1852					to=seq.scrollAmount!=="auto" ? px : amount,
1853					easing=e ? e : !once ? "mcsLinear" : c ? "mcsLinearOut" : "mcsEaseInOut",
1854					onComplete=!once ? false : true;
1855				if(once && t<17){
1856					to=seq.dir[0]==="x" ? contentPos[1] : contentPos[0];
1857				}
1858
1859				_scrollTo(el,to.toString(),{dir:seq.dir[0],scrollEasing:easing,dur:t,onComplete:onComplete});
1860				if(once){
1861					seq.dir=false;
1862					return;
1863				}
1864				clearTimeout(seq.step);
1865				seq.step=setTimeout(function(){
1866					_on();
1867				},t);
1868			}
1869			/* stops sequence */
1870			function _off(){
1871				clearTimeout(seq.step);
1872				_delete(seq,"step");
1873				_stop(el);
1874			}
1875		},
1876		/* -------------------- */
1877		
1878		
1879		/* returns a yx array from value */
1880		_arr=function(val){
1881			var o=$(this).data(pluginPfx).opt,vals=[];
1882			if(typeof val==="function"){val=val();} /* check if the value is a single anonymous function */
1883			/* check if value is object or array, its length and create an array with yx values */
1884			if(!(val instanceof Array)){ /* object value (e.g. {y:"100",x:"100"}, 100 etc.) */
1885				vals[0]=val.y ? val.y : val.x || o.axis==="x" ? null : val;
1886				vals[1]=val.x ? val.x : val.y || o.axis==="y" ? null : val;
1887			}else{ /* array value (e.g. [100,100]) */
1888				vals=val.length>1 ? [val[0],val[1]] : o.axis==="x" ? [null,val[0]] : [val[0],null];
1889			}
1890			/* check if array values are anonymous functions */
1891			if(typeof vals[0]==="function"){vals[0]=vals[0]();}
1892			if(typeof vals[1]==="function"){vals[1]=vals[1]();}
1893			return vals;
1894		},
1895		/* -------------------- */
1896		
1897		
1898		/* translates values (e.g. "top", 100, "100px", "#id") to actual scroll-to positions */
1899		_to=function(val,dir){
1900			if(val==null || typeof val=="undefined"){return;}
1901			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1902				mCSB_container=$("#mCSB_"+d.idx+"_container"),
1903				wrapper=mCSB_container.parent(),
1904				t=typeof val;
1905			if(!dir){dir=o.axis==="x" ? "x" : "y";}
1906			var contentLength=dir==="x" ? mCSB_container.outerWidth(false)-wrapper.width() : mCSB_container.outerHeight(false)-wrapper.height(),
1907				contentPos=dir==="x" ? mCSB_container[0].offsetLeft : mCSB_container[0].offsetTop,
1908				cssProp=dir==="x" ? "left" : "top";
1909			switch(t){
1910				case "function": /* this currently is not used. Consider removing it */
1911					return val();
1912					break;
1913				case "object": /* js/jquery object */
1914					var obj=val.jquery ? val : $(val);
1915					if(!obj.length){return;}
1916					return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0];
1917					break;
1918				case "string": case "number":
1919					if(_isNumeric(val)){ /* numeric value */
1920						return Math.abs(val);
1921					}else if(val.indexOf("%")!==-1){ /* percentage value */
1922						return Math.abs(contentLength*parseInt(val)/100);
1923					}else if(val.indexOf("-=")!==-1){ /* decrease value */
1924						return Math.abs(contentPos-parseInt(val.split("-=")[1]));
1925					}else if(val.indexOf("+=")!==-1){ /* inrease value */
1926						var p=(contentPos+parseInt(val.split("+=")[1]));
1927						return p>=0 ? 0 : Math.abs(p);
1928					}else if(val.indexOf("px")!==-1 && _isNumeric(val.split("px")[0])){ /* pixels string value (e.g. "100px") */
1929						return Math.abs(val.split("px")[0]);
1930					}else{
1931						if(val==="top" || val==="left"){ /* special strings */
1932							return 0;
1933						}else if(val==="bottom"){
1934							return Math.abs(wrapper.height()-mCSB_container.outerHeight(false));
1935						}else if(val==="right"){
1936							return Math.abs(wrapper.width()-mCSB_container.outerWidth(false));
1937						}else if(val==="first" || val==="last"){
1938							var obj=mCSB_container.find(":"+val);
1939							return dir==="x" ? _childPos(obj)[1] : _childPos(obj)[0];
1940						}else{
1941							if($(val).length){ /* jquery selector */
1942								return dir==="x" ? _childPos($(val))[1] : _childPos($(val))[0];
1943							}else{ /* other values (e.g. "100em") */
1944								mCSB_container.css(cssProp,val);
1945								methods.update.call(null,$this[0]);
1946								return;
1947							}
1948						}
1949					}
1950					break;
1951			}
1952		},
1953		/* -------------------- */
1954		
1955		
1956		/* calls the update method automatically */
1957		_autoUpdate=function(rem){
1958			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1959				mCSB_container=$("#mCSB_"+d.idx+"_container");
1960			if(rem){
1961				/* 
1962				removes autoUpdate timer 
1963				usage: _autoUpdate.call(this,"remove");
1964				*/
1965				clearTimeout(mCSB_container[0].autoUpdate);
1966				_delete(mCSB_container[0],"autoUpdate");
1967				return;
1968			}
1969			upd();
1970			function upd(){
1971				clearTimeout(mCSB_container[0].autoUpdate);
1972				if($this.parents("html").length===0){
1973					/* check element in dom tree */
1974					$this=null;
1975					return;
1976				}
1977				mCSB_container[0].autoUpdate=setTimeout(function(){
1978					/* update on specific selector(s) length and size change */
1979					if(o.advanced.updateOnSelectorChange){
1980						d.poll.change.n=sizesSum();
1981						if(d.poll.change.n!==d.poll.change.o){
1982							d.poll.change.o=d.poll.change.n;
1983							doUpd(3);
1984							return;
1985						}
1986					}
1987					/* update on main element and scrollbar size changes */
1988					if(o.advanced.updateOnContentResize){
1989						d.poll.size.n=$this[0].scrollHeight+$this[0].scrollWidth+mCSB_container[0].offsetHeight+$this[0].offsetHeight+$this[0].offsetWidth;
1990						if(d.poll.size.n!==d.poll.size.o){
1991							d.poll.size.o=d.poll.size.n;
1992							doUpd(1);
1993							return;
1994						}
1995					}
1996					/* update on image load */
1997					if(o.advanced.updateOnImageLoad){
1998						if(!(o.advanced.updateOnImageLoad==="auto" && o.axis==="y")){ //by default, it doesn't run on vertical content
1999							d.poll.img.n=mCSB_container.find("img").length;
2000							if(d.poll.img.n!==d.poll.img.o){
2001								d.poll.img.o=d.poll.img.n;
2002								mCSB_container.find("img").each(function(){
2003									imgLoader(this);
2004								});
2005								return;
2006							}
2007						}
2008					}
2009					if(o.advanced.updateOnSelectorChange || o.advanced.updateOnContentResize || o.advanced.updateOnImageLoad){upd();}
2010				},o.advanced.autoUpdateTimeout);
2011			}
2012			/* a tiny image loader */
2013			function imgLoader(el){
2014				if($(el).hasClass(classes[2])){doUpd(); return;}
2015				var img=new Image();
2016				function createDelegate(contextObject,delegateMethod){
2017					return function(){return delegateMethod.apply(contextObject,arguments);}
2018				}
2019				function imgOnLoad(){
2020					this.onload=null;
2021					$(el).addClass(classes[2]);
2022					doUpd(2);
2023				}
2024				img.onload=createDelegate(img,imgOnLoad);
2025				img.src=el.src;
2026			}
2027			/* returns the total height and width sum of all elements matching the selector */
2028			function sizesSum(){
2029				if(o.advanced.updateOnSelectorChange===true){o.advanced.updateOnSelectorChange="*";}
2030				var total=0,sel=mCSB_container.find(o.advanced.updateOnSelectorChange);
2031				if(o.advanced.updateOnSelectorChange && sel.length>0){sel.each(function(){total+=this.offsetHeight+this.offsetWidth;});}
2032				return total;
2033			}
2034			/* calls the update method */
2035			function doUpd(cb){
2036				clearTimeout(mCSB_container[0].autoUpdate);
2037				methods.update.call(null,$this[0],cb);
2038			}
2039		},
2040		/* -------------------- */
2041		
2042		
2043		/* snaps scrolling to a multiple of a pixels number */
2044		_snapAmount=function(to,amount,offset){
2045			return (Math.round(to/amount)*amount-offset); 
2046		},
2047		/* -------------------- */
2048		
2049		
2050		/* stops content and scrollbar animations */
2051		_stop=function(el){
2052			var d=el.data(pluginPfx),
2053				sel=$("#mCSB_"+d.idx+"_container,#mCSB_"+d.idx+"_container_wrapper,#mCSB_"+d.idx+"_dragger_vertical,#mCSB_"+d.idx+"_dragger_horizontal");
2054			sel.each(function(){
2055				_stopTween.call(this);
2056			});
2057		},
2058		/* -------------------- */
2059		
2060		
2061		/* 
2062		ANIMATES CONTENT 
2063		This is where the actual scrolling happens
2064		*/
2065		_scrollTo=function(el,to,options){
2066			var d=el.data(pluginPfx),o=d.opt,
2067				defaults={
2068					trigger:"internal",
2069					dir:"y",
2070					scrollEasing:"mcsEaseOut",
2071					drag:false,
2072					dur:o.scrollInertia,
2073					overwrite:"all",
2074					callbacks:true,
2075					onStart:true,
2076					onUpdate:true,
2077					onComplete:true
2078				},
2079				options=$.extend(defaults,options),
2080				dur=[options.dur,(options.drag ? 0 : options.dur)],
2081				mCustomScrollBox=$("#mCSB_"+d.idx),
2082				mCSB_container=$("#mCSB_"+d.idx+"_container"),
2083				wrapper=mCSB_container.parent(),
2084				totalScrollOffsets=o.callbacks.onTotalScrollOffset ? _arr.call(el,o.callbacks.onTotalScrollOffset) : [0,0],
2085				totalScrollBackOffsets=o.callbacks.onTotalScrollBackOffset ? _arr.call(el,o.callbacks.onTotalScrollBackOffset) : [0,0];
2086			d.trigger=options.trigger;
2087			if(wrapper.scrollTop()!==0 || wrapper.scrollLeft()!==0){ /* always reset scrollTop/Left */
2088				$(".mCSB_"+d.idx+"_scrollbar").css("visibility","visible");
2089				wrapper.scrollTop(0).scrollLeft(0);
2090			}
2091			if(to==="_resetY" && !d.contentReset.y){
2092				/* callbacks: onOverflowYNone */
2093				if(_cb("onOverflowYNone")){o.callbacks.onOverflowYNone.call(el[0]);}
2094				d.contentReset.y=1;
2095			}
2096			if(to==="_resetX" && !d.contentReset.x){
2097				/* callbacks: onOverflowXNone */
2098				if(_cb("onOverflowXNone")){o.callbacks.onOverflowXNone.call(el[0]);}
2099				d.contentReset.x=1;
2100			}
2101			if(to==="_resetY" || to==="_resetX"){return;}
2102			if((d.contentReset.y || !el[0].mcs) && d.overflowed[0]){
2103				/* callbacks: onOverflowY */
2104				if(_cb("onOverflowY")){o.callbacks.onOverflowY.call(el[0]);}
2105				d.contentReset.x=null;
2106			}
2107			if((d.contentReset.x || !el[0].mcs) && d.overflowed[1]){
2108				/* callbacks: onOverflowX */
2109				if(_cb("onOverflowX")){o.callbacks.onOverflowX.call(el[0]);}
2110				d.contentReset.x=null;
2111			}
2112			if(o.snapAmount){ /* scrolling snapping */
2113				var snapAmount=!(o.snapAmount instanceof Array) ? o.snapAmount : options.dir==="x" ? o.snapAmount[1] : o.snapAmount[0];
2114				to=_snapAmount(to,snapAmount,o.snapOffset);
2115			}
2116			switch(options.dir){
2117				case "x":
2118					var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_horizontal"),
2119						property="left",
2120						contentPos=mCSB_container[0].offsetLeft,
2121						limit=[
2122							mCustomScrollBox.width()-mCSB_container.outerWidth(false),
2123							mCSB_dragger.parent().width()-mCSB_dragger.width()
2124						],
2125						scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.x)],
2126						tso=totalScrollOffsets[1],
2127						tsbo=totalScrollBackOffsets[1],
2128						totalScrollOffset=tso>0 ? tso/d.scrollRatio.x : 0,
2129						totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.x : 0;
2130					break;
2131				case "y":
2132					var mCSB_dragger=$("#mCSB_"+d.idx+"_dragger_vertical"),
2133						property="top",
2134						contentPos=mCSB_container[0].offsetTop,
2135						limit=[
2136							mCustomScrollBox.height()-mCSB_container.outerHeight(false),
2137							mCSB_dragger.parent().height()-mCSB_dragger.height()
2138						],
2139						scrollTo=[to,to===0 ? 0 : (to/d.scrollRatio.y)],
2140						tso=totalScrollOffsets[0],
2141						tsbo=totalScrollBackOffsets[0],
2142						totalScrollOffset=tso>0 ? tso/d.scrollRatio.y : 0,
2143						totalScrollBackOffset=tsbo>0 ? tsbo/d.scrollRatio.y : 0;
2144					break;
2145			}
2146			if(scrollTo[1]<0 || (scrollTo[0]===0 && scrollTo[1]===0)){
2147				scrollTo=[0,0];
2148			}else if(scrollTo[1]>=limit[1]){
2149				scrollTo=[limit[0],limit[1]];
2150			}else{
2151				scrollTo[0]=-scrollTo[0];
2152			}
2153			if(!el[0].mcs){
2154				_mcs();  /* init mcs object (once) to make it available before callbacks */
2155				if(_cb("onInit")){o.callbacks.onInit.call(el[0]);} /* callbacks: onInit */
2156			}
2157			clearTimeout(mCSB_container[0].onCompleteTimeout);
2158
2159			_tweenTo(mCSB_dragger[0],property,Math.round(scrollTo[1]),dur[1],options.scrollEasing);
2160			if(!d.tweenRunning && ((contentPos===0 && scrollTo[0]>=0) || (contentPos===limit[0] && scrollTo[0]<=limit[0]))){return;}
2161			_tweenTo(mCSB_container[0],property,Math.round(scrollTo[0]),dur[0],options.scrollEasing,options.overwrite,{
2162				onStart:function(){
2163					if(options.callbacks && options.onStart && !d.tweenRunning){
2164						/* callbacks: onScrollStart */
2165						if(_cb("onScrollStart")){_mcs(); o.callbacks.onScrollStart.call(el[0]);}
2166						d.tweenRunning=true;
2167						_onDragClasses(mCSB_dragger);
2168						d.cbOffsets=_cbOffsets();
2169					}
2170				},onUpdate:function(){
2171					if(options.callbacks && options.onUpdate){
2172						/* callbacks: whileScrolling */
2173						if(_cb("whileScrolling")){_mcs(); o.callbacks.whileScrolling.call(el[0]);}
2174					}
2175				},onComplete:function(){
2176					if(options.callbacks && options.onComplete){
2177						if(o.axis==="yx"){clearTimeout(mCSB_container[0].onCompleteTimeout);}
2178						var t=mCSB_container[0].idleTimer || 0;
2179						mCSB_container[0].onCompleteTimeout=setTimeout(function(){
2180							/* callbacks: onScroll, onTotalScroll, onTotalScrollBack */
2181							if(_cb("onScroll")){_mcs(); o.callbacks.onScroll.call(el[0]);}
2182							if(_cb("onTotalScroll") && scrollTo[1]>=limit[1]-totalScrollOffset && d.cbOffsets[0]){_mcs(); o.callbacks.onTotalScroll.call(el[0]);}
2183							if(_cb("onTotalScrollBack") && scrollTo[1]<=totalScrollBackOffset && d.cbOffsets[1]){_mcs(); o.callbacks.onTotalScrollBack.call(el[0]);}
2184							d.tweenRunning=false;
2185							mCSB_container[0].idleTimer=0;
2186							_onDragClasses(mCSB_dragger,"hide");
2187						},t);
2188					}
2189				}
2190			});
2191			/* checks if callback function exists */
2192			function _cb(cb){
2193				return d && o.callbacks[cb] && typeof o.callbacks[cb]==="function";
2194			}
2195			/* checks whether callback offsets always trigger */
2196			function _cbOffsets(){
2197				return [o.callbacks.alwaysTriggerOffsets || contentPos>=limit[0]+tso,o.callbacks.alwaysTriggerOffsets || contentPos<=-tsbo];
2198			}
2199			/* 
2200			populates object with useful values for the user 
2201			values: 
2202				content: this.mcs.content
2203				content top position: this.mcs.top 
2204				content left position: this.mcs.left 
2205				dragger top position: this.mcs.draggerTop 
2206				dragger left position: this.mcs.draggerLeft 
2207				scrolling y percentage: this.mcs.topPct 
2208				scrolling x percentage: this.mcs.leftPct 
2209				scrolling direction: this.mcs.direction
2210			*/
2211			function _mcs(){
2212				var cp=[mCSB_container[0].offsetTop,mCSB_container[0].offsetLeft], /* content position */
2213					dp=[mCSB_dragger[0].offsetTop,mCSB_dragger[0].offsetLeft], /* dragger position */
2214					cl=[mCSB_container.outerHeight(false),mCSB_container.outerWidth(false)], /* content length */
2215					pl=[mCustomScrollBox.height(),mCustomScrollBox.width()]; /* content parent length */
2216				el[0].mcs={
2217					content:mCSB_container, /* original content wrapper as jquery object */
2218					top:cp[0],left:cp[1],draggerTop:dp[0],draggerLeft:dp[1],
2219					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])),
2220					direction:options.dir
2221				};
2222				/* 
2223				this refers to the original element containing the scrollbar(s)
2224				usage: this.mcs.top, this.mcs.leftPct etc. 
2225				*/
2226			}
2227		},
2228		/* -------------------- */
2229		
2230		
2231		/* 
2232		CUSTOM JAVASCRIPT ANIMATION TWEEN 
2233		Lighter and faster than jquery animate() and css transitions 
2234		Animates top/left properties and includes easings 
2235		*/
2236		_tweenTo=function(el,prop,to,duration,easing,overwrite,callbacks){
2237
2238			if(el && 
vendor: 8,106 bytes, lines 2238-2489
2238!el._mTween){el._mTween={top:{},left:{}};}
2239			var callbacks=callbacks || {},
2240				onStart=callbacks.onStart || function(){},onUpdate=callbacks.onUpdate || function(){},onComplete=callbacks.onComplete || function(){},
2241				startTime=_getTime(),_delay,progress=0,from=el.offsetTop,elStyle=el.style,_request,tobj=el._mTween[prop];
2242			if(prop==="left"){from=el.offsetLeft;}
2243			var diff=to-from;
2244			tobj.stop=0;
2245			if(overwrite!=="none"){_cancelTween();}
2246			_startTween();
2247			function _step(){
2248				if(tobj.stop){return;}
2249				if(!progress){onStart.call();}
2250				progress=_getTime()-startTime;
2251				_tween();
2252				if(progress>=tobj.time){
2253					tobj.time=(progress>tobj.time) ? progress+_delay-(progress-tobj.time) : progress+_delay-1;
2254					if(tobj.time<progress+1){tobj.time=progress+1;}
2255				}
2256				if(tobj.time<duration){tobj.id=_request(_step);}else{onComplete.call();}
2257			}
2258			function _tween(){
2259				if(duration>0){
2260					tobj.currVal=_ease(tobj.time,from,diff,duration,easing);
2261					elStyle[prop]=Math.round(tobj.currVal)+"px";
2262				}else{
2263					elStyle[prop]=to+"px";
2264				}
2265				onUpdate.call();
2266			}
2267			function _startTween(){
2268				_delay=1000/60;
2269				tobj.time=progress+_delay;
2270				_request=(!window.requestAnimationFrame) ? function(f){_tween(); return setTimeout(f,0.01);} : window.requestAnimationFrame;
2271				tobj.id=_request(_step);
2272			}
2273			function _cancelTween(){
2274				if(tobj.id==null){return;}
2275				if(!window.requestAnimationFrame){clearTimeout(tobj.id);
2276				}else{window.cancelAnimationFrame(tobj.id);}
2277				tobj.id=null;
2278			}
2279			function _ease(t,b,c,d,type){
2280				switch(type){
2281					case "linear": case "mcsLinear":
2282						return c*t/d + b;
2283						break;
2284					case "mcsLinearOut":
2285						t/=d; t--; return c * Math.sqrt(1 - t*t) + b;
2286						break;
2287					case "easeInOutSmooth":
2288						t/=d/2;
2289						if(t<1) return c/2*t*t + b;
2290						t--;
2291						return -c/2 * (t*(t-2) - 1) + b;
2292						break;
2293					case "easeInOutStrong":
2294						t/=d/2;
2295						if(t<1) return c/2 * Math.pow( 2, 10 * (t - 1) ) + b;
2296						t--;
2297						return c/2 * ( -Math.pow( 2, -10 * t) + 2 ) + b;
2298						break;
2299					case "easeInOut": case "mcsEaseInOut":
2300						t/=d/2;
2301						if(t<1) return c/2*t*t*t + b;
2302						t-=2;
2303						return c/2*(t*t*t + 2) + b;
2304						break;
2305					case "easeOutSmooth":
2306						t/=d; t--;
2307						return -c * (t*t*t*t - 1) + b;
2308						break;
2309					case "easeOutStrong":
2310						return c * ( -Math.pow( 2, -10 * t/d ) + 1 ) + b;
2311						break;
2312					case "easeOut": case "mcsEaseOut": default:
2313						var ts=(t/=d)*t,tc=ts*t;
2314						return b+c*(0.499999999999997*tc*ts + -2.5*ts*ts + 5.5*tc + -6.5*ts + 4*t);
2315				}
2316			}
2317		},
2318		/* -------------------- */
2319		
2320		
2321		/* returns current time */
2322		_getTime=function(){
2323			if(window.performance && window.performance.now){
2324				return window.performance.now();
2325			}else{
2326				if(window.performance && window.performance.webkitNow){
2327					return window.performance.webkitNow();
2328				}else{
2329					if(Date.now){return Date.now();}else{return new Date().getTime();}
2330				}
2331			}
2332		},
2333		/* -------------------- */
2334		
2335		
2336		/* stops a tween */
2337		_stopTween=function(){
2338			var el=this;
2339			if(!el._mTween){el._mTween={top:{},left:{}};}
2340			var props=["top","left"];
2341			for(var i=0; i<props.length; i++){
2342				var prop=props[i];
2343				if(el._mTween[prop].id){
2344					if(!window.requestAnimationFrame){clearTimeout(el._mTween[prop].id);
2345					}else{window.cancelAnimationFrame(el._mTween[prop].id);}
2346					el._mTween[prop].id=null;
2347					el._mTween[prop].stop=1;
2348				}
2349			}
2350		},
2351		/* -------------------- */
2352		
2353		
2354		/* deletes a property (avoiding the exception thrown by IE) */
2355		_delete=function(c,m){
2356			try{delete c[m];}catch(e){c[m]=null;}
2357		},
2358		/* -------------------- */
2359		
2360		
2361		/* detects left mouse button */
2362		_mouseBtnLeft=function(e){
2363			return !(e.which && e.which!==1);
2364		},
2365		/* -------------------- */
2366		
2367		
2368		/* detects if pointer type event is touch */
2369		_pointerTouch=function(e){
2370			var t=e.originalEvent.pointerType;
2371			return !(t && t!=="touch" && t!==2);
2372		},
2373		/* -------------------- */
2374		
2375		
2376		/* checks if value is numeric */
2377		_isNumeric=function(val){
2378			return !isNaN(parseFloat(val)) && isFinite(val);
2379		},
2380		/* -------------------- */
2381		
2382		
2383		/* returns element position according to content */
2384		_childPos=function(el){
2385			var p=el.parents(".mCSB_container");
2386			return [el.offset().top-p.offset().top,el.offset().left-p.offset().left];
2387		},
2388		/* -------------------- */
2389		
2390		
2391		/* checks if browser tab is hidden/inactive via Page Visibility API */
2392		_isTabHidden=function(){
2393			var prop=_getHiddenProp();
2394			if(!prop) return false;
2395			return document[prop];
2396			function _getHiddenProp(){
2397				var pfx=["webkit","moz","ms","o"];
2398				if("hidden" in document) return "hidden"; //natively supported
2399				for(var i=0; i<pfx.length; i++){ //prefixed
2400				    if((pfx[i]+"Hidden") in document) 
2401				        return pfx[i]+"Hidden";
2402				}
2403				return null; //not supported
2404			}
2405		};
2406		/* -------------------- */
2407		
2408	
2409	
2410	
2411	
2412	/* 
2413	----------------------------------------
2414	PLUGIN SETUP 
2415	----------------------------------------
2416	*/
2417	
2418	/* plugin constructor functions */
2419	$.fn[pluginNS]=function(method){ /* usage: $(selector).mCustomScrollbar(); */
2420		if(methods[method]){
2421			return methods[method].apply(this,Array.prototype.slice.call(arguments,1));
2422		}else if(typeof method==="object" || !method){
2423			return methods.init.apply(this,arguments);
2424		}else{
2425			$.error("Method "+method+" does not exist");
2426		}
2427	};
2428	$[pluginNS]=function(method){ /* usage: $.mCustomScrollbar(); */
2429		if(methods[method]){
2430			return methods[method].apply(this,Array.prototype.slice.call(arguments,1));
2431		}else if(typeof method==="object" || !method){
2432			return methods.init.apply(this,arguments);
2433		}else{
2434			$.error("Method "+method+" does not exist");
2435		}
2436	};
2437	
2438	/* 
2439	allow setting plugin default options. 
2440	usage: $.mCustomScrollbar.defaults.scrollInertia=500; 
2441	to apply any changed default options on default selectors (below), use inside document ready fn 
2442	e.g.: $(document).ready(function(){ $.mCustomScrollbar.defaults.scrollInertia=500; });
2443	*/
2444	$[pluginNS].defaults=defaults;
2445	
2446	/* 
2447	add window object (window.mCustomScrollbar) 
2448	usage: if(window.mCustomScrollbar){console.log("custom scrollbar plugin loaded");}
2449	*/
2450	window[pluginNS]=true;
2451	
2452	$(window).bind("load",function(){
2453		
2454		$(defaultSelector)[pluginNS](); /* add scrollbars automatically on default selector */
2455		
2456		/* extend jQuery expressions */
2457		$.extend($.expr[":"],{
2458			/* checks if element is within scrollable viewport */
2459			mcsInView:$.expr[":"].mcsInView || function(el){
2460				var $el=$(el),content=$el.parents(".mCSB_container"),wrapper,cPos;
2461				if(!content.length){return;}
2462				wrapper=content.parent();
2463				cPos=[content[0].offsetTop,content[0].offsetLeft];
2464				return 	cPos[0]+_childPos($el)[0]>=0 && cPos[0]+_childPos($el)[0]<wrapper.height()-$el.outerHeight(false) && 
2465						cPos[1]+_childPos($el)[1]>=0 && cPos[1]+_childPos($el)[1]<wrapper.width()-$el.outerWidth(false);
2466			},
2467			/* checks if element or part of element is in view of scrollable viewport */
2468			mcsInSight:$.expr[":"].mcsInSight || function(el,i,m){
2469				var $el=$(el),elD,content=$el.parents(".mCSB_container"),wrapperView,pos,wrapperViewPct,
2470					pctVals=m[3]==="exact" ? [[1,0],[1,0]] : [[0.9,0.1],[0.6,0.4]];
2471				if(!content.length){return;}
2472				elD=[$el.outerHeight(false),$el.outerWidth(false)];
2473				pos=[content[0].offsetTop+_childPos($el)[0],content[0].offsetLeft+_childPos($el)[1]];
2474				wrapperView=[content.parent()[0].offsetHeight,content.parent()[0].offsetWidth];
2475				wrapperViewPct=[elD[0]<wrapperView[0] ? pctVals[0] : pctVals[1],elD[1]<wrapperView[1] ? pctVals[0] : pctVals[1]];
2476				return 	pos[0]-(wrapperView[0]*wrapperViewPct[0][0])<0 && pos[0]+elD[0]-(wrapperView[0]*wrapperViewPct[0][1])>=0 && 
2477						pos[1]-(wrapperView[1]*wrapperViewPct[1][0])<0 && pos[1]+elD[1]-(wrapperView[1]*wrapperViewPct[1][1])>=0;
2478			},
2479			/* checks if element is overflowed having visible scrollbar(s) */
2480			mcsOverflow:$.expr[":"].mcsOverflow || function(el){
2481				var d=$(el).data(pluginPfx);
2482				if(!d){return;}
2483				return d.overflowed[0] || d.overflowed[1];
2484			}
2485		});
2486	
2487	});
2488
2489}))}));

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.