self-made accordion should fold open menu items before opening a new one
I'm learning jQuery right now and the first "bigger" project is a self made Accordion/sliding Navigation.
My HTML Code looks like this:
<dl>
<dt><a href="#">Prologue</a></dt>
<dd id="prolog">
<div>TEST</div>
</dd>
<dt><a href="#">Projekte</a></dt>
<dd id="projekte">
<ul>
<li>TEST</li>
<li>TEST</li>
<li>TEST</li>
<li>TEST</li>
</ul>
</dd>
<dt><a href="#">Fotografie</a></dt>
<dd id="fotos">
<ul>
<li>TEST</li>
<li>TEST</li>
<li>TEST</li>
<li>TEST</li>
</ul>
</dd>
<dt><a href="#">Analog</a></dt>
<dd id="analog">
<ul>
<li>TEST</li>
<li>TEST</li>
<li>TEST</li>
<li>TEST</li>
</ul>
</dd>
<dt><a href="#">Über mich</a></dt>
<dd id="about">
<ul>
<li>TEST</li>
<li>TEST</li>
<li>TEST</li>
<li>TEST</li>
</ul>
</dd>
<dt><a href="#">Kontakt</a></dt>
<dd id="kontakt">
<ul>
<li>TEST</li>
<li>TEST</li>
<li>TEST</li>
<li>TEST</li>
</ul>
</dd>
And here comes the jQuery code. The idea is to check if the user clicks on an open accordion item and if he does, just close it. Otherwise (when the clicked item is closed) it checks, if any other of the accordion items is open. If they are all hidden, it opens the clicked item. Otherwise it closes all items (don't know how to get only the open one) and opens the clicked item. This is what it looks like:
$("dt a").click(function(){
var checkElement = $(this).parent("dt").next("dd");
var main1 = $('#prolog'); var main2 = $('#projekte'); var main3 = $('#fotos'); var main4 = $('#analog'); var main5 = $('#about'); var main6 = $('#kontakt');
if(checkElement.is(':visible')) {
$(this).parent("dt").next("dd").slideUp("normal");
return false
} else {
if( (main1.is(':hidden')) &&
(main2.is(':hidden')) &&
(main3.is(':hidden')) &&
(main4.is(':hidden')) &&
(main5.is(':hidden')) &&
(main6.is(':hidden')) ) {$(this).parent("dt").next("dd").slideDown("normal");}
else {
$("dd").slideUp("normal"), checkElement.slideDown("normal");
}
return false;
};
});
So far it works fine (though the second if-request with the bunch of variables doesn't look very professional, if you could help me out here, it would be nice, although it's not the main issue). Next goal is to put the closing and opening of the accordion items in a row. I want the slideUp first and after it's finished, the slideDown should start. So I changed
else {
$("dd").slideUp("normal"), checkElement.slideDown("normal");
}
to
else {
$("dd").slideUp("normal", function() { checkElement.slideDown('normal') });
}
But here comes the bug: It first closes + opens at the same time and after that, it does the same but in a row (like I want it to). Seems like it does this part of the function twice, but one time simultaneous and afterward in a row. I just can't figure out, where the first, simultaneous animation comes from. Especially because if the functions aren't in a row, it works just fine (without doing the same twice).
Would be nice, if anyone could help me with this.
Regards
LucasPS: And please don't send me over to a finished Accordion (plugin), I 开发者_如何学Cwant to learn and understand creating one!
PS2: Sorry for my poor English, I'm from Germany. ;-)
PS3: I leave for holidays later on, but I'll be back in 10 days!
When you call this:
$("dd").slideUp()
You're calling it for all <dd>
elements, and some are already hidden, finishing immediately and running the callback immediately, so instead just animate the visible ones, like this:
$("dd:visible").slideUp("normal", function() {
checkElement.slideDown("normal");
});
This fixes the immediate problem (test here). Here's an overall more compact version though:
$("dt a").click(function(){
var dd = $(this).parent("dt").next("dd");
if(!$("dd:visible").slideUp(function() { dd.slideDown(); }).length)
dd.slideDown();
return false;
});
You can give it a try here.
精彩评论