Using a loop, but only one element is being added - javascript

I was working on some JavaScript and was trying to add things dynamically. Below is my code. My problem is that I am trying to add three "li" elements, attach "img" tags to it ans attaching the src dynamically. But it is attaching only the last image i.e in my code "bid_3" to all the "li". Help appreciated.
(function() {
var bxSlider = document.createElement("ul"); //created ul
bxSlider.setAttribute("class", "bxslider"); // gave a class name bxslider.
for (i = 1; i < 4; i++) {
var itemsList = document.createElement("li");
var linkImages = document.createElement("img");
linkImages.src = "images/bid_" + i + ".jpg";
itemsList.appendChild(linkImages);
}
bxSlider.appendChild(itemsList);
document.body.appendChild(bxSlider); //append everything to the body.
var ulNum = document.getElementsByTagName("ul");
alert(ulNum.length); // should return 1
var liNum = document.getElementsByTagName("li");
alert(liNum.length); // should return 3
var imgNum = document.getElementsByTagName("img");
alert(imgNum.length); //should return 3
//call the slider.
$(document).ready(function() {
$('.bxslider').bxSlider();
});
}());
PS:- I am not a JavaScript expert. Please forgive if my code is bad.

You're only attaching itemsList after you've passed through the loop. Try this:
// Before loop stuff...
for (i = 1; i < 4; i++) {
var itemsList = document.createElement("li");
var linkImages = document.createElement("img");
linkImages.src = "images/bid_" + i + ".jpg";
itemsList.appendChild(linkImages);
bxSlider.appendChild(itemsList);
}
// After loop stuff...

Related

I don't how why my backgroundImage doesn't work

Why does my banner doesn't change her background? Please help me.
When I run the file the console tells me:
Uncaught TypeError: flechedroite.addEventListener is not a function
I really don't understand. I'm a beginner in Javascript so please explain me with kind words how I can fix this error :)
var flechedroite = document.getElementsByClassName('fa-arrow-right');
var flechegauche = document.getElementsByClassName('switch-left');
var banner = document.getElementById('banner');
var images = [];
var changeBackground = function (bElement, bUrl) {
return bElement.style.backgroundImage = "url(" + bUrl + ")";
}
//image list
images[0] = 'images/image1.jpg';
images[1] = 'images/image2.jpg';
images[2] = 'images/image3.jpg';
flechedroite.addEventListener('click', function() {
for (var i = 0; i < images.length; i++) {
changeBackground(document.body, images[i]);
}
})
addEventListener should be called in window.onload or in $(document).ready()
Since getElementsByClassName returns an array, you need to use array index with flechedroite to add an event listener. i.e. flechedroite[0].addEventListener('click', function() {...});
You are calling changeBackground function in a loop to set the background image, effectively you will see only the last image from the array being set as background.
JS Code
var images = [];
var changeBackground = function (bElement, bUrl) {
return bElement.style.backgroundImage = "url("+bUrl+")";
}
//image list
images[0] = 'https://www.gettyimages.ie/gi-resources/images/Homepage/Hero/UK/CMS_Creative_164657191_Kingfisher.jpg';
images[1] = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTOGUhZo0Qe81U5qY_Z-seXgsD79LEEet832TVOlLMOEy10ZPsV';
images[2] = 'https://cdn.pixabay.com/photo/2016/06/18/17/42/image-1465348_960_720.jpg';
window.onload = function(){
var flechedroite = document.getElementsByClassName('fa-arrow-right');
var flechegauche = document.getElementsByClassName('switch-left');
var banner = document.getElementById('banner');
var currentImageIndex = 0;
flechedroite[0].addEventListener('click', function() {
currentImageIndex = (currentImageIndex+1)%images.length;
changeBackground(document.body, images[currentImageIndex]);
})
}
The function getElementsByClassName returns a HTMLCollection, which is an array like structure that can contain multiple elements. So you need to use an index to access the elements contained in it.
So flechedroite.addEventListener results in an error but flechedroite[0].addEventListener should work
https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByClassName
if you use 'getElementsByClassName' and you want to add an 'addEventListener', you can not do it in a 'generic' way: "flechedroite.addEventListener ('click', function () {}". You have to do this for each element:
var flechedroite = document.getElementsByClassName('fa fa-arrow-right');
//flechedroite contains all the elements that have the 'fa fa-arrow-right' classes
//on each element you have to add the "addEventListener"
for (var i = 0; i < flechedroite.length; i++) {
flechedroite[i].addEventListener('click', function() {
alert('flechedroite');
});
}
basic example JSFiddle1
a more advanced example
JSFiddle2

JavaScript createElement Line Causes Error

I'm writing a simple JavaScript program to examine every element in an HTML website and add a child node to every non-text node that labels the type of tag:
Here is my code:
window.onload = function() {
var body_elems = document.body.getElementsByTagName("*");
for (var i = 0; i < body_elems.length; i++) {
if (body_elems[i].nodeType != 3) {
var tag_name = body_elems[i].tagName;
var child = document.createElement("P");
var child_text = document.createTextNode(tag_name);
child.appendChild(child_text);
body_elems[i].appendChild(child);
body_elems[i].firstChild.className = "hoverNode";
}
}
}
For some reason the line var child = document.createElement("P") causes the page to never load; if I comment out that line then the page will load.
On the other hand, here is a slightly different version that actually works:
window.onload = function() {
var body_elems = document.body.getElementsByTagName("*");
for (var i = 0; i < body_elems.length; i++) {
if (body_elems[i].nodeType != 3) {
var tag_name = body_elems[i].tagName;
var child = document.createTextNode(tag_name);
body_elems[i].appendChild(child);
child.className="hoverNode";
}
}
}
But I can't figure out how to assign a class name to the new node in order to apply CSS, so if someone could tell me how to do that my problem would be solved.
I'm new to JS so any help would be much appreciated.

createElement or appendChild not working

I am trying to put an img element in a span element that I created dynamically with JavaScript. The problem is that the span element isn't showing in the DOM tree. However, the img elements are shown on the page and are nested in the div element (#playfield) that is hard coded in my html code. I really don't know what I'm doing wrong.
var playfield = document.getElementById("playfield");
var indexes = [0,1,2,3,4,5,6,7,8,9,10,11];
shuffle(indexes);
for (var i = 0; i < 12; i++) {
var vak1 = document.createElement("span");
var kaart1 = document.createElement("img");
var path1 = "img/kaart" + indexes[i] + ".png";
var klasse1 = "img" + indexes[i];
kaart1.setAttribute("src", "img/achterkant.png");
kaart1.setAttribute("class", klasse1);
kaart1.setAttribute("data-img", path1);
kaart1.setAttribute("height", "150");
kaart1.setAttribute("width", "150");
kaart1.setAttribute("data-turned","false");
playfield.appendChild(vak1.appendChild(kaart1));
}
playfield.appendChild(vak1.appendChild(kaart1)); Is the problem line. The result of vak1.appendChild(kaart1) is the appended child kaart1 - do these 2 operation separately:
vak1.appendChild(kaart1);
playfield.appendChild(vak1);
var playfield = document.getElementById("playfield");
var indexes = [0,1,2,3,4,5,6,7,8,9,10,11];
for (var i = 0; i < 12; i++) {
var vak1 = document.createElement("span");
var kaart1 = document.createElement("img");
var path1 = "img/kaart" + indexes[i] + ".png";
var klasse1 = "img" + indexes[i];
//kaart1.setAttribute("src", "img/achterkant.png");
kaart1.setAttribute("class", klasse1);
kaart1.setAttribute("data-img", path1);
kaart1.setAttribute("height", "150");
kaart1.setAttribute("width", "150");
kaart1.setAttribute("data-turned","false");
vak1.appendChild(kaart1)
playfield.appendChild(vak1);
}
Append to the first and then add that to the playfield.
You're adding the created <img> as a child to #playfield. If you want it in a <span>, you'll have to add it to the <span> and then add that <span> to #playfield.

Javascript regex classname issue

Apologies for the vague title of this question!
I have the following JS, it looks for img tags with images of certain sources. It then replaces the img tag with a span so that I can replace the images/icons with iconfonts.
var paths = [
"folder%2Fadd",
"folder%2Fclear",
"folder%2Fdelete",
"folder%2Fedit",
"folder%2Fmove",
"folder%2Fsort",
];
var fullPaths = paths.map(function(x) { return "img[src*='" + x + "']"; } );
var imgs = document.querySelectorAll(fullPaths);
for (var i = 0; i < imgs.length; i++) {
var span = document.createElement("span");
span.addClass("iconfont");
span.title = imgs[i].parentNode.title;
imgs[i].parentNode.replaceChild(span, imgs[i]);
}
Everything is working nicely so far, but there is one more issue that I cannot solve.
Apart from adding a class to the span of .iconfont, I also want to add two more classes to the span - 1) the original class of the replaced img element, and 2) the name of the image source as in my array, but without the 'folder/' bit in front.
So, at the moment I have:
<img class = "tinyicon" src="******/t/edit">
and my script creates this in the DOM:
<span class = "iconfont">
But I want my script to create the following:
<span class = "iconfont tinyicon edit">
That is what I am after :)
Thanks for having a look!
var paths = [
"folder%2Fadd",
"folder%2Fclear",
"folder%2Fdelete",
"folder%2Fedit",
"folder%2Fmove",
"folder%2Fsort",
];
var fullPaths = paths.map(function(x) { return "img[src*='" + x + "']"; } );
var imgs = document.querySelectorAll(fullPaths);
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i],
iClass = img.className,
iSrc = img.src.split('/').pop(),
span = $('<span />', {'class': 'iconfont '+iClass+' '+iSrc,
title : img.parentNode.title
});
$(img).replaceWith(span);
}
Change this:
var span = document.createElement("span");
span.addClass("iconfont");
to this:
var span = document.createElement("span");
span.className = "iconfont tinyicon edit";
Your addClass() wouldn't work anyway because span is a DOM node, not a jQuery object.
var span = document.createElement("span");
var className = "iconfont " + imgs[i].className + ' ' + imgs[i].src.match(/([a-z])$/i, '')
span.className = className ;
span.title = imgs[i].parentNode.title;
imgs[i].parentNode.replaceChild(span, imgs[i]);

Passing image array values and changing image source onclick

OK, so finally the penny dropped (loud clunk!) on the click issue I was having here Append dynamic div just once and a JSFiddle issue. The code now shows user a choice of pics once per node clicked. Phew.
However, now my img.src=e.target.src line is having trouble accessing the other images in the array. Only the last image in the array will add to the table. I think this is because the allImages.onclick event should be inside the loop?
I have tried that and then img is showing up as undefined. I'm guessing that is because the loop (and therefore the function) is running before var img is declared? I think it is an issue with the order of things.
All help appreciated.
var makeChart = function () {
var table = document.createElement('table'),
taskName = document.getElementById('taskname').value,
header = document.createElement('th'),
numDays = document.getElementById('days').value, //columns
howOften = document.getElementById('times').value, //rows
row,
r,
col,
c;
var myImages = new Array();
myImages[0] = "http://www.olsug.org/wiki/images/9/95/Tux-small.png";
myImages[1] = "http://a2.twimg.com/profile_images/1139237954/just-logo_normal.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);
var newList = document.createElement("ul");
newList.appendChild(allImages);
my_div = document.getElementById("showPics");
my_div.appendChild(newList);
my_div.style.display = 'none';
}
header.innerHTML = taskName;
table.appendChild(header);
header.innerHTML = taskName;
table.appendChild(header);
function addImage(col) {
var img = new Image();
img.src = "http://cdn.sstatic.net/stackoverflow/img/tag-adobe.png";
col.appendChild(img);
img.onclick = function () {
my_div.style.display = 'block';
allImages.onclick = function (e) { // I THINK THIS IS THE PROBLEM
img.src = e.target.src;
my_div.style.display = 'none';
img.onclick=null;
};
}
}
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);
document.getElementById('createChart').onclick=null;
}
Well, the problem seems to stem from different parts. First of all,
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);
var newList = document.createElement("ul");
newList.appendChild(allImages);
my_div = document.getElementById("showPics");
my_div.appendChild(newList);
my_div.style.display = 'none';
}
This loop creates a new div for EACH image in myImages, then appends a ul to that div, and finally appends the Image for the current image to the ul.
The question of what document.getElementById('showPics') returns, since there are as many divs with the id showPics appended to body as myImages.length, has a mystical magical answer which should never be spoken, or even thought, of again.
Why not do the sensible thing and create one singular happy div outside the loop? Append a single ul child to it, outside the loop. Then proceed to append as many li as you want in the loop.
var my_div = document.createElement('div');
my_div.id = 'showPics';
var newList = document.createElement('ul');
my_div.appendChild(newList);
for var i = 0; i < myImages.length; i++) {
...
var li = document.createElement('li');
li.appendChild(allImages);
newList.appendChild(li);
...
}
my_div.style.display = 'none';
Now, my_div is the one and only div containing the images. So, the click event handlers can toggle its visibility safely.
Second,
function addImage(col) {
var img = new Image();
img.src = "http://cdn.sstatic.net/stackoverflow/img/tag-adobe.png";
col.appendChild(img);
img.onclick = function () {
my_div.style.display = 'block';
allImages.onclick = function (e) { // I THINK THIS IS THE PROBLEM
img.src = e.target.src;
my_div.style.display = 'none';
img.onclick=null;
};
}
}
allImages references the same Image object now that you are out of the loop, which happens to be the last image in myImages. So, only the last image in myImages will register the handler to a click event. To solve this problem, we make a new variable.
var sel = null; //This comes before my_div
Now, we add the click handler to allImages inside the loop so that every image in myImages gets a piece of the pie, as they say.
for var i = 0; i < myImages.length; i++) {
var allImages = new Image();
allImages.src = myImages[i];
allImages.onclick = function (e) {
if(sel !== null) {
sel.src = e.target.src;
my_div.style.display = 'none';
sel.onclick=null;
sel = null;
}
};
...
}
And finally, adjust addImage so that sel can be set when the image is clicked.
function addImage(col) {
...
img.onclick = function () {
my_div.style.display = 'block';
sel = img;
}
...
}
That's all there is to it! Example.
Note that, if you comment out sel.onclick = null, you can change a particular cell's image as many times you like.
Your addImage() function makes a direct reference to the allImages variable. One problem is that since you were using (and reusing) that variable in a for loop earlier in the code it is only going to retain the last value that was assigned to it. So no matter how many times you call addImage() it's always adding the onclick function to the last image that allImages pointed to.
I'd also suggest renaming the allImages variable. That's a very misleading name because it in fact only ever represents a single image.
Hope that helps!

Categories

Resources