1/*! Copyright (c) 2011 Piotr Rochala (http://rocha.la), Lanre Adebambo 2 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 3 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. 4 * 5 * Version: 1.3.7 6 * 7 */ 8(function ($) { 9 $.fn.extend({ 10 slimScroll: function (options) { 11 var defaults = { 12 // axis to apply scrollbars x(X) / y(Y) / both 13 axis: 'y', 14 15 // width in pixels of the visible scroll area 16 width: 'auto', 17 18 // height in pixels of the visible scroll area 19 height: '250px', 20 21 // width in pixels of the scrollbar and rail 22 size: '7px', 23 24 // scrollbar color, accepts any hex/color value 25 color: '#000', 26 27 // scrollbar position - top/bottom 28 positionX: 'bottom', 29 30 // scrollbar position - left/right 31 positionY: 'right', 32 33 // distance in pixels between the side edge and the scrollbar 34 distance: '1px', 35 36 // default scroll position on load - left/right / $('selector') 37 startX: 'left', 38 39 // default scroll position on load - top / bottom / $('selector') 40 startY: 'top', 41 42 // sets scrollbar opacity 43 opacity: 0.4, 44 45 // enables always-on mode for the scrollbar 46 alwaysVisible: false, 47 48 // check if we should hide the scrollbar when user is hovering over 49 disableFadeOut: false, 50 51 // sets visibility of the rail 52 railVisible: false, 53 54 // sets rail color 55 railColor: '#333', 56 57 // sets rail opacity 58 railOpacity: 0.2, 59 60 // whether we should use jQuery UI Draggable to enable bar dragging 61 railDraggable: true, 62 63 // defautlt CSS class of the slimscroll rail in X axis 64 railClassX: 'slimScrollRailX', 65 66 // defautlt CSS class of the slimscroll bar in X Axis 67 barClassX: 'slimScrollBarX', 68 69 // defautlt CSS class of the slimscroll rail in Y axis 70 railClassY: 'slimScrollRailY', 71 72 // defautlt CSS class of the slimscroll bar in Y axis 73 barClassY: 'slimScrollBarY', 74 75 // defautlt CSS class of the slimscroll wrapper 76 wrapperClass: 'slimScrollDiv', 77 78 animate: false, 79 80 // check if mousewheel should scroll the window if we reach top/bottom 81 allowPageScroll: false, 82 83 // scroll amount applied to each mouse wheel step 84 wheelStep: 20, 85 86 // scroll amount applied when user is using gestures 87 touchScrollStep: 200, 88 89 // sets border radius 90 borderRadius: '7px', 91 92 // sets border radius of the rail 93 railBorderRadius: '7px', 94 95 // handler, when slimScroll runned 96 ggSlimscrollHandler: false, 97 }; 98 99 var o = $.extend(defaults, options); 100 101 // normalize to lower case for ease of handling 102 o.axis = o.axis.toLowerCase(); 103 104 // do it for every element that matches selector 105 this.each(function () { 106 var hasHorizontalScrollbar; 107 var hasVerticalScrollbar; 108 var t, pageX, pageY; 109 var isOverPanel, 110 isOverBarX, 111 isOverBarY, 112 isDragg, 113 queueHideX, 114 queueHideY, 115 touchDifX, 116 touchDifY, 117 barHeight, 118 barWidth, 119 percentScrollX, 120 lastScrollX, 121 percentScrollY, 122 lastScrollY, 123 divS = '<div></div>', 124 minBarHeight = 30, 125 minBarWidth = 30, 126 releaseScroll = false; 127 128 // used in event handlers and for better minification 129 var me = $(this); 130 var $doc = $(document); 131 132 // ensure we are not binding it again 133 if (me.parent().hasClass(o.wrapperClass)) { 134 $.extend(o, me.data('slimScrollConfig') || {}); //retrieve previous config 135 // start from last bar position 136 var offset_horizontal = me.scrollLeft(); 137 var offset_vertical = me.scrollTop(); 138 139 // find bar and rail 140 barX = me.siblings('.' + o.barClassX); 141 railX = me.siblings('.' + o.railClassX); 142 barY = me.siblings('.' + o.barClassY); 143 railY = me.siblings('.' + o.railClassY); 144 145 //check that scroll bars are enabled 146 hasHorizontalScrollbar = o.axis == 'both' || o.axis == 'x'; 147 hasVerticalScrollbar = o.axis == 'both' || o.axis == 'y'; 148 149 getBarXWidth(); 150 getBarYHeight(); 151 152 // check if we should scroll existing instance 153 if ($.isPlainObject(options)) { 154 // Pass width: auto to an existing slimscroll object to force a resize after contents have changed 155 if ('width' in options && hasHorizontalScrollbar) { 156 if (options.width == 'auto') { 157 me.parent().css('width', 'auto'); 158 me.css('width', 'auto'); 159 o.width = me.parent().parent().width(); 160 } else { 161 o.width = options.width; 162 me.css({ 'white-space': 'nowrap' }); 163 } 164 } 165 166 // Pass height: auto to an existing slimscroll object to force a resize after contents have changed 167 if ('height' in options && hasVerticalScrollbar) { 168 if (options.height == 'auto') { 169 me.parent().css('height', 'auto'); 170 me.css('height', 'auto'); 171 o.height = me.parent().parent().height(); 172 } else { 173 o.height = options.height; 174 } 175 } 176 177 // rewrap content 178 me.parent().css({ 179 position: 'relative', 180 overflow: 'hidden', 181 width: o.width, 182 height: o.height, 183 }); 184 185 // update style for the div 186 me.css({ 187 overflow: 'hidden', 188 width: o.width, 189 height: o.height, 190 }); 191 192 if ('scrollToX' in options) { 193 // jump to a static point 194 offset_horizontal = parseInt(o.scrollToX); 195 } else if ('scrollByX' in options) { 196 // jump by value pixels 197 offset_horizontal += parseInt(o.scrollByX); 198 } 199 if ('scrollToY' in options) { 200 // jump to a static point 201 offset_vertical = parseInt(o.scrollToY); 202 } else if ('scrollByY' in options) { 203 // jump by value pixels 204 offset_vertical += parseInt(o.scrollByY); 205 } 206 207 if ('destroy' in options) { 208 // remove slimscroll elements 209 barX.remove(); 210 railX.remove(); 211 barY.remove(); 212 railY.remove(); 213 me.unwrap(); 214 return; 215 } 216 } 217 // scroll content by the given offset 218 scrollContent(offset_horizontal, offset_vertical, false, true); 219 220 return; 221 } else if ($.isPlainObject(options)) { 222 if ('destroy' in options) { 223 return; 224 } 225 } 226 227 //check that scroll bars are enabled 228 hasHorizontalScrollbar = o.axis == 'both' || o.axis == 'x'; 229 hasVerticalScrollbar = o.axis == 'both' || o.axis == 'y'; 230 231 // optionally set height/width to the parent's height/width 232 o.height = o.height == 'auto' ? me.parent().height() : o.height; 233 o.width = o.width == 'auto' ? me.parent().width() : o.width; 234 235 //store options in DOM
236 me.data('slimScrollConfig', o); 237 238 // wrap content 239 var wrapper = $(divS).addClass(o.wrapperClass).css({ 240 position: 'relative', 241 overflow: 'hidden', 242 width: o.width, 243 height: o.height, 244 }); 245 246 // update style for the div 247 me.css({ 248 overflow: 'hidden', 249 width: o.width, 250 height: o.height, 251 }); 252 253 // wrap it 254 me.wrap(wrapper); 255 256 if (hasHorizontalScrollbar) { 257 // if width is specified remove wrapping from text 258 if (o.width != 'auto' && hasHorizontalScrollbar) { 259 me.css({ 'white-space': 'nowrap' }); 260 } 261 262 // create scrollbar rail 263 var railX = $(divS) 264 .addClass(o.railClassX) 265 .css({ 266 width: '100%', 267 height: o.size, 268 position: 'absolute', 269 left: 0, 270 display: o.alwaysVisible && o.railVisible ? 'block' : 'none', 271 'border-radius': o.railBorderRadius, 272 background: o.railColor, 273 opacity: o.railOpacity, 274 zIndex: 90, 275 }); 276 277 // create scrollbar 278 var barX = $(divS) 279 .addClass(o.barClassX) 280 .css({ 281 background: o.color, 282 height: o.size, 283 position: 'absolute', 284 left: 0, 285 opacity: o.opacity, 286 display: o.alwaysVisible ? 'block' : 'none', 287 'border-radius': o.borderRadius, 288 BorderRadius: o.borderRadius, 289 MozBorderRadius: o.borderRadius, 290 WebkitBorderRadius: o.borderRadius, 291 zIndex: 99, 292 }); 293 294 // set position 295 var xPosCss = o.positionX == 'top' ? { top: o.distance } : { bottom: o.distance }; 296 railX.css(xPosCss); 297 barX.css(xPosCss); 298 299 // append to parent div 300 me.parent().append(barX); 301 me.parent().append(railX); 302 303 // make it draggable and no longer dependent on the jqueryUI 304 if (o.railDraggable) { 305 barX 306 .on('mousedown', function (e) { 307 isDragg = true; 308 t = parseFloat(barX.css('left')); 309 pageX = e.pageX; 310 311 $doc.on('mousemove.slimscrollX', function (e) { 312 currLeft = t + e.pageX - pageX; 313 barX.css('left', currLeft); 314 scrollContent(0, 0, barX.position().left); // scroll content 315 }); 316 317 $doc.on('mouseup.slimscrollX', function (e) { 318 isDragg = false; 319 hideBarX(); 320 $doc.unbind('.slimscrollX'); 321 }); 322 return false; 323 }) 324 .on('selectstart.slimscrollX', function (e) { 325 e.stopPropagation(); 326 e.preventDefault(); 327 return false; 328 }); 329 330 railX.on('mousedown', function (e) { 331 var deltaX = ((e.offsetX - barWidth / 2) * me[0].scrollWidth) / me.outerWidth(); 332 scrollContent(deltaX, 0, false, true); // scroll content 333 t = parseFloat(barX.css('left')); 334 pageX = e.pageX; 335 336 $doc.on('mousemove.slimscrollX', function (e) { 337 currLeft = t + e.pageX - pageX; 338 barX.css('left', currLeft); 339 scrollContent(0, 0, barX.position().left); // scroll content 340 }); 341 342 $doc.on('mouseup.slimscrollX', function (e) { 343 isDragg = false; 344 hideBarX(); 345 $doc.unbind('.slimscrollX'); 346 }); 347 return false; 348 }); 349 } 350 351 // on rail over 352 railX.hover( 353 function () { 354 showBarX(); 355 }, 356 function () { 357 hideBarX(); 358 } 359 ); 360 361 // on bar over 362 barX.hover( 363 function () { 364 isOverBarX = true; 365 }, 366 function () { 367 isOverBarX = false; 368 } 369 ); 370 371 // set up initial width and height 372 getBarXWidth(); 373 374 // check start position 375 if (o.startX === 'right') { 376 // scroll content to rigth 377 barX.css({ left: me.outerWidth() - barX.outerWidth() }); 378 scrollContent(0, 0, true); 379 } else if (o.startX !== 'left') { 380 // assume jQuery selector 381 scrollContent($(o.startX).position().left, null, null, true); 382 383 // make sure bar stays hidden 384 if (!o.alwaysVisible) { 385 barX.hide(); 386 } 387 } 388 } 389 390 if (hasVerticalScrollbar) { 391 // create scrollbar rail 392 var railY = $(divS) 393 .addClass(o.railClassY) 394 .css({ 395 width: o.size, 396 height: '100%', 397 position: 'absolute', 398 top: 0, 399 display: o.alwaysVisible && o.railVisible ? 'block' : 'none', 400 'border-radius': o.railBorderRadius, 401 background: o.railColor, 402 opacity: o.railOpacity, 403 zIndex: 90, 404 }); 405 406 // create scrollbar 407 var barY = $(divS) 408 .addClass(o.barClassY) 409 .css({ 410 background: o.color, 411 width: o.size, 412 position: 'absolute', 413 top: 0, 414 opacity: o.opacity, 415 display: o.alwaysVisible ? 'block' : 'none', 416 'border-radius': o.borderRadius, 417 BorderRadius: o.borderRadius, 418 MozBorderRadius: o.borderRadius, 419 WebkitBorderRadius: o.borderRadius, 420 zIndex: 99, 421 }); 422 423 var yPosCss = o.positionY == 'right' ? { right: o.distance } : { left: o.distance }; 424 railY.css(yPosCss); 425 barY.css(yPosCss); 426 427 me.parent().append(barY); 428 me.parent().append(railY); 429 430 if (o.railDraggable) { 431 barY 432 .on('mousedown', function (e) { 433 isDragg = true; 434 t = parseFloat(barY.css('top')); 435 pageY = e.pageY; 436 437 $doc.on('mousemove.slimscrollY', function (e) { 438 currTop = t + e.pageY - pageY; 439 barY.css('top', currTop); 440 scrollContent(0, 0, barY.position().top); // scroll content 441 }); 442 443 $doc.on('mouseup.slimscrollY', function (e) { 444 isDragg = false; 445 hideBarY(); 446 $doc.unbind('.slimscrollY'); 447 }); 448 return false; 449 }) 450 .on('selectstart.slimscrollY', function (e) { 451 e.stopPropagation(); 452 e.preventDefault(); 453 return false; 454 }); 455 456 railY.on('mousedown', function (e) { 457 var deltaY = ((e.offsetY - barHeight / 2) * me[0].scrollHeight) / me.outerHeight(); 458 scrollContent(0, deltaY, false, true); // scroll content 459 t = parseFloat(barY.css('top')); 460 pageY = e.pageY; 461 462 $doc.on('mousemove.slimscrollY', function (e) { 463 currTop = t + e.pageY - pageY; 464 barY.css('top', currTop); 465 scrollContent(0, 0, barY.position().top); // scroll content 466 }); 467 468 $doc.on('mouseup.slimscrollY', function (e) { 469 isDragg = false; 470 hideBarY(); 471 $doc.unbind('.slimscrollY'); 472 }); 473 return false; 474 }); 475 } 476 477 // on rail over 478 railY.hover( 479 function () { 480 showBarY(); 481 }, 482 function () { 483 hideBarY(); 484 } 485 ); 486 487 // on bar over 488 barY.hover( 489 function () { 490 isOverBarY = true; 491 }, 492 function () { 493 isOverBarY = false; 494 } 495 ); 496 497 getBarYHeight(); 498 499 if (o.startY === 'bottom') { 500 // scroll content to bottom 501 barY.css({ top: me.outerHeight() - barY.outerHeight() }); 502 scrollContent(0, 0, true); 503 } else if (o.startY !== 'top') { 504 // assume jQuery selector 505 scrollContent(null, $(o.startY).position().top, null, true); 506 507 // make sure bar stays hidden 508 if (!o.alwaysVisible) { 509 barY.hide(); 510 } 511 } 512 } 513 514 // show on parent mouseover 515 me.hover( 516 function () { 517 isOverPanel = true; 518 showBarX(); 519 showBarY(); 520 hideBarX(); 521 hideBarY(); 522 }, 523 function () { 524 isOverPanel = false; 525 hideBarX(); 526 hideBarY(); 527 } 528 ); 529 530 // // support for mobile 531 // me.on('touchstart', function(e,b){ 532 // if (e.originalEvent.touches.length) 533 // { 534 // // record where touch started 535 // touchDifX = e.originalEvent.touches[0].pageX; 536 // touchDifY = e.originalEvent.touches[0].pageY; 537 // } 538 // }); 539 // 540 // me.on('touchmove', function(e){
541 // // prevent scrolling the page if necessary 542 // if(!releaseScroll) 543 // { 544 // e.originalEvent.preventDefault(); 545 // } 546 // if (e.originalEvent.touches.length) 547 // { 548 // // see how far user swiped 549 // var diffX = (touchDifX - e.originalEvent.touches[0].pageX) / o.touchScrollStep; 550 // var diffY = (touchDifY - e.originalEvent.touches[0].pageY) / o.touchScrollStep; 551 // // scroll content 552 // scrollContent(diffX, diffY, true); 553 // touchDifX = e.originalEvent.touches[0].pageX; 554 // touchDifY = e.originalEvent.touches[0].pageY; 555 // } 556 // }); 557 //enable gesture recognize for this plugin 558 var _triggerInit = function () { 559 if (typeof Hammer_gg == 'undefined') { 560 setTimeout(_triggerInit, 100); 561 return; 562 } 563 564 if (o.isMobile) { 565 var hammer = new Hammer_gg(this), 566 scrollWidth = 50; 567 568 hammer.get('pan').set({ 569 threshold: scrollWidth, 570 }); 571 572 hammer.on('panleft', function (e) { 573 scrollContent(0, scrollWidth, false, false, true); 574 panDistance = e.distance; 575 }); 576 577 hammer.on('panend', function (e) { 578 var offset = scrollWidth * (e.velocityX * -1) * 30; 579 scrollContent(0, offset, false, false, true); 580 }); 581 582 hammer.on('panright', function (e) { 583 scrollContent(0, -scrollWidth, false, false, true); 584 panDistance = e.distance; 585 }); 586 } 587 }; 588 _triggerInit(); 589 590 // attach scroll events 591 attachWheel(this); 592 593 function _getDeltaFromEvent(e) { 594 var deltaX = 0; 595 var deltaY = 0; 596 597 // Old school scrollwheel delta 598 //if ( 'detail' in e ) { deltaY = e.detail; } 599 //if ( 'wheelDelta' in e ) { deltaY = -1 * e.wheelDelta / 6; } 600 //if ( 'wheelDeltaY' in e ) { deltaY = -1 * e.wheelDeltaY / 6; } 601 //if ( 'wheelDeltaX' in e ) { deltaX = e.wheelDeltaX / 6; } 602 603 // stackOverFlow school )) 604 deltaX = (e.deltaX || -e.wheelDelta || e.detail) >> 10 || 1; 605 deltaY = (e.deltaY || -e.wheelDelta || e.detail) >> 10 || 1; 606 607 // Firefox < 17 horizontal scrolling related to DOMMouseScroll event 608 if ('axis' in e && e.axis === e.HORIZONTAL_AXIS) { 609 deltaX = deltaY * -1; 610 deltaY = 0; 611 } 612 613 if (deltaX !== deltaX && deltaY !== deltaY /* NaN checks */) { 614 // IE in some mouse drivers 615 deltaX = 0; 616 // deltaY = e.wheelDelta; 617 } 618 619 // New school wheel delta (wheel event) 620 //if ( 'deltaY' in e ) { 621 // deltaY = e.deltaY; 622 //} 623 //if ( 'deltaX' in e ) { 624 // deltaX = e.deltaX; 625 //} 626 627 return [deltaX, deltaY]; 628 } 629 630 function _onWheel(e) { 631 // use mouse wheel only when mouse is over 632 if (!isOverPanel) { 633 return; 634 } 635 636 e = e || window.event; 637 638 var delta = _getDeltaFromEvent(e); 639 var deltaX = delta[0]; 640 var deltaY = delta[1]; 641 642 // if (e.wheelDelta) { delta = -e.wheelDelta/120; } 643 // if (e.detail) { delta = e.detail / 3; } 644 645 var target = e.target || e.srcTarget || e.srcElement; 646 if ( 647 $(target) 648 .closest('.' + o.wrapperClass) 649 .is(me.parent()) 650 ) { 651 // scroll content 652 scrollContent(deltaX, deltaY, true); 653 } 654 655 // stop window scroll 656 if (e.preventDefault && !releaseScroll) { 657 e.preventDefault(); 658 e.stopPropagation(); 659 } 660 if (!releaseScroll) { 661 e.returnValue = false; 662 } 663 } 664
665 function scrollContent(x, y, isWheel, isJump, isPan) { 666 releaseScroll = false; 667 var needToRunWindowScroll = false, 668 prevBarXOffset = 0; 669 670 if (hasHorizontalScrollbar) { 671 var deltaX = x; 672 var maxLeft = me.outerWidth() - barX.outerWidth(), 673 totalWidth = me[0].scrollWidth, 674 scrollOffset = me.scrollLeft(), 675 barXOffset = parseFloat(barX.css('left')); 676 677 if (isWheel) { 678 if (!hasVerticalScrollbar) { 679 x = y; 680 } 681 // move bar with mouse wheel 682 deltaX = parseInt(barX.css('left')) + x * parseInt(o.wheelStep); 683 684 // move bar, make sure it doesn't go out 685 deltaX = Math.min(Math.max(deltaX, 0), maxLeft); 686 687 // if scrolling right, make sure a fractional change to the 688 // scroll position isn't rounded away when the scrollbar's CSS is set 689 // this flooring of delta would happened automatically when 690 // bar.css is set below, but we floor here for clarity 691 deltaX = x > 0 ? Math.ceil(deltaX) : Math.floor(deltaX); 692 693 // scroll the scrollbar 694 barX.css({ left: deltaX + 'px' }); 695 // recalc distance for images 696 prevBarXOffset = barXOffset; 697 barXOffset = parseFloat(barX.css('left')); 698 needToRunWindowScroll = prevBarXOffset == barXOffset; 699 } 700 701 // calculate actual scroll amount 702 percentScrollX = barXOffset / maxLeft; 703 deltaX = percentScrollX * (totalWidth - me.outerWidth()); 704 705 if (isPan) { 706 deltaX = totalWidth - (totalWidth - scrollOffset - y); 707 708 var panOffsetPercent = deltaX / (totalWidth - me.outerWidth()); 709 var scrollBarOffset = maxLeft * panOffsetPercent; 710 711 scrollBarOffset = Math.min(Math.max(scrollBarOffset, 0), maxLeft); 712 scrollBarOffset = x > 0 ? Math.ceil(scrollBarOffset) : Math.floor(scrollBarOffset); 713 714 barX.stop(true, true).animate({ left: scrollBarOffset + 'px' }, 300, 'linear'); 715 } 716 717 if (isJump) { 718 if (!hasVerticalScrollbar) { 719 x = y; 720 } 721 deltaX = x; 722 var offsetLeft = (deltaX / me[0].scrollWidth) * me.outerWidth(); 723 offsetLeft = Math.min(Math.max(offsetLeft, 0), maxLeft); 724 barX.css({ left: offsetLeft + 'px' }); 725 } 726 727 // scroll content and fire scrolling event 728 if (o.animate) { 729 me.scrollTop(deltaX); // scroll content smoothly using jquery animation 730 me.stop(true, true).animate({ scrollLeft: deltaX }, 500, 'linear'); 731 } else { 732 // scroll content 733 me.scrollLeft(deltaX); 734 } 735 me.trigger('slimscrollingX', ~~deltaX); 736 737 // ensure bar is visible 738 showBarX(needToRunWindowScroll); 739 740 // trigger hide when scroll is stopped 741 hideBarX(); 742 } 743 744 if (hasVerticalScrollbar) { 745 var deltaY = y; 746 var maxTop = me.outerHeight() - barY.outerHeight(); 747 748 if (isWheel) { 749 // move bar with mouse wheel 750 deltaY = parseInt(barY.css('top')) + (y * parseInt(o.wheelStep)) / 100; 751 752 // move bar, make sure it doesn't go out 753 deltaY = Math.min(Math.max(deltaY, 0), maxTop); 754 755 // if scrolling down, make sure a fractional change to the 756 // scroll position isn't rounded away when the scrollbar's CSS is set 757 // this flooring of delta would happened automatically when 758 // bar.css is set below, but we floor here for clarity 759 deltaY = y > 0 ? Math.ceil(deltaY) : Math.floor(deltaY); 760 761 // scroll the scrollbar 762 barY.css({ top: deltaY + 'px' }); 763 } 764 765 // calculate actual scroll amount 766 percentScrollY = parseInt(barY.css('top')) / (me.outerHeight() - barY.outerHeight()); 767 deltaY = percentScrollY * (me[0].scrollHeight - me.outerHeight()); 768 769 if (isJump) { 770 deltaY = y; 771 var offsetTop = (deltaY / me[0].scrollHeight) * me.outerHeight(); 772 offsetTop = Math.min(Math.max(offsetTop, 0), maxTop); 773 barY.css({ top: offsetTop + 'px' }); 774 } 775 776 // scroll content and fire scrolling event 777 me.scrollTop(deltaY); 778 me.trigger('slimscrollingY', ~~deltaY); 779 780 // ensure bar is visible 781 showBarY(); 782 783 // trigger hide when scroll is stopped 784 hideBarY(); 785 } 786 if (o.ggSlimscrollHandler) { 787 o.ggSlimscrollHandler(); 788 } 789 } 790 791 function attachWheel(target) { 792 if (window.addEventListener) { 793 if (typeof window.onwheel !== 'undefined') { 794 target.addEventListener('wheel', _onWheel, false); 795 } else if (typeof window.onmousewheel !== 'undefined') { 796 target.addEventListener('mousewheel', _onWheel, false); 797 } 798 target.addEventListener('DOMMouseScroll', _onWheel, false); 799 } else { 800 document.attachEvent('onmousewheel', _onWheel); 801 } 802 } 803 804 function getBarXWidth() { 805 if (!barX) { 806 return; 807 } 808 // calculate scrollbar height and make sure it is not too small 809 barWidth = Math.max((me.outerWidth() / me[0].scrollWidth) * me.outerWidth(), minBarWidth);
810 barX.css({ width: barWidth + 'px' }); 811 812 // hide scrollbar if content is not long enough 813 // var display = barWidth == me.outerWidth() ? 'none' : 'block'; 814 var display = hasHorizontalScrollbar && me[0].scrollWidth > me[0].clientWidth ? 'block' : 'none'; 815 barX.css({ display: display }); 816 } 817 818 function getBarYHeight() { 819 if (!barY) { 820 return; 821 } 822 // calculate scrollbar height and make sure it is not too small 823 barHeight = Math.max((me.outerHeight() / me[0].scrollHeight) * me.outerHeight(), minBarHeight); 824 barY.css({ height: barHeight + 'px' }); 825 826 // hide scrollbar if content is not long enough 827 // var display = barHeight == me.outerHeight() ? 'none' : 'block'; 828 var display = hasVerticalScrollbar && me[0].scrollHeight > me[0].clientHeight ? 'block' : 'none'; 829 barY.css({ display: display }); 830 } 831 832 function showBarX(needToRunWindowScroll) { 833 if (!barX) { 834 return; 835 } 836 // recalculate bar height 837 getBarXWidth(); 838 clearTimeout(queueHideX); 839 840 // when bar reached top or bottom 841 if (percentScrollX == ~~percentScrollX && needToRunWindowScroll) { 842 //release wheel 843 releaseScroll = o.allowPageScroll; 844 845 // publish approporiate event 846 if (lastScrollX != percentScrollX) { 847 var msg = ~~percentScrollX === 0 ? 'left' : 'right'; 848 me.trigger('slimscrollX', msg); 849 } 850 } else { 851 releaseScroll = false; 852 } 853 lastScrollX = percentScrollX; 854 855 // show only when required 856 if (barWidth >= me.outerWidth()) { 857 //allow window scroll 858 releaseScroll = true; 859 return; 860 } 861 barX.fadeIn('fast'); 862 if (o.railVisible) { 863 railX.stop(true, true).fadeIn('fast'); 864 } 865 } 866 867 function hideBarX() { 868 if (!barX) { 869 return; 870 } 871 // only hide when options allow it 872 if (!o.alwaysVisible) { 873 queueHideX = setTimeout(function () { 874 if (!(o.disableFadeOut && isOverPanel) && !isOverBarX && !isDragg) { 875 barX.fadeOut('slow'); 876 railX.fadeOut('slow'); 877 } 878 }, 1000); 879 } 880 } 881 882 function showBarY() { 883 if (!barY) { 884 return; 885 } 886 // recalculate bar height 887 getBarYHeight(); 888 clearTimeout(queueHideY); 889 890 // when bar reached top or bottom 891 if (percentScrollY == ~~percentScrollY) { 892 //release wheel 893 releaseScroll = o.allowPageScroll; 894 895 // publish approporiate event 896 if (lastScrollY != percentScrollY) { 897 var msg = ~~percentScrollY === 0 ? 'top' : 'bottom'; 898 me.trigger('slimscrollY', msg); 899 } 900 } else { 901 releaseScroll = false; 902 } 903 lastScrollY = percentScrollY; 904 905 // show only when required 906 if (barHeight >= me.outerHeight()) { 907 //allow window scroll 908 releaseScroll = true; 909 return; 910 } 911 barY.stop(true, true).fadeIn('fast'); 912 if (o.railVisible) { 913 railY.stop(true, true).fadeIn('fast'); 914 } 915 } 916 917 function hideBarY() { 918 if (!barY) { 919 return; 920 } 921 // only hide when options allow it 922 if (!o.alwaysVisible) { 923 queueHideY = setTimeout(function () { 924 if (!(o.disableFadeOut && isOverPanel) && !isOverBarY && !isDragg) { 925 barY.fadeOut('slow'); 926 railY.fadeOut('slow'); 927 } 928 }, 1000); 929 } 930 } 931 }); 932 933 // maintain chainability 934 return this; 935 }, 936 }); 937 938 $.fn.extend({ 939 slimscroll: $.fn.slimScroll, 940 }); 941})(jQuery);
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.