Reputation: 405
I have DOM like this in a Rails app:
<div class="post_info">
<div class="col">
<i class="post_comments">icon</i>
</div>
</div>
<div class="comments_body">
<ul>
<li>Many comments.</li>
</ul>
</div>
My target is hide and show '.comments_body'
element right below the '.post_comment'
icon which I clicked.
I've tried this:
css
.comments_body {
display: none;
}
.active {
display: block;
}
What I was trying to is target the icon's 'grandparent's next sibling', means the comments_body
relating to this icon, then toggle it's display
style.
my jquery code:
<script>
$(".post_info").click(function(event) {
$(event.target).parent().parent().next().toggleClass('active');
});
</script>
But it turns out this only works on even comments_body
like the 2nd ,4th ,6th ,8th
.
I checked dev tool, when I click on odd icon, the event wasn't be triggered.
How to solve this? Or is there better way to achieve this effect?
Update:
I tried the answers below but still not work. I put the page's github address here. Since it's a Rails app, you might need to clone it to local and try it. If so, run seed to generate fake data. Thanks!
Upvotes: 1
Views: 116
Reputation:
$(".post_info").click(function(event) {
$(event.target).parent().parent().next().toggleClass('active');
});
.comments_body {
display: none;
}
.active {
display: block !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="post_info">
<div class="col">
<i class="post_comments">icon</i>
</div>
</div>
<div class="comments_body">
<ul>
<li>Many comments.</li>
</ul>
</div>
<div class="post_info">
<div class="col">
<i class="post_comments">icon</i>
</div>
</div>
<div class="comments_body">
<ul>
<li>Many comments.</li>
</ul>
</div>
<div class="post_info">
<div class="col">
<i class="post_comments">icon</i>
</div>
</div>
<div class="comments_body">
<ul>
<li>Many comments.</li>
</ul>
</div>
I have made a example for you. It working fine. I dont see any problem in case of even odd selection. try making important your active element as
.active {
display: block !important;
}
if it still not creating desired result kindly let me know. I will put my code here. Cheers....
Upvotes: 0
Reputation: 1075925
First, you need to remove the :
from this:
.comments_body: { /* <==== Remove that : */
display: none;
}
Then, this
within your event handler is the .post_info
element, so you can use that instead of $(e.target).parent().parent()
which is inherently fragile (both because a small change to your markup breaks it, and because if you click within the .post_info
but outside the icon, it will be wrong — which I suspect is why you're seeing the inconsistent behavior).
$(".post_info").click(function(event) {
$(this).next().toggleClass('active');
});
Live Example:
$(".post_info").click(function(event) {
$(this).next().toggleClass('active');
});
.comments_body {
display: none;
}
.active {
display: block;
}
<div class="post_info">
<div class="col">
<i class="post_comments">icon 1</i>
</div>
</div>
<div class="comments_body">
<ul>
<li>Many comments 1.</li>
</ul>
</div>
<div class="post_info">
<div class="col">
<i class="post_comments">icon 2</i>
</div>
</div>
<div class="comments_body">
<ul>
<li>Many comments 2.</li>
</ul>
</div>
<div class="post_info">
<div class="col">
<i class="post_comments">icon 3</i>
</div>
</div>
<div class="comments_body">
<ul>
<li>Many comments 3.</li>
</ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Side note: You might consider using event delegation for that handler rather than hooking the event on each individual .post_info
. That way, if you add and remove .post_info
instances at runtime, the handler will keep working.
Presumably these are in some kind of container, so you'd use:
$("selector-for-the-container").on("click", ".post_info", function(event) {
$(this).next().toggleClass('active');
});
Live Example:
$("#container").on("click", ".post_info", function(event) {
$(this).next().toggleClass('active');
});
// Works on #4 even though we add it later:
setTimeout(function() {
$("#container").append(
'<div class="post_info">' +
'<div class="col">' +
'<i class="post_comments">icon 4</i>' +
'</div>' +
'</div>' +
'<div class="comments_body">' +
'<ul>' +
'<li>Many comments 4.</li>' +
'</ul>' +
'</div>'
);
}, 800);
.comments_body {
display: none;
}
.active {
display: block;
}
<div id="container">
<div class="post_info">
<div class="col">
<i class="post_comments">icon 1</i>
</div>
</div>
<div class="comments_body">
<ul>
<li>Many comments 1.</li>
</ul>
</div>
<div class="post_info">
<div class="col">
<i class="post_comments">icon 2</i>
</div>
</div>
<div class="comments_body">
<ul>
<li>Many comments 2.</li>
</ul>
</div>
<div class="post_info">
<div class="col">
<i class="post_comments">icon 3</i>
</div>
</div>
<div class="comments_body">
<ul>
<li>Many comments 3.</li>
</ul>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Upvotes: 3