views:

16175

answers:

5

So this might be really simple, but I haven't been able to find any examples to learn off of yet, so please bear with me. ;)

Here's basically what I want to do:

<div>Lots of content! Lots of content! Lots of content! ...</div>

.... 

$("div").html("Itsy-bitsy bit of content!");

I want to smoothly animate between the dimensions of the div with lots of content to the dimensions of the div with very little when the new content is injected.

Thoughts?

+1  A: 

maybe something like this?

$(".testLink").click(function(event) {
 event.preventDefault();
 $(".testDiv").hide(400,function(event) {
  $(this).html("Itsy-bitsy bit of content!").show(400);
 });
});

Close to what I think you wanted, also try slideIn/slideOut or look at the UI/Effects plugin.

lucas
Not quite what I was going for. With this, the Div shrinks to nothing before expanding again. I want to eliminate that middle shrinkage so it goes directly to the new dimensions without zero-ing out in between. Does that make sense?None of the demos for UI/Effects seem to do this either.
neezer
+7  A: 

You can use the animate method.

$("div").animate({width:"200px"},400);
Josh Bush
A: 

Hello meyahoocoma4c5ki0pprxr19sxhajsogo6jgks5dt.

You could wrap the 'content div' with an 'outer div' which is set to an absolute width value. Inject the new content with a "hide()" or "animate({width})" method, shown in the other answers. This way, the page doesn't reflow in between because the wrapper div holds a steady width.

micahwittman
+8  A: 

Try this jQuery plugin:

// Animates the dimensional changes resulting from altering element contents
// Usage examples: 
//    $("#myElement").showHtml("new HTML contents");
//    $("div").showHtml("new HTML contents", 400);
//    $(".className").showHtml("new HTML contents", 400, 
//                    function() {/* on completion */});
(function($)
{
   $.fn.showHtml = function(html, speed, callback)
   {
      return this.each(function()
      {
         // The element to be modified
         var el = $(this);

         // Preserve the original values of width and height - they'll need 
         // to be modified during the animation, but can be restored once
         // the animation has completed.
         var finish = {width: this.style.width, height: this.style.height};

         // The original width and height represented as pixel values.
         // These will only be the same as `finish` if this element had its
         // dimensions specified explicitly and in pixels. Of course, if that 
         // was done then this entire routine is pointless, as the dimensions 
         // won't change when the content is changed.
         var cur = {width: el.width()+'px', height: el.height()+'px'};

         // Modify the element's contents. Element will resize.
         el.html(html);

         // Capture the final dimensions of the element 
         // (with initial style settings still in effect)
         var next = {width: el.width()+'px', height: el.height()+'px'};

         el .css(cur) // restore initial dimensions
            .animate(next, speed, function()  // animate to final dimensions
            {
               el.css(finish); // restore initial style settings
               if ( $.isFunction(callback) ) callback();
            });
      });
   };


})(jQuery);
Shog9
What is the point of the finish variable? And how is it different from cur?
ecoffey
@ecoffey: `finish` holds the initial - and the final - values for the `width` and `height` styles. It will always be different from `cur`, which represents the styles needed to fix the element at its initial width and height; if they were ever the same, then the element's dimensions would not change with its content, and this animation would be pointless!
Shog9
you should be returning this.each
Matt
@Matt: good catch, thanks.
Shog9
@Shog9: ah ok thanks; I think I had a different assumption about what was happening. Maybe I should just ctrl+c / ctrl+v this code and see it work before I keep on critiquing it :-P
ecoffey
+3  A: 

Here is how I fixed this, I hope this will be usefull ! The animation is 100% smooth :)

HTML:

<div id="1"><div id="2">Some content here</div></div>

Javascript:

// tempory fix the outer div's width
$("#1").css({width: $("#2").width()});
// fade out inner div
$("#2").fadeOut('slow' , function(){
    // change the div content
    $("#1").html("<div id=\"2\" style=\"display: none;\">new content (with a new width)</div>", function(){
     // give the outer div the same width as the inner div with a smooth animation
     $("#1").animate({width: $("#2").width()}, function(){
      // show the inner div
      $("#2").fadeIn('slow');
     });
    });
});

There might be a shorter version of my code, but I just kept it like this.

Daan
the idea of having fadeIn inside fadeOut success event never occurred to me, thanks!
Curt