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.