Independientemente jquery alternar la altura animada solo se ejecuta una vez cada vez

This question is based on my previous question which I got a working answer to, but only for one slidetoggle element: aquí

I use the animate method to have the "hidden" elements loaded in the background. Otherwise I could just use slidetoggle, but this leads to a display:none which I don't want.

So, here's the function I got so far, but it only runs once for each h2.

HTML:

<h2>Show</h2>
    <div class="content">
        text text text
        <br />
        text text text
        <br />
        text text text
    </div>

<h2>Show</h2>
    <div class="content">
        text text text
        <br />
        text text text
        <br />
        text text text
    </div>

CSS:

.content {
  height: 0;
  overflow: hidden;
}

.heightAuto {
    height: auto;
}​

GUIÓN:

$(function(){  

    $("h2").toggle(function()

     {    
       var $content = $(this).next(".content");
       var contentHeight = $content.addClass('heightAuto').height();
       $content.removeClass('heightAuto');

       $content.removeClass('heightAuto').animate({ height: contentHeight}, 500);

     }, function() {

        $(this).next(".content").animate({ height: "0"}, 500);    

     });
});​

​Could it be a problem to get the height set to auto again? I just can't find the trick.

Here's also fiddle: jsFiddle

preguntado el 29 de junio de 12 a las 20:06

3 Respuestas

Add an extra wrapper which does not get resized:

<div class="content"><div class="inner">
    text text text
    <br />
    text text text
    <br />
    text text text
</div></div>

Entonces usa este JS:

jQuery(function($) {  
    $('h2').toggle(function() {
        var $content = $(this).next('.content');
        $content.animate({ height: $content.find('> .inner').height() }, 500);
    }, function() {
        $(this).next('.content').animate({ height: 0 }, 500);       
    });
});

EDIT: If you don't want to use an extra wrapper in your HTML, you can have the JS add a wrapper for you:

jQuery(function($) {  
    $('h2').toggle(function() {
        var $content = $(this).next('.outer');
        $content.animate({ height: $content.find('> .content').height() }, 500);
    }, function() {
        $(this).next('.outer').animate({ height: 0 }, 500);       
    }).next('.content').wrap('<div class="outer" style="height:0;overflow:hidden"></div>');
});​

If you use this approach, you should remove your CSS for the .content blocks. See updated fiddle: http://jsfiddle.net/QwmJP/21/

Respondido el 29 de junio de 12 a las 20:06

Wow, thank you! This finally works! But would there be also a way without the additional wrapper? - Melros

I must admit, I don't understand fully why you aren't just using .slideToggle() - Marcos Eirich

Thank's! Ok, here's my explanation, please correct me if I'm wrong here. I have a page with 5 hidden container. Each of them has youtube-videos, soundcloud player and third party tools in them. If I use slideToggle which leads to display: none all these elements are not fully ready till display: block sets in which leads to a very huge lack not only in the slideToggle effect but also in the loading time. With height:0 I ensure that all elements get loaded correctly in the background and will work fine when a panel gets animated. Or am I seeing it wrong? - Melros

If you have tested and verified that your content doesn't load with display:none, then you are correct. I think that images will load even in display:none, but perhaps these 3rd-party tools have JS that detects when they are hidden. If you used my answer, please do me a favor and mark it as "accepted". - Marcos Eirich

And just done so! And yes, I did some testing and it's the 3rd-party tools that do the trouble here. No problem with images. Thank's again! - Melros

To overcome your problem, set overflow:hidden if height is 0.

Remitir DEMO EN VIVO

JS:

$(function(){
    $("h2").toggle(
        function() {    
            var $content = $(this).next(".content");
            var contentHeight = $content.addClass('heightAuto').height();
            if (contentHeight == 0) {
                contentHeight = $content.attr({
                    style:'overflow:hidden'
                }).height(); 
            }            
            $content.removeClass('heightAuto').animate({ height: contentHeight}, 500);
        }, 
        function() {
            $(this).next(".content").animate({height:0}, 500);
        });
});​

Respondido el 29 de junio de 12 a las 21:06

Because you set height to 0 the first time, it is zero the next time, so .height() value returns zero.

use the offsetHeight property instead: it will always be the content's natural height.

Respondido el 29 de junio de 12 a las 20:06

Thank you for the quick answer but that unfortunately that doest't work and the animation doesn't work anymore. Any other idea? - Melros

it is a property, not a function, so not offsetHeight(); w3schools.com/jsref/dom_obj_all.asp - FlavorScape

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.