Machine
Machine

Reputation: 31

JS for -loop always use last element - scope issues

var url_array = ["ulr1", "ulr2", "ulr3", "ulr4", "ulr5"];

var img = document.createElement('img');

for (i = 0; i < url_array.length; i++){
    var div = document.createElement('div');
    div.setAttribute("id", "div"+i);
    document.getElementById('main').appendChild(div);

    document.getElementById('div'+i).style.width = ImageWidth+5+"px";
    document.getElementById('div'+i).style.height = ImageHeight+5+"px";

    console.log("\ncreate all the DIVs. \nFor loop count: "+i);

    img.src = loadImage(url_array[i], ImageWidth, ImageHeight);

    try{throw img}
    catch(c_img) {

        document.getElementById('div'+i).appendChild(c_img);

        console.log("after load, and append, in Catch: "+img.src);
        console.log("div NR = "+document.getElementById('div'+i).id);
        console.log(document.getElementById('div'+i).childNodes.length);
    } //catch
} // FOR

function loadImage(URL, h, w)
{
    console.log("loadImage callaed with URL = "+URL);
    return url = URL+Date.now().toString(10);
}

For-Loop is supposed to retrieve urls address of an images (from camera) and append them to DIV. DIV and IMGs are created on the fly. Problem is that only last DIV become image holder.

I am using catch-try to force execute code immediately so each separate Div+i will have distinctive image. Also construction like this one (immediately invoked function expression):

(function(){
  something here;
  })();

for creating "private" scope gives no hope. Either "Let" - which supposed to define variable locally is not helping. *My knowledge here is limited and I'm relying on data found on web site (can give link later if it is not against rules).

Output of console.log() is not helping much. Everything goes as it should, except for the childNodes.length which is 1 for each for-loop iteration - that means each DIV have its IMG child I guess... If so - why I can't see them?

I feel I am close to what I want to achieve - using Intervals() refresh each DIV with new camera snapshot, but I need to solve this current issue.

Example of code ready to use: js.js:

var url_array = [
"https://images.pexels.com/photos/104827/cat-pet-animal-domestic-104827.jpeg",
"https://images.pexels.com/photos/45201/kitty-cat-kitten-pet-45201.jpeg",
"https://images.pexels.com/photos/617278/pexels-photo-617278.jpeg"
];

var ImageWidth = 640;
var ImageHeight = 480;

var img = document.createElement('img');

for (i = 0; i < url_array.length; i++){

    var div = document.createElement('div');//.setAttribute("id", "div0");
    div.setAttribute("id", "div"+i);
    document.getElementById('main').appendChild(div);

    document.getElementById('div'+i).style.width = ImageWidth+5+"px";
    document.getElementById('div'+i).style.height = ImageHeight+5+"px";
    var color = ((Math.floor(Math.random() * (16777215)) + 1).toString(16)); // from 1 to (256^3) -> converted to HEX
    document.getElementById('div'+i).style.background = "#"+color;


    document.getElementById('div'+i).style.width = ImageWidth+5+"px";
    document.getElementById('div'+i).style.height = ImageHeight+5+"px";

    console.log("\ncreate all the DIVs. \nFor loop count: "+i);

    img.src = loadImage(url_array[i], ImageWidth, ImageHeight);

    try{throw img}
    catch(c_img) {

        document.getElementById('div'+i).appendChild(c_img);

        console.log("after load, and append, in Catch: "+img.src);
        console.log("div NR = "+document.getElementById('div'+i).id);
        console.log(document.getElementById('div'+i).childNodes.length);
    } // catch
} // FOR

function loadImage(URL, h, w)
{
    console.log("loadImage callaed with URL = "+URL);
    return url = URL+"?auto=compress&h="+h+"&w="+w;
}

HTML:

<html>
<head>
<meta charset="utf-8">
<STYLE>

div#main {
    padding: 5px;
    background: black;
}
</STYLE>
</head>
<body>



<script type="text/javascript">

function downloadJSAtOnload() {
var element = document.createElement("script");
element.src = "js.js";
document.body.appendChild(element);
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
</script>
<div id="main"></div>
</body>
</html>

Upvotes: 1

Views: 170

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370769

The problem is that your

var img = document.createElement('img');

is outside the loop - you're only ever creating one img. When appendChild is called on an element that already exists in the DOM (such as on the second, third, fourth, etc iteration), the element gets removed from its previous location and inserted into the new location.

Create the image inside the loop instead, and try not to implicitly create global variables - when declaring new variables, always use let or const.

Also, when you do

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

you have a reference to the div you just created - there's no need to assign an id to it in order to select it with

document.getElementById('div'+i)

in below lines in the same scope. Instead, just keep referencing the div:

const ImageWidth = 200;
const ImageHeight = 200;
const main = document.getElementById('main');
var url_array = ["ulr1", "ulr2", "ulr3", "ulr4", "ulr5"];

for (let i = 0; i < url_array.length; i++){
  const img = document.createElement('img');
  const div = document.createElement('div');
  main.appendChild(div);
  div.style.width = ImageWidth+5+"px";
  div.style.height = ImageHeight+5+"px";
  img.src = loadImage(url_array[i], ImageWidth, ImageHeight);
  div.appendChild(img);
}
console.log(main.innerHTML);

function loadImage(URL, h, w) {
  return URL+Date.now().toString(10);
}
div#main {
    padding: 5px;
    background: black;
}
<div id="main">
</div>

Upvotes: 1

Related Questions