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