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