Reputation: 7520
I have a problem in dealing with my problem. My problem is I am creating a static navigation. That uses trigger event. Because I am displaying a simple collapsible div. What I did is I include all my id name in an array and I loop it to create an event. But when I click a link i doesn't call my jquery event. Is there a way how can I prevent hard coded of navigation?
Here's my sample code:
var toggleState = true;
var header_name = ["ParentA", "ParentB", "ParentC", "ParentD"];
var child_name = ["ChildA", "ChildB", "ChildC", "ChildD"];
for (var x = 0; x < header_name.length; x++) {
$("#" + header_name[x]).click(function (e) {
if (toggleState) {
$("#" + child_name[x]).show("slide");
} else {
$("#" + child_name[x]).hide("slide");
}
toggleState = !toggleState;
});
}
<div id="ParentA">Click A</div>
<div id="ChildA" style="display: none">Child A</div>
<div id="ParentB">Click A</div>
<div id="ChildB" style="display: none">Child B</div>
<div id="ParentC">Click A</div>
<div id="ChildC" style="display: none">Child C</div>
Here's the fiddle: http://jsfiddle.net/rochellecanale/cveze/3/
Upvotes: 1
Views: 233
Reputation: 388446
If you can make minor changes to the html it should be as simple as
<div id="ParentA" class="click-toggle" data-target="#ChildA">Click A</div>
<div id="ChildA" style="display: none">Child A</div>
<div id="ParentB" class="click-toggle" data-target="#ChildB">Click B</div>
<div id="ChildB" style="display: none">Child B</div>
<div id="ParentC" class="click-toggle" data-target="#ChildC">Click C</div>
<div id="ChildC" style="display: none">Child C</div>
then
$(document).ready(function(){
$('.click-toggle').click(function () {
$($(this).data('target')).stop(true, true).slideToggle();
})
});
Demo: Fiddle
or even
<div id="ParentA" class="click-toggle">Click A</div>
<div id="ChildA" style="display: none">Child A</div>
<div id="ParentB" class="click-toggle">Click B</div>
<div id="ChildB" style="display: none">Child B</div>
<div id="ParentC" class="click-toggle">Click C</div>
<div id="ChildC" style="display: none">Child C</div>
then
$(document).ready(function(){
$('.click-toggle').click(function () {
$(this).next().stop(true, true).slideToggle();
})
});
Demo: Fiddle, if you want to maintain left -> right slide: Fiddle
to make your code work... the main problem is the use of shared closure variable toggleState
... each menu item should have its own state variable... the solution is to create a private closure for each one
$(document).ready(function () {
var header_name = ["ParentA", "ParentB", "ParentC", "ParentD"];
var child_name = ["ChildA", "ChildB", "ChildC", "ChildD"];
$.each(header_name, function (idx, id) {
var toggleState = true;
$('#' + id).click(function () {
if (toggleState) {
$("#" + child_name[idx]).show("slide");
} else {
$("#" + child_name[idx]).hide("slide");
}
toggleState = !toggleState;
})
})
});
Demo: Fiddle
Upvotes: 1
Reputation: 102793
You need to create a local copy of x for each iteration of the loop. The simplest way to do this is to create a helper function like getClickHandler
:
function getClickHandler(x) {
return function(e){
if(toggleState){
$("#" + child_name[x]).show("slide");
}else{
$("#" + child_name[x]).hide("slide");
}
toggleState = !toggleState;
};
}
for(var x = 0; x < header_name.length; x++){
$("#" + header_name[x]).click(getClickHandler(x));
}
The key point here is that the function inside click
runs at a later time (asynchronously). Because of how variable scope works in Javascript, your code passes the same reference to x
in to each handler, which is why all of them end up getting the last iteration of the array. Doing the above creates a copy of x
at the current iteration, and stores it in a local reference (inside the handler function).
Upvotes: 2
Reputation: 2343
change this:
var header_name = ("Parent A", "Parent B", "Parent C", "Parent D");
to this
var header_name = ["Parent A", "Parent B", "Parent C", "Parent D"];
likewise with the next variable
Upvotes: 2