1(function ($) { 2 3 $.fn.customScrollbar = function (options, args) { 4 5 var defaultOptions = { 6 skin: undefined, 7 hScroll: true, 8 vScroll: true, 9 updateOnWindowResize: false, 10 animationSpeed: 300, 11 onCustomScroll: undefined, 12 swipeSpeed: 1, 13 wheelSpeed: 40, 14 fixedThumbWidth: undefined, 15 fixedThumbHeight: undefined, 16 preventDefaultScroll: false 17 } 18 19 var Scrollable = function (element, options) { 20 this.$element = $(element); 21 this.options = options; 22 this.addScrollableClass(); 23 this.addSkinClass(); 24 this.addScrollBarComponents(); 25 if (this.options.vScroll) 26 this.vScrollbar = new Scrollbar(this, new VSizing()); 27 if (this.options.hScroll) 28 this.hScrollbar = new Scrollbar(this, new HSizing()); 29 this.$element.data("scrollable", this); 30 this.initKeyboardScrolling(); 31 this.bindEvents(); 32 } 33 34 Scrollable.prototype = { 35 36 addScrollableClass: function () { 37 if (!this.$element.hasClass("scrollable")) { 38 this.scrollableAdded = true; 39 this.$element.addClass("scrollable"); 40 } 41 }, 42 43 removeScrollableClass: function () { 44 if (this.scrollableAdded) 45 this.$element.removeClass("scrollable"); 46 }, 47 48 addSkinClass: function () { 49 if (typeof(this.options.skin) == "string" && !this.$element.hasClass(this.options.skin)) { 50 this.skinClassAdded = true; 51 this.$element.addClass(this.options.skin); 52 } 53 }, 54 55 removeSkinClass: function () { 56 if (this.skinClassAdded) 57 this.$element.removeClass(this.options.skin); 58 }, 59 60 addScrollBarComponents: function () { 61 this.assignViewPort(); 62 if (this.$viewPort.length == 0) { 63 this.$element.wrapInner("<div class=\"viewport\" />"); 64 this.assignViewPort(); 65 this.viewPortAdded = true; 66 } 67 this.assignOverview(); 68 if (this.$overview.length == 0) { 69 this.$viewPort.wrapInner("<div class=\"overview\" />"); 70 this.assignOverview(); 71 this.overviewAdded = true; 72 } 73 this.addScrollBar("vertical", "prepend"); 74 this.addScrollBar("horizontal", "append"); 75 }, 76 77 removeScrollbarComponents: function () { 78 this.removeScrollbar("vertical"); 79 this.removeScrollbar("horizontal"); 80 if (this.overviewAdded) 81 this.$element.unwrap(); 82 if (this.viewPortAdded) 83 this.$element.unwrap(); 84 }, 85 86 removeScrollbar: function (orientation) { 87 if (this[orientation + "ScrollbarAdded"]) 88 this.$element.find(".scroll-bar." + orientation).remove(); 89 }, 90 91 assignViewPort: function () { 92 this.$viewPort = this.$element.find(".viewport"); 93 }, 94 95 assignOverview: function () { 96 this.$overview = this.$viewPort.find(".overview"); 97 }, 98 99 addScrollBar: function (orientation, fun) { 100 if (this.$element.find(".scroll-bar." + orientation).length == 0) { 101 this.$element[fun]("<div class='scroll-bar " + orientation + "'><div class='thumb'></div></div>") 102 this[orientation + "ScrollbarAdded"] = true; 103 } 104 }, 105 106 resize: function (keepPosition) { 107 if (this.vScrollbar) 108 this.vScrollbar.resize(keepPosition); 109 if (this.hScrollbar) 110 this.hScrollbar.resize(keepPosition); 111 }, 112 113 scrollTo: function (element) { 114 if (this.vScrollbar) 115 this.vScrollbar.scrollToElement(element); 116 if (this.hScrollbar) 117 this.hScrollbar.scrollToElement(element); 118 }, 119 120 scrollToXY: function (x, y) { 121 this.scrollToX(x); 122 this.scrollToY(y); 123 }, 124 125 scrollToX: function (x) { 126 if (this.hScrollbar) 127 this.hScrollbar.scrollOverviewTo(x, true); 128 }, 129 130 scrollToY: function (y) { 131 if (this.vScrollbar) 132 this.vScrollbar.scrollOverviewTo(y, true); 133 }, 134 135 scrollByX: function (x) { 136 if (this.hScrollbar) 137 this.scrollToX(this.hScrollbar.overviewPosition() + x); 138 }, 139 140 scrollByY: function (y) { 141 if (this.vScrollbar) 142 this.scrollToY(this.vScrollbar.overviewPosition() + y); 143 }, 144 145 remove: function () { 146 this.removeScrollableClass(); 147 this.removeSkinClass(); 148 this.removeScrollbarComponents(); 149 this.$element.data("scrollable", null); 150 this.removeKeyboardScrolling(); 151 if (this.vScrollbar) 152 this.vScrollbar.remove(); 153 if (this.hScrollbar) 154 this.hScrollbar.remove(); 155 }, 156 157 setAnimationSpeed: function (speed) { 158 this.options.animationSpeed = speed; 159 }, 160 161 isInside: function (element, wrappingElement) { 162 var $element = $(element); 163 var $wrappingElement = $(wrappingElement); 164 var elementOffset = $element.offset(); 165 var wrappingElementOffset = $wrappingElement.offset(); 166 return (elementOffset.top >= wrappingElementOffset.top) && (elementOffset.left >= wrappingElementOffset.left) && 167 (elementOffset.top + $element.height() <= wrappingElementOffset.top + $wrappingElement.height()) && 168 (elementOffset.left + $element.width() <= wrappingElementOffset.left + $wrappingElement.width()) 169 }, 170 171 initKeyboardScrolling: function () { 172 var _this = this; 173
174 this.elementKeydown = function (event) { 175 if (document.activeElement === _this.$element[0]) { 176 if (_this.vScrollbar) 177 _this.vScrollbar.keyScroll(event); 178 if (_this.hScrollbar) 179 _this.hScrollbar.keyScroll(event); 180 } 181 } 182 183 this.$element 184 .attr('tabindex', '-1') 185 .keydown(this.elementKeydown); 186 }, 187 188 removeKeyboardScrolling: function () { 189 this.$element 190 .removeAttr('tabindex') 191 .unbind("keydown", this.elementKeydown); 192 }, 193 194 bindEvents: function () { 195 if (this.options.onCustomScroll) 196 this.$element.on("customScroll", this.options.onCustomScroll); 197 } 198 199 } 200 201 var Scrollbar = function (scrollable, sizing) { 202 this.scrollable = scrollable; 203 this.sizing = sizing 204 this.$scrollBar = this.sizing.scrollBar(this.scrollable.$element); 205 this.$thumb = this.$scrollBar.find(".thumb"); 206 this.setScrollPosition(0, 0); 207 this.resize(); 208 this.initMouseMoveScrolling(); 209 this.initMouseWheelScrolling(); 210 this.initTouchScrolling(); 211 this.initMouseClickScrolling(); 212 this.initWindowResize(); 213 } 214 215 Scrollbar.prototype = { 216 217 resize: function (keepPosition) { 218 this.overviewSize = this.sizing.size(this.scrollable.$overview); 219 this.calculateViewPortSize(); 220 this.sizing.size(this.scrollable.$viewPort, this.viewPortSize); 221 this.ratio = this.viewPortSize / this.overviewSize; 222 this.sizing.size(this.$scrollBar, this.viewPortSize); 223 this.thumbSize = this.calculateThumbSize(); 224 this.sizing.size(this.$thumb, this.thumbSize); 225 this.maxThumbPosition = this.calculateMaxThumbPosition(); 226 this.maxOverviewPosition = this.calculateMaxOverviewPosition(); 227 this.enabled = (this.overviewSize > this.viewPortSize); 228 if (this.scrollPercent === undefined) 229 this.scrollPercent = 0.0; 230 if (this.enabled) 231 this.rescroll(keepPosition); 232 else 233 this.setScrollPosition(0, 0); 234 this.$scrollBar.toggle(this.enabled); 235 }, 236 237 calculateViewPortSize: function () { 238 var elementSize = this.sizing.size(this.scrollable.$element); 239 if (elementSize > 0 && !this.maxSizeUsed) { 240 this.viewPortSize = elementSize; 241 this.maxSizeUsed = false; 242 } 243 else { 244 var maxSize = this.sizing.maxSize(this.scrollable.$element); 245 this.viewPortSize = Math.min(maxSize, this.overviewSize); 246 this.maxSizeUsed = true; 247 } 248 }, 249 250 calculateThumbSize: function () { 251 var fixedSize = this.sizing.fixedThumbSize(this.scrollable.options) 252 var size; 253 if (fixedSize) 254 size = fixedSize; 255 else 256 size = this.ratio * this.viewPortSize 257 return Math.max(size, this.sizing.minSize(this.$thumb)); 258 }, 259 260 initMouseMoveScrolling: function () { 261 var _this = this; 262 this.$thumb.mousedown(function (event) { 263 if (_this.enabled) 264 _this.startMouseMoveScrolling(event); 265 }); 266 this.documentMouseup = function (event) { 267 _this.stopMouseMoveScrolling(event); 268 }; 269 $(document).mouseup(this.documentMouseup); 270 this.documentMousemove = function (event) { 271 _this.mouseMoveScroll(event); 272 }; 273 $(document).mousemove(this.documentMousemove); 274 this.$thumb.click(function (event) { 275 event.stopPropagation(); 276 }); 277 }, 278 279 removeMouseMoveScrolling: function () { 280 this.$thumb.unbind(); 281 $(document).unbind("mouseup", this.documentMouseup); 282 $(document).unbind("mousemove", this.documentMousemove); 283 }, 284 285 initMouseWheelScrolling: function () { 286 var _this = this; 287 this.scrollable.$element.mousewheel(function (event, delta, deltaX, deltaY) { 288 if (_this.enabled) { 289 var scrolled = _this.mouseWheelScroll(deltaX, deltaY); 290 _this.stopEventConditionally(event, scrolled); 291 } 292 }); 293 }, 294 295 removeMouseWheelScrolling: function () { 296 this.scrollable.$element.unbind("mousewheel"); 297 }, 298 299 initTouchScrolling: function () { 300 if (document.addEventListener) { 301 var _this = this; 302 this.elementTouchstart = function (event) { 303 if (_this.enabled) 304 _this.startTouchScrolling(event); 305 } 306 this.scrollable.$element[0].addEventListener("touchstart", this.elementTouchstart); 307 this.documentTouchmove = function (event) { 308 _this.touchScroll(event); 309 } 310 this.scrollable.$element[0].addEventListener("touchmove", this.documentTouchmove); 311 this.elementTouchend = function (event) { 312 _this.stopTouchScrolling(event); 313 } 314 this.scrollable.$element[0].addEventListener("touchend", this.elementTouchend); 315 } 316 }, 317 318 removeTouchScrolling: function () { 319 if (document.addEventListener) { 320 this.scrollable.$element[0].removeEventListener("touchstart", this.elementTouchstart); 321 document.removeEventListener("touchmove", this.documentTouchmove); 322 this.scrollable.$element[0].removeEventListener("touchend", this.elementTouchend); 323 } 324 }, 325 326 initMouseClickScrolling: function () { 327 var _this = this; 328 this.scrollBarClick = function (event) { 329 _this.mouseClickScroll(event); 330 }; 331 this.$scrollBar.click(this.scrollBarClick); 332 }, 333 334 removeMouseClickScrolling: function () { 335 this.$scrollBar.unbind("click", this.scrollBarClick); 336 }, 337 338 initWindowResize: function () { 339 if (this.scrollable.options.updateOnWindowResize) { 340 var _this = this; 341 this.windowResize = function () { 342 _this.resize(); 343 }; 344 $(window).resize(this.windowResize); 345 } 346 }, 347 348 removeWindowResize: function () { 349 $(window).unbind("resize", this.windowResize); 350 }, 351 352 isKeyScrolling: function (key) { 353 return this.keyScrollDelta(key) != null; 354 }, 355 356 keyScrollDelta: function (key) { 357 for (var scrollingKey in this.sizing.scrollingKeys) 358 if (scrollingKey == key) 359 return this.sizing.scrollingKeys[key](this.viewPortSize); 360 return null; 361 }, 362 363 startMouseMoveScrolling: function (event) { 364 this.mouseMoveScrolling = true; 365 $("body").addClass("not-selectable"); 366 this.setUnselectable($("body"), "on"); 367 this.setScrollEvent(event); 368 event.preventDefault(); 369 }, 370 371 stopMouseMoveScrolling: function (event) { 372 this.mouseMoveScrolling = false;
373 $("body").removeClass("not-selectable"); 374 this.setUnselectable($("body"), null); 375 }, 376 377 setUnselectable: function (element, value) { 378 if (element.attr("unselectable") != value) { 379 element.attr("unselectable", value); 380 element.find(':not(input)').attr('unselectable', value); 381 } 382 }, 383 384 mouseMoveScroll: function (event) { 385 if (this.mouseMoveScrolling) { 386 var delta = this.sizing.mouseDelta(this.scrollEvent, event); 387 this.scrollThumbBy(delta); 388 this.setScrollEvent(event); 389 } 390 }, 391 392 startTouchScrolling: function (event) { 393 if (event.touches && event.touches.length == 1) { 394 this.setScrollEvent(event.touches[0]); 395 this.touchScrolling = true; 396 event.stopPropagation(); 397 } 398 }, 399 400 touchScroll: function (event) { 401 if (this.touchScrolling && event.touches && event.touches.length == 1) { 402 var delta = -this.sizing.mouseDelta(this.scrollEvent, event.touches[0]) * this.scrollable.options.swipeSpeed; 403 var scrolled = this.scrollOverviewBy(delta); 404 if (scrolled) 405 this.setScrollEvent(event.touches[0]); 406 this.stopEventConditionally(event, scrolled); 407 } 408 }, 409 410 stopTouchScrolling: function (event) { 411 this.touchScrolling = false; 412 event.stopPropagation(); 413 }, 414 415 mouseWheelScroll: function (deltaX, deltaY) { 416 var delta = -this.sizing.wheelDelta(deltaX, deltaY) * this.scrollable.options.wheelSpeed; 417 if (delta != 0) 418 return this.scrollOverviewBy(delta); 419 }, 420 421 mouseClickScroll: function (event) { 422 var delta = this.viewPortSize - 20; 423 if (event["page" + this.sizing.scrollAxis()] < this.$thumb.offset()[this.sizing.offsetComponent()]) 424 // mouse click over thumb 425 delta = -delta; 426 this.scrollOverviewBy(delta); 427 }, 428 429 keyScroll: function (event) { 430 var keyDown = event.which; 431 if (this.enabled && this.isKeyScrolling(keyDown)) { 432 var scrolled = this.scrollOverviewBy(this.keyScrollDelta(keyDown)); 433 this.stopEventConditionally(event, scrolled); 434 } 435 }, 436 437 scrollThumbBy: function (delta) { 438 var thumbPosition = this.thumbPosition(); 439 thumbPosition += delta; 440 thumbPosition = this.positionOrMax(thumbPosition, this.maxThumbPosition); 441 var oldScrollPercent = this.scrollPercent; 442 this.scrollPercent = thumbPosition / this.maxThumbPosition; 443 if (oldScrollPercent != this.scrollPercent) { 444 var overviewPosition = (thumbPosition * this.maxOverviewPosition) / this.maxThumbPosition; 445 this.setScrollPosition(overviewPosition, thumbPosition); 446 this.triggerCustomScroll(oldScrollPercent); 447 return true 448 } 449 else 450 return false; 451 }, 452 453 thumbPosition: function () { 454 return this.$thumb.position()[this.sizing.offsetComponent()]; 455 }, 456 457 scrollOverviewBy: function (delta) { 458 var overviewPosition = this.overviewPosition() + delta; 459 return this.scrollOverviewTo(overviewPosition, false); 460 }, 461 462 overviewPosition: function () { 463 return -this.scrollable.$overview.position()[this.sizing.offsetComponent()]; 464 }, 465 466 scrollOverviewTo: function (overviewPosition, animate) { 467 overviewPosition = this.positionOrMax(overviewPosition, this.maxOverviewPosition); 468 var oldScrollPercent = this.scrollPercent; 469 this.scrollPercent = overviewPosition / this.maxOverviewPosition; 470 if (oldScrollPercent != this.scrollPercent) { 471 var thumbPosition = this.scrollPercent * this.maxThumbPosition; 472 if (animate) 473 this.setScrollPositionWithAnimation(overviewPosition, thumbPosition); 474 else 475 this.setScrollPosition(overviewPosition, thumbPosition); 476 this.triggerCustomScroll(oldScrollPercent); 477 return true; 478 } 479 else 480 return false; 481 }, 482 483 positionOrMax: function (p, max) { 484 if (p < 0) 485 return 0; 486 else if (p > max) 487 return max; 488 else 489 return p; 490 }, 491 492 triggerCustomScroll: function (oldScrollPercent) { 493 this.scrollable.$element.trigger("customScroll", { 494 scrollAxis: this.sizing.scrollAxis(), 495 direction: this.sizing.scrollDirection(oldScrollPercent, this.scrollPercent), 496 scrollPercent: this.scrollPercent * 100 497 } 498 ); 499 }, 500 501 rescroll: function (keepPosition) { 502 if (keepPosition) { 503 var overviewPosition = this.positionOrMax(this.overviewPosition(), this.maxOverviewPosition); 504 this.scrollPercent = overviewPosition / this.maxOverviewPosition; 505 var thumbPosition = this.scrollPercent * this.maxThumbPosition; 506 this.setScrollPosition(overviewPosition, thumbPosition); 507 } 508 else { 509 var thumbPosition = this.scrollPercent * this.maxThumbPosition; 510 var overviewPosition = this.scrollPercent * this.maxOverviewPosition; 511 this.setScrollPosition(overviewPosition, thumbPosition); 512 } 513 }, 514 515 setScrollPosition: function (overviewPosition, thumbPosition) { 516 this.$thumb.css(this.sizing.offsetComponent(), thumbPosition + "px"); 517 this.scrollable.$overview.css(this.sizing.offsetComponent(), -overviewPosition + "px"); 518 }, 519 520 setScrollPositionWithAnimation: function (overviewPosition, thumbPosition) { 521 var thumbAnimationOpts = {}; 522 var overviewAnimationOpts = {}; 523 thumbAnimationOpts[this.sizing.offsetComponent()] = thumbPosition + "px"; 524 this.$thumb.animate(thumbAnimationOpts, this.scrollable.options.animationSpeed); 525 overviewAnimationOpts[this.sizing.offsetComponent()] = -overviewPosition + "px"; 526 this.scrollable.$overview.animate(overviewAnimationOpts, this.scrollable.options.animationSpeed); 527 }, 528 529 calculateMaxThumbPosition: function () { 530 return Math.max(0, this.sizing.size(this.$scrollBar) - this.thumbSize); 531 }, 532 533 calculateMaxOverviewPosition: function () { 534 return Math.max(0, this.sizing.size(this.scrollable.$overview) - this.sizing.size(this.scrollable.$viewPort)); 535 }, 536 537 setScrollEvent: function (event) { 538 var attr = "page" + this.sizing.scrollAxis(); 539 if (!this.scrollEvent || this.scrollEvent[attr] != event[attr]) 540 this.scrollEvent = {pageX: event.pageX, pageY: event.pageY}; 541 }, 542 543 scrollToElement: function (element) { 544 var $element = $(element); 545 if (this.sizing.isInside($element, this.scrollable.$overview) && !this.sizing.isInside($element, this.scrollable.$viewPort)) { 546 var elementOffset = $element.offset(); 547 var overviewOffset = this.scrollable.$overview.offset(); 548 var viewPortOffset = this.scrollable.$viewPort.offset(); 549 this.scrollOverviewTo(elementOffset[this.sizing.offsetComponent()] - overviewOffset[this.sizing.offsetComponent()], true); 550 } 551 }, 552 553 remove: function () { 554 this.removeMouseMoveScrolling(); 555 this.removeMouseWheelScrolling(); 556 this.removeTouchScrolling(); 557 this.removeMouseClickScrolling(); 558 this.removeWindowResize(); 559 }, 560 561 stopEventConditionally: function (event, condition) { 562 if (condition || this.scrollable.options.preventDefaultScroll) { 563 event.preventDefault(); 564 event.stopPropagation(); 565 } 566 } 567 568 } 569 570 var HSizing = function () { 571 } 572 573 HSizing.prototype = { 574 size: function ($el, arg) { 575 if (arg) 576 return $el.width(arg); 577 else 578 return $el.width(); 579 }, 580 581 minSize: function ($el) { 582 return parseInt($el.css("min-width")) || 0; 583 }, 584 585 maxSize: function ($el) { 586 return parseInt($el.css("max-width")) || 0; 587 }, 588 589 fixedThumbSize: function (options) { 590 return options.fixedThumbWidth; 591 }, 592 593 scrollBar: function ($el) { 594 return $el.find(".scroll-bar.horizontal"); 595 }, 596 597 mouseDelta: function (event1, event2) { 598 return event2.pageX - event1.pageX; 599 }, 600 601 offsetComponent: function () { 602 return "left"; 603 }, 604 605 wheelDelta: function (deltaX, deltaY) { 606 return deltaX; 607 }, 608 609 scrollAxis: function () { 610 return "X"; 611 }, 612 613 scrollDirection: function (oldPercent, newPercent) { 614 return oldPercent < newPercent ? "right" : "left"; 615 }, 616 617 scrollingKeys: { 618 37: function (viewPortSize) { 619 return -10; //arrow left 620 }, 621 39: function (viewPortSize) { 622 return 10; //arrow right 623 } 624 }, 625 626 isInside: function (element, wrappingElement) { 627 var $element = $(element); 628 var $wrappingElement = $(wrappingElement); 629 var elementOffset = $element.offset(); 630 var wrappingElementOffset = $wrappingElement.offset(); 631 return (elementOffset.left >= wrappingElementOffset.left) && 632 (elementOffset.left + $element.width() <= wrappingElementOffset.left + $wrappingElement.width()); 633 } 634 635 } 636 637 var VSizing = function () { 638 } 639 640 VSizing.prototype = { 641 642 size: function ($el, arg) { 643 if (arg) 644 return $el.height(arg); 645 else 646 return $el.height(); 647 }, 648 649 minSize: function ($el) { 650 return parseInt($el.css("min-height")) || 0; 651 }, 652 653 maxSize: function ($el) { 654 return parseInt($el.css("max-height")) || 0; 655 }, 656 657 fixedThumbSize: function (options) { 658 return options.fixedThumbHeight; 659 }, 660 661 scrollBar: function ($el) { 662 return $el.find(".scroll-bar.vertical"); 663 }, 664 665 mouseDelta: function (event1, event2) { 666 return event2.pageY - event1.pageY; 667 }, 668 669 offsetComponent: function () { 670 return "top"; 671 }, 672 673 wheelDelta: function (deltaX, deltaY) { 674 return deltaY; 675 }, 676 677 scrollAxis: function () { 678 return "Y"; 679 }, 680 681 scrollDirection: function (oldPercent, newPercent) { 682 return oldPercent < newPercent ? "down" : "up"; 683 }, 684 685 scrollingKeys: { 686 38: function (viewPortSize) { 687 return -10; //arrow up 688 }, 689 40: function (viewPortSize) { 690 return 10; //arrow down 691 }, 692 33: function (viewPortSize) { 693 return -(viewPortSize - 20); //page up 694 }, 695 34: function (viewPortSize) { 696 return viewPortSize - 20; //page down 697 } 698 }, 699 700 isInside: function (element, wrappingElement) { 701 var $element = $(element); 702 var $wrappingElement = $(wrappingElement); 703 var elementOffset = $element.offset(); 704 var wrappingElementOffset = $wrappingElement.offset(); 705 return (elementOffset.top >= wrappingElementOffset.top) && 706 (elementOffset.top + $element.height() <= wrappingElementOffset.top + $wrappingElement.height()); 707 } 708 709 } 710 711 return this.each(function () { 712 if (options == undefined) 713 options = defaultOptions; 714 if (typeof(options) == "string") { 715 var scrollable = $(this).data("scrollable"); 716 if (scrollable) 717 scrollable[options](args); 718 } 719 else if (typeof(options) == "object") { 720 options = $.extend(defaultOptions, options); 721 new Scrollable($(this), options); 722 } 723 else 724 throw "Invalid type of options"; 725 }); 726 727 } 728 ; 729 730}) 731 (jQuery); 732 733(function ($) { 734 735 var types = ['DOMMouseScroll', 'mousewheel']; 736 737 if ($.event.fixHooks) { 738 for (var i = types.length; i;) { 739 $.event.fixHooks[ types[--i] ] = $.event.mouseHooks; 740 } 741 } 742 743 $.event.special.mousewheel = { 744 setup: function () { 745 if (this.addEventListener) { 746 for (var i = types.length; i;) { 747 this.addEventListener(types[--i], handler, false); 748 } 749 } else { 750 this.onmousewheel = handler; 751 } 752 }, 753 754 teardown: function () { 755 if (this.removeEventListener) { 756 for (var i = types.length; i;) { 757 this.removeEventListener(types[--i], handler, false); 758 } 759 } else { 760 this.onmousewheel = null; 761 } 762 } 763 }; 764 765 $.fn.extend({ 766 mousewheel: function (fn) { 767 return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); 768 }, 769 770 unmousewheel: function (fn) { 771 return this.unbind("mousewheel", fn); 772 } 773 }); 774 775 776 function handler(event) { 777 var orgEvent = event || window.event, args = [].slice.call(arguments, 1), delta = 0, returnValue = true, deltaX = 0, deltaY = 0; 778 event = $.event.fix(orgEvent); 779 event.type = "mousewheel"; 780 781 // Old school scrollwheel delta 782 if (orgEvent.wheelDelta) { 783 delta = orgEvent.wheelDelta / 120; 784 } 785 if (orgEvent.detail) { 786 delta = -orgEvent.detail / 3; 787 } 788 789 // New school multidimensional scroll (touchpads) deltas 790 deltaY = delta; 791 792 // Gecko 793 if (orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) { 794 deltaY = 0; 795 deltaX = delta; 796 } 797 798 // Webkit 799 if (orgEvent.wheelDeltaY !== undefined) { 800 deltaY = orgEvent.wheelDeltaY / 120; 801 } 802 if (orgEvent.wheelDeltaX !== undefined) { 803 deltaX = orgEvent.wheelDeltaX / 120; 804 } 805 806 // Add event and delta to the front of the arguments 807 args.unshift(event, delta, deltaX, deltaY); 808 809 return ($.event.dispatch || $.event.handle).apply(this, args); 810 } 811 812})(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.