1/*! perfect-scrollbar - v0.4.11 2* http://noraesae.github.com/perfect-scrollbar/ 3* Copyright (c) 2014 Hyeonje Alex Jun; Licensed MIT 4* 5* Edited by Rik de Vos (www.rikdevos.com) 6* 7*/ 8(function (factory) { 9 'use strict'; 10 11 if (typeof define === 'function' && define.amd) { 12 // AMD. Register as an anonymous module. 13 define(['jquery'], factory); 14 } else if (typeof exports === 'object') { 15 // Node/CommonJS 16 factory(require('jquery')); 17 } else { 18 // Browser globals 19 factory(jQuery); 20 } 21}(function ($) { 22 'use strict'; 23 24 // The default settings for the plugin 25 var defaultSettings = { 26 wheelSpeed: 10, 27 wheelPropagation: false, 28 minScrollbarLength: null, 29 maxScrollbarLength: null, 30 useBothWheelAxes: false, 31 useKeyboard: true, 32 suppressScrollX: false, 33 suppressScrollY: false, 34 scrollXMarginOffset: 0, 35 scrollYMarginOffset: 0, 36 includePadding: false 37 }; 38 39 var getEventClassName = (function () { 40 var incrementingId = 0; 41 return function () { 42 var id = incrementingId; 43 incrementingId += 1; 44 return '.perfect-scrollbar-' + id; 45 }; 46 }()); 47 48 $.fn.perfectScrollbarTimetable = function (suppliedSettings, option) { 49 50 return this.each(function () { 51 // Use the default settings 52 var settings = $.extend(true, {}, defaultSettings), 53 $this = $(this); 54 55 if (typeof suppliedSettings === "object") { 56 // But over-ride any supplied 57 $.extend(true, settings, suppliedSettings); 58 } else { 59 // If no settings were supplied, then the first param must be the option 60 option = suppliedSettings; 61 } 62 63 // Catch options 64 65 if (option === 'update') { 66 if ($this.data('perfect-scrollbar-update')) { 67 $this.data('perfect-scrollbar-update')(); 68 } 69 return $this; 70 } 71 else if (option === 'destroy') { 72 if ($this.data('perfect-scrollbar-destroy')) { 73 $this.data('perfect-scrollbar-destroy')(); 74 } 75 return $this; 76 } 77 78 if ($this.data('perfect-scrollbar')) { 79 // if there's already perfect-scrollbar 80 return $this.data('perfect-scrollbar'); 81 } 82 83 84 // Or generate new perfectScrollbar 85 86 // Set class to the container 87 $this.addClass('ps-container'); 88 89 var $scrollbarXRail = $("<div class='ps-scrollbar-x-rail'></div>").appendTo($this), 90 $scrollbarYRail = $("<div class='ps-scrollbar-y-rail'></div>").appendTo($this), 91 $scrollbarX = $("<div class='ps-scrollbar-x'></div>").appendTo($scrollbarXRail), 92 $scrollbarY = $("<div class='ps-scrollbar-y'></div>").appendTo($scrollbarYRail), 93 scrollbarXActive, 94 scrollbarYActive, 95 containerWidth, 96 containerHeight, 97 contentWidth, 98 contentHeight, 99 scrollbarXWidth, 100 scrollbarXLeft, 101 scrollbarXBottom = parseInt($scrollbarXRail.css('bottom'), 10), 102 isScrollbarXUsingBottom = scrollbarXBottom === scrollbarXBottom, // !isNaN 103 scrollbarXTop = isScrollbarXUsingBottom ? null : parseInt($scrollbarXRail.css('top'), 10), 104 scrollbarYHeight, 105 scrollbarYTop, 106 scrollbarYRight = parseInt($scrollbarYRail.css('right'), 10), 107 isScrollbarYUsingRight = scrollbarYRight === scrollbarYRight, // !isNaN 108 scrollbarYLeft = isScrollbarYUsingRight ? null: parseInt($scrollbarYRail.css('left'), 10), 109 isRtl = $this.css('direction') === "rtl", 110 eventClassName = getEventClassName(), 111 railBorderXWidth = parseInt($scrollbarXRail.css('borderLeftWidth'), 10) + parseInt($scrollbarXRail.css('borderRightWidth'), 10), 112 railBorderYWidth = parseInt($scrollbarXRail.css('borderTopWidth'), 10) + parseInt($scrollbarXRail.css('borderBottomWidth'), 10); 113 114 var updateContentScrollTop = function (currentTop, deltaY) { 115 var newTop = currentTop + deltaY, 116 maxTop = containerHeight - scrollbarYHeight; 117 118 if (newTop < 0) { 119 scrollbarYTop = 0; 120 } 121 else if (newTop > maxTop) { 122 scrollbarYTop = maxTop; 123 } 124 else { 125 scrollbarYTop = newTop; 126 } 127 128 var scrollTop = parseInt(scrollbarYTop * (contentHeight - containerHeight) / (containerHeight - scrollbarYHeight), 10); 129 $this.scrollTop(scrollTop); 130 }; 131 132 var updateContentScrollLeft = function (currentLeft, deltaX) { 133 134 var newLeft = currentLeft + deltaX, 135 maxLeft = containerWidth - scrollbarXWidth; 136 137 if (newLeft < 0) { 138 scrollbarXLeft = 0; 139 } 140 else if (newLeft > maxLeft) { 141 scrollbarXLeft = maxLeft; 142 } 143 else { 144 scrollbarXLeft = newLeft; 145 } 146 147 var scrollLeft = parseInt(scrollbarXLeft * (contentWidth - containerWidth) / (containerWidth - scrollbarXWidth), 10); 148 $this.scrollLeft(scrollLeft); 149 }; 150 151 var getSettingsAdjustedThumbSize = function (thumbSize) { 152 if (settings.minScrollbarLength) { 153 thumbSize = Math.max(thumbSize, settings.minScrollbarLength); 154 } 155 if (settings.maxScrollbarLength) { 156 thumbSize = Math.min(thumbSize, settings.maxScrollbarLength); 157 } 158 return thumbSize; 159 }; 160 161 var updateScrollbarCss = function () { 162 163 var scrollbarXStyles = {width: containerWidth, display: scrollbarXActive ? "inherit": "none"}; 164 if (isRtl) { 165 scrollbarXStyles.left = $this.scrollLeft() + containerWidth - contentWidth; 166 } else { 167 scrollbarXStyles.left = $this.scrollLeft(); 168 } 169 if (isScrollbarXUsingBottom) { 170 scrollbarXStyles.bottom = scrollbarXBottom - $this.scrollTop(); 171 } else { 172 scrollbarXStyles.top = scrollbarXTop + $this.scrollTop(); 173 } 174 $scrollbarXRail.css(scrollbarXStyles); 175 176 var scrollbarYStyles = {top: $this.scrollTop(), height: containerHeight, display: scrollbarYActive ? "inherit": "none"}; 177 178 if (isScrollbarYUsingRight) { 179 if (isRtl) { 180 scrollbarYStyles.right = contentWidth - $this.scrollLeft() - scrollbarYRight - $scrollbarY.outerWidth(); 181 } else { 182 scrollbarYStyles.right = scrollbarYRight - $this.scrollLeft(); 183 } 184 } else { 185 if (isRtl) { 186 scrollbarYStyles.left = $this.scrollLeft() + containerWidth * 2 - contentWidth - scrollbarYLeft - $scrollbarY.outerWidth(); 187 } else { 188 scrollbarYStyles.left = scrollbarYLeft + $this.scrollLeft(); 189 } 190 } 191 $scrollbarYRail.css(scrollbarYStyles); 192 193 $scrollbarX.css({left: scrollbarXLeft, width: scrollbarXWidth - railBorderXWidth}); 194 $scrollbarY.css({top: scrollbarYTop, height: scrollbarYHeight - railBorderYWidth}); 195 196 if (scrollbarXActive) { 197 $this.addClass('ps-active-x'); 198 } else { 199 $this.removeClass('ps-active-x'); 200 } 201 202 if (scrollbarYActive) { 203 $this.addClass('ps-active-y'); 204 } else { 205 $this.removeClass('ps-active-y'); 206 } 207 208 //add callback
209 if(typeof(settings.scroll) !== typeof(undefined)) { 210 settings.scroll($this.scrollLeft()); 211 } 212 213 }; 214 215 var updateBarSizeAndPosition = function () { 216 containerWidth = settings.includePadding ? $this.innerWidth() : $this.width(); 217 containerHeight = settings.includePadding ? $this.innerHeight() : $this.height(); 218 contentWidth = $this.prop('scrollWidth'); 219 contentHeight = $this.prop('scrollHeight'); 220 221 if (!settings.suppressScrollX && containerWidth + settings.scrollXMarginOffset < contentWidth) { 222 scrollbarXActive = true; 223 scrollbarXWidth = getSettingsAdjustedThumbSize(parseInt(containerWidth * containerWidth / contentWidth, 10)); 224 scrollbarXLeft = parseInt($this.scrollLeft() * (containerWidth - scrollbarXWidth) / (contentWidth - containerWidth), 10); 225 } 226 else { 227 scrollbarXActive = false; 228 scrollbarXWidth = 0; 229 scrollbarXLeft = 0; 230 $this.scrollLeft(0); 231 } 232 233 if (!settings.suppressScrollY && containerHeight + settings.scrollYMarginOffset < contentHeight) { 234 scrollbarYActive = true; 235 scrollbarYHeight = getSettingsAdjustedThumbSize(parseInt(containerHeight * containerHeight / contentHeight, 10)); 236 scrollbarYTop = parseInt($this.scrollTop() * (containerHeight - scrollbarYHeight) / (contentHeight - containerHeight), 10); 237 } 238 else { 239 scrollbarYActive = false; 240 scrollbarYHeight = 0; 241 scrollbarYTop = 0; 242 $this.scrollTop(0); 243 } 244 245 if (scrollbarYTop >= containerHeight - scrollbarYHeight) { 246 scrollbarYTop = containerHeight - scrollbarYHeight; 247 } 248 if (scrollbarXLeft >= containerWidth - scrollbarXWidth) { 249 scrollbarXLeft = containerWidth - scrollbarXWidth; 250 } 251 252 updateScrollbarCss(); 253 }; 254 255 var bindMouseScrollXHandler = function () { 256 var currentLeft, 257 currentPageX; 258 259 $scrollbarX.bind('mousedown' + eventClassName, function (e) { 260 currentPageX = e.pageX; 261 currentLeft = $scrollbarX.position().left; 262 $scrollbarXRail.addClass('in-scrolling'); 263 e.stopPropagation(); 264 e.preventDefault(); 265 }); 266 267 $(document).bind('mousemove' + eventClassName, function (e) { 268 if ($scrollbarXRail.hasClass('in-scrolling')) { 269 updateContentScrollLeft(currentLeft, e.pageX - currentPageX); 270 updateBarSizeAndPosition(); 271 e.stopPropagation(); 272 e.preventDefault(); 273 } 274 }); 275 276 $(document).bind('mouseup' + eventClassName, function (e) { 277 if ($scrollbarXRail.hasClass('in-scrolling')) { 278 $scrollbarXRail.removeClass('in-scrolling'); 279 } 280 }); 281 282 currentLeft = 283 currentPageX = null; 284 }; 285 286 var bindMouseScrollYHandler = function () { 287 var currentTop, 288 currentPageY; 289 290 $scrollbarY.bind('mousedown' + eventClassName, function (e) { 291 currentPageY = e.pageY; 292 currentTop = $scrollbarY.position().top; 293 $scrollbarYRail.addClass('in-scrolling'); 294 e.stopPropagation(); 295 e.preventDefault(); 296 }); 297 298 $(document).bind('mousemove' + eventClassName, function (e) { 299 if ($scrollbarYRail.hasClass('in-scrolling')) { 300 updateContentScrollTop(currentTop, e.pageY - currentPageY); 301 updateBarSizeAndPosition(); 302 e.stopPropagation(); 303 e.preventDefault(); 304 } 305 }); 306 307 $(document).bind('mouseup' + eventClassName, function (e) { 308 if ($scrollbarYRail.hasClass('in-scrolling')) { 309 $scrollbarYRail.removeClass('in-scrolling'); 310 } 311 }); 312 313 currentTop = 314 currentPageY = null; 315 }; 316 317 // check if the default scrolling should be prevented. 318 var shouldPreventDefault = function (deltaX, deltaY) { 319 var scrollTop = $this.scrollTop(); 320 if (deltaX === 0) { 321 if (!scrollbarYActive) { 322 return false;
323 } 324 if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= contentHeight - containerHeight && deltaY < 0)) { 325 return !settings.wheelPropagation; 326 } 327 } 328 329 var scrollLeft = $this.scrollLeft(); 330 if (deltaY === 0) { 331 if (!scrollbarXActive) { 332 return false; 333 } 334 if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= contentWidth - containerWidth && deltaX > 0)) { 335 return !settings.wheelPropagation; 336 } 337 } 338 return true; 339 }; 340 341 // bind handlers 342 var bindMouseWheelHandler = function () { 343 // FIXME: Backward compatibility. 344 // After e.deltaFactor applied, wheelSpeed should have smaller value. 345 // Currently, there's no way to change the settings after the scrollbar initialized. 346 // But if the way is implemented in the future, wheelSpeed should be reset. 347 settings.wheelSpeed /= 10; 348 349 var shouldPrevent = false; 350 $this.bind('mousewheel' + eventClassName, function (e, deprecatedDelta, deprecatedDeltaX, deprecatedDeltaY) { 351 var deltaX = e.deltaX * e.deltaFactor || deprecatedDeltaX, 352 deltaY = e.deltaY * e.deltaFactor || deprecatedDeltaY; 353 354 shouldPrevent = false; 355 if (!settings.useBothWheelAxes) { 356 // deltaX will only be used for horizontal scrolling and deltaY will 357 // only be used for vertical scrolling - this is the default 358 $this.scrollTop($this.scrollTop() - (deltaY * settings.wheelSpeed)); 359 $this.scrollLeft($this.scrollLeft() + (deltaX * settings.wheelSpeed)); 360 } else if (scrollbarYActive && !scrollbarXActive) { 361 // only vertical scrollbar is active and useBothWheelAxes option is 362 // active, so let's scroll vertical bar using both mouse wheel axes 363 if (deltaY) { 364 $this.scrollTop($this.scrollTop() - (deltaY * settings.wheelSpeed)); 365 } else { 366 $this.scrollTop($this.scrollTop() + (deltaX * settings.wheelSpeed)); 367 } 368 shouldPrevent = true; 369 } else if (scrollbarXActive && !scrollbarYActive) { 370 // useBothWheelAxes and only horizontal bar is active, so use both 371 // wheel axes for horizontal bar 372 if (deltaX) { 373 $this.scrollLeft($this.scrollLeft() + (deltaX * settings.wheelSpeed)); 374 } else { 375 $this.scrollLeft($this.scrollLeft() - (deltaY * settings.wheelSpeed)); 376 } 377 shouldPrevent = true; 378 } 379 380 // update bar position 381 updateBarSizeAndPosition(); 382 383 shouldPrevent = (shouldPrevent || shouldPreventDefault(deltaX, deltaY)); 384 if (shouldPrevent) { 385 e.stopPropagation(); 386 e.preventDefault(); 387 } 388 }); 389 390 // fix Firefox scroll problem 391 $this.bind('MozMousePixelScroll' + eventClassName, function (e) { 392 if (shouldPrevent) { 393 e.preventDefault(); 394 } 395 }); 396 }; 397 398 var bindKeyboardHandler = function () { 399 var hovered = false; 400 $this.bind('mouseenter' + eventClassName, function (e) { 401 hovered = true; 402 }); 403 $this.bind('mouseleave' + eventClassName, function (e) { 404 hovered = false; 405 }); 406 407 var shouldPrevent = false; 408 $(document).bind('keydown' + eventClassName, function (e) { 409 if (e.isDefaultPrevented && e.isDefaultPrevented()) { 410 return; 411 } 412 413 if (!hovered || $(document.activeElement).is(":input,[contenteditable]")) { 414 return; 415 } 416 417 var deltaX = 0, 418 deltaY = 0; 419 420 switch (e.which) { 421 case 37: // left 422 deltaX = -30; 423 break; 424 case 38: // up 425 deltaY = 30; 426 break; 427 case 39: // right 428 deltaX = 30; 429 break; 430 case 40: // down 431 deltaY = -30; 432 break; 433 case 33: // page up 434 deltaY = 90; 435 break; 436 case 32: // space bar 437 case 34: // page down 438 deltaY = -90; 439 break; 440 case 35: // end 441 deltaY = -containerHeight; 442 break; 443 case 36: // home 444 deltaY = containerHeight; 445 break; 446 default: 447 return; 448 } 449 450 $this.scrollTop($this.scrollTop() - deltaY); 451 $this.scrollLeft($this.scrollLeft() + deltaX); 452 453 shouldPrevent = shouldPreventDefault(deltaX, deltaY); 454 if (shouldPrevent) { 455 e.preventDefault(); 456 } 457 }); 458 }; 459 460 var bindRailClickHandler = function () { 461 var stopPropagation = function (e) { e.stopPropagation(); }; 462
463 $scrollbarY.bind('click' + eventClassName, stopPropagation); 464 $scrollbarYRail.bind('click' + eventClassName, function (e) { 465 var halfOfScrollbarLength = parseInt(scrollbarYHeight / 2, 10), 466 positionTop = e.pageY - $scrollbarYRail.offset().top - halfOfScrollbarLength, 467 maxPositionTop = containerHeight - scrollbarYHeight, 468 positionRatio = positionTop / maxPositionTop; 469 470 if (positionRatio < 0) { 471 positionRatio = 0; 472 } else if (positionRatio > 1) { 473 positionRatio = 1; 474 } 475 476 $this.scrollTop((contentHeight - containerHeight) * positionRatio); 477 }); 478 479 $scrollbarX.bind('click' + eventClassName, stopPropagation); 480 $scrollbarXRail.bind('click' + eventClassName, function (e) { 481 var halfOfScrollbarLength = parseInt(scrollbarXWidth / 2, 10), 482 positionLeft = e.pageX - $scrollbarXRail.offset().left - halfOfScrollbarLength, 483 maxPositionLeft = containerWidth - scrollbarXWidth, 484 positionRatio = positionLeft / maxPositionLeft; 485 486 if (positionRatio < 0) { 487 positionRatio = 0; 488 } else if (positionRatio > 1) { 489 positionRatio = 1; 490 } 491 492 $this.scrollLeft((contentWidth - containerWidth) * positionRatio); 493 }); 494 }; 495 496 // bind mobile touch handler 497 var bindMobileTouchHandler = function () { 498 var applyTouchMove = function (differenceX, differenceY) { 499 if(isNaN(differenceY) || differenceY == NaN || !differenceY) { 500 return; 501 } 502 $this.scrollTop($this.scrollTop() - differenceY); 503 $this.scrollLeft($this.scrollLeft() - differenceX); 504 505 // update bar position 506 updateBarSizeAndPosition(); 507 }; 508 509 var startCoords = {}, 510 startTime = 0, 511 speed = {}, 512 breakingProcess = null, 513 inGlobalTouch = false; 514 515 $(window).bind("touchstart" + eventClassName, function (e) { 516 inGlobalTouch = true; 517 }); 518 $(window).bind("touchend" + eventClassName, function (e) { 519 inGlobalTouch = false; 520 }); 521 522 $this.bind("touchstart" + eventClassName, function (e) { 523 var touch = e.originalEvent.targetTouches[0]; 524 525 startCoords.pageX = touch.pageX; 526 startCoords.pageY = touch.pageY; 527 528 startTime = (new Date()).getTime(); 529 530 if (breakingProcess !== null) { 531 clearInterval(breakingProcess); 532 } 533 534 e.stopPropagation(); 535 }); 536 $this.bind("touchmove" + eventClassName, function (e) { 537 if (!inGlobalTouch && e.originalEvent.targetTouches.length === 1) { 538 var touch = e.originalEvent.targetTouches[0]; 539 540 var currentCoords = {}; 541 currentCoords.pageX = touch.pageX; 542 currentCoords.pageY = touch.pageY; 543
544 var differenceX = currentCoords.pageX - startCoords.pageX, 545 differenceY = currentCoords.pageY - startCoords.pageY; 546 547 applyTouchMove(differenceX, differenceY); 548 startCoords = currentCoords; 549 550 var currentTime = (new Date()).getTime(); 551 552 var timeGap = currentTime - startTime; 553 if (timeGap > 0) { 554 speed.x = differenceX / timeGap; 555 speed.y = differenceY / timeGap; 556 startTime = currentTime; 557 } 558 559 e.preventDefault(); 560 } 561 }); 562 $this.bind("touchend" + eventClassName, function (e) { 563 clearInterval(breakingProcess); 564 breakingProcess = setInterval(function () { 565 if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) { 566 clearInterval(breakingProcess); 567 return; 568 } 569 570 applyTouchMove(speed.x * 30, speed.y * 30); 571 572 speed.x *= 0.8; 573 speed.y *= 0.8; 574 }, 10); 575 }); 576 }; 577 578 var bindScrollHandler = function () { 579 $this.bind('scroll' + eventClassName, function (e) { 580 updateBarSizeAndPosition(); 581 }); 582 }; 583 584 var destroy = function () { 585 $this.unbind(eventClassName); 586 $(window).unbind(eventClassName); 587 $(document).unbind(eventClassName); 588 $this.data('perfect-scrollbar', null); 589 $this.data('perfect-scrollbar-update', null); 590 $this.data('perfect-scrollbar-destroy', null); 591 $scrollbarX.remove(); 592 $scrollbarY.remove(); 593 $scrollbarXRail.remove(); 594 $scrollbarYRail.remove(); 595 596 // clean all variables 597 $scrollbarXRail = 598 $scrollbarYRail = 599 $scrollbarX = 600 $scrollbarY = 601 scrollbarXActive = 602 scrollbarYActive = 603 containerWidth = 604 containerHeight = 605 contentWidth = 606 contentHeight = 607 scrollbarXWidth = 608 scrollbarXLeft = 609 scrollbarXBottom = 610 isScrollbarXUsingBottom = 611 scrollbarXTop = 612 scrollbarYHeight = 613 scrollbarYTop = 614 scrollbarYRight = 615 isScrollbarYUsingRight = 616 scrollbarYLeft = 617 isRtl = 618 eventClassName = null; 619 }; 620 621 var ieSupport = function (version) { 622 $this.addClass('ie').addClass('ie' + version); 623 624 var bindHoverHandlers = function () { 625 var mouseenter = function () { 626 $(this).addClass('hover'); 627 }; 628 var mouseleave = function () { 629 $(this).removeClass('hover'); 630 }; 631 $this.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave); 632 $scrollbarXRail.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave); 633 $scrollbarYRail.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave); 634 $scrollbarX.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave); 635 $scrollbarY.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave); 636 }; 637 638 var fixIe6ScrollbarPosition = function () { 639 updateScrollbarCss = function () { 640 var scrollbarXStyles = {left: scrollbarXLeft + $this.scrollLeft(), width: scrollbarXWidth}; 641 if (isScrollbarXUsingBottom) { 642 scrollbarXStyles.bottom = scrollbarXBottom; 643 } else { 644 scrollbarXStyles.top = scrollbarXTop; 645 } 646 $scrollbarX.css(scrollbarXStyles); 647 648 var scrollbarYStyles = {top: scrollbarYTop + $this.scrollTop(), height: scrollbarYHeight}; 649 if (isScrollbarYUsingRight) { 650 scrollbarYStyles.right = scrollbarYRight; 651 } else { 652 scrollbarYStyles.left = scrollbarYLeft; 653 } 654 655 $scrollbarY.css(scrollbarYStyles); 656 $scrollbarX.hide().show(); 657 $scrollbarY.hide().show(); 658 }; 659 }; 660 661 if (version === 6) { 662 bindHoverHandlers(); 663 fixIe6ScrollbarPosition(); 664 } 665 }; 666 667 var supportsTouch = (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch); 668 669 var initialize = function () { 670 var ieMatch = navigator.userAgent.toLowerCase().match(/(msie) ([\w.]+)/); 671 if (ieMatch && ieMatch[1] === 'msie') { 672 // must be executed at first, because 'ieSupport' may addClass to the container 673 ieSupport(parseInt(ieMatch[2], 10)); 674 } 675 676 updateBarSizeAndPosition(); 677 bindScrollHandler(); 678 bindMouseScrollXHandler(); 679 bindMouseScrollYHandler(); 680 bindRailClickHandler(); 681 if (supportsTouch) { 682 bindMobileTouchHandler(); 683 } 684 if ($this.mousewheel) { 685 bindMouseWheelHandler(); 686 } 687 if (settings.useKeyboard) { 688 bindKeyboardHandler(); 689 } 690 $this.data('perfect-scrollbar', $this); 691 $this.data('perfect-scrollbar-update', updateBarSizeAndPosition); 692 $this.data('perfect-scrollbar-destroy', destroy); 693 }; 694 695 // initialize 696 initialize(); 697 698 return $this; 699 }); 700 }; 701}));
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.