I have a program which stores images and their names in an array. The names are displayed in a list, the corresponding image is displayed on click
I also want to count the clicks on the image once it is displayed. At a later point per image, right now I am just trying to count total clicks.
The code below does not display the clicks in the Console, I do not get any error.
Is it not possible to nest two immediately invoked functions like this?
for (var i = 0; i < cats.length; i++) {
//Building the list . Creating a list item and textnode. The textnode reads out the catnames. Append the textnode to the list. Append all of it to the catlist in the HTML
var catitem = document.createElement("LI");
var textnode = document.createTextNode(cats[i].id);
catitem.appendChild(textnode);
document.getElementById("catlist").appendChild(catitem);
//Adding the catname to the div
var currentcat = cats[i].id;
var currentimage = cats[i].img;
catitem.addEventListener('click', (function(currentimage_copy) {
return function() {
var clicks = 0;
var x = document.createElement("IMG");
x.setAttribute("src", currentimage_copy);
var item = document.getElementById("catimage");
var y = document.getElementById("catimage").childNodes[0];
item.replaceChild(x, y);
x.setAttribute("onclick", (function countClicks(clickscopy) {
return function countClicks() {
clicks++;
console.log(clickscopy);
};
})(clicks));
Here is the full code
<!DOCTYPE html>
<html>
<body>
<title>||Cats||</title>
</head>
<body>
<h1>This is the list of cats<h1>
<h2>Click the cat to see an image of the cat</h2>
<ul id="catlist">
</ul>
<div id="catimage">
</div>
<div id="catname"></div>
<div id="current"></div>
<script>
document.body.onload = addElement;
function addElement() {
var cats = [{
img: "cat.jpg",
id: "cleo"
},
{
img: "shimi.png",
id: "shimi"
},
{
img: "miezi.png",
id: "miezi"
},
{
img: "tom.jpg",
id: "tom"
},
{
img: "chrissie.jpg",
id: "chrissie"
}
];
for (var i = 0; i < cats.length; i++) {
//Building the list . Creating a list item and textnode. The textnode reads out the catnames. Append the textnode to the list. Append all of it to the catlist in the HTML
var catitem = document.createElement("LI");
var textnode = document.createTextNode(cats[i].id);
catitem.appendChild(textnode);
document.getElementById("catlist").appendChild(catitem);
//Adding the catname to the div
var currentcat = cats[i].id;
var currentimage = cats[i].img;
catitem.addEventListener('click', (function(currentimage_copy) {
return function() {
var clicks = 0;
var x = document.createElement("IMG");
x.setAttribute("src", currentimage_copy);
var item = document.getElementById("catimage");
var y = document.getElementById("catimage").childNodes[0];
item.replaceChild(x, y);
x.setAttribute("onclick", (function countClicks(clickscopy) {
return function countClicks() {
clicks++;
console.log(clickscopy);
};
})(clicks));
};
})(currentimage));
}
}
</script>
</body>
</html>
Use addEventListener instead of setAttribute
Try this:
var cats = [{
id: 1,
img: 'https://jsfiddle.net/img/logo.png'
}, {
id: 2,
img: 'https://www.google.co.in/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png'
}, ]
for (var i = 0; i < cats.length; i++) {
//Building the list . Creating a list item and textnode. The textnode reads out the catnames. Append the textnode to the list. Append all of it to the catlist in the HTML
var catitem = document.createElement("LI");
var textnode = document.createTextNode(cats[i].id);
catitem.appendChild(textnode);
document.getElementById("catlist").appendChild(catitem);
//Adding the catname to the div
var currentcat = cats[i].id;
var currentimage = cats[i].img;
catitem.addEventListener('click', (function(currentimage_copy) {
return function() {
var clicks = 0;
var x = document.createElement("IMG");
x.setAttribute("src", currentimage_copy);
var item = document.getElementById("catimage");
var y = document.getElementById("catimage").childNodes[0];
item.replaceChild(x, y);
x.addEventListener("click", (function countClicks(clickscopy) {
return function countClicks() {
clickscopy++;
console.log(clickscopy);
};
})(clicks));
}
})(currentimage))
}
<ul id='catlist'></ul>
<div id='catimage'>
<img src="" alt="">
</div>
Related
I have a small problem trying to create a script that changes the images in the array. The main objective is to show 10 pictures when you click on the button. Clicking on the next button starts mixing all the 10 pictures and not leaving. It should be done without jQuery. Thanks for the advices.
HTML
<button value="show" id="Show">Show Images</button>
<button value="swap" id="Swap" onclick="swapimg()">Swap Images</button>
<div id="image"></div>
<ul>
</ul>
JS
var ul = document.querySelector('ul');
var buttons = document.querySelector('#Show');
buttons.addEventListener('click', add);
var img = ["a.jpg","b.jpg","c.jpg","d.jpg","e.jpg","f.jpg","g.jpg","h.jpg","i.jpg","j.jpg"];
function add() {
for(var i=0; i<10; i++) {
var li = document.createElement('li');
var img1 = document.createElement('img');
img1.src=img[i];
ul.appendChild(li);
li.appendChild(img1);
buttons.style.display = "none";
}
}
function swapimg() {
var myImage1 = new Array();
myImage1[1] = "a.jpg";
myImage1[2] = "b.jpg";
myImage1[3] = "c.jpg";
myImage1[4] = "d.jpg";
myImage1[5] = "e.jpg";
myImage1[6] = "f.jpg";
myImage1[7] = "g.jpg";
myImage1[8] = "h.jpg";
myImage1[9] = "i.jpg";
myImage1[10] = "j.jpg";
var random = Math.floor(Math.random() * myImage1.length);
document.getElementById("image").innerHTML = "<img src='"
+ myImage1[random] + "' alt='image'></img>";
}
You could use a random function that shuffle in every click to gives you a random array that could be used to generate rando images :
function swapimg() {
var random = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].sort(function() {
return .5 - Math.random();
});
ul.innerHTML = "";
for (var i = 0; i < random.length; i++) {
add(random[i]);
}
}
Snippet:
var ul = document.querySelector('ul');
var buttons = document.querySelector('#Show');
buttons.addEventListener('click', addImg);
var img = ["a.jpg", "b.jpg", "c.jpg", "d.jpg", "e.jpg", "f.jpg", "g.jpg", "h.jpg", "i.jpg", "j.jpg"];
function addImg() {
ul.innerHTML = "";
for (var i = 0; i < 10; i++) {
add(i);
}
}
function add(i) {
var li = document.createElement('li');
var img1 = document.createElement('img');
img1.src = img[i];
img1.alt = img[i];
ul.appendChild(li);
li.appendChild(img1);
buttons.style.display = "none";
}
function swapimg() {
var random = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].sort(function() {
return .5 - Math.random();
});
ul.innerHTML = "";
for (var i = 0; i < random.length; i++) {
add(random[i]);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button value="show" id="Show">Show Images</button>
<button value="swap" id="Swap" onclick="swapimg()">Swap Images</button>
<div id="image"></div>
<ul>
</ul>
The problem is that you are not shuffling. With a random number, you could find that you have repeated images. I made something similar a couple of months ago. The following code shuffles a list. Hope it helps:
function shuffle(list) {
if(list.length <= 1) return list;
const first = list.splice(list.length/2);
if(Math.random() > 0.5) return suffle(first).concat(shuffle(list));
else return suffle(list).concat(suffle(first));
}
This code divides the list in half until you got only one element, and then it starts merging it again but with a 50% chance of swaping the given lists.
I am trying to create a new list and add it to the DOM, and then add list items to new list along with text node to each list item.
This is what I have so far, after trying several ways to do this, but still not accomplishing goal. any help is appreciated.The first 4 lines of code is HTML snippet, the code below that is the JavaScript code. Again thank you for any help with this.
<body>
<div id="nav"></div>
<script src="js/script.js"></script>
</body>
var newList = document.createElement("ul");
var newListItem = document.createElement("li");
var stringArray = ["Home","About","Our Services","Contact Us"];
var newUL = document.getElementById("nav").appendChild(newList);
function buildList(){
for( var i = 0; i < stringArray.length; i++){
newUL.appendChild(newListItem);
}
var listItems = document.getElementsByTagName("li");
for( var i = 0; i < listItems.length; i++){
listItems[i].appendChild(stringArray[i]);
}
}
buildList();
Two problems:
You're appending the same li over and over. You need to create a new one for each item.
You can't append a string to a DOM element, but you can set its textContent:
var stringArray = ["Home","About","Our Services","Contact Us"];
function buildList(){
var newList = document.createElement("ul");
var newListItem;
document.getElementById("nav").appendChild(newList);
for( var i = 0; i < stringArray.length; i++){
newListItem = document.createElement('li');
newListItem.textContent = stringArray[i];
newList.appendChild(newListItem);
}
}
buildList();
<div id="nav"></div>
Slightly cleaner version with .forEach():
var stringArray = ["Home","About","Our Services","Contact Us"];
function buildList(){
var newList = document.createElement("ul");
document.getElementById("nav").appendChild(newList);
stringArray.forEach(function (title) {
var newListItem = document.createElement('li');
newListItem.textContent = title;
newList.appendChild(newListItem);
});
}
buildList();
<div id="nav"></div>
You need to create a text node and append it to the <li> element.
var newList = document.createElement("ul");
var stringArray = ["Home","About","Our Services","Contact Us"];
// Create a <ul> element
var newUL = document.getElementById("nav").appendChild(newList);
function buildList(){
for(var i = 0; i < stringArray.length; i++){
// Create a text node
var newTextNode = document.createTextNode(stringArray[i]);
// Create a list element
var newListItem = document.createElement("li");
// Append text node and list item
newListItem.appendChild(newTextNode);
newUL.appendChild(newListItem);
}
}
buildList();
<body>
<div id="nav"></div>
</body>
Just loop over the string array and add lis, like this:
var nav = document.querySelector("nav");
var list = document.createElement("ul");
var items = ["Home","About","Our Services","Contact Us"];
items.forEach(function(item) {
var li = document.createElement("li");
li.innerText = item;
list.appendChild(li);
})
nav.appendChild(list);
Codepen example here
If it's supposed to be a site navigation, you may want to add links. That's easy, too – just append <a> in the loop like this:
var nav = document.querySelector("nav");
var list = document.createElement("ul");
var items = [{
text: "Home",
url: "/home"
}, {
text: "About",
url: "/about"
}, {
text: "Our services",
url: "/services"
}, {
text: "Contact Us",
url: "/contact"
}]
items.forEach(function(item) {
var li = document.createElement("li");
var link = document.createElement("a");
link.innerText = item.text;
link.href = item.url;
li.appendChild(link);
list.appendChild(li);
})
nav.appendChild(list);
Codepen example here
In this case, I would contend that using innerHTML and Array#join is simpler and more readable than other alternatives:
var stringArray = ["Home", "About", "Our Services", "Contact Us"];
function buildList() {
document.getElementById('nav').innerHTML = '<ul><li>' + stringArray.join('</li><li>') + '</li></ul>'
}
buildList()
<nav id="nav"></nav>
how to display element one by one on click using only Javascript, in my example when I click all elements show at once, but i need only one click - one element. I appreciate if you show the simplest way to do if in order to i can understand how it works
$(function() {
var cars = ["audi", "bmw", "volvo"];
var x = "";
var i;
for (i = 0; i <cars.length; i++) {
x += cars[i] + "<br>";
}
document.getElementById("btn").onclick = function() {
document.getElementById("text").innerHTML = x;
}
});
You may update your code as follows. At the very beginnig, your are initializing x with empty string. Then for each click on button, append an element from array with new line tag.
var cars = ["audi", "bmw", "volvo"];
var x = "";
var i = 0;
document.getElementById("btn").onclick = function() {
if( i < cars.length) {
x += cars[i++] + "<br>";
}
document.getElementById("text").innerHTML = x;
}
<p id="text"></p>
<button id="btn">Result</button>
<html>
<script>
var cars = ["audi", "bmw", "volvo"];
var x = "";
var count = 0;
function appendArray(){
if(count<cars.length){
x += cars[count]+ "<br>";
document.getElementById("appendText").innerHTML = x;
count++;
}else{
count = 0;
document.getElementById("appendText").innerHTML = "";
}
}
</script>
<p id="appendText"></p>
<button onclick="appendArray()">Submit</button>
</html>
Here is one solution in vanilla javascript:
var button = document.getElementsByTagName('button')[0];
var i = 0;
function addCar(i) {
var cars = ['audi', 'bmw', 'volvo'];
var paragraph = document.getElementsByTagName('p')[0];
if (i < cars.length) {
var newLine = document.createElement('br');
var newCar = document.createTextNode(cars[i]);
paragraph.appendChild(newLine);
paragraph.appendChild(newCar);
}
}
button.addEventListener('click',function(){addCar(i); i++;},false);
<p></p>
<button>Click for a New Car</button>
So I got multiple divs with different images embedded. Each one has its unique name attributes. I'm trying to apply the hover effect to each divs by changing the image source. I don't want to write multiple scripts, rather I'm trying to write a just one block of script that would effect every div.
<div id="div1" >
<img id="img1" name="img1" src="img1_up.jpg" />
</div>
<div id="div2">
<img id="img2" name="img2" src="img2_up.jpg" />
</div>...and so on
Now here is the script that I currently have for the rollover effects
<script>
var var1 = document.getElementById("div1");
var1.addEventListener("mouseover", changeImage1);
var1.addEventListener("mouseout", restoreImage1);
function changeImage1() {
document.getElementById("img1").src = "img1_ro.jpg";
}
function restoreImage1() {
document.getElementById("img1").src = "img1_up.jpg";
}
var var2 = document.getElementById("div2");
var2.addEventListener("mouseover", changeImage2);
var2.addEventListener("mouseout", restoreImage2);
function changeImage2() {
document.getElementById("img2").src = "img2_ro.jpg";
}
function restoreImage2() {
document.getElementById("img2").src = "img2_up.jpg";
}...and so on
</script>
I would like to use the name attributes from each images to create dynamic code to apply to all images. Here is what I have in mind but not sure the exact way to write it. PLEASE HELP
...
var dynamicVar = ????
dynamicVar.addEventListener("mouseover", changeImage();
dynamicVar.addEventListener("mouseout", restoreImage();
function changeImage() {
document.getElementById(dynamicVar).src = dynamicVar + "_ro.jpg";
}
function restoreImage() {
document.getElementById(dynamicVar).src = dynamicVar + "_up.jpg";
}
You can use loop to add event, don't need to specify id for each div:
var inputs = document.getElementsByTagName("div");
for(var i = 0; i < inputs.length; i++) {
if(inputs[i].id.indexOf('div') >= 0) {
inputs[i].addEventListener("mouseover", changeImage);
inputs[i].addEventListener("mouseout", restoreImage);
}
}
function changeImage(){
var tmpStr = this.id;
var divIndex = tmpStr.substring(3, tmpStr.length);
document.getElementById("img" + divIndex).src = divIndex + "_ro.jpg";
}
function restoreImage(){
var tmpStr = this.id;
var divIndex = tmpStr.substring(3, tmpStr.length);
document.getElementById("img" + divIndex).src = divIndex + "_up.jpg";
}
See on fiddle: Link
try this
var parent = document.getElementById("parent");
var childs = parent.getElementsByTagName('div');
for (var i = 0; i < childs.length; i++) {
(function () {
var e = childs[i];
e.addEventListener("mouseover", function () {
changeImage(e);
});
e.addEventListener("mouseout", function () {
restoreImage(e);
});
}());
}
function changeImage(element) {
var imgs = element.getElementsByTagName('img');
for (var i = 0; i < imgs.length; i++) {
alert(imgs[i].id);
}
}
function restoreImage(element) {
var imgs = element.getElementsByTagName('img');
for (var i = 0; i < imgs.length; i++) {
imgs[i].src = img_ro;
}
}
you can check this fiddle
I have this code below:
for (var index in mv.exifImages) {
var p = document.createElement("p");
var oText = document.createTextNode("link" + index);
p.appendChild(oText);
var info = mv.exifImages[index];
p.onclick = function() {
mv.openNewWindow(info);
};
ele.appendChild(p);
}
I want to create paragraph elements and when I click on them open a new window with correct array content. But I am anable to biuld different links. All my paragraphs open a new window with the array contents at the last index. Is there a trick around this?
I think this should work:
for (var index in mv.exifImages) {
var p = document.createElement("p");
var oText = document.createTextNode("link" + index);
p.setAttribute("indexAttr",index);
p.appendChild(oText);
p.onclick = function() {
mv.openNewWindow(mv.exifImages[this.getAttribute("indexAttr")]);
};
ele.appendChild(p);
}
The following works...
for (var index in mv.exifImages) {
var p = document.createElement("p");
var oText = document.createTextNode("link" + index);
p.appendChild(oText);
var info = mv.exifImages[index];
p.onclick = openNew(info);
ele.appendChild(p);
}
function openNew(a) {
return function() {
mv.openNewWindow(a);
}
}