ref: master
public/javascripts/vendor/jquery.scrollTo.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
/** * jQuery.ScrollTo * Copyright (c) 2007-2009 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com * Dual licensed under MIT and GPL. * Date: 5/25/2009 * * @projectDescription Easy element scrolling using jQuery. * http://flesler.blogspot.com/2007/10/jqueryscrollto.html * Works with jQuery +1.2.6. Tested on FF 2/3, IE 6/7/8, Opera 9.5/6, Safari 3, Chrome 1 on WinXP. * * @author Ariel Flesler * @version 1.4.2 * * @id jQuery.scrollTo * @id jQuery.fn.scrollTo * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements. * The different options for target are: * - A number position (will be applied to all axes). * - A string position ('44', '100px', '+=90', etc ) will be applied to all axes * - A jQuery/DOM element ( logically, child of the element to scroll ) * - A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc ) * - A hash { top:x, left:y }, x and y can be any kind of number/string like above. * - A percentage of the container's dimension/s, for example: 50% to go to the middle. * - The string 'max' for go-to-end. * @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead. * @param {Object,Function} settings Optional set of settings or the onAfter callback. * @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'. * @option {Number} duration The OVERALL length of the animation. * @option {String} easing The easing method for the animation. * @option {Boolean} margin If true, the margin of the target element will be deducted from the final position. * @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }. * @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes. * @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends. * @option {Function} onAfter Function to be called after the scrolling ends. * @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends. * @return {jQuery} Returns the same jQuery object, for chaining. * * @desc Scroll to a fixed position * @example $('div').scrollTo( 340 ); * * @desc Scroll relatively to the actual position * @example $('div').scrollTo( '+=340px', { axis:'y' } ); * * @dec Scroll using a selector (relative to the scrolled element) * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } ); * * @ Scroll to a DOM element (same for jQuery object) * @example var second_child = document.getElementById('container').firstChild.nextSibling; * $('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){ * alert('scrolled!!'); * }}); * * @desc Scroll on both axes, to different values * @example $('div').scrollTo( { top: 300, left:'+=200' }, { axis:'xy', offset:-20 } ); */ ;(function( $ ){ var $scrollTo = $.scrollTo = function( target, duration, settings ){ $(window).scrollTo( target, duration, settings ); }; $scrollTo.defaults = { axis:'xy', duration: parseFloat($.fn.jquery) >= 1.3 ? 0 : 1 }; // Returns the element that needs to be animated to scroll the window. // Kept for backwards compatibility (specially for localScroll & serialScroll) $scrollTo.window = function( scope ){ return $(window)._scrollable(); }; // Hack, hack, hack :) // Returns the real elements to scroll (supports window/iframes, documents and regular nodes) $.fn._scrollable = function(){ return this.map(function(){ var elem = this, isWin = !elem.nodeName || $.inArray( elem.nodeName.toLowerCase(), ['iframe','#document','html','body'] ) != -1; if( !isWin ) return elem; var doc = (elem.contentWindow || elem).document || elem.ownerDocument || elem; return $.browser.safari || doc.compatMode == 'BackCompat' ? doc.body : doc.documentElement; }); }; $.fn.scrollTo = function( target, duration, settings ){ if( typeof duration == 'object' ){ settings = duration; duration = 0; } if( typeof settings == 'function' ) settings = { onAfter:settings }; if( target == 'max' ) target = 9e9; settings = $.extend( {}, $scrollTo.defaults, settings ); // Speed is still recognized for backwards compatibility duration = duration || settings.speed || settings.duration; // Make sure the settings are given right settings.queue = settings.queue && settings.axis.length > 1; if( settings.queue ) // Let's keep the overall duration duration /= 2; settings.offset = both( settings.offset ); settings.over = both( settings.over ); return this._scrollable().each(function(){ var elem = this, $elem = $(elem), targ = target, toff, attr = {}, win = $elem.is('html,body'); switch( typeof targ ){ // A number will pass the regex case 'number': case 'string': if( /^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(targ) ){ targ = both( targ ); // We are done break; } // Relative selector, no break! targ = $(targ,this); case 'object': // DOMElement / jQuery if( targ.is || targ.style ) // Get the real position of the target toff = (targ = $(targ)).offset(); } $.each( settings.axis.split(''), function( i, axis ){ var Pos = axis == 'x' ? 'Left' : 'Top', pos = Pos.toLowerCase(), key = 'scroll' + Pos, old = elem[key], max = $scrollTo.max(elem, axis); if( toff ){// jQuery / DOMElement attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] ); // If it's a dom element, reduce the margin if( settings.margin ){ attr[key] -= parseInt(targ.css('margin'+Pos)) || 0; attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0; } attr[key] += settings.offset[pos] || 0; if( settings.over[pos] ) // Scroll to a fraction of its width/height attr[key] += targ[axis=='x'?'width':'height']() * settings.over[pos]; }else{ var val = targ[pos]; // Handle percentage values attr[key] = val.slice && val.slice(-1) == '%' ? parseFloat(val) / 100 * max : val; } // Number or 'number' if( /^\d+$/.test(attr[key]) ) // Check the limits attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max ); // Queueing axes if( !i && settings.queue ){ // Don't waste time animating, if there's no need. if( old != attr[key] ) // Intermediate animation animate( settings.onAfterFirst ); // Don't animate this axis again in the next iteration. delete attr[key]; } }); animate( settings.onAfter ); function animate( callback ){ $elem.animate( attr, duration, settings.easing, callback && function(){ callback.call(this, target, settings); }); }; }).end(); }; // Max scrolling position, works on quirks mode // It only fails (not too badly) on IE, quirks mode. $scrollTo.max = function( elem, axis ){ var Dim = axis == 'x' ? 'Width' : 'Height', scroll = 'scroll'+Dim; if( !$(elem).is('html,body') ) return elem[scroll] - $(elem)[Dim.toLowerCase()](); var size = 'client' + Dim, html = elem.ownerDocument.documentElement, body = elem.ownerDocument.body; return Math.max( html[scroll], body[scroll] ) - Math.min( html[size] , body[size] ); }; function both( val ){ return typeof val == 'object' ? val : { top:val, left:val }; }; })( jQuery ); |