/*! Overthrow. An overflow:auto polyfill for responsive design. (c) 2012: Scott Jehl, Filament Group, Inc. http://filamentgroup.github.com/Overthrow/license.txt */ (function( w, o, undefined ){ // o is overthrow reference from overthrow-polyfill.js if( o === undefined ){ return; } // Easing can use any of Robert Penner's equations (http://www.robertpenner.com/easing_terms_of_use.html). By default, overthrow includes ease-out-cubic // arguments: t = current iteration, b = initial value, c = end value, d = total iterations // use w.overthrow.easing to provide a custom function externally, or pass an easing function as a callback to the toss method o.easing = function (t, b, c, d) { return c*((t=t/d-1)*t*t + 1) + b; }; // tossing property is true during a programatic scroll o.tossing = false; // Keeper of intervals var timeKeeper; /* toss scrolls and element with easing // elem is the element to scroll // options hash: * left is the desired horizontal scroll. Default is "+0". For relative distances, pass a string with "+" or "-" in front. * top is the desired vertical scroll. Default is "+0". For relative distances, pass a string with "+" or "-" in front. * duration is the number of milliseconds the throw will take. Default is 100. * easing is an optional custom easing function. Default is w.overthrow.easing. Must follow the easing function signature */ o.toss = function( elem, options ){ o.intercept(); var i = 0, sLeft = elem.scrollLeft, sTop = elem.scrollTop, // Toss defaults op = { top: "+0", left: "+0", duration: 50, easing: o.easing, finished: function() {} }, endLeft, endTop, finished = false; // Mixin based on predefined defaults if( options ){ for( var j in op ){ if( options[ j ] !== undefined ){ op[ j ] = options[ j ]; } } } // Convert relative values to ints // First the left val if( typeof op.left === "string" ){ op.left = parseFloat( op.left ); endLeft = op.left + sLeft; } else { endLeft = op.left; op.left = op.left - sLeft; } // Then the top val if( typeof op.top === "string" ){ op.top = parseFloat( op.top ); endTop = op.top + sTop; } else { endTop = op.top; op.top = op.top - sTop; } o.tossing = true; timeKeeper = setInterval(function(){ if( i++ < op.duration ){ elem.scrollLeft = op.easing( i, sLeft, op.left, op.duration ); elem.scrollTop = op.easing( i, sTop, op.top, op.duration ); } else{ if( endLeft !== elem.scrollLeft ){ elem.scrollLeft = endLeft; } else { // if the end of the vertical scrolling has taken place // we know that we're done here call the callback // otherwise signal that horizontal scrolling is complete if( finished ) { op.finished(); } finished = true; } if( endTop !== elem.scrollTop ){ elem.scrollTop = endTop; } else { // if the end of the horizontal scrolling has taken place // we know that we're done here call the callback if( finished ) { op.finished(); } finished = true; } o.intercept(); } }, 1 ); // Return the values, post-mixin, with end values specified return { top: endTop, left: endLeft, duration: o.duration, easing: o.easing }; }; // Intercept any throw in progress o.intercept = function(){ clearInterval( timeKeeper ); o.tossing = false; }; })( this, this.overthrow );