I am trying to present pics to users, they can choose one and it adds to the table. This is fine but when I try to add a different image to another table node the full list is generated again. Basically, I want an image picker. I understand that the img.onclick
is building the image list every time the click is called, but I can't get my head around it. I have tried:
var element = document.getElementById("menu");
element.parentNode.removeChild(element);
method to try and remove the appended div every time the event is called, but it is not working for me. Been trying to work this out for a while so all help really appreciated.
function addImage(col) {
var img = new Image();
img.src = "../www/images/TEST.png";
col.appendChild(img);
img.onclick = function () {
var myImages = new Array();
myImages[0] = "../www/images/TEST3.png";
myImages[1] = "../www/images/TEST2.png";
myImages[2] = "../www/images/TEST4.png";
for (var i = 0; i < myImages.length; i++) {
var allImages = new Image();
allImages.src = myImages[i];
var my_div = document.createElement("div");
my_div.id = "showPics";
document.body.appendChild(my_div);
newList = document.createElement("ul");
newList.appendChild(allImages);
my_div.appendChild(newList);
my_div.style.display = 'block';
allImages.onclick = function (e) {
img.src = e.target.src;
my_div.style.display = 'none';
};
}
};
}
for (r = 0; r < howOften; r++) {
row = table.insertRow(-1);
for (c = 0; c < numDays; c++) {
col = row.insertCell(-1);
addImage(col);
}
}
document.getElementById('holdTable').appendChild(table);
I've created an updated version of the code, here: http://jsfiddle.net/NyxCu/15/ which probably does what you want to do.
There are details of JavaScript style that you'll need to learn. But let's review the problems first:
In these lines:
var my_div = document.createElement("div");
my_div.id = "showPics";
document.body.appendChild(my_div);
You are creating a div with the same id several times. But ids should be unique in your document. The browser is not going to complain about it, but you'll get an unwanted div if you do a getElementById
later.
In the jsfiddle link that you sent (http://jsfiddle.net/Inkers/NyxCu/) the code does a getElementById
a few lines later:
my_div = document.getElementById("showPics");
my_div.appendChild(newList);
It means that for each click on the first image, second images are added always to the same div (that's why images are duplicated over and over).
Probably you did that hack because the onclick
event handler set on the loop:
allImages.onclick = function (e) {
img.src = e.target.src;
my_div.style.display = 'none';
};
Didn't work as expected. The problem is that JavaScript variable scope only applies at function level.
It means that:
for (var i = 0; i < length; i++) {
var item = create(i);
}
Is equivalent to:
var i, item;
for (i = 0; i < length; i++) {
item = create(i);
}
This is important. Because when you create an event handler, like this:
var i, item;
for (i = 0; i < length; i++) {
item = create(i);
something.onclick = function () {
use(item);
}
}
item
is not what you expect. The function assigned to onclick
is a closure that has a reference to the parent environment: the parent function not the scope of the for loop. It means that item
will be always equal to create(length - 1);
.
That is why in the code you got the unexpected my_div
.
Another problem in the code (that I didn't change, in the rewritten code of the link), is that the second list of images is generated over and over (inspect the HTML to see that).
To summarize:
Ids of elements should be unique. Duplicated ids doesn't generate error, but find by id is going to give you unexpected results.
Be aware of the JavaScript scope differences, and closures. Once that you learn it, is very uniform: JavaScript variable scope is always at function level.
Some tips:
Learn a little bit of jQuery, is going to help you a lot with DOM manipulation.
Avoid new Array()
, using array literals is shorter and more readable.
Take a look into ECMAScript forEach
, map
and filter
. They will help you to write JavaScript with a functional style that for my taste is easier to read (they are not available in old versions of Explorer but you can use a shim or Underscore.js).