When using jQuery, I often "collapse" certain DOM elements by decreasing their width to 0px and fading them out. Here is an example:
$(".slideoutmenu").animate({ width: 0, opacity: 0}, function() { $(this).hide(); });
The widths of these elements can vary, but the document layout is set up correctly through CSS without specifying a specific width.
To show these elements again, you could simply do something like this:
$(".slideoutmenu").stop().show().css({ width: '', opacity: 1 });
However, I want to animate these elements in reverse (fade in and expand).
Normally, I would use something like this:
$(this).children(".slideoutmenu").stop().show().animate({ width: 250, opacity: 1 });
So here's what I tried:
$(this).children(".slideoutmenu").stop().show().animate({ width: "", opacity: 1 });
Unfortunately, this approach didn't work as expected.
The issue lies in the fixed "250" value used above. Since the widths are variable, I need to find a way to combine the result of setting an empty string for the width and animating it, but I haven't been able to figure it out. I've experimented with different values like 'undefined', 'null', '-1', '' without success.
I know I could potentially manipulate measurements while keeping the element hidden from the user, but I believe this must be a common problem and there should be a standard solution available, or perhaps it's built into jQuery in some way that I'm unaware of.
Thank you for reading.
FOLLOW UP:
After receiving helpful input from Michael, I created a simple plugin to achieve this functionality dynamically. Below is the plugin code:
(function( $ ){
$.fn.cacheCss = function( prop ) {
return this.each(function() {
var $this = $(this);
if (prop instanceof Array)
{
for (var pname in prop)
{
if ($this.data('cssCache-' + prop[pname]) != undefined)
continue;
$this.data('cssCache-' + prop[pname], $this.css(prop[pname]));
}
}
else
{
if ($this.data('cssCache-' + prop) != undefined)
return $this;
$this.data('cssCache-' + prop, $this.css(prop));
}
return $this;
});
};
$.fn.revertCss = function(settings, prop, animated) {
if (settings == null)
settings = {};
return this.each(function() {
var $this = $(this);
if (prop instanceof Array)
{
for (var pname in prop)
{
if ($this.data('cssCache-' + prop[pname]) != undefined)
settings[prop[pname]] = $this.data('cssCache-' + prop[pname]).replace(/px$/, "");
}
}
else
{
if ($this.data('cssCache-' + prop) != undefined)
settings[prop] = $this.data('cssCache-' + prop).replace(/px$/, "");
}
if (!animated)
return $this.css(settings);
return $this.animate(settings);
});
};
})( jQuery );
Here is how I implemented the plugin with my existing code:
The original line that set the css property:
$(".slideoutmenu").animate({ width: 0, opacity: 0 }, function() { $(this).hide(); });
was replaced with:
$(".slideoutmenu").cacheCss('width').animate({ width: 0, opacity: 0}, function() { $(this).hide(); });
The ".cacheCss('width')" now caches the value of the css property before starting the animation.
And when I needed to revert those changes:
$(this).children(".slideoutmenu").stop().show().animate({ width: 250, opacity: 1 });
was replaced with:
$(this).children(".slideoutmenu").stop().show().revertCss({ opacity: 1 }, 'width', true);
Now, ".revertCss(...)" uses the cached settings to revert the width property in an animated manner.
The plugin also accepts arrays, allowing you to cache multiple properties and then revert them together:
.cacheCss(['width', 'height'])
and later:
.revertCss(null, ['width', 'height'], true)
The third parameter specifies whether the reversion should be animated or not.
If you have other properties to animate alongside (e.g., 'opacity' as shown earlier), you can pass them in just like you would for the .animate() function.
I believe this plugin has room for improvement, but thought it might still be useful to share.
Lastly, I had to remove extra "px" at the end of the css values using a basic regex – there may be a more efficient method for doing this.