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