PageSourceSearch

https://www.diariodeavila.es/galeria/jquery.mThumbnailScroller.js

js diariodeavila.es collected 2026-10-02 05:47:25 UTC 67,392 bytes, 1,689 lines download raw bytes

1/*
2== malihu jquery thumbnail scroller plugin == 
3Version: 2.0.3 
4Plugin URI: http://manos.malihu.gr/jquery-thumbnail-scroller 
5Author: malihu
6Author URI: http://manos.malihu.gr
7License: MIT License (MIT)
8*/
9
10/*
11Copyright 2010 Manos Malihutsakis (email: [email protected])
12
13Permission is hereby granted, free of charge, to any person obtaining a copy
14of this software and associated documentation files (the "Software"), to deal
15in the Software without restriction, including without limitation the rights
16to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17copies of the Software, and to permit persons to whom the Software is
18furnished to do so, subject to the following conditions:
19
20The above copyright notice and this permission notice shall be included in
21all copies or substantial portions of the Software.
22
23THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29THE SOFTWARE.
30*/
31
32/*
33The code below is fairly long, fully commented and should be normally used in development. 
34For production, use the minified jquery.mThumbnailScroller.min.js script. 
35*/
36
37;(function($,window,document){
38	
39	/* 
40	----------------------------------------
41	PLUGIN NAMESPACE, PREFIX, DEFAULT SELECTOR(S) 
42	----------------------------------------
43	*/
44	
45	var pluginNS="mThumbnailScroller",
46		pluginPfx="mTS",
47		defaultSelector=".mThumbnailScroller",
48	
49	
50		
51	
52	
53	/* 
54	----------------------------------------
55	DEFAULT OPTIONS 
56	----------------------------------------
57	*/
58	
59		defaults={
60			/*
61			set element/content width/height programmatically 
62			values: boolean, pixels, percentage 
63				option						default
64				-------------------------------------
65				setWidth					false
66				setHeight					false
67			*/
68			/*
69			set the initial css top property of content  
70			values: string (e.g. "-100px", "10%" etc.)
71			*/
72			setTop:0,
73			/*
74			set the initial css left property of content  
75			values: string (e.g. "-100px", "10%" etc.)
76			*/
77			setLeft:0,
78			/* 
79			set the scrolling type 
80			values (string): "hover-0"/"hover-100" (number indicating percentage), "hover-precise", "click-0"/"click-100" (number indicating percentage), "click-thumb"
81			*/
82			type:"hover-50",
83			/* 
84			scroller axis (vertical and/or horizontal) 
85			values (string): "y", "x", "yx"
86			*/
87			axis:"x",
88			/*
89			scrolling speed
90			values: integer (higher=faster)
91			*/
92			speed:15,
93			/*
94			enable content touch-swipe scrolling 
95			values: boolean, integer, string (number)
96			integer values define the axis-specific minimum amount required for scrolling momentum
97			*/
98			contentTouchScroll:25,
99			/*
100			markup option parameters
101			*/
102			markup:{
103				/*
104				thumbnailsContainer sets the element containing your thumbnails. By default this is an unordered list ("ul") 
105				thumbnailContainer sets the element containing each thumbnail. By default this is a list-item ("li") 
106				thumbnailElement sets the actual thumbnail element. By default this is an image tag ("img") 
107				values: boolean, string
108					option						default
109					-------------------------------------
110					thumbnailsContainer			null
111					thumbnailContainer			null
112					thumbnailElement			null
113					
114				*/
115				/*
116				set the placeholder element of the buttons 
117				values: boolean, string
118				*/
119				buttonsPlaceholder:false,
120				/*
121				set buttons HTML
122				*/
123				buttonsHTML:{
124					up:"SVG set 1",
125					down:"SVG set 1",
126					left:"SVG set 1",
127					right:"SVG set 1"
128				}
129			},
130			/*
131			advanced option parameters
132			*/
133			advanced:{
134				/*
135				auto-expand content horizontally (for "x" or "yx" axis) 
136				values: boolean
137				*/
138				autoExpandHorizontalScroll:true,
139				/*
140				auto-update scrollers on content, element or viewport resize 
141				should be true for fluid layouts/elements, adding/removing content dynamically, hiding/showing elements, content with images etc. 
142				values: boolean
143				*/
144				updateOnContentResize:true,
145				/*
146				auto-update scrollers each time each image inside the element is fully loaded 
147				values: boolean
148				*/
149				updateOnImageLoad:true
150				/*
151				auto-update scrollers based on the amount and size changes of specific selectors 
152				useful when you need to update the scroller(s) automatically, each time a type of element is added, removed or changes its size 
153				values: boolean, string (e.g. "ul li" will auto-update the scroller each time list-items inside the element are changed) 
154				a value of true (boolean) will auto-update the scroller each time any element is changed
155					option						default
156					-------------------------------------
157					updateOnSelectorChange		null
158				*/
159			},
160			/* 
161			scroller theme 
162			values: string 
163			*/
164			theme:"none",
165			/*
166			user defined callback functions
167			*/
168			callbacks:{
169				/*
170				Available callbacks: 
171					callback					default
172					-------------------------------------
173					onInit						null
174					onScrollStart				null
175					onScroll					null
176					onTotalScroll				null
177					onTotalScrollBack			null
178					whileScrolling				null
179				*/
180				onTotalScrollOffset:0,
181				onTotalScrollBackOffset:0,
182				alwaysTriggerOffsets:true
183			}
184			/*
185			add scroller(s) on all elements matching the current selector, now and in the future 
186			values: boolean, string 
187			string values: "on" (enable), "once" (disable after first invocation), "off" (disable)
188			liveSelector values: string (selector)
189				option						default
190				-------------------------------------
191				live						false
192				liveSelector				null
193			*/
194		},
195	
196	
197	
198	
199	
200	/* 
201	----------------------------------------
202	VARS, CONSTANTS 
203	----------------------------------------
204	*/
205	
206		totalInstances=0, /* plugin instances amount */
207		liveTimers={}, /* live option timers */
208		oldIE=(window.attachEvent && !window.addEventListener) ? 1 : 0, /* detect IE < 9 */
209		touchActive=false, /* global touch state (for touch and pointer events) */
210		touchi, /* touch interface */
211		/* general plugin classes */
212		classes=["mTS_disabled","mTS_destroyed","mTS_no_scroll"],
213		
214	
215	
216	
217	
218	/* 
219	----------------------------------------
220	METHODS 
221	----------------------------------------
222	*/
223	
224		methods={
225			
226			/* 
227			plugin initialization method 
228			creates the scroller(s), plugin data object and options
229			----------------------------------------
230			*/
231			
232			init:function(options){
233				
234				var options=$.extend(true,{},defaults,options),
235					selector=_selector.call(this); /* validate selector */
236				
237				/* 
238				if live option is enabled, monitor for elements matching the current selector and 
239				apply scroller(s) when found (now and in the future) 
240				*/
241				if(options.live){
242					var liveSelector=options.liveSelector || this.selector || defaultSelector, /* live selector(s) */
243						$liveSelector=$(liveSelector); /* live selector(s) as jquery object */
244					if(options.live==="off"){
245						/* 
246						disable live if requested 
247						usage: $(selector).mThumbnailScroller({live:"off"}); 
248						*/
249						removeLiveTimers(liveSelector);
250						return;
251					}
252					liveTimers[liveSelector]=setTimeout(function(){
253						/* call mThumbnailScroller fn on live selector(s) every half-second */
254						$liveSelector.mThumbnailScroller(options);
255						if(options.live==="once" && $liveSelector.length){
256							/* disable live after first invocation */
257							removeLiveTimers(liveSelector);
258						}
259					},500);
260				}else{
261					removeLiveTimers(liveSelector);
262				}
263				
264				/* options  normalization */
265				options.speed=options.speed===0 ? 100 : options.speed;
266				
267				_theme(options); /* theme-specific options */
268				
269				/* plugin constructor */
270				return $(selector).each(function(){
271					
272					var $this=$(this);
273					
274					if(!$this.data(pluginPfx)){ /* prevent multiple instantiations */
275					
276						/* store options and create objects in jquery data */
277						$this.data(pluginPfx,{
278							idx:++totalInstances, /* instance index */
279							opt:options, /* options */
280							html:null, /* element original html */
281							overflowed:null, /* overflowed axis */
282							bindEvents:false, /* object to check if events are bound */
283							tweenRunning:false, /* object to check if tween is running */
284							langDir:$this.css("direction"), /* detect/store direction (ltr or rtl) */
285							cbOffsets:null, /* object to check whether callback offsets always trigger */
286							/* 
287							object to check how scrolling events where last triggered 
288							"internal" (default - triggered by this script), "external" (triggered by other scripts, e.g. via scrollTo method) 
289							usage: object.data("mTS").trigger
290							*/
291							trigger:null
292						});
293						
294						/* HTML data attributes */
295						var o=$this.data(pluginPfx).opt,
296							htmlDataAxis=$this.data("mts-axis"),htmlDataType=$this.data("mts-type"),htmlDataTheme=$this.data("mts-theme");
297						if(htmlDataAxis){o.axis=htmlDataAxis;} /* usage example: data-mts-axis="y" */
298						if(htmlDataType){o.type=htmlDataType;} /* usage example: data-mts-type="hover-50" */
299						if(htmlDataTheme){ /* usage example: data-mts-theme="theme-name" */
300							o.theme=htmlDataTheme;
301							_theme(o); /* theme-specific options */
302						}
303						
304						_pluginMarkup.call(this); /* add plugin markup */
305						
306						methods.update.call(null,$this); /* call the update method */
307					
308					}
309					
310				});
311				
312			},
313			/* ---------------------------------------- */
314			
315			
316			
317			/* 
318			plugin update method 
319			updates content and scroller values, events and status 
320			----------------------------------------
321			usage: $(selector).mThumbnailScroller("update");
322			*/
323			
324			update:function(el){
325				
326				var selector=el || _selector.call(this); /* validate selector */
327				
328				return $(selector).each(function(){
329					
330					var $this=$(this);
331					
332					if($this.data(pluginPfx)){ /* check if plugin has initialized */
333						
334						var d=$this.data(pluginPfx),o=d.opt,
335							mTS_container=$("#mTS_"+d.idx+"_container");
336						
337						if(!mTS_container.length){return;}
338						
339						if(d.tweenRunning){_stop($this);} /* stop any running tweens while updating */
340						
341						/* if element was disabled or destroyed, remove class(es) */
342						if($this.hasClass(classes[0])){$this.removeClass(classes[0]);}
343						if($this.hasClass(classes[1])){$this.removeClass(classes[1]);}
344						
345						_maxHeight.call(this); /* detect/set css max-height value */
346						
347						_expandContentHorizontally.call(this); /* expand content horizontally */
348						
349						d.overflowed=_overflowed.call(this); /* determine if scrolling is required */
350						
351						_buttonsVisibility.call(this); /* show/hide buttons */
352						
353						_bindEvents.call(this); /* bind scroller events */
354						
355						/* reset scrolling position and/or events */
356						var to=[(mTS_container[0].offsetTop),(mTS_container[0].offsetLeft)];
357						if(o.axis!=="x"){ /* y/yx axis */
358							if(!d.overflowed[0]){ /* y scrolling is not required */
359								_resetContentPosition.call(this); /* reset content position */
360								if(o.axis==="y"){
361									_scrollTo($this,"0",{dir:"y",dur:0,overwrite:"none"});
362									_unbindEvents.call(this);
363								}else if(o.axis==="yx" && d.overflowed[1]){
364									_scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"});
365								}
366							}else{ /* y scrolling is required */
367								_scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"});
368							}
369						}
370						if(o.axis!=="y"){ /* x/yx axis */
371							if(!d.overflowed[1]){ /* x scrolling is not required */
372								_resetContentPosition.call(this); /* reset content position */
373								if(o.axis==="x"){
374									_scrollTo($this,"0",{dir:"x",dur:0,overwrite:"none"});
375									_unbindEvents.call(this);
376								}else if(o.axis==="yx" && d.overflowed[0]){
377									_scrollTo($this,to[0].toString(),{dir:"y",dur:0,overwrite:"none"});
378								}
379							}else{ /* x scrolling is required */
380								_scrollTo($this,to[1].toString(),{dir:"x",dur:0,overwrite:"none"});
381							}
382						}
383						
384						/* no scroll class */
385						if(!d.overflowed[0] && !d.overflowed[1]){
386							$this.addClass(classes[2]);
387						}else{
388							$this.removeClass(classes[2]);
389						}
390						
391						_autoUpdate.call(this); /* initialize automatic updating (for dynamic content, fluid layouts etc.) */
392						
393					}
394					
395				});
396				
397			},
398			/* ---------------------------------------- */
399			
400			
401			
402			/* 
403			plugin scrollTo method 
404			triggers a scrolling event to a specific value
405			----------------------------------------
406			usage: $(selector).mThumbnailScroller("scrollTo",value,options);
407			*/
408		
409			scrollTo:function(val,options){
410				
411				/* prevent silly things like $(selector).mThumbnailScroller("scrollTo",undefined); */
412				if(typeof val=="undefined" || val==null){return;}
413				
414				var selector=_selector.call(this); /* validate selector */
415				
416				return $(selector).each(function(){
417					
418					var $this=$(this);
419					
420					if($this.data(pluginPfx)){ /* check if plugin has initialized */
421					
422						var d=$this.data(pluginPfx),o=d.opt,
423							/* method default options */
424							methodDefaults={
425								trigger:"external", /* method is by default triggered externally (e.g. from other scripts) */
426								speed:o.speed, /* scrolling speed */
427								duration:1000, /* animation duration */
428								easing:"easeInOut", /* animation easing */
429								timeout:60, /* scroll-to delay */
430								callbacks:true, /* enable/disable callbacks */
431								onStart:true,
432								onUpdate:true,
433								onComplete:true
434							},
435							methodOptions=$.extend(true,{},methodDefaults,options),
436							to=_arr.call(this,val),dur=methodOptions.duration ? methodOptions.duration : 7000/(methodOptions.speed || 1);
437						
438						/* translate yx values to actual scroll-to positions */
439						to[0]=_to.call(this,to[0],"y");
440						to[1]=_to.call(this,to[1],"x");
441						
442						methodOptions.dur=dur>0 && dur<17 ? 17 : dur;
443						
444						setTimeout(function(){ 
445							/* do the scrolling */
446							if(to[0]!==null && typeof to[0]!=="undefined" && o.axis!=="x" && d.overflowed[0]){ /* scroll y */
447								methodOptions.dir="y";
448								methodOptions.overwrite="all";
449								_scrollTo($this,-to[0].toString(),methodOptions);
450							}
451							if(to[1]!==null && typeof to[1]!=="undefined" && o.axis!=="y" && d.overflowed[1]){ /* scroll x */
452								methodOptions.dir="x";
453								methodOptions.overwrite="none";
454								_scrollTo($this,-to[1].toString(),methodOptions);
455							}
456						},methodOptions.timeout);
457						
458					}
459					
460				});
461				
462			},
463			/* ---------------------------------------- */
464			
465			
466			
467			/*
468			plugin stop method 
469			stops scrolling animation
470			----------------------------------------
471			usage: $(selector).mThumbnailScroller("stop");
472			*/
473			stop:function(){
474				
475				var selector=_selector.call(this); /* validate selector */
476				
477				return $(selector).each(function(){
478					
479					var $this=$(this);
480					
481					if($this.data(pluginPfx)){ /* check if plugin has initialized */
482										
483						_stop($this);
484					
485					}
486					
487				});
488				
489			},
490			/* ---------------------------------------- */
491			
492			
493			
494			/*
495			plugin disable method 
496			temporarily disables the scroller 
497			----------------------------------------
498			usage: $(selector).mThumbnailScroller("disable",reset); 
499			reset (boolean): resets content position to 0 
500			*/
501			disable:function(r){
502				
503				var selector=_selector.call(this); /* validate selector */
504				
505				return $(selector).each(function(){
506					
507					var $this=$(this);
508					
509					if($this.data(pluginPfx)){ /* check if plugin has initialized */
510						
511						var d=$this.data(pluginPfx),o=d.opt;
512						
513						_autoUpdate.call(this,"remove"); /* remove automatic updating */
514						
515						_unbindEvents.call(this); /* unbind events */
516						
517						if(r){_resetContentPosition.call(this);} /* reset content position */
518						
519						_buttonsVisibility.call(this,true); /* show/hide buttons */
520						
vendor: 1,822 bytes, lines 521-569
521						$this.addClass(classes[0]); /* add disable class */
522					
523					}
524					
525				});
526				
527			},
528			/* ---------------------------------------- */
529			
530			
531			
532			/*
533			plugin destroy method 
534			completely removes the scrollber and returns the element to its original state
535			----------------------------------------
536			usage: $(selector).mThumbnailScroller("destroy"); 
537			*/
538			destroy:function(){
539				
540				var selector=_selector.call(this); /* validate selector */
541				
542				return $(selector).each(function(){
543					
544					var $this=$(this);
545					
546					if($this.data(pluginPfx)){ /* check if plugin has initialized */
547					
548						var d=$this.data(pluginPfx),o=d.opt,
549							mTS_wrapper=$("#mTS_"+d.idx),
550							mTS_container=$("#mTS_"+d.idx+"_container"),
551							mTS_buttons=$("#mTS_"+d.idx+"_buttonUp,#mTS_"+d.idx+"_buttonDown,#mTS_"+d.idx+"_buttonLeft,#mTS_"+d.idx+"_buttonRight");
552					
553						if(o.live){removeLiveTimers(selector);} /* remove live timer */
554						
555						_autoUpdate.call(this,"remove"); /* remove automatic updating */
556						
557						_unbindEvents.call(this); /* unbind events */
558						
559						_resetContentPosition.call(this); /* reset content position */
560						
561						$this.removeData(pluginPfx); /* remove plugin data object */
562						
563						_delete(this,"mts"); /* delete callbacks object */
564						
565						/* remove plugin markup */
566						mTS_buttons.remove(); /* remove buttons first (those can be either inside or outside plugin's inner wrapper) */
567						mTS_wrapper.replaceWith(d.html); /* replace plugin's inner wrapper with the original content */
568						/* remove plugin classes from the element and add destroy class */
569						$this.removeClass(pluginNS+" _"+pluginPfx+"_"+d.idx+" "+pluginPfx+"-"+o.theme+" "+classes[2]+" "+classes[0]).addClass(classe
569s[1]);
570					
571					}
572					
573				});
574				
575			}
576			/* ---------------------------------------- */
577			
578		},
579	
580	
581	
582	
583		
584	/* 
585	----------------------------------------
586	FUNCTIONS
587	----------------------------------------
588	*/
589	
590		/* validates selector (if selector is invalid or undefined uses the default one) */
591		_selector=function(){
592			return (typeof $(this)!=="object" || $(this).length<1) ? defaultSelector : this;
593		},
594		/* -------------------- */
595		
596		/* changes options according to theme */
597		_theme=function(obj){
598			var buttonsPlaceholderOutside=["buttons-out"],
599				buttonsHtmlSet2=["buttons-in"],
600				buttonsHtmlSet3=["buttons-out"],
601				typeHover85=["hover-classic"],
602				typeHoverPrecise=["hover-full"];
603			obj.markup.buttonsPlaceholder=$.inArray(obj.theme,buttonsPlaceholderOutside) > -1 ? "outside" : obj.markup.buttonsPlaceholder;
604			obj.markup.buttonsHTML=$.inArray(obj.theme,buttonsHtmlSet2) > -1 ? {up:"SVG set 2",down:"SVG set 2",left:"SVG set 2",right:"SVG set 2"} : $.inArray(obj.theme,buttonsHtmlSet3) > -1 ? {up:"SVG set 3",down:"SVG set 3",left:"SVG set 3",right:"SVG set 3"} : obj.markup.buttonsHTML;
605			obj.type=$.inArray(obj.theme,typeHover85) > -1 ? "hover-85" : $.inArray(obj.theme,typeHoverPrecise) > -1 ? "hover-precise" : obj.type;
606			obj.speed=$.inArray(obj.theme,typeHover85) > -1 ? 60 : $.inArray(obj.theme,typeHoverPrecise) > -1 ? 10 : obj.speed;
607		},
608		/* -------------------- */
609		
610		
611		/* live option timers removal */
612		removeLiveTimers=function(selector){
613			if(liveTimers[selector]){
614				clearTimeout(liveTimers[selector]);
615				_delete(liveTimers,selector);
616			}
617		},
618		/* -------------------- */
619		
620		
621		/* generates plugin markup */
622		_pluginMarkup=function(){
623			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
624				wrapperClass=o.axis==="yx" ? "mTS_vertical_horizontal" : o.axis==="x" ? "mTS_horizontal" : "mTS_vertical",
625				thumbsContainer=o.markup.thumbnailsContainer || "ul",
626				thumbContainer=o.markup.thumbnailContainer || "li",
627				thumbElement=o.markup.thumbnailElement || "img";
628			d.html=$this.children().clone(true,true); /* store element original html to restore when destroy method is called */
629			if(!$this.find(thumbsContainer).length){ /* create images container automatically if not present */
630				var thumbsAutoContainer=$this.find("li").length ? "<ul class='"+pluginPfx+"AutoContainer' />" : "<div class='"+pluginPfx+"AutoContainer' />";
631				$this.wrapInner(thumbsAutoContainer);
632				thumbsContainer="."+pluginPfx+"AutoContainer";
633			}
634			if(o.setWidth){$this.css("width",o.setWidth);} /* set element width */
635			if(o.setHeight){$this.css("height",o.setHeight);} /* set element height */
636			o.setLeft=(o.axis!=="y" && d.langDir==="rtl") ? "-989999px" : o.setLeft; /* adjust left position for rtl direction */
637			$this	.addClass(pluginNS+" _"+pluginPfx+"_"+d.idx+" "+pluginPfx+"-"+o.theme)
638					.find(thumbsContainer).wrap("<div id='mTS_"+d.idx+"' class='mTSWrapper "+wrapperClass+"' />")
639						.addClass(pluginPfx+"Container").attr("id","mTS_"+d.idx+"_container")
640						.css({"position":"relative","top":o.setTop,"left":o.setLeft})
641					.find(thumbContainer).addClass(pluginPfx+"ThumbContainer")
642					.find(thumbElement).addClass(pluginPfx+"Thumb");
643			_scrollButtons.call(this); /* add scroller buttons */
644		},
645		/* -------------------- */
646		
647		
648		/* expands content horizontally */
649		_expandContentHorizontally=function(){
650			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
651				mTS_container=$("#mTS_"+d.idx+"_container");
652			if(o.advanced.autoExpandHorizontalScroll && o.axis!=="y"){
653				/* 
654				wrap content with an infinite width div and set its position to absolute and width to auto. 
655				Setting width to auto before calculating the actual width is important! 
656				We must let the browser set the width as browser zoom values are impossible to calculate.
657				*/
658				mTS_container.css({"position":"absolute","width":"auto"})
659					.wrap("<div class='mTS_h_wrapper' style='position:relative; left:0; width:999999px;' />")
660					.css({ /* set actual width, original position and un-wrap */
661						/* 
662						get the exact width (with decimals) and then round-up. 
663						Using jquery outerWidth() will round the width value which will mess up with inner elements that have non-integer width
664						*/
665						"width":(Math.ceil(mTS_container[0].getBoundingClientRect().right)-Math.floor(mTS_container[0].getBoundingClientRect().left)),
666						"position":"relative"
667					}).unwrap();
668			}
669		},
670		/* -------------------- */
671		
672		
673		/* adds scroller buttons */
674        _scrollButtons = function () {
675            try {
676                var $this = $(this), d = $this.data(pluginPfx), o = d.opt,
677                    placeholder = !o.markup.buttonsPlaceholder ? $("#mTS_" + d.idx) : o.markup.buttonsPlaceholder === "outside" ? $this : $(o.markup.buttonsPlaceholder),
678                    btnHTML = [
679                        "<a href='#' id='mTS_" + d.idx + "_buttonUp' class='mTSButton mTSButtonUp'><span class='mTSButtonIconContainer'>" + _scrollButtonsIcons.call(this, "up") + "</span></a>",
680                        "<a href='#' id='mTS_" + d.idx + "_buttonDown' class='mTSButton mTSButtonDown'><span class='mTSButtonIconContainer'>" + _scrollButtonsIcons.call(this, "down") + "</span></a>",
681                        "<a href='#' id='mTS_" + d.idx + "_buttonLeft' class='mTSButton mTSButtonLeft'><span class='mTSButtonIconContainer'>" + _scrollButtonsIcons.call(this, "left") + "</span></a>",
682                        "<a href='#' id='mTS_" + d.idx + "_buttonRight' class='mTSButton mTSButtonRight'><span class='mTSButtonIconContainer'>" + _scrollButtonsIcons.call(this, "right") + "</span></a>"
683                    ],
684                    btn = [(o.axis === "x" ? btnHTML[2] : btnHTML[0]), (o.axis === "x" ? btnHTML[3] : btnHTML[1])];
685                if (placeholder.hasClass(pluginNS) && placeholder.css("position") === "static") { /* requires elements with non-static position */
686                    placeholder.css("position", "relative");
687                }
688                if (o.type.indexOf("click") !== -1) {
689                    if (o.axis !== "x") {
690                        placeholder.append(btnHTML[0] + btnHTML[1]);
691                    }
692                    if (o.axis !== "y") {
693                        placeholder.append(btnHTML[2] + btnHTML[3]);
694                    }
695                }
696            }
697            catch (err) { console.log(err);}
698		},
699		/* -------------------- */
700		
701		
702		/* sets scroller buttons icons */
703		_scrollButtonsIcons=function(b){
704			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
705				btn=o.markup.buttonsHTML,
706				i=btn[b]==="SVG set 1" ? 0 : btn[b]==="SVG set 2" ? 1 : btn[b]==="SVG set 3" ? 2 : btn[b]==="SVG set 4" ? 3 : btn[b]==="SVG set 5" ? 4 : null;
707			switch(b){
708				case "up":
709					return i===null ? btn[b] : oldIE ? "&uarr;" : _icons(btn[b])[i][0];
710					break;
711				case "down":
712					return i===null ? btn[b] : oldIE ? "&darr;" : _icons(btn[b])[i][1];
713					break;
714				case "left":
715					return i===null ? btn[b] : oldIE ? "&larr;" : _icons(btn[b])[i][2];
716					break;
717				case "right":
718					return i===null ? btn[b] : oldIE ? "&rarr;" : _icons(btn[b])[i][3];
719					break;
720			}
721		},
722		/* -------------------- */
723		
724		
725		/* icons */
726		_icons=function(){
727			/* SVG */
728			var svgo="<svg version='1.1' viewBox='0 0 24 24' preserveAspectRatio='xMinYMin meet' class='mTSButtonIcon'><g><line stroke-width='1' x1='' y1='' x2='' y2='' stroke='#449FDB' opacity=''></line></g>",
729				svgc="</svg>";
730			return [
731				/* set 1 */
732				[svgo+"<path d='M20.561 9.439l-7.5-7.5c-0.586-0.586-1.535-0.586-2.121 0l-7.5 7.5c-0.586 0.586-0.586 1.536 0 2.121s1.536 0.586 2.121 0l4.939-4.939v14.379c0 0.828 0.672 1.5 1.5 1.5s1.5-0.672 1.5-1.5v-14.379l4.939 4.939c0.293 0.293 0.677 0.439 1.061 0.439s0.768-0.146 1.061-0.439c0.586-0.586 0.586-1.535 0-2.121z'></path>"+svgc,svgo+"<path d='M3.439 14.561l7.5 7.5c0.586 0.586 1.536 0.586 2.121 0l7.5-7.5c0.586-0.586 0.586-1.536 0-2.121s-1.536-0.586-2.121 0l-4.939 4.939v-14.379c0-0.828-0.672-1.5-1.5-1.5s-1.5 0.672-1.5 1.5v14.379l-4.939-4.939c-0.293-0.293-0.677-0.439-1.061-0.439s-0.768 0.146-1.061 0.439c-0.586 0.586-0.586 1.536 0 2.121z'></path>"+svgc,svgo+"<path d='M9.439 3.439l-7.5 7.5c-0.586 0.586-0.586 1.536 0 2.121l7.5 7.5c0.586 0.586 1.536 0.586 2.121 0s0.586-1.536 0-2.121l-4.939-4.939h14.379c0.828 0 1.5-0.672 1.5-1.5s-0.672-1.5-1.5-1.5h-14.379l4.939-4.939c0.293-0.293 0.439-0.677 0.439-1.061s-0.146-0.768-0.439-1.061c-0.586-0.586-1.536-0.586-2.121 0z'></path>"+svgc,svgo+"<path d='M14.561 20.561l7.5-7.5c0.586-0.586 0.586-1.536 0-2.121l-7.5-7.5c-0.586-0.586-1.536-0.586-2.121 0s-0.586 1.536 0 2.121l4.939 4.939h-14.379c-0.828 0-1.5 0.672-1.5 1.5s0.672 1.5 1.5 1.5h14.379l-4.939 4.939c-0.293 0.293-0.439 0.677-0.439 1.061s0.146 0.768 0.439 1.061c0.586 0.586 1.536 0.586 2.121 0z'></path>"+svgc],
733				/* set 2 */
734				[svgo+"<path d='M18.58 13.724c-0.488-0.502-5.634-5.402-5.634-5.402-0.262-0.268-0.604-0.402-0.946-0.402-0.343 0-0.685 0.134
734-0.946 0.402 0 0-5.146 4.901-5.635 5.402-0.488 0.502-0.522 1.404 0 1.939 0.523 0.534 1.252 0.577 1.891 0l4.69-4.496 4.688 4.496c0.641 0.577 1.37 0.534 1.891 0 0.523-0.536 0.491-1.439 0-1.939z'</path>"+svgc,svgo+"<path d='M18.58 10.276c-0.488 0.502-5.634 5.404-5.634 5.404-0.262 0.268-0.604 0.401-0.946 0.401-0.343 0-0.685-0.133-0.946-0.401 0 0-5.146-4.902-5.635-5.404-0.488-0.502-0.522-1.403 0-1.939 0.523-0.535 1.252-0.577 1.891 0l4.69 4.498 4.688-4.496c0.641-0.577 1.37-0.535 1.891 0 0.523 0.535 0.491 1.438 0 1.938z'></path>"+svgc,svgo+"<path d='M13.724 5.419c-0.502 0.49-5.402 5.635-5.402 5.635-0.268 0.262-0.401 0.604-0.401 0.946s0.133 0.684 0.401 0.946c0 0 4.901 5.146 5.402 5.634 0.502 0.49 1.404 0.523 1.939 0 0.534-0.522 0.576-1.25-0.001-1.89l-4.496-4.69 4.496-4.69c0.577-0.641 0.535-1.369 0.001-1.891-0.536-0.522-1.439-0.49-1.939 0z'></path>"+svgc,svgo+"<path d='M10.276 5.419c0.502 0.49 5.402 5.635 5.402 5.635 0.269 0.262 0.402 0.604 0.402 0.946s-0.133 0.684-0.402 0.946c0 0-4.901 5.146-5.402 5.634-0.502 0.49-1.403 0.523-1.939 0-0.535-0.522-0.577-1.25 0-1.89l4.498-4.69-4.496-4.69c-0.577-0.641-0.535-1.369 0-1.891s1.438-0.49 1.938 0z'></path>"+svgc],
735				/* set 3 */
736				[svgo+"<path d='M20.902 17.279c0.325 0.322 0.851 0.322 1.175 0 0.325-0.322 0.325-0.841 0-1.163l-9.49-9.396c-0.324-0.322-0.85-0.322-1.174 0l-9.49 9.396c-0.324 0.322-0.325 0.841 0 1.163s0.85 0.322 1.175 0l8.902-8.569 8.902 8.569z'></path>"+svgc,svgo+"<path d='M3.098 6.721c-0.325-0.322-0.851-0.322-1.175 0-0.324 0.32-0.324 0.841 0 1.163l9.49 9.396c0.325 0.322 0.85 0.322 1.175 0l9.49-9.396c0.324-0.322 0.325-0.841 0-1.163s-0.852-0.322-1.175-0.001l-8.903 8.569-8.902-8.568z'></path>"+svgc,svgo+"<path d='M17.279 20.902c0.322 0.325 0.322 0.85 0 1.175s-0.841 0.325-1.163 0l-9.396-9.488c-0.322-0.325-0.322-0.851 0-1.175l9.396-9.49c0.322-0.325 0.841-0.325 1.163 0s0.322 0.85 0 1.175l-8.568 8.902 8.568 8.902z'</path>"+svgc,svgo+"<path d='M6.72 20.902c-0.322 0.325-0.322 0.85 0 1.175s0.841 0.325 1.163 0l9.396-9.488c0.322-0.325 0.322-0.851 0-1.175l-9.396-9.49c-0.322-0.325-0.841-0.325-1.163 0s-0.322 0.85 0 1.175l8.568 8.902-8.568 8.902z'</path>"+svgc],
737				/* set 4 */
738				[svgo+"<path d='M12 0l-12 12h7.5v12l9 0v-12h7.5z'></path>"+svgc,svgo+"<path d='M12 24l12-12h-7.5v-12l-9-0v12h-7.5z'></path>"+svgc,svgo+"<path d='M0 12l12 12v-7.5h12l0-9h-12v-7.5z'></path>"+svgc,svgo+"<path d='M24 12l-12-12v7.5h-12l-0 9h12v7.5z'></path>"+svgc],
739				/* set 5 */
740				[svgo+"<path d='M6.48 16.8h11.040l-5.521-9.6z'></path>"+svgc,svgo+"<path d='M17.52 7.201l-11.040-0.001 5.52 9.6z'></path>"+svgc,svgo+"<path d='M16.799 6.48l0.001 11.040-9.6-5.52z'></path>"+svgc,svgo+"<path d='M7.201 6.48l-0.001 11.040 9.6-5.52z'></path>"+svgc]
741			];
742		},
743		/* -------------------- */
744		
745		
746		/* detects/sets css max-height value */
747		_maxHeight=function(){
748			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
749				mTS_wrapper=$("#mTS_"+d.idx),
750				mh=$this.css("max-height"),pct=mh.indexOf("%")!==-1,
751				bs=$this.css("box-sizing");
752			if(mh!=="none"){
753				var val=pct ? $this.parent().height()*parseInt(mh)/100 : parseInt(mh);
754				/* if element's css box-sizing is "border-box", subtract any paddings and/or borders from max-height value */
755				if(bs==="border-box"){val-=(($this.innerHeight()-$this.height())+($this.outerHeight()-$this.innerHeight()));}
756				mTS_wrapper.css("max-height",Math.round(val));
757			}
758		},
759		/* -------------------- */
760		
761		
762		/* checks if content overflows its container to determine if scrolling is required */
763		_overflowed=function(){
764			var $this=$(this),d=$this.data(pluginPfx),
765				mTS_wrapper=$("#mTS_"+d.idx),
766				mTS_container=$("#mTS_"+d.idx+"_container");
767			return [mTS_container.height()>mTS_wrapper.height(),mTS_container.width()>mTS_wrapper.width()];
768		},
769		/* -------------------- */
770		
771		
772		/* resets content position to 0 */
773		_resetContentPosition=function(){
774			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
775				mTS_wrapper=$("#mTS_"+d.idx),
776				mTS_container=$("#mTS_"+d.idx+"_container");
777			_stop($this); /* stop any current scrolling before resetting */
778			if((o.axis!=="x" && !d.overflowed[0]) || (o.axis==="y" && d.overflowed[0])){mTS_container.css("top",0);} /* reset y */
779			if((o.axis!=="y" && !d.overflowed[1]) || (o.axis==="x" && d.overflowed[1])){ /* reset x */
780				var rp=d.langDir==="rtl" ? mTS_wrapper.width()-mTS_container.width() : 0;
781				mTS_container.css("left",rp);
782			}
783		},
784		/* -------------------- */
785		
786		
787		/* binds scroller events */
788		_bindEvents=function(){
789			var $this=$(this),d=$this.data(pluginPfx),o=d.opt;
790			if(!d.bindEvents){ /* check if events are already bound */
791				if(o.contentTouchScroll){_contentDraggable.call(this);}
792				if(o.type.indexOf("hover")!==-1){
793					if(o.type==="hover-precise"){
794						_hoverPrecise.call(this);
795					}else{
796						_hover.call(this);
797					}
798				}else if(o.type.indexOf("click")!==-1){
799					_click.call(this);
800				}
801				d.bindEvents=true;
802			}
803		},
804		/* -------------------- */
805		
806		
807		/* unbinds scroller events */
808		_unbindEvents=function(){
809			var $this=$(this),d=$this.data(pluginPfx),
810				namespace=pluginPfx+"_"+d.idx,
811				sel=$("#mTS_"+d.idx+",#mTS_"+d.idx+"_container,#mTS_"+d.idx+"_buttonUp,#mTS_"+d.idx+"_buttonDown,#mTS_"+d.idx+"_buttonLeft,#mTS_"+d.idx+"_buttonRight"),
812				mTS_container=$("#mTS_"+d.idx+"_container");
813			if(d.bindEvents){ /* check if events are bound */
814				/* unbind namespaced events from selectors */
815				sel.each(function(){
816					$(this).unbind("."+namespace);
817				});
818				/* clear and delete timeouts/objects */
819				clearTimeout(mTS_container[0].onCompleteTimeout); _delete(mTS_container[0],"onCompleteTimeout");
820				d.bindEvents=false;
821			}
822		},
823		/* -------------------- */
824		
825		
826		/* toggles scroller buttons visibility */
827		_buttonsVisibility=function(disabled,hideBtn,dir){
828			var $this=$(this),d=$this.data(pluginPfx),o=d.opt;
829			if(o.type.indexOf("click")!==-1){
830				if(!dir){dir=o.axis;}
831				var	mTS_buttons=[$("#mTS_"+d.idx+"_buttonUp"),$("#mTS_"+d.idx+"_buttonDown"),$("#mTS_"+d.idx+"_buttonLeft"),$("#mTS_"+d.idx+"_buttonRight")],
832					hideClass=pluginPfx+"-hidden";
833				if(dir!=="x"){
834					if(d.overflowed[0] && !disabled && !hideBtn){
835						sel=[!d.overflowed[1] ? mTS_buttons[2].add(mTS_buttons[3]) : null,mTS_buttons[0].add(mTS_buttons[1])];
836					}else{
837						sel=hideBtn===1 ? [mTS_buttons[0],mTS_buttons[1]] : hideBtn===2 ? [mTS_buttons[1],mTS_buttons[0]] : [mTS_buttons[0].add(mTS_buttons[1]),null];
838					}
839				}
840				if(dir!=="y"){
841					if(d.overflowed[1] && !disabled && !hideBtn){
842						sel=[!d.overflowed[0] ? mTS_buttons[0].add(mTS_buttons[1]) : null,mTS_buttons[2].add(mTS_buttons[3])];
843					}else{
844						sel=hideBtn===1 ? [mTS_buttons[2],mTS_buttons[3]] : hideBtn===2 ? [mTS_buttons[3],mTS_buttons[2]] : [mTS_buttons[2].add(mTS_buttons[3]),null];
845					}
846				}
847				if(sel[0]){sel[0].addClass(hideClass);}
848				if(sel[1]){sel[1].removeClass(hideClass);}
849			}
850		},
851		/* -------------------- */
852		
853		
854		/* returns input coordinates of pointer, touch and mouse events (relative to document) */
855		_coordinates=function(e){
856			var t=e.type;
857			switch(t){
858				case "pointerdown": case "MSPointerDown": case "pointermove": case "MSPointerMove": case "pointerup": case "MSPointerUp":
859					return [e.originalEvent.pageY,e.originalEvent.pageX];
860					break;
861				case "touchstart": case "touchmove": case "touchend":
862					var touch=e.originalEvent.touches[0] || e.originalEvent.changedTouches[0];
863					return [touch.pageY,touch.pageX];
864					break;
865				default:
866					return [e.pageY,e.pageX];
867			}
868		},
869		/* -------------------- */
870		
871		/* returns input type */
872		_inputType=function(e){
873			return touchi || e.type.indexOf("touch")!==-1 || (typeof e.pointerType!=="undefined" && (e.pointerType===2 || e.pointerType==="touch")) ? "touch" : "mouse";
874		},
875		/* -------------------- */
876		
877		
878		/* 
879		TOUCH SWIPE EVENTS
880		scrolls content via touch swipe 
881		Emulates the native touch-swipe scrolling with momentum found in iOS, Android and WP devices 
882		*/
883		_contentDraggable=function(){
884			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
885				namespace=pluginPfx+"_"+d.idx,
886				mTS_wrapper=$("#mTS_"+d.idx),
887				mTS_container=$("#mTS_"+d.idx+"_container"),
888				dragY,dragX,touchStartY,touchStartX,touchMoveY=[],touchMoveX=[],startTime,runningTime,endTime,distance,speed,amount,
889				durA=0,durB,overwrite=o.axis==="yx" ? "none" : "all",touchIntent=[];
890			mTS_container.bind("touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){
891				if(!_pointerTouch(e) || touchActive){return;}
892				$this.removeClass("mTS_touch_action");
893				var offset=mTS_container.offset();
894				dragY=_coordinates(e)[0]-offset.top;
895				dragX=_coordinates(e)[1]-offset.left;
896				touchIntent=[_coordinates(e)[0],_coordinates(e)[1]];
897			}).bind("touchmove."+namespace+" pointermove."+namespace+" MSPointerMove."+namespace,function(e){
898				if(!_pointerTouch(e) || touchActive){return;}
899				e.stopImmediatePropagation();
900				runningTime=_getTime();
901				var offset=mTS_wrapper.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left,
902					easing="linearOut";
903				touchMoveY.push(y);
904				touchMoveX.push(x);
905				touchIntent[2]=Math.abs(_coordinates(e)[0]-touchIntent[0]); touchIntent[3]=Math.abs(_coordinates(e)[1]-touchIntent[1]);
906				if(d.overflowed[0]){
907					var limit=mTS_wrapper.height()-mTS_container.height(),
908						prevent=((dragY-y)>0 && (y-dragY)>limit && (touchIntent[3]*2<touchIntent[2]));
909				}
910				if(d.overflowed[1]){
911					var limitX=mTS_wrapper.width()-mTS_container.width(),
912						preventX=((dragX-x)>0 && (x-dragX)>limitX && (touchIntent[2]*2<touchIntent[3]));
913				}
914				if(prevent || preventX){e.preventDefault();}else{$this.addClass("mTS_touch_action");} /* prevent native document scrolling */
915				amount=o.axis==="yx" ? [(dragY-y),(dragX-x)] : o.axis==="x" ? [null,(dragX-x)] : [(dragY-y),null];
916				mTS_container[0].idleTimer=250;
917				if(d.overflowed[0]){_drag(amount[0],durA,easing,"y","all");}
918				if(d.overflowed[1]){_drag(amount[1],durA,easing,"x",overwrite);}
919			});
920			mTS_wrapper.bind("touchstart."+namespace+" pointerdown."+namespace+" MSPointerDown."+namespace,function(e){
921				if(!_pointerTouch(e) || touchActive){return;}
922				e.stopImmediatePropagation();
923				touchi=true;
924				_stop($this);
925				startTime=_getTime();
926				var offset=mTS_wrapper.offset();
927				touchStartY=_coordinates(e)[0]-offset.top;
928				touchStartX=_coordinates(e)[1]-offset.left;
929				touchMoveY=[]; touchMoveX=[];
930			}).bind("touchend."+namespace+" pointerup."+namespace+" MSPointerUp."+namespace,function(e){
931				if(!_pointerTouch(e) || touchActive){return;}
932				e.stopImmediatePropagation();
933				endTime=_getTime();
934				var offset=mTS_wrapper.offset(),y=_coordinates(e)[0]-offset.top,x=_coordinates(e)[1]-offset.left;
935				if((endTime-runningTime)>30){return;}
936				speed=1000/(endTime-startTime);
937				var easing="easeOut",slow=speed<2.5,
938					diff=slow ? [touchMoveY[touchMoveY.length-2],touchMoveX[touchMoveX.length-2]] : [0,0];
939				distance=slow ? [(y-diff[0]),(x-diff[1])] : [y-touchStartY,x-touchStartX];
940				var absDistance=[Math.abs(distance[0]),Math.abs(distance[1])];
941				speed=slow ? [Math.abs(distance[0]/4),Math.abs(distance[1]/4)] : [speed,speed];
942				var a=[
943					Math.abs(mTS_container[0].offsetTop)-(distance[0]*_m((absDistance[0]/speed[0]),speed[0])),
944					Math.abs(mTS_container[0].offsetLeft)-(distance[1]*_m((absDistance[1]/speed[1]),speed[1]))
945				];
946				amount=o.axis==="yx" ? [a[0],a[1]] : o.axis==="x" ? [null,a[1]] : [a[0],null];
947				durB=[(absDistance[0]*4)+(o.speed*60),(absDistance[1]*4)+(o.speed*60)];
948				var md=parseInt(o.contentTouchScroll) || 0; /* absolute minimum distance required */
949				amount[0]=absDistance[0]>md ? amount[0] : 0;
950				amount[1]=absDistance[1]>md ? amount[1] : 0;
951				if(d.overflowed[0]){_drag(amount[0],durB[0],easing,"y",overwrite);}
952				if(d.overflowed[1]){_drag(amount[1],durB[1],easing,"x",overwrite);}
953			});
954			function _m(ds,s){
955				var r=[s*1.5,s*2,s/1.5,s/2];
956				if(ds>90){
957					return s>4 ? r[0] : r[3];
958				}else if(ds>60){
959					return s>3 ? r[3] : r[2];
960				}else if(ds>30){
961					return s>8 ? r[1] : s>6 ? r[0] : s>4 ? s : r[2];
962				}else{
963					return s>8 ? s : r[3];
964				}
965			}
966			function _drag(amount,dur,easing,dir,overwrite){
967				if(!amount){return;}
968				_scrollTo($this,-amount.toString(),{dur:dur,easing:easing,dir:dir,overwrite:overwrite});
969			}
970		},
971		/* -------------------- */
972		
973		
974		/* 
975		HOVER PRECISE EVENT
976		scrolls content via cursor movement
977		*/
978		_hoverPrecise=function(){
979			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
980				namespace=pluginPfx+"_"+d.idx,
981				mTS_wrapper=$("#mTS_"+d.idx),
982				mTS_container=$("#mTS_"+d.idx+"_container"),
983				evt=window.navigator.pointerEnabled ? "pointermove" : window.navigator.msPointerEnabled ? "MSPointerMove" : "mousemove",
984				cursor,dest,to;
985			mTS_wrapper.bind(evt+"."+namespace,function(e){
986				if(_inputType(e.originalEvent || e)==="touch" || (!d.overflowed[0] && !d.overflowed[1])){return;}
987				e.preventDefault();
988				var wrapperHeight=mTS_wrapper.height(),containerHeight=mTS_container.height(),
989					wrapperWidth=mTS_wrapper.width(),containerWidth=mTS_container.width(),
990					speed=((containerWidth/wrapperWidth)*7000)/(o.speed || 1);
991				cursor=[_coordinates(e)[0]-mTS_wrapper.offset().top,_coordinates(e)[1]-mTS_wrapper.offset().left];
992				dest=[cursor[0]/mTS_wrapper.height(),cursor[1]/mTS_wrapper.width()];
993				to=[Math.round(-((containerHeight-wrapperHeight)*(dest[0]))),Math.round(-((containerWidth-wrapperWidth)*(dest[1])))];
994				if(o.axis!=="x" && d.overflowed[0]){
995					_scrollTo($this,to[0].toString(),{dir:"y",dur:speed,easing:"easeOut"});
996				}
997				if(o.axis!=="y" && d.overflowed[1]){
998					_scrollTo($this,to[1].toString(),{dir:"x",dur:speed,easing:"easeOut"});
999				}
1000			});
1001		},
1002		/* -------------------- */
1003		
1004		
1005		/* 
1006		HOVER EVENT
1007		scrolls content via cursor movement
1008		*/
1009		_hover=function(){
1010			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1011				namespace=pluginPfx+"_"+d.idx,
1012				mTS_wrapper=$("#mTS_"+d.idx),
1013				mTS_container=$("#mTS_"+d.idx+"_container"),
1014				evt=window.navigator.pointerEnabled ? ["pointerover","pointermove","pointerout"] : 
1015					window.navigator.msPointerEnabled ? ["MSPointerOver","MSPointerMove","MSPointerOut"] : 
1016					["mouseenter","mousemove","mouseleave"],
1017				rAF,cursor,dest,to,fps,delay=(!window.requestAnimationFrame) ? 17 : 0,
1018				speed=o.speed,pct=parseInt(o.type.split("hover-")[1]) || 1,idle=speed*pct/100,
1019				_pause=[0,0];
1020			mTS_wrapper.bind(evt[0]+"."+namespace,function(e){
1021				if(_inputType(e.originalEvent || e)==="touch" || (!d.overflowed[0] && !d.overflowed[1])){return;}
1022				_on();
1023			}).bind(evt[1]+"."+namespace,function(e){
1024				if(_inputType(e.originalEvent || e)==="touch" || (!d.overflowed[0] && !d.overflowed[1])){return;}
1025				cursor=[_coordinates(e)[0]-mTS_wrapper.offset().top,_coordinates(e)[1]-mTS_wrapper.offset().left];
1026				dest=[Math.round((Math.cos((cursor[0]/mTS_wrapper.height())*Math.PI))*speed),Math.round((Math.cos((cursor[1]/mTS_wrapper.width())*Math.PI))*speed)];
1027				dest[0]=dest[0]<=-idle ? dest[0]+=idle : dest[0]>=idle ? dest[0]-=idle : dest[0]=0;
1028				dest[1]=dest[1]<=-idle ? dest[1]+=idle : dest[1]>=idle ? dest[1]-=idle : dest[1]=0;
1029				_pause=[0,0];
1030			}).bind(evt[2]+"."+namespace,function(e){
1031				if(_inputType(e.originalEvent || e)==="touch" || (!d.overflowed[0] && !d.overflowed[1])){return;}
1032				_off();
1033			});
1034			function _on(){
1035				if(mTS_wrapper[0].rAF){return;}
1036				rAF=(!window.requestAnimationFrame) ? function(f){return setTimeout(f,17);} : window.requestAnimationFrame;
1037				mTS_wrapper[0].rAF=rAF(_anim);
1038			}
1039			function _off(){
1040				if(mTS_wrapper[0].rAF==null){return;}
1041				if(!window.requestAnimationFrame){
1042					clearTimeout(mTS_wrapper[0].rAF);
1043				}else{
1044					window.cancelAnimationFrame(mTS_wrapper[0].rAF);
1045				}
1046				clearTimeout(fps);
1047				mTS_wrapper[0].rAF=null;
1048			}
1049			function _anim(){
1050				if(touchi){return;} /* this is for android native browser (at least for version 4.1.2) */
1051				to=[dest[0]+mTS_container[0].offsetTop,dest[1]+mTS_container[0].offsetLeft];
1052				var limit=[mTS_wrapper.height()-mTS_container.height(),mTS_wrapper.width()-mTS_container.width()];
1053				if(o.axis!=="x" && d.overflowed[0]){
1054					to[0]=to[0]>0 ? 0 : to[0]<limit[0] ? limit[0] : to[0];
1055					if(dest[0] && !_pause[0]){
1056						_scrollTo($this,to[0],{dir:"y",dur:0,easing:"linear"});
1057					}
1058					if(to[0]>=0 || to[0]<=limit[0]){
1059						_pause[0]=1;
1060					}
1061				}
1062				if(o.axis!=="y" && d.overflowed[1]){
1063					to[1]=to[1]>0 ? 0 : to[1]<limit[1] ? limit[1] : to[1];
1064					if(dest[1] && !_pause[1]){
1065						_scrollTo($this,to[1],{dir:"x",dur:0,easing:"linear"});
1066					}
1067					if(to[1]>=0 || to[1]<=limit[1]){
1068						_pause[1]=1;
1069					}
1070				}
1071				fps=setTimeout(function(){mTS_wrapper[0].rAF=rAF(_anim);},delay);					
1072			}
1073		},
1074		/* -------------------- */
1075		
1076		
1077		/* 
1078		CLICK EVENT
1079		scrolls content via scrolling buttons
1080		*/
1081		_click=function(){
1082			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1083				namespace=pluginPfx+"_"+d.idx,
1084				mTS_wrapper=$("#mTS_"+d.idx),
1085				mTS_container=$("#mTS_"+d.idx+"_container"),
1086				mTS_buttons=[$("#mTS_"+d.idx+"_buttonUp"),$("#mTS_"+d.idx+"_buttonDown"),$("#mTS_"+d.idx+"_buttonLeft"),$("#mTS_"+d.idx+"_buttonRight")],
1087				sel=mTS_buttons[0].add(mTS_buttons[1]).add(mTS_buttons[2]).add(mTS_buttons[3]);
1088			sel.bind("click."+namespace,function(e){
1089				if(!_mouseBtnLeft(e) || (!d.overflowed[0] && !d.overflowed[1])){return;}
1090				e.preventDefault();
1091				if(d.tweenRunning){return;}
1092				if(o.axis!=="x" && d.overflowed[0]){
1093					var h=mTS_wrapper.height(),dir=o.type==="click-thumb" ? 0 : $(this).hasClass("mTSButtonUp") ? "+=" : $(this).hasClass("mTSButtonDown") ? "-=" : 0;
1094					if(o.type!=="click-thumb"){
1095						var pct=parseInt(o.type.split("click-")[1]) || 1,amount=dir ? [dir+(h*pct/100),null] : 0;
1096					}else{
1097						var firstThumb=_firstLast.call($this[0])[0],lastThumb=_firstLast.call($this[0])[1];
1098						if($(this).hasClass("mTSButtonDown")){
1099							var	amount=lastThumb ? (lastThumb[0].offsetTop-parseInt(lastThumb.css("margin-bottom")))-h : 989999;
1100						}else if($(this).hasClass("mTSButtonUp")){
1101							var	amount=firstThumb ? firstThumb[0].offsetTop-parseInt(firstThumb.css("margin-top")) : 0;
1102							if(mTS_container[0].offsetTop===0){return;}
1103						}
1104					}
1105				}
1106				if(o.axis!=="y" && d.overflowed[1]){
1107					var w=mTS_wrapper.width(),dir=o.type==="click-thumb" ? 0 : $(this).hasClass("mTSButtonLeft") ? "+=" : $(this).hasClass("mTSButtonRight") ? "-=" : 0;
1108					if(o.type!=="click-thumb"){
1109						var pct=parseInt(o.type.split("click-")[1]) || 1,amount=dir ? [null,dir+(w*pct/100)] : amount;
1110					}else{
1111						var firstThumb=_firstLast.call($this[0])[2],lastThumb=_firstLast.call($this[0])[3];
1112						if($(this).hasClass("mTSButtonRight")){
1113							var	amount=lastThumb ? (lastThumb[0].offsetLeft-parseInt(lastThumb.css("margin-right")))-w : 989999;
1114						}else if($(this).hasClass("mTSButtonLeft")){
1115							var	amount=firstThumb ? firstThumb[0].offsetLeft-parseInt(firstThumb.css("margin-left")) : 0;
1116							if(mTS_container[0].offsetLeft===0){return;}
1117						}
1118					}
1119				}
1120				if(amount!==null){methods.scrollTo.call($this[0],amount,{duration:0});}
1121			});
1122		},
1123		/* -------------------- */
1124		
1125		
1126		/* returns the first and last items within the viewport */
1127		_firstLast=function(){
1128			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1129				mTS_container=$("#mTS_"+d.idx+"_container"),
1130				mTS_wrapper=$("#mTS_"+d.idx),
1131				mTS_item=mTS_container.find(".mTSThumbContainer"),
1132				f,l,fx,lx;
1133			mTS_item.each(function(){
1134				var el=$(this),
1135					pos=[
1136						Math.round((el.offset().top-mTS_container.offset().top)+mTS_container[0].offsetTop),
1137						Math.round((el.offset().left-mTS_container.offset().left)+mTS_container[0].offsetLeft)
1138					];
1139				if(pos[0]<=0-parseInt(el.css("margin-top"))){
1140					f=pos[0]===0 ? mTS_item.eq(el.index()-1) : mTS_item.eq(el.index());
1141				}else if(pos[0]<=mTS_wrapper.height()+parseInt(el.css("margin-bottom"))){
1142					var i=mTS_item.eq(el.index()+1);
1143					l=i.length ? i : null;
1144				}
1145				if(pos[1]<=0-parseInt(el.css("margin-left"))){
1146					fx=pos[1]===0 ? mTS_item.eq(el.index()-1) : mTS_item.eq(el.index());
1147				}else if(pos[1]<=mTS_wrapper.width()+parseInt(el.css("margin-right"))){
1148					var ix=mTS_item.eq(el.index()+1);
1149					lx=ix.length ? ix : null;
1150				}
1151			});
1152			return [f,l,fx,lx];
1153		},
1154		/* -------------------- */
1155		
1156		
1157		/* returns a yx array from value */
1158		_arr=function(val){
1159			var o=$(this).data(pluginPfx).opt,vals=[];
1160			if(typeof val==="function"){val=val();} /* check if the value is a single anonymous function */
1161			/* check if value is object or array, its length and create an array with yx values */
1162			if(!(val instanceof Array)){ /* object value (e.g. {y:"100",x:"100"}, 100 etc.) */
1163				vals[0]=val.y ? val.y : val.x || o.axis==="x" ? null : val;
1164				vals[1]=val.x ? val.x : val.y || o.axis==="y" ? null : val;
1165			}else{ /* array value (e.g. [100,100]) */
1166				vals=val.length>1 ? [val[0],val[1]] : o.axis==="x" ? [null,val[0]] : [val[0],null];
1167			}
1168			/* check if array values are anonymous functions */
1169			if(typeof vals[0]==="function"){vals[0]=vals[0]();}
1170			if(typeof vals[1]==="function"){vals[1]=vals[1]();}
1171			return vals;
1172		},
1173		/* -------------------- */
1174		
1175		
1176		/* translates values (e.g. "top", 100, "100px", "#id") to actual scroll-to positions */
1177		_to=function(val,dir){
1178			if(val==null || typeof val=="undefined"){return;}
1179			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1180				mTS_wrapper=$("#mTS_"+d.idx),
1181				mTS_container=$("#mTS_"+d.idx+"_container"),
1182				t=typeof val;
1183			if(!dir){dir=o.axis==="x" ? "x" : "y";}
1184			var contentLength=dir==="x" ? mTS_container.width() : mTS_container.height(),
1185				contentOffset=dir==="x" ? mTS_container.offset().left : mTS_container.offset().top,
1186				contentPos=dir==="x" ? mTS_container[0].offsetLeft : mTS_container[0].offsetTop,
1187				cssProp=dir==="x" ? "left" : "top";
1188			switch(t){
1189				case "function": /* this currently is not used. Consider removing it */
1190					return val();
1191					break;
1192				case "object":
1193					if(val.nodeType){ /* DOM */
1194						var objOffset=dir==="x" ? $(val).offset().left : $(val).offset().top;
1195					}else if(val.jquery){ /* jquery object */
1196						if(!val.length){return;}
1197						var objOffset=dir==="x" ? val.offset().left : val.offset().top;
1198					}
1199					return objOffset-contentOffset;
1200					break;
1201				case "string": case "number":
1202					if(_isNumeric(val)){ /* numeric value */
1203						return Math.abs(val);
1204					}else if(val.indexOf("%")!==-1){ /* percentage value */
1205						return Math.abs(contentLength*parseInt(val)/100);
1206					}else if(val.indexOf("-=")!==-1){ /* decrease value */
1207						return Math.abs(contentPos-parseInt(val.split("-=")[1]));
1208					}else if(val.indexOf("+=")!==-1){ /* inrease value */
1209						var p=(contentPos+parseInt(val.split("+=")[1]));
1210						return p>=0 ? 0 : Math.abs(p);
1211					}else if(val.indexOf("px")!==-1 && _isNumeric(val.split("px")[0])){ /* pixels string value (e.g. "100px") */
1212						return Math.abs(val.split("px")[0]);
1213					}else{
1214						if(val==="top" || val==="left"){ /* special strings */
1215							return 0;
1216						}else if(val==="bottom"){
1217							return Math.abs(mTS_wrapper.height()-mTS_container.height());
1218						}else if(val==="right"){
1219							return Math.abs(mTS_wrapper.width()-mTS_container.width());
1220						}else if(val==="first" || val==="last"){
1221							var obj=mTS_container.find(":"+val),
1222								objOffset=dir==="x" ? $(obj).offset().left : $(obj).offset().top;
1223							return objOffset-contentOffset;
1224						}else{
1225							if($(val).length){ /* jquery selector */
1226								var objOffset=dir==="x" ? $(val).offset().left : $(val).offset().top;
1227								return objOffset-contentOffset;
1228							}else{ /* other values (e.g. "100em") */
1229								mTS_container.css(cssProp,val);
1230								methods.update.call(null,$this[0]);
1231								return;
1232							}
1233						}
1234					}
1235					break;
1236			}
1237		},
1238		/* -------------------- */
1239		
1240		
1241		/* calls the update method automatically */
1242		_autoUpdate=function(rem){
1243			var $this=$(this),d=$this.data(pluginPfx),o=d.opt,
1244				mTS_wrapper=$("#mTS_"+d.idx),
1245				mTS_container=$("#mTS_"+d.idx+"_container");
1246			if(rem){
1247				/* 
1248				removes autoUpdate timer 
1249				usage: functions._autoUpdate.call(this,"remove");
1250				*/
1251				clearTimeout(mTS_container[0].autoUpdate);
1252				_delete(mTS_container[0],"autoUpdate");
1253				return;
1254			}
1255			var	oldSelSize=sizesSum(),newSelSize,
1256				os=[mTS_container.height(),mTS_container.width(),mTS_wrapper.height(),mTS_wrapper.width(),$this.height(),$this.width()],ns,
1257				oldImgsLen=imgSum(),newImgsLen;
1258			upd();
1259			function upd(){
1260				clearTimeout(mTS_container[0].autoUpdate);
1261				if($this.parents("html").length===0){
1262					/* check element in dom tree */
1263					$this=null;
1264					return;
1265				}
1266				mTS_container[0].autoUpdate=setTimeout(function(){
1267					/* update on specific selector(s) length and size change */
1268					if(o.advanced.updateOnSelectorChange){
1269						newSelSize=sizesSum();
1270						if(newSelSize!==oldSelSize){
1271							doUpd();
1272							oldSelSize=newSelSize;
1273							return;
1274						}
1275					}
1276					/* update on main element and scroller size changes */
1277					if(o.advanced.updateOnContentResize){
1278						ns=[mTS_container.height(),mTS_container.width(),mTS_wrapper.height(),mTS_wrapper.width(),$this.height(),$this.width()];
1279						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]){
1280							doUpd();
1281							os=ns;
1282						}
1283					}
1284					/* update on image load */
1285					if(o.advanced.updateOnImageLoad){
1286						newImgsLen=imgSum();
1287						if(newImgsLen!==oldImgsLen){
1288							mTS_container.find("img").each(function(){
1289								imgLoader(this.src);
1290							});
vendor: 10,808 bytes, lines 1291-1602
1291							oldImgsLen=newImgsLen;
1292						}
1293					}
1294					if(o.advanced.updateOnSelectorChange || o.advanced.updateOnContentResize || o.advanced.updateOnImageLoad){upd();}
1295				},60);
1296			}
1297			/* returns images amount */
1298			function imgSum(){
1299				var total=0
1300				if(o.advanced.updateOnImageLoad){total=mTS_container.find("img").length;}
1301				return total;
1302			}
1303			/* a tiny image loader */
1304			function imgLoader(src){
1305				var img=new Image();
1306				function createDelegate(contextObject,delegateMethod){
1307					return function(){return delegateMethod.apply(contextObject,arguments);}
1308				}
1309				function imgOnLoad(){
1310					this.onload=null;
1311					doUpd();
1312				}
1313				img.onload=createDelegate(img,imgOnLoad);
1314				img.src=src;
1315			}
1316			/* returns the total height and width sum of all elements matching the selector */
1317			function sizesSum(){
1318				if(o.advanced.updateOnSelectorChange===true){o.advanced.updateOnSelectorChange="*";}
1319				var total=0,sel=mTS_container.find(o.advanced.updateOnSelectorChange);
1320				if(o.advanced.updateOnSelectorChange && sel.length>0){sel.each(function(){total+=$(this).height()+$(this).width();});}
1321				return total;
1322			}
1323			/* calls the update method */
1324			function doUpd(){
1325				clearTimeout(mTS_container[0].autoUpdate); 
1326				methods.update.call(null,$this[0]);
1327			}
1328		},
1329		/* -------------------- */
1330		
1331		
1332		/* stops content animations */
1333		_stop=function(el){
1334			var d=el.data(pluginPfx),
1335				sel=$("#mTS_"+d.idx+"_container");
1336			sel.each(function(){
1337				_stopTween.call(this);
1338			});
1339		},
1340		/* -------------------- */
1341		
1342		
1343		/* 
1344		ANIMATES CONTENT 
1345		This is where the actual scrolling happens
1346		*/
1347		_scrollTo=function(el,to,options){
1348			var d=el.data(pluginPfx),o=d.opt,
1349				defaults={
1350					trigger:"internal",
1351					dir:"y",
1352					easing:"easeOut",
1353					dur:o.speed*60,
1354					overwrite:"all",
1355					callbacks:true,
1356					onStart:true,
1357					onUpdate:true,
1358					onComplete:true
1359				},
1360				options=$.extend(defaults,options),
1361				mTS_wrapper=$("#mTS_"+d.idx),
1362				mTS_container=$("#mTS_"+d.idx+"_container"),
1363				totalScrollOffsets=o.callbacks.onTotalScrollOffset ? _arr.call(el,o.callbacks.onTotalScrollOffset) : [0,0],
1364				totalScrollBackOffsets=o.callbacks.onTotalScrollBackOffset ? _arr.call(el,o.callbacks.onTotalScrollBackOffset) : [0,0];
1365			d.trigger=options.trigger;
1366			if(mTS_wrapper.scrollTop()!==0 || mTS_wrapper.scrollLeft()!==0){ /* always reset scrollTop/Left */
1367				mTS_wrapper.scrollTop(0).scrollLeft(0);
1368			}
1369			switch(options.dir){
1370				case "x":
1371					var property="left",
1372						contentPos=mTS_container[0].offsetLeft,
1373						limit=mTS_wrapper.width()-mTS_container.width(),
1374						scrollTo=to,
1375						tso=totalScrollOffsets[1],
1376						tsbo=totalScrollBackOffsets[1],
1377						totalScrollOffset=tso>0 ? tso : 0,
1378						totalScrollBackOffset=tsbo>0 ? tsbo : 0;
1379					break;
1380				case "y":
1381					var property="top",
1382						contentPos=mTS_container[0].offsetTop,
1383						limit=mTS_wrapper.height()-mTS_container.height(),
1384						scrollTo=to,
1385						tso=totalScrollOffsets[0],
1386						tsbo=totalScrollBackOffsets[0],
1387						totalScrollOffset=tso>0 ? tso : 0,
1388						totalScrollBackOffset=tsbo>0 ? tsbo : 0;
1389					break;
1390			}
1391			if(scrollTo>=0){
1392				scrollTo=0;
1393				_buttonsVisibility.call(el,false,1,options.dir); /* show/hide buttons */
1394			}else if(scrollTo<=limit){
1395				scrollTo=limit;
1396				_buttonsVisibility.call(el,false,2,options.dir); /* show/hide buttons */
1397			}else{
1398				scrollTo=scrollTo;
1399				_buttonsVisibility.call(el,false,0,options.dir); /* show/hide buttons */
1400			}
1401			if(!el[0].mts){ 
1402				_mts(); /* init mts object (once) to make it available before callbacks */
1403				if(_cb("onInit")){o.callbacks.onInit.call(el[0]);} /* callbacks: onInit */
1404			}
1405			clearTimeout(mTS_container[0].onCompleteTimeout);
1406			if(!d.tweenRunning && ((contentPos===0 && scrollTo>=0) || (contentPos===limit && scrollTo<=limit))){return;}
1407			_tweenTo(mTS_container[0],property,Math.round(scrollTo),options.dur,options.easing,options.overwrite,{
1408				onStart:function(){
1409					if(options.callbacks && options.onStart && !d.tweenRunning){
1410						/* callbacks: onScrollStart */
1411						if(_cb("onScrollStart")){_mts(); o.callbacks.onScrollStart.call(el[0]);}
1412						d.tweenRunning=true;
1413						d.cbOffsets=_cbOffsets();
1414					}
1415				},onUpdate:function(){
1416					if(options.callbacks && options.onUpdate){
1417						/* callbacks: whileScrolling */
1418						if(_cb("whileScrolling")){_mts(); o.callbacks.whileScrolling.call(el[0]);}
1419					}
1420				},onComplete:function(){
1421					if(options.callbacks && options.onComplete){
1422						if(o.axis==="yx"){clearTimeout(mTS_container[0].onCompleteTimeout);}
1423						var t=mTS_container[0].idleTimer || 0;
1424						mTS_container[0].onCompleteTimeout=setTimeout(function(){
1425							/* callbacks: onScroll, onTotalScroll, onTotalScrollBack */
1426							if(_cb("onScroll")){_mts(); o.callbacks.onScroll.call(el[0]);}
1427							if(_cb("onTotalScroll") && scrollTo<=limit+totalScrollOffset && d.cbOffsets[0]){_mts(); o.callbacks.onTotalScroll.call(el[0]);}
1428							if(_cb("onTotalScrollBack") && scrollTo>=-totalScrollBackOffset && d.cbOffsets[1]){_mts(); o.callbacks.onTotalScrollBack.call(el[0]);}
1429							d.tweenRunning=false;
1430							mTS_container[0].idleTimer=0;
1431						},t);
1432					}
1433				}
1434			});
1435			/* checks if callback function exists */
1436			function _cb(cb){
1437				return d && o.callbacks[cb] && typeof o.callbacks[cb]==="function";
1438			}
1439			/* checks whether callback offsets always trigger */
1440			function _cbOffsets(){
1441				return [o.callbacks.alwaysTriggerOffsets || contentPos>=limit+tso,o.callbacks.alwaysTriggerOffsets || contentPos<=-tsbo];
1442			}
1443			/* 
1444			populates object with useful values for the user 
1445			values: 
1446				content: this.mts.content
1447				content top position: this.mts.top 
1448				content left position: this.mts.left 
1449				scrolling y percentage: this.mts.topPct 
1450				scrolling x percentage: this.mts.leftPct 
1451				scrolling direction: this.mts.direction
1452			*/
1453			function _mts(){
1454				var cp=[mTS_container[0].offsetTop,mTS_container[0].offsetLeft], /* content position */
1455					cl=[mTS_container.height(),mTS_container.width()], /* content length */
1456					pl=[mTS_wrapper.height(),mTS_wrapper.width()]; /* content parent length */
1457				el[0].mts={
1458					content:mTS_container, /* original content wrapper as jquery object */
1459					top:cp[0],left:cp[1],
1460					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])),
1461					direction:options.dir
1462				};
1463				/* 
1464				this refers to the original element containing the scroller
1465				usage: this.mts.top, this.mts.leftPct etc. 
1466				*/
1467			}
1468		},
1469		/* -------------------- */
1470		
1471		
1472		/* 
1473		CUSTOM JAVASCRIPT ANIMATION TWEEN 
1474		Lighter and faster than jquery animate() and css transitions 
1475		Animates top/left properties and includes easings 
1476		*/
1477		_tweenTo=function(el,prop,to,duration,easing,overwrite,callbacks){
1478			if(!el._mTween){el._mTween={top:{},left:{}};}
1479			var callbacks=callbacks || {},
1480				onStart=callbacks.onStart || function(){},onUpdate=callbacks.onUpdate || function(){},onComplete=callbacks.onComplete || function(){},
1481				startTime=_getTime(),_delay,progress=0,from=el.offsetTop,elStyle=el.style,_request,tobj=el._mTween[prop];
1482			if(prop==="left"){from=el.offsetLeft;}
1483			var diff=to-from;
1484			tobj.stop=0;
1485			if(overwrite!=="none"){_cancelTween();}
1486			_startTween();
1487			function _step(){
1488				if(tobj.stop){return;}
1489				if(!progress){onStart.call();}
1490				progress=_getTime()-startTime;
1491				_tween();
1492				if(progress>=tobj.time){
1493					tobj.time=(progress>tobj.time) ? progress+_delay-(progress-tobj.time) : progress+_delay-1;
1494					if(tobj.time<progress+1){tobj.time=progress+1;}
1495				}
1496				if(tobj.time<duration){tobj.id=_request(_step);}else{onComplete.call();}
1497			}
1498			function _tween(){
1499				if(duration>0){
1500					tobj.currVal=_ease(tobj.time,from,diff,duration,easing);
1501					elStyle[prop]=Math.round(tobj.currVal)+"px";
1502				}else{
1503					elStyle[prop]=to+"px";
1504				}
1505				onUpdate.call();
1506			}
1507			function _startTween(){
1508				_delay=1000/60;
1509				tobj.time=progress+_delay;
1510				_request=(!window.requestAnimationFrame) ? function(f){_tween(); return setTimeout(f,0.01);} : window.requestAnimationFrame;
1511				tobj.id=_request(_step);
1512			}
1513			function _cancelTween(){
1514				if(tobj.id==null){return;}
1515				if(!window.requestAnimationFrame){clearTimeout(tobj.id);
1516				}else{window.cancelAnimationFrame(tobj.id);}
1517				tobj.id=null;
1518			}
1519			function _ease(t,b,c,d,type){
1520				switch(type){
1521					case "linear":
1522						return c*t/d + b;
1523						break;
1524					case "linearOut":
1525						t/=d; t--; return c * Math.sqrt(1 - t*t) + b;
1526						break;
1527					case "easeInOutSmooth":
1528						t/=d/2;
1529						if(t<1) return c/2*t*t + b;
1530						t--;
1531						return -c/2 * (t*(t-2) - 1) + b;
1532						break;
1533					case "easeInOutStrong":
1534						t/=d/2;
1535						if(t<1) return c/2 * Math.pow( 2, 10 * (t - 1) ) + b;
1536						t--;
1537						return c/2 * ( -Math.pow( 2, -10 * t) + 2 ) + b;
1538						break;
1539					case "easeInOut":
1540						t/=d/2;
1541						if(t<1) return c/2*t*t*t + b;
1542						t-=2;
1543						return c/2*(t*t*t + 2) + b;
1544						break;
1545					case "easeOutSmooth":
1546						t/=d; t--;
1547						return -c * (t*t*t*t - 1) + b;
1548						break;
1549					case "easeOutStrong":
1550						return c * ( -Math.pow( 2, -10 * t/d ) + 1 ) + b;
1551						break;
1552					case "easeOut": default:
1553						var ts=(t/=d)*t,tc=ts*t;
1554						return b+c*(0.499999999999997*tc*ts + -2.5*ts*ts + 5.5*tc + -6.5*ts + 4*t);
1555				}
1556			}
1557		},
1558		/* -------------------- */
1559		
1560		
1561		/* returns current time */
1562		_getTime=function(){
1563			if(window.performance && window.performance.now){
1564				return window.performance.now();
1565			}else{
1566				if(window.performance && window.performance.webkitNow){
1567					return window.performance.webkitNow();
1568				}else{
1569					if(Date.now){return Date.now();}else{return new Date().getTime();}
1570				}
1571			}
1572		},
1573		/* -------------------- */
1574		
1575		
1576		/* stops a tween */
1577		_stopTween=function(){
1578			var el=this;
1579			if(!el._mTween){el._mTween={top:{},left:{}};}
1580			var props=["top","left"];
1581			for(var i=0; i<props.length; i++){
1582				var prop=props[i];
1583				if(el._mTween[prop].id){
1584					if(!window.requestAnimationFrame){clearTimeout(el._mTween[prop].id);
1585					}else{window.cancelAnimationFrame(el._mTween[prop].id);}
1586					el._mTween[prop].id=null;
1587					el._mTween[prop].stop=1;
1588				}
1589			}
1590		},
1591		/* -------------------- */
1592		
1593		
1594		/* deletes a property (avoiding the exception thrown by IE) */
1595		_delete=function(c,m){
1596			try{delete c[m];}catch(e){c[m]=null;}
1597		},
1598		/* -------------------- */
1599		
1600		
1601		/* detects left mouse button */
1602		_mouseBtnLeft=function(e){
1603			return !(e.which && e.which!==1);
1604		},
1605		/* -------------------- */
1606		
1607		
1608		/* detects if pointer type event is touch */
1609		_pointerTouch=function(e){
1610			var t=e.originalEvent.pointerType;
1611			return !(t && t!=="touch" && t!==2);
1612		},
1613		/* -------------------- */
1614		
1615		
1616		/* checks if value is numeric */
1617		_isNumeric=function(val){
1618			return !isNaN(parseFloat(val)) && isFinite(val);
1619		};
1620		/* -------------------- */
1621		
1622	
1623	
1624	
1625	
1626	/* 
1627	----------------------------------------
1628	PLUGIN SETUP 
1629	----------------------------------------
1630	*/
1631	
1632	/* plugin constructor functions */
1633	$.fn[pluginNS]=function(method){ /* usage: $(selector).fn(); */
1634		if(methods[method]){
1635			return methods[method].apply(this,Array.prototype.slice.call(arguments,1));
1636		}else if(typeof method==="object" || !method){
1637			return methods.init.apply(this,arguments);
1638		}else{
1639			$.error("Method "+method+" does not exist");
1640		}
1641	};
1642	$[pluginNS]=function(method){ /* usage: $.fn(); */
1643		if(methods[method]){
1644			return methods[method].apply(this,Array.prototype.slice.call(arguments,1));
1645		}else if(typeof method==="object" || !method){
1646			return methods.init.apply(this,arguments);
1647		}else{
1648			$.error("Method "+method+" does not exist");
1649		}
1650	};
1651	
1652	/* 
1653	allow setting plugin default options. 
1654	usage: $.mThumbnailScroller.defaults.speed=15; 
1655	to apply any changed default options on default selectors (below), use inside document ready fn 
1656	e.g.: $(document).ready(function(){ $.mThumbnailScroller.defaults.speed=15; });
1657	*/
1658	$[pluginNS].defaults=defaults;
1659	
1660	/* 
1661	add window object (window.mThumbnailScroller) 
1662	usage: if(window.mThumbnailScroller){console.log("plugin script loaded");}
1663	*/
1664	window[pluginNS]=true;
1665	
1666	/* call plugin fn automatically on default selector with HTML data attributes */
1667    $(window).on("load",function () {
1668        try {
1669		    var elems=$(defaultSelector),instances=[];
1670		    if(elems.length){
1671			    elems.each(function(){
1672				    var elem=$(this),axis=elem.data("mts-axis") || defaults.axis,type=elem.data("mts-type") || defaults.type,theme=elem.data("mts-theme") || defaults.theme,
1673					    elemClass="auto-"+pluginPfx+"-"+axis+"-"+type+"-"+theme,instance=[elemClass,axis,type];
1674				    elem.addClass(elemClass);
1675				    if($.inArray(elemClass,instances)===-1){
1676					    instances.push(instance);
1677				    }
1678			    });
1679			    for(var i=0; i<instances.length; i++){
1680				    $("."+instances[i][0])[pluginNS]({axis:instances[i][1],type:instances[i][2]}); 
1681			    }
1682            }
1683        }
1684        catch (err) {
1685            console.log(err);
1686        }
1687	});
1688	
1689})(jQuery,window,document);

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.