1 | /*! Copyright (c) 2013 Brandon Aaron (http://brandon.aaron.sh) |
---|
2 | * Licensed under the MIT License (LICENSE.txt). |
---|
3 | * |
---|
4 | * Version: 3.1.11 |
---|
5 | * |
---|
6 | * Requires: jQuery 1.2.2+ |
---|
7 | */ |
---|
8 | |
---|
9 | (function (factory) { |
---|
10 | if ( typeof define === 'function' && define.amd ) { |
---|
11 | // AMD. Register as an anonymous module. |
---|
12 | define(['jquery'], factory); |
---|
13 | } else if (typeof exports === 'object') { |
---|
14 | // Node/CommonJS style for Browserify |
---|
15 | module.exports = factory; |
---|
16 | } else { |
---|
17 | // Browser globals |
---|
18 | factory(jQuery); |
---|
19 | } |
---|
20 | }(function ($) { |
---|
21 | |
---|
22 | var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'], |
---|
23 | toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? |
---|
24 | ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'], |
---|
25 | slice = Array.prototype.slice, |
---|
26 | nullLowestDeltaTimeout, lowestDelta; |
---|
27 | |
---|
28 | if ( $.event.fixHooks ) { |
---|
29 | for ( var i = toFix.length; i; ) { |
---|
30 | $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks; |
---|
31 | } |
---|
32 | } |
---|
33 | |
---|
34 | var special = $.event.special.mousewheel = { |
---|
35 | version: '3.1.11', |
---|
36 | |
---|
37 | setup: function() { |
---|
38 | if ( this.addEventListener ) { |
---|
39 | for ( var i = toBind.length; i; ) { |
---|
40 | this.addEventListener( toBind[--i], handler, false ); |
---|
41 | } |
---|
42 | } else { |
---|
43 | this.onmousewheel = handler; |
---|
44 | } |
---|
45 | // Store the line height and page height for this particular element |
---|
46 | $.data(this, 'mousewheel-line-height', special.getLineHeight(this)); |
---|
47 | $.data(this, 'mousewheel-page-height', special.getPageHeight(this)); |
---|
48 | }, |
---|
49 | |
---|
50 | teardown: function() { |
---|
51 | if ( this.removeEventListener ) { |
---|
52 | for ( var i = toBind.length; i; ) { |
---|
53 | this.removeEventListener( toBind[--i], handler, false ); |
---|
54 | } |
---|
55 | } else { |
---|
56 | this.onmousewheel = null; |
---|
57 | } |
---|
58 | // Clean up the data we added to the element |
---|
59 | $.removeData(this, 'mousewheel-line-height'); |
---|
60 | $.removeData(this, 'mousewheel-page-height'); |
---|
61 | }, |
---|
62 | |
---|
63 | getLineHeight: function(elem) { |
---|
64 | var $parent = $(elem)['offsetParent' in $.fn ? 'offsetParent' : 'parent'](); |
---|
65 | if (!$parent.length) { |
---|
66 | $parent = $('body'); |
---|
67 | } |
---|
68 | return parseInt($parent.css('fontSize'), 10); |
---|
69 | }, |
---|
70 | |
---|
71 | getPageHeight: function(elem) { |
---|
72 | return $(elem).height(); |
---|
73 | }, |
---|
74 | |
---|
75 | settings: { |
---|
76 | adjustOldDeltas: true, // see shouldAdjustOldDeltas() below |
---|
77 | normalizeOffset: true // calls getBoundingClientRect for each event |
---|
78 | } |
---|
79 | }; |
---|
80 | |
---|
81 | $.fn.extend({ |
---|
82 | mousewheel: function(fn) { |
---|
83 | return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel'); |
---|
84 | }, |
---|
85 | |
---|
86 | unmousewheel: function(fn) { |
---|
87 | return this.unbind('mousewheel', fn); |
---|
88 | } |
---|
89 | }); |
---|
90 | |
---|
91 | |
---|
92 | function handler(event) { |
---|
93 | var orgEvent = event || window.event, |
---|
94 | args = slice.call(arguments, 1), |
---|
95 | delta = 0, |
---|
96 | deltaX = 0, |
---|
97 | deltaY = 0, |
---|
98 | absDelta = 0, |
---|
99 | offsetX = 0, |
---|
100 | offsetY = 0; |
---|
101 | event = $.event.fix(orgEvent); |
---|
102 | event.type = 'mousewheel'; |
---|
103 | |
---|
104 | // Old school scrollwheel delta |
---|
105 | if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; } |
---|
106 | if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; } |
---|
107 | if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; } |
---|
108 | if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; } |
---|
109 | |
---|
110 | // Firefox < 17 horizontal scrolling related to DOMMouseScroll event |
---|
111 | if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) { |
---|
112 | deltaX = deltaY * -1; |
---|
113 | deltaY = 0; |
---|
114 | } |
---|
115 | |
---|
116 | // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy |
---|
117 | delta = deltaY === 0 ? deltaX : deltaY; |
---|
118 | |
---|
119 | // New school wheel delta (wheel event) |
---|
120 | if ( 'deltaY' in orgEvent ) { |
---|
121 | deltaY = orgEvent.deltaY * -1; |
---|
122 | delta = deltaY; |
---|
123 | } |
---|
124 | if ( 'deltaX' in orgEvent ) { |
---|
125 | deltaX = orgEvent.deltaX; |
---|
126 | if ( deltaY === 0 ) { delta = deltaX * -1; } |
---|
127 | } |
---|
128 | |
---|
129 | // No change actually happened, no reason to go any further |
---|
130 | if ( deltaY === 0 && deltaX === 0 ) { return; } |
---|
131 | |
---|
132 | // Need to convert lines and pages to pixels if we aren't already in pixels |
---|
133 | // There are three delta modes: |
---|
134 | // * deltaMode 0 is by pixels, nothing to do |
---|
135 | // * deltaMode 1 is by lines |
---|
136 | // * deltaMode 2 is by pages |
---|
137 | if ( orgEvent.deltaMode === 1 ) { |
---|
138 | var lineHeight = $.data(this, 'mousewheel-line-height'); |
---|
139 | delta *= lineHeight; |
---|
140 | deltaY *= lineHeight; |
---|
141 | deltaX *= lineHeight; |
---|
142 | } else if ( orgEvent.deltaMode === 2 ) { |
---|
143 | var pageHeight = $.data(this, 'mousewheel-page-height'); |
---|
144 | delta *= pageHeight; |
---|
145 | deltaY *= pageHeight; |
---|
146 | deltaX *= pageHeight; |
---|
147 | } |
---|
148 | |
---|
149 | // Store lowest absolute delta to normalize the delta values |
---|
150 | absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) ); |
---|
151 | |
---|
152 | if ( !lowestDelta || absDelta < lowestDelta ) { |
---|
153 | lowestDelta = absDelta; |
---|
154 | |
---|
155 | // Adjust older deltas if necessary |
---|
156 | if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) { |
---|
157 | lowestDelta /= 40; |
---|
158 | } |
---|
159 | } |
---|
160 | |
---|
161 | // Adjust older deltas if necessary |
---|
162 | if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) { |
---|
163 | // Divide all the things by 40! |
---|
164 | delta /= 40; |
---|
165 | deltaX /= 40; |
---|
166 | deltaY /= 40; |
---|
167 | } |
---|
168 | |
---|
169 | // Get a whole, normalized value for the deltas |
---|
170 | delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta); |
---|
171 | deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta); |
---|
172 | deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta); |
---|
173 | |
---|
174 | // Normalise offsetX and offsetY properties |
---|
175 | if ( special.settings.normalizeOffset && this.getBoundingClientRect ) { |
---|
176 | var boundingRect = this.getBoundingClientRect(); |
---|
177 | offsetX = event.clientX - boundingRect.left; |
---|
178 | offsetY = event.clientY - boundingRect.top; |
---|
179 | } |
---|
180 | |
---|
181 | // Add information to the event object |
---|
182 | event.deltaX = deltaX; |
---|
183 | event.deltaY = deltaY; |
---|
184 | event.deltaFactor = lowestDelta; |
---|
185 | event.offsetX = offsetX; |
---|
186 | event.offsetY = offsetY; |
---|
187 | // Go ahead and set deltaMode to 0 since we converted to pixels |
---|
188 | // Although this is a little odd since we overwrite the deltaX/Y |
---|
189 | // properties with normalized deltas. |
---|
190 | event.deltaMode = 0; |
---|
191 | |
---|
192 | // Add event and delta to the front of the arguments |
---|
193 | args.unshift(event, delta, deltaX, deltaY); |
---|
194 | |
---|
195 | // Clearout lowestDelta after sometime to better |
---|
196 | // handle multiple device types that give different |
---|
197 | // a different lowestDelta |
---|
198 | // Ex: trackpad = 3 and mouse wheel = 120 |
---|
199 | if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); } |
---|
200 | nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200); |
---|
201 | |
---|
202 | return ($.event.dispatch || $.event.handle).apply(this, args); |
---|
203 | } |
---|
204 | |
---|
205 | function nullLowestDelta() { |
---|
206 | lowestDelta = null; |
---|
207 | } |
---|
208 | |
---|
209 | function shouldAdjustOldDeltas(orgEvent, absDelta) { |
---|
210 | // If this is an older event and the delta is divisable by 120, |
---|
211 | // then we are assuming that the browser is treating this as an |
---|
212 | // older mouse wheel event and that we should divide the deltas |
---|
213 | // by 40 to try and get a more usable deltaFactor. |
---|
214 | // Side note, this actually impacts the reported scroll distance |
---|
215 | // in older browsers and can cause scrolling to be slower than native. |
---|
216 | // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false. |
---|
217 | return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0; |
---|
218 | } |
---|
219 | |
---|
220 | })); |
---|