How can I change the code so that when I click on the reply-img, only the following element with the reply-form class is displayed, but the others are not displayed at the same time.
I have several elements with the reply-img class and I always want to display the closest element with the reply-form class
HTML blade.php
<div >
@foreach($comments as $comment)
<div >
...
<div >
<img src="{{asset('img/react.svg')}}" alt="">
</div>
</div>
...
<form class='login-form mmm ml-x reply-form'</form>
@endforeach
...
</div>
JS
<script>
// Get all image elements
var images = document.querySelectorAll(".reply-img");
// Attach a click event listener to each image
images.forEach(function(image) {
image.addEventListener("click", function() {
// Show all forms
var forms = document.querySelectorAll(".reply-form");
forms.forEach(function(form) {
form.style.display = "block";
});
});
});
</script>
CodePudding user response:
You can use the image element's .parentElement
twice to navigate up the tree to the <div >
. Then use .nextElementSibling
to get to the form
element.
Like this:
const img = document.querySelector('img');
const form = img.parentElement.parentElement.nextElementSibling;
console.log(form.innerHTML);
<div >
<div >
<img src="https://via.placeholder.com/150" />
</div>
</div>
<form class='login-form mmm ml-x reply-form'>blah</form>
CodePudding user response:
you will need to change your function so that it shows only the next form and not all of them:
images.forEach(function(image) {
image.addEventListener("click", function() {
let ele = image.parentNode.nextElementSibling;
while(ele){
if(ele.matches('.reply-form')){
ele.style.display = "block";
return;
}
ele = ele.nextElementSibling;
}
});
});
CodePudding user response:
I find it cleaner to toggle a class on the comments to indicate the active comment. Then we can handle the forms with CSS.
Here's an example of that:
const comments = document.querySelectorAll('.comments');
document.querySelectorAll('.reply-img').forEach(img => img.addEventListener('click', function() {
comments.forEach(x => x.classList.remove('active-comment'));
this.parentElement.classList.add('active-comment');
}))
.reply-form {
width: 100px;
height: 50px;
background: lightblue;
margin: 10px 0;
}
.comments:not(.active-comment) .reply-form {
display: none;
}
<div >
<div >
<div >
<img src="https://via.placeholder.com/50" alt="">
</div>
</div>
...
<form class='login-form mmm ml-x reply-form'></form>
<div >
<div >
<img src="https://via.placeholder.com/50" alt="">
</div>
</div>
...
<form class='login-form mmm ml-x reply-form'></form>
<div >
<div >
<img src="https://via.placeholder.com/50" alt="">
</div>
</div>
<form class='login-form mmm ml-x reply-form'></form>
...
</div>
This can also be done without JavaScript, just CSS.
By adding the tabindex
attribute to the comments, the comments get a focus state. Now we can use the focus state to toggle the display of the forms.
Note that in this case clicking on the comment will cause the form to display, not only clicking on the image.
.reply-form {
width: 100px;
height: 50px;
background: lightblue;
margin: 10px 0;
}
.comments:not(:focus) .reply-form {
display: none;
}
<div >
<div tabindex="0">
<div >
<img src="https://via.placeholder.com/50" alt="">
</div>
</div>
...
<form class='login-form mmm ml-x reply-form'></form>
<div tabindex="0">
<div >
<img src="https://via.placeholder.com/50" alt="">
</div>
</div>
...
<form class='login-form mmm ml-x reply-form'></form>
<div tabindex="0">
<div >
<img src="https://via.placeholder.com/50" alt="">
</div>
</div>
<form class='login-form mmm ml-x reply-form'></form>
...
</div>