Create closable div elements using pure js

1.9k views Asked by At

I am trying to make a button that creates small windows that you can close after pressing X. The problem I have is that i can only close the last created window.

function openNote() {

var base = document.createElement('div'); 
base.id = 'note';
var in_ = document.createElement('div');
in_.id = 'note_in';
var in_2 = document.createElement('div');
in_2.id = 'note_in2';
var ex = document.createElement('div');
ex.id = 'ex';
var ext = document.createTextNode("X");

base.appendChild(in_);
in_.appendChild(in_2);
in_2.appendChild(ex);
ex.appendChild(ext);
document.body.appendChild(base);


document.getElementById('ex').onclick = function(){
var r = document.getElementById('note');
r.parentNode.removeChild(r);
}
}
#note{
background:#819C9A;
height : 200px;
width : 150px;
border: 2px solid;
border-radius: 25px;
border-color:#49706E;
margin:10px;

}
#note_in{
float:left;
height : 35px;
width : 150px;
background:rgba(255,255,255,0.2);
}
#note_in2
{
float:right;
height : 25px;
width : 25px;
margin:5px;
background:#9DCCCA;
border-radius: 15px;
text-align: center;
cursor:pointer;
}
#ex{

margin-top: 4px;
 
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css"/>
<script src="script.js"></script>

</head>
<body>

<button onClick="openNote();">Press me!</button>


</body>
</html>

I'm fairly new to JavaScript and would appreciate any help or advice.

5

There are 5 answers

1
Artūras On BEST ANSWER

Problem you are facing is that you create more than one dom element with same id, id is unique per page.

What happens now is every time when you click 'Press me!' new dom element is created, but the document.getElementById('ex') only gets the first in the tree so you are always binding event to the first element no matter how many you add later.

Options for fixing would be few:

  • Use classes and bind to class.
  • Check if a note was already open, if it was, do not open another one, or destroy the previous
  • 3rd option use already created ex and base variables (example bellow)

function openNote() {

var base = document.createElement('div'); 
base.id = 'note';
var in_ = document.createElement('div');
in_.id = 'note_in';
var in_2 = document.createElement('div');
in_2.id = 'note_in2';
var ex = document.createElement('div');
ex.id = 'ex';
var ext = document.createTextNode("X");

base.appendChild(in_);
in_.appendChild(in_2);
in_2.appendChild(ex);
ex.appendChild(ext);
document.body.appendChild(base);


ex.onclick = function(){
 
base.parentNode.removeChild(base);
}
}
#note{
background:#819C9A;
height : 200px;
width : 150px;
border: 2px solid;
border-radius: 25px;
border-color:#49706E;
margin:10px;

}
#note_in{
float:left;
height : 35px;
width : 150px;
background:rgba(255,255,255,0.2);
}
#note_in2
{
float:right;
height : 25px;
width : 25px;
margin:5px;
background:#9DCCCA;
border-radius: 15px;
text-align: center;
cursor:pointer;
}
#ex{

margin-top: 4px;
 
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css"/>
<script src="script.js"></script>

</head>
<body>

<button onClick="openNote();">Press me!</button>


</body>
</html>

Using 3rd option you could actually skip all id's

0
mutlei On

You are assigning the same ID to multiple divs, assign a class to them so they all have the same behavior.

That will make them all close when you click the close button. Use sequential ID's if you want specific divs to close.

0
Yowser On

Couple of things really. The reason why only the last div was removed is because all of the divs share the same id. I'd change it to have unique ids. that said, you can use the 'this' keyword to refer to the current div and add an event listener:

function openNote() {

var base = document.createElement('div'); 
base.id = 'note';
    base.innerHTML = "<br /><br />" + Math.random();
var in_ = document.createElement('div');
in_.id = 'note_in';
var in_2 = document.createElement('div');
in_2.id = 'note_in2';
var ex = document.createElement('div');
ex.id = 'ex';
ex.addEventListener("click", closeWindow);
var ext = document.createTextNode("X");

base.appendChild(in_);
in_.appendChild(in_2);
in_2.appendChild(ex);
ex.appendChild(ext);
document.body.appendChild(base);



function closeWindow()
{  
  var r = this.parentNode.parentNode.parentNode;
  r.parentNode.removeChild(r);
}
}
#note{
position: relative;
background:#819C9A;
height : 200px;
width : 150px;
border: 2px solid;
border-radius: 25px;
border-color:#49706E;
margin:10px;

}
#note_in{
position: absolute;
top: 0px;
left: 0px;
height : 35px;
width : 150px;
background:rgba(255,255,255,0.2);
}
#note_in2
{
float:right;
height : 25px;
width : 25px;
margin:5px;
background:#9DCCCA;
border-radius: 15px;
text-align: center;
cursor:pointer;
}
#ex{

margin-top: 4px;
 
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css"/>
<script src="script.js"></script>

</head>
<body>

<button onClick="openNote();">Press me!</button>


</body>
</html>

I also added some random text just to show which div has been removed. Also changed the css to make note position relative and note_in position absolute at position 0,0 (ie note_in is positioned absolutely with regard to note). If you don't set note's position, any child nodes will be positioned relative to note's parent (ie body).

Cheers

0
Rey Rajesh On
//global var
var x = 0;

function openNote() {

var base = document.createElement('div'); 
base.id = 'note' + x;
var in_ = document.createElement('div');
in_.id = 'note_in' + x;
var in_2 = document.createElement('div');
in_2.id = 'note_in2' + x;
var ex = document.createElement('div');
ex.id = 'ex' + x;
var ext = document.createTextNode("X");

base.appendChild(in_);
in_.appendChild(in_2);
in_2.appendChild(ex);
ex.appendChild(ext);
document.body.appendChild(base);
x = x + 1;

}
for(y = 0; y < 10; y++){
document.getElementById('ext' + y).onClick(function(){
var r = document.getElementById('note' + x);
r.parentNode.removeChild(r);
});

You could try like this.. This code is not the exact solution but just to give you idea..

0
Zudwa On

As n0mercy mentioned, avoid dublicating elements IDs.

Second, you can remove element without using Ids or classes, use closures:

function openNote() {
    var base = document.createElement('div'); 
    base.className = 'note';

    var in_ = document.createElement('div');
    in_.className = 'note_in';

    var in_2 = document.createElement('div');
    in_2.className = 'note_in2';

    var ex = document.createElement('div');
    ex.className = 'ex';

    var ext = document.createTextNode("X");

    base.appendChild(in_);
    in_.appendChild(in_2);
    in_2.appendChild(ex);
    ex.appendChild(ext);
    document.body.appendChild(base);

    document.getElementById('ex').onclick = function(){
        base.parentNode.removeChild(base);
    }
}