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