PageSourceSearch

https://191art.com.tw/scripts/plugins/mCustomScrollbar/jquery.mCustomScrollbar.concat.min.js

js 191art.com.tw collected 2026-10-02 06:32:29 UTC 91,139 bytes, 2,424 lines download raw bytes

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

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.