/*! copyright (c) 2013 brandon aaron (http://brandon.aaron.sh) * licensed under the mit license (license.txt). * * version: 3.1.9 * * requires: jquery 1.2.2+ */ (function (factory) { if ( typeof define === 'function' && define.amd ) { // amd. register as an anonymous module. define(['jquery'], factory); } else if (typeof exports === 'object') { // node/commonjs style for browserify module.exports = factory; } else { // browser globals factory(jquery); } }(function ($) { var tofix = ['wheel', 'mousewheel', 'dommousescroll', 'mozmousepixelscroll'], tobind = ( 'onwheel' in document || document.documentmode >= 9 ) ? ['wheel'] : ['mousewheel', 'dommousescroll', 'mozmousepixelscroll'], slice = array.prototype.slice, nulllowestdeltatimeout, lowestdelta; if ( $.event.fixhooks ) { for ( var i = tofix.length; i; ) { $.event.fixhooks[ tofix[--i] ] = $.event.mousehooks; } } var special = $.event.special.mousewheel = { version: '3.1.9', setup: function() { if ( this.addeventlistener ) { for ( var i = tobind.length; i; ) { this.addeventlistener( tobind[--i], handler, false ); } } else { this.onmousewheel = handler; } // store the line height and page height for this particular element $.data(this, 'mousewheel-line-height', special.getlineheight(this)); $.data(this, 'mousewheel-page-height', special.getpageheight(this)); }, teardown: function() { if ( this.removeeventlistener ) { for ( var i = tobind.length; i; ) { this.removeeventlistener( tobind[--i], handler, false ); } } else { this.onmousewheel = null; } }, getlineheight: function(elem) { return parseint($(elem)['offsetparent' in $.fn ? 'offsetparent' : 'parent']().css('fontsize'), 10); }, getpageheight: function(elem) { return $(elem).height(); }, settings: { adjustolddeltas: true } }; $.fn.extend({ mousewheel: function(fn) { return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel'); }, unmousewheel: function(fn) { return this.unbind('mousewheel', fn); } }); function handler(event) { var orgevent = event || window.event, args = slice.call(arguments, 1), delta = 0, deltax = 0, deltay = 0, absdelta = 0; event = $.event.fix(orgevent); event.type = 'mousewheel'; // old school scrollwheel delta if ( 'detail' in orgevent ) { deltay = orgevent.detail * -1; } if ( 'wheeldelta' in orgevent ) { deltay = orgevent.wheeldelta; } if ( 'wheeldeltay' in orgevent ) { deltay = orgevent.wheeldeltay; } if ( 'wheeldeltax' in orgevent ) { deltax = orgevent.wheeldeltax * -1; } // firefox < 17 horizontal scrolling related to dommousescroll event if ( 'axis' in orgevent && orgevent.axis === orgevent.horizontal_axis ) { deltax = deltay * -1; deltay = 0; } // set delta to be deltay or deltax if deltay is 0 for backwards compatabilitiy delta = deltay === 0 ? deltax : deltay; // new school wheel delta (wheel event) if ( 'deltay' in orgevent ) { deltay = orgevent.deltay * -1; delta = deltay; } if ( 'deltax' in orgevent ) { deltax = orgevent.deltax; if ( deltay === 0 ) { delta = deltax * -1; } } // no change actually happened, no reason to go any further if ( deltay === 0 && deltax === 0 ) { return; } // need to convert lines and pages to pixels if we aren't already in pixels // there are three delta modes: // * deltamode 0 is by pixels, nothing to do // * deltamode 1 is by lines // * deltamode 2 is by pages if ( orgevent.deltamode === 1 ) { var lineheight = $.data(this, 'mousewheel-line-height'); delta *= lineheight; deltay *= lineheight; deltax *= lineheight; } else if ( orgevent.deltamode === 2 ) { var pageheight = $.data(this, 'mousewheel-page-height'); delta *= pageheight; deltay *= pageheight; deltax *= pageheight; } // store lowest absolute delta to normalize the delta values absdelta = math.max( math.abs(deltay), math.abs(deltax) ); if ( !lowestdelta || absdelta < lowestdelta ) { lowestdelta = absdelta; // adjust older deltas if necessary if ( shouldadjustolddeltas(orgevent, absdelta) ) { lowestdelta /= 40; } } // adjust older deltas if necessary if ( shouldadjustolddeltas(orgevent, absdelta) ) { // divide all the things by 40! delta /= 40; deltax /= 40; deltay /= 40; } // get a whole, normalized value for the deltas delta = math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestdelta); deltax = math[ deltax >= 1 ? 'floor' : 'ceil' ](deltax / lowestdelta); deltay = math[ deltay >= 1 ? 'floor' : 'ceil' ](deltay / lowestdelta); // add information to the event object event.deltax = deltax; event.deltay = deltay; event.deltafactor = lowestdelta; // go ahead and set deltamode to 0 since we converted to pixels // although this is a little odd since we overwrite the deltax/y // properties with normalized deltas. event.deltamode = 0; // add event and delta to the front of the arguments args.unshift(event, delta, deltax, deltay); // clearout lowestdelta after sometime to better // handle multiple device types that give different // a different lowestdelta // ex: trackpad = 3 and mouse wheel = 120 if (nulllowestdeltatimeout) { cleartimeout(nulllowestdeltatimeout); } nulllowestdeltatimeout = settimeout(nulllowestdelta, 200); return ($.event.dispatch || $.event.handle).apply(this, args); } function nulllowestdelta() { lowestdelta = null; } function shouldadjustolddeltas(orgevent, absdelta) { // if this is an older event and the delta is divisable by 120, // then we are assuming that the browser is treating this as an // older mouse wheel event and that we should divide the deltas // by 40 to try and get a more usable deltafactor. // side note, this actually impacts the reported scroll distance // in older browsers and can cause scrolling to be slower than native. // turn this off by setting $.event.special.mousewheel.settings.adjustolddeltas to false. return special.settings.adjustolddeltas && orgevent.type === 'mousewheel' && absdelta % 120 === 0; } }));