I'm fairly new to Javascript, and i've reached an issue I can't figure out yet, so I'll explain it as best as I can.
I've got 2 divs containing a reply link with the same ID, OnClick. Only difference is the data-attribute which I thought could be used to differentiate the two. There are 2 reply divs that are styled to be hidden. The aim is once the reply link is clicked, the correct div will display below it.
The issue is, when you click any of the two Reply links, it only opens the first reply div below the first parent div. I'll created a little example to give a better understanding:
// Opens reply div and retrieves data-attribute (reply_id) to insert into MYSQL database
function replyLink(element) {
document.getElementById('reply').style.display = "block";
}
// Close div link, displays after opening reply box
function closeLink() {
document.getElementById('reply').style.display = "none";
}
#comment{
border: 1px solid #333333;
width: 500px;
height: 85px;
padding: 5px;
margin: 10px 10px 15px 10px;
}
#comment #content{
border: none;
padding: 15px;
font-size: 12px;
}
#comment #link{
border: none;
padding: 5px;
margin-top: 5px;
}
#comment #link a{
border: none;
text-decoration: none;
font-size: 12px;
color: blue;
}
#comment #link a:hover{
border: none;
text-decoration: underline;
font-size: 12px;
color: blue;
}
#reply{
border: 1px solid red;
padding: 15px;
margin: 0px 0px 10px 45px;
width: 400px;
}
<div id="comment">
<div id="content">
Content #1
</div>
<div id="link">
<a href='javascript:void(0);' onclick="replyLink()" data-test='1'>Reply</a>
</div>
</div>
<div id="reply" style="display: none;">
reply container 1
<a href='javascript:void(0);' onclick='closeLink()' />[Close]</a>
</div>
<div id="comment">
<div id="content">
Content #2
</div>
<div id="link">
<a href='javascript:void(0);' onclick="replyLink()" data-test='2'>Reply</a>
</div>
</div>
<div id="reply" style="display: none;">
reply container 2
<a href='javascript:void(0);' onclick='closeLink()' />[Close]</a>
</div>
Would a java genius be able to help me out.
CodePudding user response:
You can use the classes for styling and IDs with indexes to identify the unique div boxes. Here is the working example
function replyLink(index) {
document.getElementById('reply_' index).style.display = "block";
}
// Close div link, displays after opening reply box
function closeLink(index) {
document.getElementById('reply_' index).style.display = "none";
}
.comment {
border: 1px solid #333333;
width: 500px;
height: 85px;
padding: 5px;
margin: 10px 10px 15px 10px;
}
.comment .content {
border: none;
padding: 15px;
font-size: 12px;
}
.comment .link {
border: none;
padding: 5px;
margin-top: 5px;
}
.comment .link a {
border: none;
text-decoration: none;
font-size: 12px;
color: blue;
}
.comment .link a:hover {
border: none;
text-decoration: underline;
font-size: 12px;
color: blue;
}
.reply {
border: 1px solid red;
padding: 15px;
margin: 0px 0px 10px 45px;
width: 400px;
}
<div >
<div >
Content #1
</div>
<div >
<a href='javascript:void(0);' onclick="replyLink(0)" data-test='1'>Reply</a>
</div>
</div>
<div id="reply_0" style="display: none;">
reply container 1
<a href='javascript:void(0);' onclick='closeLink(0)'>[Close]</a>
</div>
<div >
<div >
Content #2
</div>
<div >
<a href='javascript:void(0);' onclick="replyLink(1)" data-test='2'>Reply</a>
</div>
</div>
<div id="reply_1" style="display: none;">
reply container 2
<a href='javascript:void(0);' onclick='closeLink(1)'>[Close]</a>
</div>
CodePudding user response:
While the use of an id is straightforward when first working with JavaScript and HTML, it's use is discouraged as an anti-pattern. IDs make for brittle code (as you are seeing here) and don't scale well. Instead, don't use ids at all and instead use classes or a relative reference to the elements, such as this, .closest(), nextElementSibling, parentNode, etc.
Also, using hyperlinks as a "hook" to initiate some code upon a click event is semantically incorrect. Hyperlinks are for navigation and people who use screen readers will have difficulty navigating your page. Just about every visible HTML element supports a click event, so just attach a click handler directly to the element instead of wrapping the element with a hyperlink.
Lastly, there is no need for separate show and hide functions. Just add or remove a "hidden" class based on what was clicked.
You can see in my answer how much cleaner the HTML and JavaScript are without id
s.
See comments inline below.
// Set up a single event handler for any clicks to any reply or Close
document.addEventListener("click", function(event){
// Check to see if the click originated at a Reply element
if(event.target.classList.contains("reply")){
// Find the closest ".comment" ancestor of the clicked reply
// element and then get the next element sibling to that and
// unhide it.
event.target.closest(".comment")
.nextElementSibling.classList.remove("hidden");
} else if(event.target.classList.contains("replyContainer")){
event.target.classList.add("hidden");
}
});
.hidden { display:none; }
.comment{
border: 1px solid #333333;
width: 500px;
height: 85px;
padding: 5px;
margin: 10px 10px 15px 10px;
}
.comment .reply{
padding: 5px;
margin-top: 5px;
}
.replyContainer{
border: 1px solid red;
padding: 15px;
margin: 0px 0px 10px 45px;
width: 400px;
}
<div >
<div >Content #1</div>
<div >Reply</div>
</div>
<div >reply container 1[Close]</div>
<div >
<div >Content #2</div>
<div >Reply</div>
</div>
<div >reply container 2[Close]</div>
<div >
<div >Content #3</div>
<div >Reply</div>
</div>
<div >reply container 3[Close]</div>
CodePudding user response:
You can use the DOM structure to your advantage. Normally you wouldn't want to rely too deeply on it though. For toggling div
it's perfectly ok. By using element which was clicked we can look for closest common ancestor. That way we can find the related div
.
function replyLink(elem) {
elem.closest("article").querySelector("#reply").style.display = "block";
}
function closeLink(elem) {
elem.closest("article").querySelector("#reply").style.display = "none";
}
// just for demo:
document.body.innerHTML = document.body.innerHTML document.body.innerHTML
document.body.innerHTML = document.body.innerHTML document.body.innerHTML
<article>
<div id="comment">
<div id="content">
Content #N
</div>
<div id="link">
<a href='javascript:void(0);' onclick="replyLink(this)" data-test='1'>Reply</a>
</div>
</div>
<div id="reply" style="display: none;">
reply container 1
<a href='javascript:void(0);' onclick='closeLink(this)'>[Close]</a>
</div>
</article>