I have posted about this already, but I think my question was poorly explained. I have multiple divs with class of "popupEdit".
I want to be able to target these using getElementsByClassName
with the result being a popup with some input field. See the code below
I know that getElementsByClassName
returns an array of all the elements with the class EditQuestion, but I have failed to write a function that works to use this array due to my lack of skill (I'm a newbie).
Could someone give me the solution so I have something I can study? Apologies for asking directly for the answer... I have tried numerous things without success.
Many thanks
window.onload = function() {
document.getElementsByClassName("EditQuestion").onclick = function() {
var overlay2 = document.getElementsByClassName("overlay2");
var popupEdit = document.getElementsByClassName("popupEdit");
overlay2.style.display = "block";
popupEdit.style.display = "block";
};
document.getElementsByClassName("CloseBtn2").onclick = function() {
var overlay2 = document.getElementsByClassName("overlay2");
var popupEdit = document.getElementsByClassName("popupEdit");
overlay2.style.display = "none";
popupEdit.style.display = "none";
};
};
button.EditQuestion {
padding: 0;
border: none;
background: none;
color: #A8A8A8;
font-weight: bold;
}
button.CloseBtn2 {
padding: 0;
border: none;
background: none;
position: absolute;
right: 10px;
top: 5px;
}
.popupEdit {
display: none;
position: fixed;
left: 40%;
top: 30%;
width: 600px;
height: 150px;
margin-top: -75px;
margin-left: -150px;
background: #FFFFFF;
border: 1px solid #000;
z-index: 100000;
}
.overlay2 {
display: none;
position: fixed;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
background: #000;
opacity: 0.5;
z-index: 99999;
}
<button class="EditQuestion">Edit</button>
<div class="overlay2"></div>
<div class="popupEdit">
<h2>Edit Question, some input box here..</h2>
<button class="CloseBtn2">Close</button>
</div>
Edited version - I have tried to use querySelectorAll
as suggested by TJ Crowder. The querySelector
works, but when I add in the for loop and change to querySelectorAll
, it fails. Any suggestions?
window.onload = function () {
document.querySelectorAll(".EditQuestion").onclick = function () {
var overlay2 = document.querySelectorAll(".overlay2");
var popupEdit = document.querySelectorAll(".popupEdit");
var index;
for (index = 0; index < overlay2.length; ++index) {
overlay2[index].style.display = "none";
popupEdit[index].style.display = "block";
}
};
document.querySelectorAll(".CloseBtn2").onclick = function () {
var overlay2 = document.querySelectorAll(".overlay2");
var popupEdit = document.querySelectorAll(".popupEdit");
var index;
for (index = 0; index < overlay2.length; ++index) {
overlay2[index].style.display = "none";
popupEdit[index].style.display = "block";
}
};
};
getElementsByClassName
(on the browsers where it exists) returns a list, not a single element. So this line and similar:
overlay2.style.display = "none";
...fails, because the list doesn't have a style
property.
If you just want to handle the first match, you can grab it via [0]
:
overlay2[0].style.display = "none";
(That will fail if there are no matches, though.) Or, since getElementsByClassName
isn't as well-supported as querySelector
, you might prefer:
overlay2 = document.querySelector(".overlay2"); // Gives you the first match; note the dot
overlay2.style.display = "none";
Or if you want to loop through all of them, you need a loop:
var index;
for (index = 0; index < overlay2.length; ++index) {
overlay2[index].style.display = "none";
}
To get the list for that loop, either use getElementsByClassName
as you are currently (but it won't work on IE8), or use querySelectorAll
(which will):
overlay2 = document.querySelectorAll(".overlay2"); // Gives you a list
Could you show me how you would incorporate this loop into the JS function.
I don't think you want a loop; you just want to handle the specific overlay and popup related to the button, right?
I'd probably change the HTML slightly so that each group has a group div or similar around it:
<div class="question"><!-- Wrapper div for each question -->
<button class="EditQuestion">Edit</button>
<div class="overlay2" style="display: none"></div><!-- Note I've hidden ... -->
<div class="popupEdit" style="display: none"> <!-- ...these by default -->
<h2>Edit Question, some input box here..</h2>
<button class="CloseBtn2">Close</button>
</div>
</div>
...and use event delegation:
var container = document.getElementById("questions");
hookEvent(container, "click", function(event) {
var button, group, overlay, display;
// Find the button that was clicked, if any
button = event.target;
while (button && (
button.tagName.toUpperCase() !== "BUTTON" ||
!button.className.match(/\bEditQuestion\b|\bCloseBtn2\b/)
)) {
button = button.parentNode;
}
if (button) {
// One of our desired buttons was clicked, find the parent
group = button.parentNode;
while (group && !group.className.match(/\bquestion\b/)) {
group = group.parentNode;
}
if (group) {
overlay = group.querySelector(".overlay2");
display = overlay.style.display === "block" ? "none" : "block";
overlay.style.display = display;
group.querySelector(".popupEdit").style.display = display;
}
}
});
...where hookEvent
looks something like this:
function hookEvent(element, eventName, handler) {
if (element.addEventListener) {
element.addEventListener(eventName, handler, false);
} else if (element.attachEvent) {
element.attachEvent("on" + eventName, function(event) {
var e = event || window.event;
if (!e.target) {
e.target = e.srcElement;
}
handler.call(element, e);
});
} else {
throw "addEventListener or attachEvent required";
}
}
The great thing about event delegation is that since you're handling the event on a container, it doesn't matter how much you add or remove questions in the container, it just keeps working.
A lot of the code above is to deal with IE weirdness, and to handle the event delegation. FWIW, a good DOM library can make that all a LOT simpler for you. Here's a jQuery example:
$("selector for the container").on("click", ".EditButton, .CloseBtn2", function() {
var button = $(this);
button.closest('.question').find(".overlay2, .popupEdit").toggle(button.is(".EditButton"));
});