PageSourceSearch

https://yueyang.gov.cn/yys/js/qrqw_01.js

js yueyang.gov.cn collected 2026-09-24 19:35:06 UTC 88,792 bytes, 2,322 lines download raw bytes

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

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.