2 * Interface Elements for jQuery
\r
5 * http://interface.eyecon.ro
\r
7 * Copyright (c) 2006 Stefan Petre
\r
8 * Dual licensed under the MIT (MIT-LICENSE.txt)
\r
9 * and GPL (GPL-LICENSE.txt) licenses.
\r
15 * Validates elements that can be animated
\r
17 jQuery.fxCheckTag = function(e)
\r
19 if (/^tr$|^td$|^tbody$|^caption$|^thead$|^tfoot$|^col$|^colgroup$|^th$|^body$|^header$|^script$|^frame$|^frameset$|^option$|^optgroup$|^meta$/i.test(e.nodeName) )
\r
26 * Destroy the wrapper used for some animations
\r
28 jQuery.fx.destroyWrapper = function(e, old)
\r
30 var c = e.firstChild;
\r
32 cs.position = old.position;
\r
33 cs.marginTop = old.margins.t;
\r
34 cs.marginLeft = old.margins.l;
\r
35 cs.marginBottom = old.margins.b;
\r
36 cs.marginRight = old.margins.r;
\r
37 cs.top = old.top + 'px';
\r
38 cs.left = old.left + 'px';
\r
39 e.parentNode.insertBefore(c, e);
\r
40 e.parentNode.removeChild(e);
\r
44 * Builds a wrapper used for some animations
\r
46 jQuery.fx.buildWrapper = function(e)
\r
48 if (!jQuery.fxCheckTag(e))
\r
52 var restoreStyle = false;
\r
54 if (t.css('display') == 'none') {
\r
55 oldVisibility = t.css('visibility');
\r
56 t.css('visibility', 'hidden').show();
\r
57 restoreStyle = true;
\r
60 oldStyle.position = t.css('position');
\r
61 oldStyle.sizes = jQuery.iUtil.getSize(e);
\r
62 oldStyle.margins = jQuery.iUtil.getMargins(e);
\r
64 var oldFloat = e.currentStyle ? e.currentStyle.styleFloat : t.css('float');
\r
65 oldStyle.top = parseInt(t.css('top'))||0;
\r
66 oldStyle.left = parseInt(t.css('left'))||0;
\r
67 var wid = 'w_' + parseInt(Math.random() * 10000);
\r
68 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);
\r
69 jQuery.attr(wr,'id', wid);
\r
70 var wrapEl = jQuery(wr).addClass('fxWrapper');
\r
74 if (oldStyle.position == 'relative' || oldStyle.position == 'absolute'){
\r
76 left = oldStyle.left;
\r
79 wrs.top = top + 'px';
\r
80 wrs.left = left + 'px';
\r
81 wrs.position = oldStyle.position != 'relative' && oldStyle.position != 'absolute' ? 'relative' : oldStyle.position;
\r
82 wrs.height = oldStyle.sizes.hb + 'px';
\r
83 wrs.width = oldStyle.sizes.wb + 'px';
\r
84 wrs.marginTop = oldStyle.margins.t;
\r
85 wrs.marginRight = oldStyle.margins.r;
\r
86 wrs.marginBottom = oldStyle.margins.b;
\r
87 wrs.marginLeft = oldStyle.margins.l;
\r
88 wrs.overflow = 'hidden';
\r
89 if (jQuery.browser.msie) {
\r
90 wrs.styleFloat = oldFloat;
\r
92 wrs.cssFloat = oldFloat;
\r
94 if (jQuery.browser == "msie") {
\r
95 es.filter = "alpha(opacity=" + 0.999*100 + ")";
\r
99 e.parentNode.insertBefore(wr, e);
\r
101 es.marginTop = '0px';
\r
102 es.marginRight = '0px';
\r
103 es.marginBottom = '0px';
\r
104 es.marginLeft = '0px';
\r
105 es.position = 'absolute';
\r
106 es.listStyle = 'none';
\r
109 if (restoreStyle) {
\r
111 es.visibility = oldVisibility;
\r
113 return {oldStyle:oldStyle, wrapper:jQuery(wr)};
\r
119 jQuery.fx.namedColors = {
\r
121 azure:[240,255,255],
\r
122 beige:[245,245,220],
\r
127 darkblue:[0,0,139],
\r
128 darkcyan:[0,139,139],
\r
129 darkgrey:[169,169,169],
\r
130 darkgreen:[0,100,0],
\r
131 darkkhaki:[189,183,107],
\r
132 darkmagenta:[139,0,139],
\r
133 darkolivegreen:[85,107,47],
\r
134 darkorange:[255,140,0],
\r
135 darkorchid:[153,50,204],
\r
137 darksalmon:[233,150,122],
\r
138 darkviolet:[148,0,211],
\r
139 fuchsia:[255,0,255],
\r
143 khaki:[240,230,140],
\r
144 lightblue:[173,216,230],
\r
145 lightcyan:[224,255,255],
\r
146 lightgreen:[144,238,144],
\r
147 lightgrey:[211,211,211],
\r
148 lightpink:[255,182,193],
\r
149 lightyellow:[255,255,224],
\r
151 magenta:[255,0,255],
\r
155 orange:[255,165,0],
\r
156 pink:[255,192,203],
\r
157 purple:[128,0,128],
\r
159 silver:[192,192,192],
\r
160 white:[255,255,255],
\r
165 * parses a color to an object for reg, green and blue
\r
167 jQuery.fx.parseColor = function(color, notColor)
\r
169 if (jQuery.fx.namedColors[color])
\r
171 r: jQuery.fx.namedColors[color][0],
\r
172 g: jQuery.fx.namedColors[color][1],
\r
173 b: jQuery.fx.namedColors[color][2]
\r
175 else if (result = /^rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)$/.exec(color))
\r
177 r: parseInt(result[1]),
\r
178 g: parseInt(result[2]),
\r
179 b: parseInt(result[3])
\r
181 else if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)$/.exec(color))
\r
183 r: parseFloat(result[1])*2.55,
\r
184 g: parseFloat(result[2])*2.55,
\r
185 b: parseFloat(result[3])*2.55
\r
187 else if (result = /^#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])$/.exec(color))
\r
189 r: parseInt("0x"+ result[1] + result[1]),
\r
190 g: parseInt("0x" + result[2] + result[2]),
\r
191 b: parseInt("0x" + result[3] + result[3])
\r
193 else if (result = /^#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})$/.exec(color))
\r
195 r: parseInt("0x" + result[1]),
\r
196 g: parseInt("0x" + result[2]),
\r
197 b: parseInt("0x" + result[3])
\r
200 return notColor == true ? false : {r: 255, g: 255, b: 255};
\r
203 * CSS rules that can be animated
\r
205 jQuery.fx.cssProps = {
\r
206 borderBottomWidth:1,
\r
208 borderRightWidth:1,
\r
238 * CSS color rules that can be animated
\r
240 jQuery.fx.colorCssProps = {
\r
242 borderBottomColor:1,
\r
244 borderRightColor:1,
\r
250 jQuery.fx.cssSides = ['Top', 'Right', 'Bottom', 'Left'];
\r
251 jQuery.fx.cssSidesEnd = {
\r
252 'borderWidth': ['border', 'Width'],
\r
253 'borderColor': ['border', 'Color'],
\r
254 'margin': ['margin', ''],
\r
255 'padding': ['padding', '']
\r
259 * Overwrite animation to use new FX function
\r
263 animate: function( prop, speed, easing, callback ) {
\r
264 return this.queue(function(){
\r
265 var opt = jQuery.speed(speed, easing, callback);
\r
266 var e = new jQuery.fxe( this, opt, prop );
\r
270 pause: function(speed, callback) {
\r
271 return this.queue(function(){
\r
272 var opt = jQuery.speed(speed, callback);
\r
273 var e = new jQuery.pause( this, opt );
\r
276 stop : function(step) {
\r
277 return this.each(function(){
\r
278 if (this.animationHandler)
\r
279 jQuery.stopAnim(this, step);
\r
283 stopAll : function(step) {
\r
284 return this.each(function(){
\r
285 if (this.animationHandler)
\r
286 jQuery.stopAnim(this, step);
\r
287 if ( this.queue && this.queue['fx'] )
\r
288 this.queue.fx = [];
\r
293 * Improved FXC function that aniamtes collection of properties per timer. Accepts inline styles and class names to animate
\r
296 pause: function(elem, options)
\r
298 var z = this, values;
\r
299 z.step = function()
\r
301 if ( jQuery.isFunction( options.complete ) )
\r
302 options.complete.apply( elem );
\r
304 z.timer=setInterval(function(){z.step();},options.duration);
\r
305 elem.animationHandler = z;
\r
308 linear: function(p, n, firstNum, delta, duration) {
\r
309 return ((-Math.cos(p*Math.PI)/2) + 0.5) * delta + firstNum;
\r
312 fxe: function( elem, options, prop ){
\r
313 var z = this, values;
\r
316 var y = elem.style;
\r
317 var oldOverflow = jQuery.css(elem, "overflow");
\r
318 var oldDisplay= jQuery.css(elem, "display");
\r
320 z.startTime = (new Date()).getTime();
\r
321 options.easing = options.easing && jQuery.easing[options.easing] ? options.easing : 'linear';
\r
323 z.getValues = function(tp, vp)
\r
325 if (jQuery.fx.cssProps[tp]) {
\r
326 if (vp == 'show' || vp == 'hide' || vp == 'toggle') {
\r
327 if ( !elem.orig ) elem.orig = {};
\r
328 var r = parseFloat( jQuery.curCSS(elem, tp) );
\r
329 elem.orig[tp] = r && r > -10000 ? r : (parseFloat( jQuery.css(elem,tp) )||0);
\r
330 vp = vp == 'toggle' ? ( oldDisplay == 'none' ? 'show' : 'hide') : vp;
\r
331 options[vp] = true;
\r
332 props[tp] = vp == 'show' ? [0, elem.orig[tp]] : [elem.orig[tp], 0];
\r
333 if (tp != 'opacity')
\r
334 y[tp] = props[tp][0] + (tp != 'zIndex' && tp != 'fontWeight' ? 'px':'');
\r
336 jQuery.attr(y, "opacity", props[tp][0]);
\r
338 props[tp] = [parseFloat( jQuery.curCSS(elem, tp) ), parseFloat(vp)||0];
\r
340 } else if (jQuery.fx.colorCssProps[tp])
\r
341 props[tp] = [jQuery.fx.parseColor(jQuery.curCSS(elem, tp)), jQuery.fx.parseColor(vp)];
\r
342 else if(/^margin$|padding$|border$|borderColor$|borderWidth$/i.test(tp)) {
\r
343 var m = vp.replace(/\s+/g, ' ').replace(/rgb\s*\(\s*/g,'rgb(').replace(/\s*,\s*/g,',').replace(/\s*\)/g,')').match(/([^\s]+)/g);
\r
347 case 'borderWidth':
\r
348 case 'borderColor':
\r
349 m[3] = m[3]||m[1]||m[0];
\r
352 for(var i = 0; i < jQuery.fx.cssSides.length; i++) {
\r
353 var nmp = jQuery.fx.cssSidesEnd[tp][0] + jQuery.fx.cssSides[i] + jQuery.fx.cssSidesEnd[tp][1];
\r
354 props[nmp] = tp == 'borderColor' ?
\r
355 [jQuery.fx.parseColor(jQuery.curCSS(elem, nmp)), jQuery.fx.parseColor(m[i])]
\r
356 : [parseFloat( jQuery.curCSS(elem, nmp) ), parseFloat(m[i])];
\r
360 for(var i = 0; i< m.length; i++) {
\r
361 var floatVal = parseFloat(m[i]);
\r
362 var sideEnd = !isNaN(floatVal) ? 'Width' : (!/transparent|none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset/i.test(m[i]) ? 'Color' : false);
\r
364 for(var j = 0; j < jQuery.fx.cssSides.length; j++) {
\r
365 nmp = 'border' + jQuery.fx.cssSides[j] + sideEnd;
\r
366 props[nmp] = sideEnd == 'Color' ?
\r
367 [jQuery.fx.parseColor(jQuery.curCSS(elem, nmp)), jQuery.fx.parseColor(m[i])]
\r
368 : [parseFloat( jQuery.curCSS(elem, nmp) ), floatVal];
\r
371 y['borderStyle'] = m[i];
\r
383 if (p == 'style') {
\r
384 var newStyles = jQuery.parseStyle(prop[p]);
\r
385 for (np in newStyles) {
\r
386 this.getValues(np, newStyles[np]);
\r
388 } else if (p == 'className') {
\r
389 if (document.styleSheets)
\r
390 for (var i=0; i<document.styleSheets.length; i++){
\r
391 var cssRules = document.styleSheets[i].cssRules||document.styleSheets[i].rules||null;
\r
393 for (var j=0; j<cssRules.length; j++) {
\r
394 if(cssRules[j].selectorText == '.' + prop[p]) {
\r
395 var rule = new RegExp('\.' + prop[p] + ' {');
\r
396 var styles = cssRules[j].style.cssText;
\r
397 var newStyles = jQuery.parseStyle(styles.replace(rule, '').replace(/}/g, ''));
\r
398 for (np in newStyles) {
\r
399 this.getValues(np, newStyles[np]);
\r
406 this.getValues(p, prop[p]);
\r
409 y.display = oldDisplay == 'none' ? 'block' : oldDisplay;
\r
410 y.overflow = 'hidden';
\r
412 /*if (options.show)
\r
415 z.step = function(){
\r
416 var t = (new Date()).getTime();
\r
417 if (t > options.duration + z.startTime) {
\r
418 clearInterval(z.timer);
\r
421 if ( p == "opacity" )
\r
422 jQuery.attr(y, "opacity", props[p][1]);
\r
423 else if (typeof props[p][1] == 'object')
\r
424 y[p] = 'rgb(' + props[p][1].r +',' + props[p][1].g +',' + props[p][1].b +')';
\r
426 y[p] = props[p][1] + (p != 'zIndex' && p != 'fontWeight' ? 'px':'');
\r
428 if ( options.hide || options.show )
\r
429 for ( var p in elem.orig )
\r
430 if (p == "opacity")
\r
431 jQuery.attr(y, p, elem.orig[p]);
\r
434 y.display = options.hide ? 'none' : (oldDisplay !='none' ? oldDisplay : 'block');
\r
435 y.overflow = oldOverflow;
\r
436 elem.animationHandler = null;
\r
437 if ( jQuery.isFunction( options.complete ) )
\r
438 options.complete.apply( elem );
\r
440 var n = t - this.startTime;
\r
441 var pr = n / options.duration;
\r
443 if (typeof props[p][1] == 'object') {
\r
445 + parseInt(jQuery.easing[options.easing](pr, n, props[p][0].r, (props[p][1].r-props[p][0].r), options.duration))
\r
447 + parseInt(jQuery.easing[options.easing](pr, n, props[p][0].g, (props[p][1].g-props[p][0].g), options.duration))
\r
449 + parseInt(jQuery.easing[options.easing](pr, n, props[p][0].b, (props[p][1].b-props[p][0].b), options.duration))
\r
452 var pValue = jQuery.easing[options.easing](pr, n, props[p][0], (props[p][1]-props[p][0]), options.duration);
\r
453 if ( p == "opacity" )
\r
454 jQuery.attr(y, "opacity", pValue);
\r
456 y[p] = pValue + (p != 'zIndex' && p != 'fontWeight' ? 'px':'');
\r
462 z.timer=setInterval(function(){z.step();},13);
\r
463 elem.animationHandler = z;
\r
465 stopAnim: function(elem, step)
\r
468 elem.animationHandler.startTime -= 100000000;
\r
470 window.clearInterval(elem.animationHandler.timer);
\r
471 elem.animationHandler = null;
\r
472 jQuery.dequeue(elem, "fx");
\r
478 jQuery.parseStyle = function(styles) {
\r
479 var newStyles = {};
\r
480 if (typeof styles == 'string') {
\r
481 styles = styles.toLowerCase().split(';');
\r
482 for(var i=0; i< styles.length; i++){
\r
483 rule = styles[i].split(':');
\r
484 if (rule.length == 2) {
\r
485 newStyles[jQuery.trim(rule[0].replace(/\-(\w)/g,function(m,c){return c.toUpperCase();}))] = jQuery.trim(rule[1]);
\r