After clicking elements (the red square), the func function gets called and it gets the first child node, then that node changes It's children display to block. Now, I'm trying to set them back to none after clicking background_dim (the dark background) by getting background_dim's parent node, then iterating throught the children and setting their display to none. But apparently this doesn't work. It only works If I set their position to relative, but I'd have to change the other function as well.
function func(element) {
var _first_child = element.children[0];
for (var i = 0; i < _first_child.children.length; ++i)
_first_child.children[i].style.display = "block";
}
function func_t(element) {
var _parent = element.parentNode;
for (var i = 0; i < _parent.children.length; ++i)
_parent.children[i].style.display = "none";
}
.elements {
width: 40px;
height: 40px;
background-color: red;
}
.background {
display: none;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
height: 100%;
width: 100%;
background-color: rgb(0, 0, 0, 0.7);
}
.display-container
{
display: none;
position: fixed;
top: 50%;
bottom: 30%;
left: 50%;
right: 0;
height: 100%;
width: 100%;
background-color: green;
}
<html>
<body>
<ul>
<li class="elements" onclick="func(this);">
<div class="_display_job_dim_">
<div class="background" onclick="func_t(this);"></div>
<div class="display-container"></div>
</div>
</li>
</ul>
</body>
</html>
https://jsfiddle.net/waxebm81/285/
Your problem is that if a click happens on background_dim it will by default propagate up in the DOM, so after func_t was called, the event will propagate to .elements and func(this) is called which will show the elements again.
So you ned to stop the propagation of the event:
document.querySelector('.elements').addEventListener('click', func, false)
document.querySelector('.background_dim').addEventListener('click', func_t, false)
function func(evt) {
evt.stopPropagation();
var element = evt.target;
var _first_child = element.children[0];
for (var i = 0; i < _first_child.children.length; ++i) {
_first_child.children[i].style.display = "block";
}
}
function func_t(evt) {
evt.stopPropagation();
var element = evt.target;
var _parent = element.parentNode;
for (var i = 0; i < _parent.children.length; ++i) {
_parent.children[i].style.display = "none";
}
return false;
}
.elements {
width: 40px;
height: 40px;
background-color: red;
}
.background_dim {
display: none;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
height: 100%;
width: 100%;
background-color: rgb(0, 0, 0, 0.7);
}
.display-container {
display: none;
position: fixed;
top: 50%;
bottom: 30%;
left: 50%;
right: 0;
height: 100%;
width: 100%;
background-color: green;
}
<html>
<body>
<ul>
<li class="elements">
<div class="_display_job_dim_">
<div class="background_dim"></div>
<div class="display-container"></div>
</div>
</li>
</ul>
</body>
</html>
Related
I have markup that is added via JS that has an onclick action (it's a close button).
Essentially:
User clicks play button
A modal appears with the video and a close modal button (both which are added via JS)
As my close button (.modal--close) isn't on the page on load, I'm getting a Cannot set properties of null (setting 'onclick') (I think).
My thoughts are that the because the DOMContentLoaded event was already fired at this point, it is causing the error? But unsure how to resolve it.
Demo
if (document.readyState === "complete") {
ready();
} else {
document.addEventListener("DOMContentLoaded", ready);
}
function ready() {
if(document.querySelector(".open-video")){
document.querySelector(".open-video").onclick = function (e) {
e.preventDefault();
var modal = document.querySelector(".videoModal");
// get data
var triggerURL = this.getAttribute("href");
var triggerID = this.getAttribute("data-modal");
// update modal attributes with trigger data
modal.setAttribute("data-video", triggerURL);
modal.setAttribute("id", triggerID);
var modalID = '#'+ triggerID;
modal.classList.add("modal--open");
var html = '<div class="modal__wrapper"><iframe width="640" height="360" src="'+ triggerURL + '?rel=0&autoplay=1" frameborder="0" allowfullscreen></iframe></div><div class="modal__overlay"></div>';
modal.innerHTML = html;
return false;
}
}
// close modal
document.querySelector(".modal--close").onclick = function (e) {
e.preventDefault();
console.log("test");
}
}
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99999;
overflow: hidden;
display: none;
padding: 70px 80px;
}
.modal--close {
position: fixed;
right: 50%;
top: 32px;
width: 16px;
height: 16px;
z-index: 999999;
pointer-events: auto !important;
}
.modal--close:hover:before, .modal--close:hover:after {
background-color: #F15A40;
}
.modal--close:before, .modal--close:after {
content: "";
position: absolute;
left: 15px;
height: 16px;
width: 2px;
background-color: #FFFFFF;
}
.modal--close:before {
transform: rotate(45deg);
}
.modal--close:after {
transform: rotate(-45deg);
}
.modal--open {
display: block;
}
.modal .modal__wrapper {
position: relative;
top: 50%;
transform: translateY(-50%);
max-height: 100%;
overflow: hidden;
z-index: 150;
}
.modal .modal__wrapper:before {
content: "";
display: block;
padding-top: 56.25%;
}
.modal .modal__wrapper iframe, .modal .modal__wrapper video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
outline: none;
}
.modal .modal__overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000000;
}
<a class="button--play open-video" data-modal="video--1" href="https://www.youtube.com/embed/NpEaa2P7qZI">Click me</a>
<div class="videoModal modal modal__post--modal">
<a id="modal_close" class="modal__close"></a>
<div class="modal__wrapper"></div>
<div class="modal__overlay"></div>
</div>
Edit
Have also tried moving the event listener after the markup has been added:
if (document.readyState === "complete") {
ready();
} else {
document.addEventListener("DOMContentLoaded", ready);
}
function ready() {
let video_btn = document.querySelector(".open-video");
let close_btn = document.querySelector(".modal--close");
let modal = document.querySelector(".videoModal");
if(video_btn){
video_btn.addEventListener("click", function (e) {
e.preventDefault();
// get data
var triggerURL = this.getAttribute("href");
var triggerID = this.getAttribute("data-modal");
// update modal attributes with trigger data
modal.setAttribute("data-video", triggerURL);
modal.setAttribute("id", triggerID);
var modalID = '#'+ triggerID;
modal.classList.add("modal--open");
var html = '<div class="modal__wrapper"><iframe width="640" height="360" src="'+ triggerURL + '?rel=0&autoplay=1" frameborder="0" allowfullscreen></iframe></div><div class="modal__overlay"></div>';
modal.innerHTML = html;
return false;
close_btn.addEventListener("click", function (e) {
e.preventDefault();
console.log("test");
});
});
}
}
With the above, the modal launches fine, but when I click .modal--close, nothing happens (no console.log and no console errors).
Edit 2
Have also tried moving the second event listener above the code snippet that adds the markup:
var html = '<div class="modal__wrapper"><iframe width="640" height="360" src="'+ triggerURL + '?rel=0&autoplay=1" frameborder="0" allowfullscreen></iframe></div><div class="modal__overlay"></div>';
close_btn.addEventListener("click", function (e) {
e.preventDefault();
console.log("test");
});
modal.innerHTML = html;
return false;
With the above however, when I click the .open-video button, I get the error Cannot read properties of null (reading 'addEventListener')
if (document.readyState === "complete") {
ready();
} else {
document.addEventListener("DOMContentLoaded", ready);
}
function ready() {
var modal = document.querySelector(".videoModal");
var triggerURL;
if(document.querySelector(".open-video")){
document.querySelector(".open-video").onclick = function (e) {
e.preventDefault();
// get data
triggerURL = this.getAttribute("href");
var triggerID = this.getAttribute("data-modal");
// update modal attributes with trigger data
modal.setAttribute("data-video", triggerURL);
modal.setAttribute("id", triggerID);
var modalID = '#'+ triggerID;
modal.classList.add("modal--open");
return false;
}
}
// close modal
var html = '<div class="modal__wrapper"><iframe width="640" height="360" src="'+ triggerURL + '?rel=0&autoplay=1" frameborder="0" allowfullscreen></iframe></div><div class="modal__overlay"></div>';
modal.innerHTML = html;
if(document.querySelector(".modal--close")){
document.querySelector(".modal--close").onclick = function (e) {
e.preventDefault();
console.log("test");
}
}
}
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99999;
overflow: hidden;
display: none;
padding: 70px 80px;
}
.modal--close {
position: fixed;
right: 50%;
top: 32px;
width: 16px;
height: 16px;
z-index: 999999;
pointer-events: auto !important;
}
.modal--close:hover:before, .modal--close:hover:after {
background-color: #F15A40;
}
.modal--close:before, .modal--close:after {
content: "";
position: absolute;
left: 15px;
height: 16px;
width: 2px;
background-color: #FFFFFF;
}
.modal--close:before {
transform: rotate(45deg);
}
.modal--close:after {
transform: rotate(-45deg);
}
.modal--open {
display: block;
}
.modal .modal__wrapper {
position: relative;
top: 50%;
transform: translateY(-50%);
max-height: 100%;
overflow: hidden;
z-index: 150;
}
.modal .modal__wrapper:before {
content: "";
display: block;
padding-top: 56.25%;
}
.modal .modal__wrapper iframe, .modal .modal__wrapper video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
outline: none;
}
.modal .modal__overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000000;
}
<a class="button--play open-video" data-modal="video--1" href="https://www.youtube.com/embed/NpEaa2P7qZI">Click me</a>
<div class="videoModal modal modal__post--modal">
<a id="modal_close" class="modal__close"></a>
<div class="modal__wrapper"></div>
<div class="modal__overlay"></div>
</div>
Just wrap the code snippet that fires the issues with below function.
if(document.querySelector(".modal--close")){
}
I am currently trying to create a Character Selection for Airconsole.
I thought I could create this using a Jquery method like a Gallery.
So I need a previous button, a next button and the character display.
It seems that I am making a mistake that I can't figure out, because I am not used to working with Javascript.
var speed = 100;
$(".prev").click(function() {
var now = $(this).parent().next("ul.char_display").children(":visible"),
last = $(this).parent().next("ul.char_display").children(":last"),
prev = now.prev();
prev = prev.index() == -1 ? last : prev;
now.fadeOut(speed, function() {
prev.fadeIn(speed);
});
});
$(".next").click(function() {
var now = $(this).parent().next("ul.char_display").children(':visible'),
first = $(this).parent().next("ul.char_display").children(':first'),
next = now.next();
next = next.index() == -1 ? first : next;
now.fadeOut(speed, function() {
next.fadeIn(speed);
});
});
$(".char_display li").click(function() {
var first = $(this).parent().children(':first'),
next = $(this).next();
next = next.index() == -1 ? first : next;
$(this).fadeOut(speed, function() {
next.fadeIn(speed);
});
});
.prev {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.next {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
.char_display li {
display: none;
list-style: none;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.char_display li:first-child {
display: block;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.char_display {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
.char {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
#char1 {
background: blue;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
#char2 {
background: red;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="characterScreen_characterBlock">
<div id="characterScreen_leftArrow" class="characterScreen_left" ontouchend="otherChar(true);" ontouchend="otherChar(true);">
<div class="prev"></div>
</div>
<div id="characterScreen_characterDisplay" class="characterScreen_center">
<ul class="char_display">
<li>
<div class="char" id="char1"></div>
</li>
<li>
<div class="char" id="char2"></div>
</li>
</ul>
</div>
<div id="characterScreen_rightArrow" class="characterScreen_right" ontouchend="otherChar(false);" ontouchend="otherChar(false);">
<div class="next"></div>
</div>
</div>
I haven't look through all of your code, but I am pretty sure
$(this).parent().next("ul.char_display").children("...")
doesn't do what you want it to. Especially since it always returns an error for pushing the next-button.
$.next() returns the next DOM-element. characterScreen_rightArrow however doesn't have a next element (in this snippet)
What you were searching for is probably $.siblings(). Personally I would however use the qualifier #characterScreen_characterDisplay ul instead of searching for it relatively.
I have some code here and I want the squares to go blue, green, indigo then go back to the beginning. Each time I click the button the colour will change. The code here goes blue, green, indigo and then changes between indigo and black while I want it to go to blue again. Is there a way of restarting the entire code again?
<--code for animated squares!-->
<!DOCTYPE html>
<html>
<style>
#container {
width: 400px;
height: 400px;
position: relative;
background: Black;
}
div#animate {
width: 50px;
height: 50px;
position: absolute;
left: 175px;
top: 0px;
background-color: Blue;
}
</style>
<style>
#containertwo {
width: 400px;
height: 400px;
position: relative;
background: Black;
}
div#animatetwo {
width: 50px;
height: 50px;
position: absolute;
left: 175px;
top: 175px;
background-color: Black;
}
</style>
<body>
<style>
#containerthree {
width: 400px;
height: 400px;
position: relative;
background: Black;
}
div#animatethree {
width: 50px;
height: 50px;
position: absolute;
left: 175px;
top: 350px;
background-color: Black;
}
</style>
<body>
<p>
<button onClick="button_click();button_clicktwo();button_clickthree()">Change Colour</button>
</p>
<div id ="container">
<div id ="animate"></div>
<div id ="animatetwo"></div>
<div id ="animatethree"></div>
</div>
<div id="box" onClick="button_click(j)();"></div>
<script>
var colors = ["Black","Black","Blue"];
function button_click() {
var box = document.getElementById("animate");
var background_color = box.style.backgroundColor;
var i = colors.indexOf(background_color);
if (i === colors.length-1) {
i = -1;
}
animate.style.backgroundColor = colors[i+1];
}
</script>
<div id="box" onClick="button_clicktwo();"></div>
<script>
var colorstwo = ["Green","Black","Black",];
function button_clicktwo() {
var box = document.getElementById("animatetwo");
var background_color = box.style.backgroundColor;
var i = colorstwo.indexOf(background_color);
if (i === colorstwo.length-1) {
i = -1;
}
animatetwo.style.backgroundColor = colorstwo[i+1];
}
</script>
<div id="box" onClick="button_clickthree();"></div>
<script>
var colorsthree = ["Black","Indigo","Black"];
function button_clickthree() {
var box = document.getElementById("animatethree");
var background_color = box.style.backgroundColor;
var i = colorsthree.indexOf(background_color);
if (i === colorstwo.length-1) {
i = -1;
}
animatethree.style.backgroundColor = colorsthree[i+1];
}
</script>
There's quite a bit of invalid and repetitive code, so for simplicity, I just reworked the entire thing. I'll note some of the problems below.
Since there were so many changes made to the HTML, CSS and JS, I won't list them all, but will leave it to you to observe the differences.
// Gather the colors and elements, and set a shared `i` to `0`
var colors = ["Blue", "Green", "Indigo"];
var elems = document.querySelectorAll(".animate");
var i = 0;
// Have a single function that makes the current element black and the next
// one a different color
function button_click() {
elems[i].style.backgroundColor = "Black";
if (++i === colors.length) {
i = 0
}
elems[i].style.backgroundColor = colors[i];
}
#container {
width: 400px;
height: 400px;
position: relative;
background: Black;
}
.animate {
width: 50px;
height: 50px;
left: 175px;
position: absolute;
}
.animate:nth-child(1) {
top: 0px;
background-color: Blue;
}
.animate:nth-child(2) {
top: 175px;
}
.animate:nth-child(3) {
top: 350px;
}
<p>
<button onClick="button_click();">Change Colour</button>
</p>
<div id="container">
<div class="animate"></div>
<div class="animate"></div>
<div class="animate"></div>
</div>
Note that there are other ways to do this too, like having each color set in the CSS, and then setting the visibility to hidden or visible with JavaScript.
Some of the general problems were:
the same ID attribute used more than once
an extra <body> tag
lots of repeating CSS, JS and HTML that was able to be greatly reduced
I am learning javascript these days and I have a little problem with my code.
I have three elements on page wrapper1, wrapper2 and wrapper3 and every of these has its triggerand redbox element.
My goal is when the trigger is hit, it will show the redbox element corresponding to number.
Examples:
clicking trigger1 inside wrapper1 element shows up redbox1 element,
trigger2 inside wrapper2 element shows up redbox2 element etc.
The problem is, when I click on trigger3 for example it always shows redbox1 element. (as example shows).
What I am doing wrong? I am just a begginer.
function showTheRedBox() {
var theRedBox = document.getElementsByClassName('redbox');
theRedBox[0].style.display = 'block';
}
body {background: #222;}
.wrapper {
background: yellow;
width: 100px;
height: 100px;
}
.trigger {
background: blue;
width: 50px;
height: 50px;
position: absolute;
margin-top: 50px;
margin-left: 50px;
}
.redbox {
background: red;
width: 200px;
height: 100px;
margin-left: 100px;
position: absolute;
display: none;
}
<div class="wrapper">
<div class="trigger" onclick="showTheRedBox();">trigger1</div>
<div class="redbox">hurrah1</div>
wrapper1</div>
<div class="wrapper">
<div class="trigger" onclick="showTheRedBox();">trigger2</div>
<div class="redbox">hurrah2</div>
wrapper2</div>
<div class="wrapper">
<div class="trigger" onclick="showTheRedBox();">trigger3</div>
<div class="redbox">hurrah3</div>
wrapper3</div>
You can use a for loop and a closure to access the .wrapper information for each onclick event. This method will work whether there are the same amount of children or not, and will always show the correct child.
Also, it is best to not use inline JavaScript attributes (e.g. onclick="showTheRedBox();") you should always assign your event handlers in your script for readability and maintainability.
var wrappers = document.querySelectorAll('.wrapper'), i;
var redboxes = document.querySelectorAll('.redbox');
for(i = wrappers.length - 1; i >= 0; --i) {
(function(wrapper){
wrapper.querySelector('.trigger').onclick = function() {
hideAll();
wrapper.querySelector('.redbox').style.display = 'block';
}
})(wrappers[i]);
}
function hideAll() {
for(i = redboxes.length - 1; i >= 0; --i) {
redboxes[i].style.display = 'none';
}
}
var wrappers = document.querySelectorAll('.wrapper'), i;
var redboxes = document.querySelectorAll('.redbox');
for(i = wrappers.length - 1; i >= 0; --i) {
(function(wrapper){
wrapper.querySelector('.trigger').onclick = function() {
hideAll();
wrapper.querySelector('.redbox').style.display = 'block';
}
})(wrappers[i]);
}
function hideAll() {
for(i = redboxes.length - 1; i >= 0; --i) {
redboxes[i].style.display = 'none';
}
}
body {background: #222;}
.wrapper {
background: yellow;
width: 100px;
height: 100px;
}
.trigger {
background: blue;
width: 50px;
height: 50px;
position: absolute;
margin-top: 50px;
margin-left: 50px;
}
.redbox {
background: red;
width: 200px;
height: 100px;
margin-left: 100px;
position: absolute;
display: none;
}
<div class="wrapper">
<div class="trigger">trigger1</div>
<div class="redbox">hurrah1</div>
wrapper1</div>
<div class="wrapper">
<div class="trigger">trigger2</div>
<div class="redbox">hurrah2</div>
wrapper2</div>
<div class="wrapper">
<div class="trigger">trigger3</div>
<div class="redbox">hurrah3</div>
wrapper3</div>
This method will also work, but it will use more memory as it queries the DOM once more than the above solution.
var wrappers = document.querySelectorAll('.wrapper'), i;
var redboxes = document.querySelectorAll('.redbox');
for(i = wrappers.length - 1; i >= 0; --i) {
wrappers[i].querySelector('.trigger').onclick = function() {
hideAll();
this.parentNode.querySelector('.redbox').style.display = 'block';
}
}
function hideAll() {
for(i = redboxes.length - 1; i >= 0; --i) {
redboxes[i].style.display = 'none';
}
}
var wrappers = document.querySelectorAll('.wrapper'), i;
var redboxes = document.querySelectorAll('.redbox');
for(i = wrappers.length - 1; i >= 0; --i) {
wrappers[i].querySelector('.trigger').onclick = function() {
hideAll();
this.parentNode.querySelector('.redbox').style.display = 'block';
}
}
function hideAll() {
for(i = redboxes.length - 1; i >= 0; --i) {
redboxes[i].style.display = 'none';
}
}
body {background: #222;}
.wrapper {
background: yellow;
width: 100px;
height: 100px;
}
.trigger {
background: blue;
width: 50px;
height: 50px;
position: absolute;
margin-top: 50px;
margin-left: 50px;
}
.redbox {
background: red;
width: 200px;
height: 100px;
margin-left: 100px;
position: absolute;
display: none;
}
<div class="wrapper">
<div class="trigger">trigger1</div>
<div class="redbox">hurrah1</div>
wrapper1</div>
<div class="wrapper">
<div class="trigger">trigger2</div>
<div class="redbox">hurrah2</div>
wrapper2</div>
<div class="wrapper">
<div class="trigger">trigger3</div>
<div class="redbox">hurrah3</div>
wrapper3</div>
The problem you have was that the method "getElementsByClassName", returns you an Array that contains all the elements of that class. So, when you where doing this:
theRedBox[0].style.display = 'block'
You were changing the display style of the First element of the Array, in this case "wrapper1".
Here's a modify version that functions whit the others wrappers:
<!DOCTYPE html>
<html lang = 'es'>
<head>
<title> MY TEST </title>
<style>
body {
background: #222;
}
.wrapper {
background: yellow;
width: 100px;
height: 100px;
}
.trigger {
background: blue;
width: 50px;
height: 50px;
position: absolute;
margin-top: 50px;
margin-left: 50px;
}
.redbox {
background: red;
width: 200px;
height: 100px;
margin-left: 100px;
position: absolute;
display: none;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="trigger" onclick="showTheRedBox(0)">trigger1</div> <!-- When the onClick event is trigered the function "showTheRedBox receives a parameter , that parameter is the position of the element in the Array "theRedBox"-->
<div class="redbox">hurrah1</div>
wrapper1
</div>
<div class="wrapper">
<div class="trigger" onclick="showTheRedBox(1)">trigger2</div>
<div class="redbox">hurrah2</div>
wrapper2
</div>
<div class="wrapper">
<div class="trigger" onclick="showTheRedBox(2)">trigger3</div>
<div class="redbox">hurrah3</div>
wrapper3</div>
<script>
function showTheRedBox(wrapperNumber) {
var theRedBox = document.getElementsByClassName('redbox');
theRedBox[wrapperNumber].style.display = 'block';
}
</script>
</body>
</html>
In one of my projects, I have requirement of multiple pop up div's on the same page. That means when user clicks on a link, some content should open in a pop up. There will be many such links with their own pop ups. With little knowledge of javascript, I have tried to write a javascript for it but it works only for one pop up. When I click on second, third... links, only first pop up opens rather than opening second, third... pop ups. Here is my code. Please tell the modifications to it.
<!DOCTYPE html>
<html >
<head>
<script>
window.document.onkeydown = function (e)
{
if (!e)
{
e = event;
}
if (e.keyCode == 27)
{
lightbox_close();
}
}
function lightbox_open()
{
window.scrollTo(0,0);
document.getElementById('light').style.display='block';
document.getElementById('fade').style.display='block';
}
function lightbox_close()
{
document.getElementById('light').style.display='none';
document.getElementById('fade').style.display='none';
}
</script>
<style>
#fade
{
display: none;
position: fixed;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
background-color: #000;
z-index:1001;
-moz-opacity: 0.7;
opacity:.70;
filter: alpha(opacity=70);
}
#light
{
display: none;
position: absolute;
top: 50%;
left: 50%;
width: 300px;
height: 200px;
margin-left: -150px;
margin-top: -100px;
padding: 10px;
border: 2px solid #FFF;
background: #CCC;
z-index:1002;
overflow:visible;
}
</style>
</head>
<body>
Open 1
<div id="light">div 1</div>
<div id="fade" onClick="lightbox_close();"></div>
Open 2
<div id="light">div 2</div>
<div id="fade" onClick="lightbox_close();"></div>
Open 3
<div id="light">div 3</div>
<div id="fade" onClick="lightbox_close();"></div>
</body>
</html>
Here's a way to achieve what you want. I'm sure it can be improved, but it's up to you then.
First, IDs should be unique across the page. If you want to group elements, give them a shared class instead.
With the changes, your HTML would look like this:
Open 1
<div class="light">div 1</div>
<div class="fade" onClick="lightbox_close()"></div>
Open 2
<div class="light">div 2</div>
<div class="fade" onClick="lightbox_close()"></div>
Open 3
<div class="light">div 3</div>
<div class="fade" onClick="lightbox_close()"></div>
Your CSS:
html, body {
width: 100%;
height: 100%;
}
.fade {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: #000;
z-index:1001;
-moz-opacity: 0.7;
opacity:.70;
filter: alpha(opacity=70);
}
.light {
display: none;
position: absolute;
top: 50%;
left: 50%;
width: 300px;
height: 200px;
margin-left: -150px;
margin-top: -100px;
padding: 10px;
border: 2px solid #FFF;
background: #CCC;
z-index:1002;
overflow:visible;
}
And your Javascript:
window.document.onkeydown = function (e) {
if (!e) {
e = event;
}
if (e.keyCode == 27) {
lightbox_close();
}
}
// Note that the function is receiving the clicked element reference.
function lightbox_open(el) {
window.scrollTo(0,0);
// All the anchors that have a class lightbox.
var anchors = document.querySelectorAll('a.lightbox');
// All the elements with class light.
var light = document.querySelectorAll('.light');
// All the elements with class fade.
var fade = document.querySelectorAll('.fade');
// Iterate over the anchors elements.
for (var i = 0; i < anchors.length; i++) {
// If the anchor matches the clicked one.
if (anchors[i] == el) {
// Look for the light and fade with the same index
// and display them.
light[i].style.display = 'block';
fade[i].style.display = 'block';
}
}
}
function lightbox_close() {
// All the elements with class light or fade.
var els = document.querySelectorAll('.light, .fade');
// Loop through the list.
for (var i = 0; i < els.length; i++) {
// Hide them.
els[i].style.display = 'none';
}
}
Demo