Why won't jQuery toggle this div?
I have a set of divs that represent story categories. In each category, there's a div holding the category head, and a sibling div containing summaries of the stories.
I start out with all the stories divs hidden, except for the category that contains the default story; its stories div starts out visible (cat2 below):
[ cat1 < ]
[ cat2 V ]
- story2-1
- story2-2
[ cat3 < ]
When I click on any of the other category heads, I remove the 'expanded' class that sets the down-triangle icon on all the category head divs, hide all the story divs, then toggle the 'expanded' class on the clicked category head, and finally toggle the stories div that's the sibling of the clicked category head.
All this work fine if I click a category head other than the currently expanded one.
PROBLEM: If I click the currently-expanded category head to collapse it, so they're ALL collapsed, nothing happens. Or more specifically, when I log the results, I see that the story div gets its 'display' property set to 'block' and then immediately to 'none' again. Why???
The code
<html>
<head>
<style type="text/css">
.category { width: 200px; }
.category-hed { cursor: pointer; }
.category-hed h2 {
background-image: url( /_img/b/category-hed-arrow-collapsed.gif );
background-repeat: no-repeat;
background-position: center right;
}
.category-hed h2.expanded {
background-image: url( /_img/b/category-hed-arrow-expanded.gif );
}
.category .stories { /* default hidden; clicking category-hed will toggle it */
display: none;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
// set click handlers on the category section headers to expand/collapse the sections
$(".category-hed").click( function() {
$(".category-hed h2").removeClass("expanded"); // unset the 'expanded' indicators in all categories
$(".stories").hide(); // hide the "stories" divs in all categories
// TODO: this doesn't collapse an already-expanded section... why?
$("h2", this).toggleClass("expanded"); // 2nd arg to $() sets context of the selection: h2 under this
$(this).siblings(".stories").toggle(); // show this category's "stories" div
});
// the default story's category section should initially be expanded
var defaultStoryCatID = "#category-2";
$( "h2", defaultStoryCatID ).toggleClass("expanded");
$( ".stories", defaultStoryCatID ).show();
});
</script>
</head>
<body>
<div class="category" id="category-1">
开发者_StackOverflow社区 <!-- nested H2 below to aid border styling; CSS omitted -->
<div class="category-hed"><h2>Category 1</h2></div>
<div class="stories">
<div class="story">
<h3>cat 1 story1 head</h3>
<p>... the story...</p>
</div>
<div class="story">
<h3>cat 1 story2 head</h3>
<p>... another story...</p>
</div>
</div>
</div>
<div class="category" id="category-2">
<div class="category-hed"><h2>Category 2</h2></div>
<div class="stories">
<div class="story">
<h3>cat 2 story1 head</h3>
<p>... the story...</p>
</div>
<div class="story">
<h3>cat 2 story2 head</h3>
<p>... another story...</p>
</div>
</div>
</div>
<div class="category" id="category-3">
<div class="category-hed"><h2>Category 3</h2></div>
<div class="stories">
<div class="story">
<h3>cat 3 story1 head</h3>
<p>... the story...</p>
</div>
<div class="story">
<h3>cat 3 story2 head</h3>
<p>... another story...</p>
</div>
</div>
</div>
</body>
</html>
The first thing is that your code is malformed. For example,
<div class="category" id="category-3">
<div class="category-hed"><h2>Category 3</h2></div>
<div class="stories">
<div class="story">
<h3>cat 3 story1 head</h3>
<p>... the story...</p>
</div>
<div class="story">
<h3>cat 3 story2 head</h3>
<p>... another story...</p>
</div>
</div>
</div>
</div>
has one too many /div tags in it. It should look like this...
<div class="category" id="category-3">
<div class="category-hed"><h2>Category 3</h2></div>
<div class="stories">
<div class="story">
<h3>cat 3 story1 head</h3>
<p>... the story...</p>
</div>
<div class="story">
<h3>cat 3 story2 head</h3>
<p>... another story...</p>
</div>
</div>
</div>
I did a little bit of reordering in the click function...
$(".category-hed").click( function() {
// TODO: this doesn't collapse an already-expanded section... why?
$("h2", this).toggleClass("expanded"); // 2nd arg to $() sets context of the selection: h2 under this
$(this).siblings(".stories").toggle(); // show this category's "stories" div
$(".category-hed").not(this).find("h2").removeClass("expanded"); // unset the 'expanded' indicators in all categories
$(".category-hed").not(this).siblings(".stories").hide(); // hide the "stories" divs in all categories
});
Try that out and let me know how it goes!
If I undersand your question correctly, it's because when you click on the already-expanded category-hed
, it is first "collapsed" (by removing the expanded
class), then the expanded
class is immediately re-added by .toggleClass()
. In your code, there is always going to be something that ends up being expanded, because prior state is not accounted for. Something as simple as this should fix the problem:
$(".category-hed").click( function() {
if($(this).hasClass("expanded")
var dont_reexpand = true;
$(".category-hed h2").removeClass("expanded"); // unset the 'expanded' indicators in all categories
$(".stories").hide(); // hide the "stories" divs in all categories
if(!dont_reexpand) {
// TODO: this doesn't collapse an already-expanded section... why?
$("h2", this).toggleClass("expanded"); // 2nd arg to $() sets context of the selection: h2 under this
$(this).siblings(".stories").toggle(); // show this category's "stories" div
}
});
There are probably better ways to do this, but you get the idea.
精彩评论