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