X-Git-Url: https://git.mdrn.pl/wolnelektury.git/blobdiff_plain/ae60b2a3949e96357477cc04f90fd0873cee8a92..085a24c27a95689480a9efd31821ea4bf461f19b:/src/wolnelektury/static/js/contrib/jquery.scrollto.js diff --git a/src/wolnelektury/static/js/contrib/jquery.scrollto.js b/src/wolnelektury/static/js/contrib/jquery.scrollto.js index c403ab9df..0717e0aa6 100644 --- a/src/wolnelektury/static/js/contrib/jquery.scrollto.js +++ b/src/wolnelektury/static/js/contrib/jquery.scrollto.js @@ -1,194 +1,215 @@ -/** - * jQuery.ScrollTo - * Copyright (c) 2007-2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com - * Dual licensed under MIT and GPL. - * Date: 9/11/2008 - * - * @projectDescription Easy element scrolling using jQuery. - * http://flesler.blogspot.com/2007/10/jqueryscrollto.html - * Tested with jQuery 1.2.6. On FF 2/3, IE 6/7, Opera 9.2/5 and Safari 3. on Windows. - * +/*! + * jQuery.scrollTo + * Copyright (c) 2007 Ariel Flesler - aflesler ○ gmail • com | https://github.com/flesler + * Licensed under MIT + * https://github.com/flesler/jquery.scrollTo + * @projectDescription Lightweight, cross-browser and highly customizable animated scrolling with jQuery * @author Ariel Flesler - * @version 1.4 - * - * @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. - * @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 } ); + * @version 2.1.3 */ -;(function( $ ){ - - var $scrollTo = $.scrollTo = function( target, duration, settings ){ - $(window).scrollTo( target, duration, settings ); +;(function(factory) { + 'use strict'; + if (typeof define === 'function' && define.amd) { + // AMD + define(['jquery'], factory); + } else if (typeof module !== 'undefined' && module.exports) { + // CommonJS + module.exports = factory(require('jquery')); + } else { + // Global + factory(jQuery); + } +})(function($) { + 'use strict'; + + var $scrollTo = $.scrollTo = function(target, duration, settings) { + return $(window).scrollTo(target, duration, settings); }; $scrollTo.defaults = { - axis:'y', - duration:1 + axis:'xy', + duration: 0, + limit:true }; - // 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(); - }; + function isWin(elem) { + return !elem.nodeName || + $.inArray(elem.nodeName.toLowerCase(), ['iframe','#document','html','body']) !== -1; + } - // Hack, hack, hack... stay away! - // Returns the real elements to scroll (supports window/iframes, documents and regular nodes) - $.fn.scrollable = function(){ - return this.map(function(){ - // Just store it, we might need it - var win = this.parentWindow || this.defaultView, - // If it's a document, get its iframe or the window if it's THE document - elem = this.nodeName == '#document' ? win.frameElement || win : this, - // Get the corresponding document - doc = elem.contentDocument || (elem.contentWindow || elem).document, - isWin = elem.setInterval; - - return elem.nodeName == 'IFRAME' || isWin && $.browser.safari ? doc.body - : isWin ? doc.documentElement - : this; - }); - }; + function isFunction(obj) { + // Brought from jQuery since it's deprecated + return typeof obj === 'function' + } - $.fn.scrollTo = function( target, duration, settings ){ - if( typeof duration == 'object' ){ + $.fn.scrollTo = function(target, duration, settings) { + if (typeof duration === 'object') { settings = duration; duration = 0; } - if( typeof settings == 'function' ) + if (typeof settings === 'function') { settings = { onAfter:settings }; + } + if (target === 'max') { + target = 9e9; + } - settings = $.extend( {}, $scrollTo.defaults, settings ); + settings = $.extend({}, $scrollTo.defaults, settings); // Speed is still recognized for backwards compatibility - duration = duration || settings.speed || settings.duration; + duration = duration || settings.duration; // Make sure the settings are given right - settings.queue = settings.queue && settings.axis.length > 1; - - if( settings.queue ) + var queue = settings.queue && settings.axis.length > 1; + if (queue) { // Let's keep the overall duration duration /= 2; - settings.offset = both( settings.offset ); - settings.over = both( settings.over ); + } + settings.offset = both(settings.offset); + settings.over = both(settings.over); + + return this.each(function() { + // Null target yields nothing, just like jQuery does + if (target === null) return; - return this.scrollable().each(function(){ - var elem = this, + var win = isWin(this), + elem = win ? this.contentWindow || window : this, $elem = $(elem), - targ = target, toff, attr = {}, - win = $elem.is('html,body'); + targ = target, + attr = {}, + toff; - switch( typeof targ ){ + switch (typeof targ) { // A number will pass the regex case 'number': case 'string': - if( /^([+-]=)?\d+(px)?$/.test(targ) ){ - targ = both( targ ); + if (/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)) { + targ = both(targ); // We are done break; } - // Relative selector, no break! - targ = $(targ,this); + // Relative/Absolute selector + targ = win ? $(targ) : $(targ, elem); + /* falls through */ case 'object': + if (targ.length === 0) return; // DOMElement / jQuery - if( targ.is || targ.style ) + 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', + + var offset = isFunction(settings.offset) && settings.offset(elem, targ) || settings.offset; + + $.each(settings.axis.split(''), function(i, axis) { + var Pos = axis === 'x' ? 'Left' : 'Top', pos = Pos.toLowerCase(), key = 'scroll' + Pos, - old = elem[key], - Dim = axis == 'x' ? 'Width' : 'Height', - dim = Dim.toLowerCase(); + prev = $elem[key](), + max = $scrollTo.max(elem, axis); - if( toff ){// jQuery / DOMElement - attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] ); + if (toff) {// jQuery / DOMElement + attr[key] = toff[pos] + (win ? 0 : prev - $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; + if (settings.margin) { + attr[key] -= parseInt(targ.css('margin'+Pos), 10) || 0; + attr[key] -= parseInt(targ.css('border'+Pos+'Width'), 10) || 0; } - attr[key] += settings.offset[pos] || 0; + attr[key] += offset[pos] || 0; - if( settings.over[pos] ) + if (settings.over[pos]) { // Scroll to a fraction of its width/height - attr[key] += targ[dim]() * settings.over[pos]; - }else - attr[key] = targ[pos]; + 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]) ) + if (settings.limit && /^\d+$/.test(attr[key])) { // Check the limits - attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max(Dim) ); + 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] ) + // Don't waste time animating, if there's no need. + if (!i && settings.axis.length > 1) { + if (prev === attr[key]) { + // No animation needed + attr = {}; + } else if (queue) { // Intermediate animation - animate( settings.onAfterFirst ); - // Don't animate this axis again in the next iteration. - delete attr[key]; + animate(settings.onAfterFirst); + // Don't animate this axis again in the next iteration. + attr = {}; + } } }); - animate( settings.onAfter ); - function animate( callback ){ - $elem.animate( attr, duration, settings.easing, callback && function(){ - callback.call(this, target, settings); + animate(settings.onAfter); + + function animate(callback) { + var opts = $.extend({}, settings, { + // The queue setting conflicts with animate() + // Force it to always be true + queue: true, + duration: duration, + complete: callback && function() { + callback.call(elem, targ, settings); + } }); - }; - function max( Dim ){ - var attr ='scroll'+Dim, - doc = elem.ownerDocument; - - return win - ? Math.max( doc.documentElement[attr], doc.body[attr] ) - : elem[attr]; - }; - }).end(); + $elem.animate(attr, opts); + } + }); + }; + + // 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 (!isWin(elem)) + return elem[scroll] - $(elem)[Dim.toLowerCase()](); + + var size = 'client' + Dim, + doc = elem.ownerDocument || elem.document, + html = doc.documentElement, + body = doc.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 }; + function both(val) { + return isFunction(val) || $.isPlainObject(val) ? val : { top:val, left:val }; + } + + // Add special hooks so that window scroll properties can be animated + $.Tween.propHooks.scrollLeft = + $.Tween.propHooks.scrollTop = { + get: function(t) { + return $(t.elem)[t.prop](); + }, + set: function(t) { + var curr = this.get(t); + // If interrupt is true and user scrolled, stop animating + if (t.options.interrupt && t._last && t._last !== curr) { + return $(t.elem).stop(); + } + var next = Math.round(t.now); + // Don't waste CPU + // Browsers don't render floating point scroll + if (curr !== next) { + $(t.elem)[t.prop](next); + t._last = this.get(t); + } + } }; -})( jQuery ); \ No newline at end of file + // AMD requirement + return $scrollTo; +});