Reputation: 141
I am trying to make a image grid with download buttons using javascript to put them in html.
I tried insertBefore.
var list = ["https://via.placeholder.com/50", "https://via.placeholder.com/75", "https://via.placeholder.com/100", "https://via.placeholder.com/125"];
var template, item, item1, item2, fin, i, target, ta;
template = document.getElementById("item");
item = template.content.getElementById("grid-itm");
item1 = template.content.getElementById("imgtit");
item2 = template.content.getElementById("linktit");
target = document.getElementById("gc");
for (i = 0; i < list.length; i++) {
target = document.getElementById("gc");
ta = list[i];
item1.src = ta;
item2.href = ta;
item.appendChild(item1);
item.appendChild(item2);
target.appendChild(item);
}
<template id="item">
<div class="grid-item" id="grid-itm">
</div>
<img src="" id="imgtit">
<a href="" id="linktit"><p>Download</p></a>
</template>
<div class="grid-container" id="gc"></div>
In .grid-container should be all my pictures, but it's only the last from the list.
Upvotes: 0
Views: 1172
Reputation: 43940
The content of a <template>
must be cloned
const copy = template.content.cloneNode(true)
The parameter for cloneNode(param)
is a Boolean -- true
will clone all of targeted tag's descendant tags.
ids must be unique, otherwise HTML is invalid. Moreover JavaScript/jQuery that manipulates DOM (such as OP) will break. Assign class to duplicated tags and use .querySelector()
to reference them.
const image = copy.querySelector('.image');
Clone and reference template content and assign clone properties within the loop
for (let url of list) {
const copy = template.content.cloneNode(true);
const image = copy.querySelector('.image');
image.src = url;
document.body.appendChild(copy);
}
Always modify the DOM as the last step of any process. Although mostly relevant in large scale applications, performance suffers the most when removing, adding, mutating, traversing, etc. anything in the DOM. It costs less in memory and processing time when modifying a tag not attached to DOM (ex. image.src = url;
then document.body.appendChild(copy);
)
const list = ["https://via.placeholder.com/50", "https://via.placeholder.com/75", "https://via.placeholder.com/100", "https://via.placeholder.com/125"];
function imgGrid(array) {
const grid = document.querySelector(".grid");
const template = document.querySelector(".temp");
for (let url of array) {
const item = template.content.cloneNode(true);
item.querySelector('.image').src = url;
item.querySelector('.link').href = url;
grid.appendChild(item);
}
}
imgGrid(list);
.grid {
display: flex;
flex-wrap: wrap;
max-width: 100vw
}
.item {
text-align: center;
width: fit-content;
}
<section class="grid"></section>
<template class="temp">
<figure class="item">
<img src="" class="image">
<figcaption>
<a href="" class="link">Download</a>
</figcaption>
</figure>
</template>
Upvotes: 0
Reputation: 370889
You only assign to the item
variables once, before the loop begins, and when you call appendChild
with an element already in the DOM, it will be removed from where it existed previously. Inside the loop, clone the elements instead (and remove their IDs, since duplicate IDs in a single document is invalid HTML):
const list = ["IMG_20190704_133046.jpg", "IMG_201810055.jpg", "DSCN0994.JPG", "IMG_20181104_160735.jpg", "IMG_201810054.jpg", "IMG_20181007_152306.jpg", "IMG_20180721_210459.jpg", "PANO_20180719_202625-01.jpeg", "IMG_20180719_200505.jpg"];
const target = document.getElementById("gc");
const template = document.querySelector('#item');
for (let i = 0; i < list.length; i++) {
const [div, img, a] = [...template.content.children].map(node => node.cloneNode());
const src = "imgs/" + list[i];
img.src = src;
a.href = src;
div.appendChild(img);
div.appendChild(a);
target.appendChild(div);
}
const list = ["IMG_20190704_133046.jpg", "IMG_201810055.jpg", "DSCN0994.JPG", "IMG_20181104_160735.jpg", "IMG_201810054.jpg", "IMG_20181007_152306.jpg", "IMG_20180721_210459.jpg", "PANO_20180719_202625-01.jpeg", "IMG_20180719_200505.jpg"];
const target = document.getElementById("gc");
const template = document.querySelector('#item');
for (let i = 0; i < list.length; i++) {
const [div, img, a] = [...template.content.children].map(node => node.cloneNode());
const src = "imgs/" + list[i];
img.src = src;
a.href = src;
div.appendChild(img);
div.appendChild(a);
target.appendChild(div);
}
<template id="item">
<div class="grid-item">
</div>
<img>
<a><p>Download</p></a>
</template>
<div id="gc"></div>
Upvotes: 2