/** * Interface Elements for jQuery * FX * * http://interface.eyecon.ro * * Copyright (c) 2006 Stefan Petre * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * * */ /** * Validates elements that can be animated */ jQuery.fxCheckTag = function(e) { if (/^tr$|^td$|^tbody$|^caption$|^thead$|^tfoot$|^col$|^colgroup$|^th$|^body$|^header$|^script$|^frame$|^frameset$|^option$|^optgroup$|^meta$/i.test(e.nodeName) ) return false; else return true; }; /** * Destroy the wrapper used for some animations */ jQuery.fx.destroyWrapper = function(e, old) { var c = e.firstChild; var cs = c.style; cs.position = old.position; cs.marginTop = old.margins.t; cs.marginLeft = old.margins.l; cs.marginBottom = old.margins.b; cs.marginRight = old.margins.r; cs.top = old.top + 'px'; cs.left = old.left + 'px'; e.parentNode.insertBefore(c, e); e.parentNode.removeChild(e); }; /** * Builds a wrapper used for some animations */ jQuery.fx.buildWrapper = function(e) { if (!jQuery.fxCheckTag(e)) return false; var t = jQuery(e); var es = e.style; var restoreStyle = false; var oldStyle = {}; oldStyle.position = t.css('position'); if (t.css('display') == 'none') { oldVisibility = t.css('visibility'); es.visibility = 'hidden'; es.display = ''; restoreStyle = true; } oldStyle.sizes = jQuery.iUtil.getSize(e); oldStyle.margins = jQuery.iUtil.getMargins(e); var oldFloat = e.currentStyle ? e.currentStyle.styleFloat : t.css('float'); oldStyle.top = parseInt(t.css('top'))||0; oldStyle.left = parseInt(t.css('left'))||0; var wid = 'w_' + parseInt(Math.random() * 10000); var wr = document.createElement(/^img$|^br$|^input$|^hr$|^select$|^textarea$|^object$|^iframe$|^button$|^form$|^table$|^ul$|^dl$|^ol$/i.test(e.nodeName) ? 'div' : e.nodeName); jQuery.attr(wr,'id', wid); wr.className = 'fxWrapper'; var wrs = wr.style; var top = 0; var left = 0; if (oldStyle.position == 'relative' || oldStyle.position == 'absolute'){ top = oldStyle.top; left = oldStyle.left; } wrs.display = 'none'; wrs.top = top + 'px'; wrs.left = left + 'px'; wrs.position = oldStyle.position != 'relative' && oldStyle.position != 'absolute' ? 'relative' : oldStyle.position; wrs.overflow = 'hidden'; wrs.height = oldStyle.sizes.hb + 'px'; wrs.width = oldStyle.sizes.wb + 'px'; wrs.marginTop = oldStyle.margins.t; wrs.marginRight = oldStyle.margins.r; wrs.marginBottom = oldStyle.margins.b; wrs.marginLeft = oldStyle.margins.l; if (jQuery.browser.msie) { wrs.styleFloat = oldFloat; } else { wrs.cssFloat = oldFloat; } e.parentNode.insertBefore(wr, e); es.marginTop = '0px'; es.marginRight = '0px'; es.marginBottom = '0px'; es.marginLeft = '0px'; es.position = 'absolute'; es.listStyle = 'none'; es.top = '0px'; es.left = '0px'; if (restoreStyle) { es.display = 'none'; es.visibility = oldVisibility; } wr.appendChild(e); wrs.display = 'block'; return {oldStyle:oldStyle, wrapper:jQuery(wr)}; }; /** * named colors */ jQuery.fx.namedColors = { aqua:[0,255,255], azure:[240,255,255], beige:[245,245,220], black:[0,0,0], blue:[0,0,255], brown:[165,42,42], cyan:[0,255,255], darkblue:[0,0,139], darkcyan:[0,139,139], darkgrey:[169,169,169], darkgreen:[0,100,0], darkkhaki:[189,183,107], darkmagenta:[139,0,139], darkolivegreen:[85,107,47], darkorange:[255,140,0], darkorchid:[153,50,204], darkred:[139,0,0], darksalmon:[233,150,122], darkviolet:[148,0,211], fuchsia:[255,0,255], gold:[255,215,0], green:[0,128,0], indigo:[75,0,130], khaki:[240,230,140], lightblue:[173,216,230], lightcyan:[224,255,255], lightgreen:[144,238,144], lightgrey:[211,211,211], lightpink:[255,182,193], lightyellow:[255,255,224], lime:[0,255,0], magenta:[255,0,255], maroon:[128,0,0], navy:[0,0,128], olive:[128,128,0], orange:[255,165,0], pink:[255,192,203], purple:[128,0,128], red:[255,0,0], silver:[192,192,192], white:[255,255,255], yellow:[255,255,0] }; /** * parses a color to an object for reg, green and blue */ jQuery.fx.parseColor = function(color, notColor) { if (jQuery.fx.namedColors[color]) return { r: jQuery.fx.namedColors[color][0], g: jQuery.fx.namedColors[color][1], b: jQuery.fx.namedColors[color][2] }; else if (result = /^rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)$/.exec(color)) return { r: parseInt(result[1]), g: parseInt(result[2]), b: parseInt(result[3]) }; else if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)$/.exec(color)) return { r: parseFloat(result[1])*2.55, g: parseFloat(result[2])*2.55, b: parseFloat(result[3])*2.55 }; else if (result = /^#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])$/.exec(color)) return { r: parseInt("0x"+ result[1] + result[1]), g: parseInt("0x" + result[2] + result[2]), b: parseInt("0x" + result[3] + result[3]) }; else if (result = /^#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})$/.exec(color)) return { r: parseInt("0x" + result[1]), g: parseInt("0x" + result[2]), b: parseInt("0x" + result[3]) }; else return notColor == true ? false : {r: 255, g: 255, b: 255}; }; /** * CSS rules that can be animated */ jQuery.fx.cssProps = { borderBottomWidth:1, borderLeftWidth:1, borderRightWidth:1, borderTopWidth:1, bottom:1, fontSize:1, height:1, left:1, letterSpacing:1, lineHeight:1, marginBottom:1, marginLeft:1, marginRight:1, marginTop:1, maxHeight:1, maxWidth:1, minHeight:1, minWidth:1, opacity:1, outlineOffset:1, outlineWidth:1, paddingBottom:1, paddingLeft:1, paddingRight:1, paddingTop:1, right:1, textIndent:1, top:1, width:1, zIndex:1 }; /** * CSS color rules that can be animated */ jQuery.fx.colorCssProps = { backgroundColor:1, borderBottomColor:1, borderLeftColor:1, borderRightColor:1, borderTopColor:1, color:1, outlineColor:1 }; jQuery.fx.cssSides = ['Top', 'Right', 'Bottom', 'Left']; jQuery.fx.cssSidesEnd = { 'borderWidth': ['border', 'Width'], 'borderColor': ['border', 'Color'], 'margin': ['margin', ''], 'padding': ['padding', ''] }; /** * Overwrite animation to use new FX function */ jQuery.fn.extend({ animate: function( prop, speed, easing, callback ) { return this.queue(function(){ var opt = jQuery.speed(speed, easing, callback); var e = new jQuery.fxe( this, opt, prop ); }); }, pause: function(speed, callback) { return this.queue(function(){ var opt = jQuery.speed(speed, callback); var e = new jQuery.pause( this, opt ); }); }, stop : function(step) { return this.each(function(){ if (this.animationHandler) jQuery.stopAnim(this, step); }); }, stopAll : function(step) { return this.each(function(){ if (this.animationHandler) jQuery.stopAnim(this, step); if ( this.queue && this.queue['fx'] ) this.queue.fx = []; }); } }); /** * Improved FX function that aniamtes collection of properties per timer. Accepts inline styles and class names to animate */ jQuery.extend({ pause: function(elem, options) { var z = this, values; z.step = function() { if ( jQuery.isFunction( options.complete ) ) options.complete.apply( elem ); }; z.timer=setInterval(function(){z.step();},options.duration); elem.animationHandler = z; }, easing : { linear: function(p, n, firstNum, delta, duration) { return ((-Math.cos(p*Math.PI)/2) + 0.5) * delta + firstNum; } }, fxe: function( elem, options, prop ){ var z = this, values; // The styles var y = elem.style; var oldOverflow = jQuery.css(elem, "overflow"); var oldDisplay= jQuery.css(elem, "display"); var props = {}; z.startTime = (new Date()).getTime(); options.easing = options.easing && jQuery.easing[options.easing] ? options.easing : 'linear'; z.getValues = function(tp, vp) { if (jQuery.fx.cssProps[tp]) { if (vp == 'show' || vp == 'hide' || vp == 'toggle') { if ( !elem.orig ) elem.orig = {}; var r = parseFloat( jQuery.curCSS(elem, tp) ); elem.orig[tp] = r && r > -10000 ? r : (parseFloat( jQuery.css(elem,tp) )||0); vp = vp == 'toggle' ? ( oldDisplay == 'none' ? 'show' : 'hide') : vp; options[vp] = true; props[tp] = vp == 'show' ? [0, elem.orig[tp]] : [elem.orig[tp], 0]; if (tp != 'opacity') y[tp] = props[tp][0] + (tp != 'zIndex' && tp != 'fontWeight' ? 'px':''); else jQuery.attr(y, "opacity", props[tp][0]); } else { props[tp] = [parseFloat( jQuery.curCSS(elem, tp) ), parseFloat(vp)||0]; } } else if (jQuery.fx.colorCssProps[tp]) props[tp] = [jQuery.fx.parseColor(jQuery.curCSS(elem, tp)), jQuery.fx.parseColor(vp)]; else if(/^margin$|padding$|border$|borderColor$|borderWidth$/i.test(tp)) { var m = vp.replace(/\s+/g, ' ').replace(/rgb\s*\(\s*/g,'rgb(').replace(/\s*,\s*/g,',').replace(/\s*\)/g,')').match(/([^\s]+)/g); switch(tp){ case 'margin': case 'padding': case 'borderWidth': case 'borderColor': m[3] = m[3]||m[1]||m[0]; m[2] = m[2]||m[0]; m[1] = m[1]||m[0]; for(var i = 0; i < jQuery.fx.cssSides.length; i++) { var nmp = jQuery.fx.cssSidesEnd[tp][0] + jQuery.fx.cssSides[i] + jQuery.fx.cssSidesEnd[tp][1]; props[nmp] = tp == 'borderColor' ? [jQuery.fx.parseColor(jQuery.curCSS(elem, nmp)), jQuery.fx.parseColor(m[i])] : [parseFloat( jQuery.curCSS(elem, nmp) ), parseFloat(m[i])]; } break; case 'border': for(var i = 0; i< m.length; i++) { var floatVal = parseFloat(m[i]); var sideEnd = !isNaN(floatVal) ? 'Width' : (!/transparent|none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset/i.test(m[i]) ? 'Color' : false); if (sideEnd) { for(var j = 0; j < jQuery.fx.cssSides.length; j++) { nmp = 'border' + jQuery.fx.cssSides[j] + sideEnd; props[nmp] = sideEnd == 'Color' ? [jQuery.fx.parseColor(jQuery.curCSS(elem, nmp)), jQuery.fx.parseColor(m[i])] : [parseFloat( jQuery.curCSS(elem, nmp) ), floatVal]; } } else { y['borderStyle'] = m[i]; } } break; } } else { y[tp] = vp; } return false; }; for(p in prop) { if (p == 'style') { var newStyles = jQuery.parseStyle(prop[p]); for (np in newStyles) { this.getValues(np, newStyles[np]); } } else if (p == 'className') { if (document.styleSheets) for (var i=0; i options.duration + z.startTime) { clearInterval(z.timer); z.timer = null; for (p in props) { if ( p == "opacity" ) jQuery.attr(y, "opacity", props[p][1]); else if (typeof props[p][1] == 'object') y[p] = 'rgb(' + props[p][1].r +',' + props[p][1].g +',' + props[p][1].b +')'; else y[p] = props[p][1] + (p != 'zIndex' && p != 'fontWeight' ? 'px':''); } if ( options.hide || options.show ) for ( var p in elem.orig ) if (p == "opacity") jQuery.attr(y, p, elem.orig[p]); else y[p] = ""; y.display = options.hide ? 'none' : (oldDisplay !='none' ? oldDisplay : 'block'); y.overflow = oldOverflow; elem.animationHandler = null; if ( jQuery.isFunction( options.complete ) ) options.complete.apply( elem ); } else { var n = t - this.startTime; var pr = n / options.duration; for (p in props) { if (typeof props[p][1] == 'object') { y[p] = 'rgb(' + parseInt(jQuery.easing[options.easing](pr, n, props[p][0].r, (props[p][1].r-props[p][0].r), options.duration)) + ',' + parseInt(jQuery.easing[options.easing](pr, n, props[p][0].g, (props[p][1].g-props[p][0].g), options.duration)) + ',' + parseInt(jQuery.easing[options.easing](pr, n, props[p][0].b, (props[p][1].b-props[p][0].b), options.duration)) +')'; } else { var pValue = jQuery.easing[options.easing](pr, n, props[p][0], (props[p][1]-props[p][0]), options.duration); if ( p == "opacity" ) jQuery.attr(y, "opacity", pValue); else y[p] = pValue + (p != 'zIndex' && p != 'fontWeight' ? 'px':''); } } } }; z.timer=setInterval(function(){z.step();},13); elem.animationHandler = z; }, stopAnim: function(elem, step) { if (step) elem.animationHandler.startTime -= 100000000; else { window.clearInterval(elem.animationHandler.timer); elem.animationHandler = null; jQuery.dequeue(elem, "fx"); } } } ); jQuery.parseStyle = function(styles) { var newStyles = {}; if (typeof styles == 'string') { styles = styles.toLowerCase().split(';'); for(var i=0; i< styles.length; i++){ rule = styles[i].split(':'); if (rule.length == 2) { newStyles[jQuery.trim(rule[0].replace(/\-(\w)/g,function(m,c){return c.toUpperCase();}))] = jQuery.trim(rule[1]); } } } return newStyles;