Change the image with JS every time the button is clicked - javascript

I am trying to implement the following:
Change the image every time i click the button "next".
Right now the code gives me the very last image from the array book just after I click the button next once. Is there a way it can be done?
HTML code:
<body>
<div class="main_page">
<button type="button" id="start">Start</button>
<button type="button" id="next">Next</button>
</div>
</body>
JS code:
document.addEventListener('DOMContentLoaded', () => {
let book = [
{
name: 'page1',
img: 'img/page1.png'
},
{
name: 'page2',
img: 'img/page2.png'
},
{
name: 'page3',
img: 'img/page3.png'
}
]
const main_page = document.querySelector('.main_page');// with this variable I have conttrol of
// div with class .main_page
let mainImg = document.createElement('img') // similar to HTML tag <img>. this var-ble creates <img> tag in HTML Document
mainImg.setAttribute('src', book[0].img) // making attribute to <img> tag through JavaScript
main_page.appendChild(mainImg);// appending <img> tag to the div with class main_page
let next = document.getElementById('next');
const turnPage = (count) =>{
//if(mainImg.getAttribute("src") == 'img/page2.png') alert("hey")//mainImg.src = {firstpage}
next.addEventListener('click', () => {
if(mainImg.getAttribute("src") == book[count].img){
//alert("hey")
mainImg.src = book[count+1].img
}})
}
for(let i = 0; i< book.length; i++){
turnPage(i);
}
})

You have a few problems with your code, as others have pointed out. As Teemu said, you are adding 3 click listeners to the button. You also need to put the turn page function into your listener, instead of calling it outside. These are the main changes you need:
1: You need to declare a variable outside of the listeners and any loops to keep count of the pages
let count = 0;
2: Add a listener that will call your turnpage function on each click. In that listener, you need to check that the next page isn't greater than the total number of pages before calling turnPage- otherwise you will get an error when the code tries to access the image from a non-existent page.
(You could instead start again at page 1, but as you have a Start button I assumed that you will intend to use that instead of having a continuous loop).
next.addEventListener('click', () => {
if ((count+1) < book.length)
turnPage(count);
count++;
})
3: Finally, your turnPage function just needs to set up the next image
const turnPage = (count) => {
mainImg.src = book[count + 1].img
}
Here is the full working snippet:
document.addEventListener('DOMContentLoaded', () => {
let book = [{
name: 'page1',
img: 'https://lorempixel.com/output/animals-q-c-200-200-9.jpg'
},
{
name: 'page2',
img: 'https://lorempixel.com/output/animals-q-c-200-200-10.jpg'
},
{
name: 'page3',
img: 'https://lorempixel.com/output/animals-q-c-200-200-4.jpg'
}
]
const main_page = document.querySelector('.main_page'); // with this variable I have conttrol of
// div with class .main_page
let mainImg = document.createElement('img') // similar to HTML tag <img>. this var-ble creates <img> tag in HTML Document
mainImg.setAttribute('src', book[0].img) // making attribute to <img> tag through JavaScript
main_page.appendChild(mainImg); // appending <img> tag to the div with class main_page
let next = document.getElementById('next');
// set up your listener to turn the page on each click
next.addEventListener('click', () => {
let count = 0; // declare your variable for page count
// check if the next page is greater than the total number of pages
if ((count+1) < book.length)
turnPage(count);
count++;
})
// your turnPage function
const turnPage = (count) => {
if (mainImg.getAttribute("src") == book[count].img) {
mainImg.src = book[count + 1].img
}
}
})
<body>
<div class="main_page">
<button type="button" id="start">Start</button>
<button type="button" id="next">Next</button>
</div>
</body>
FYI I'm not sure what this line is for, but I've left it in, in case you need it for something you haven't included here:
if (mainImg.getAttribute("src") == book[count].img) {
Also, you could just use the count variable in your pageTurn without passing it in in the click listener. You could check if you are the the end in there - it all depends on how this fits in with the rest of what you need to do.

What Teemu said in the comments is right. I can't comment as my reputation is low. So providing the code here. Just remove turnPage function definition and for loop. And replace it with the code below.
let count = 0, len = book.length;
next.addEventListener('click', () => {
if(mainImg.getAttribute("src") == book[count].img){
count = (count + 1) % len;
mainImg.src = book[count].img
}
});

You can use array to store your image and then display it in your codes
But you also have to make sure you use <img src=""> tag
Example
<img src="" id="myImage">
<br />
<button type="button" id="next">Next</button>
//JavaScript Codes
//Get HTML Elements
let images = [];
let img = document.querySelector("#myImage");
let button = document.querySelector("#next");
let defaultIndex = 0;
//Make a function to be executed once you click the button
function makeIt() {
//Make sure defaultIndex won't be above your array
if (defaultIndex < images.length) {
//Then go to the next image using incrementation
defaultIndex += 1;
//Assign your new value to the img tag
img.src = images[defaultIndex];
}
You can even make previous feature by using decrement.
I hope this will help you. If you find any mistake, feel free to correct!

Related

Between Page Navigation in Javascript

This is what I've tried, is there a better way of doing it? if so please LMK. Thanks :).
There's a div inside my HTML with an Id of 'content'. Each button have an eventListener and when clicked the eventListener checks the button's dataset and passes it through a dictionary and whatever value they get back will be the page the display inside 'content'.
HTML:
<body>
<div class="content"></div>
</body>
Javascript:
const content = document.querySelector(".content");
const pageOne = `This is page one of the three pages. <button id="next" onclick="showNextPage()" data-next="pageThree">Show Next Page</button> <button id="prev" data-prev="pageOne">Show Previous Page</button>`;
const pageTwo = `Behold the second page of the three pages. <button id="next" onclick="showNextPage()" data-next="pageThree"> Show Next Page</button><button id="prev" data-prev="pageOne">Show Previous Page</button>`;
const pageThree = `Finally the last page, page three of the three pages. <button id="next" onclick="showNextPage()" data-next="pageOne"> Show Next Page</button><button id="prev" data-prev="pageTwo">Show Previous Page</button>`;
content.innerHTML = pageOne;
const dict = {
"pageOne": pageOne,
"pageTwo": pageTwo,
"pageThree": pageThree,
}
function showNextPage() {
let button = document.getElementById("next");
content.innerHTML = dict[button.dataset.next];
}
function showPrevPage() {
let button = document.getElementById("prev");
content.innerHTML = dict[button.dataset.prev];
}
You can try solving the pagination with the counter variable,
and additional function for checking if the buttons should be disabled.
Also rewrite object to an array of objects, for easier accessing current page's content.
When it comes to templating as you wrote, consider using also maybe Handlebars or similar.
I played a bit to help you, if needed:
const content = document.querySelector(".content");
const next = document.querySelector("#next");
const prev = document.querySelector("#prev");
let counter = 0;
const dict = [{
contentText: "This is page one of the three pages."
},
{
contentText: "Behold the second page of the three pages"
},
{
contentText: "Finally the last page, page three of the three pages."
}
]
function showNextPage() {
counter += 1;
check()
}
function showPrevPage() {
counter -= 1;
check()
}
function check() {
// sets new html content
content.innerHTML = dict[counter].contentText
// disabling buttons
if (counter == 0) {
prev.disabled = true;
} else if (counter == 2) {
next.disabled = true;
} else {
next.disabled = false;
prev.disabled = false;
}
}
<body>
<div class="content">
This is page one of the three pages.
</div>
<button id="prev" disabled="true" onclick="showPrevPage()">Show Previous Page</button>
<button id="next" onclick="showNextPage()">Show Next Page</button>
</body>

Can I save a random generated var so I can call the result back later in javascript

I'm working on a project where I generate a random var to create random scenes. One of them is location. I want it to be possible to generate a location with one button. Then press another button to generate a new location and when I press on the first button I want to get back the generated location I generated with that button
The function I generate the location with looks like this
function inhoudFunction()
{
var locs = ["movie", "park", "garden", "home"];
var loc = locs[Math.floor(Math.random()*locs.length)];
document.getElementById('inhoud').innerHTML="<h2>Locatie</h2>" + loc;
And these are the buttons I use to run the codes
<button type="button" onclick="introFunction()">intro</button>
<button type="button" onclick="midFunction()">mid</button>
To know if the button was pressed twice I used this code
function introFunction(){
if (introClicked == 1){
document.getElementById('introClicked').innerHTML="<div id=inhoud></div>";
}
else{
document.getElementById('introClicked').innerHTML="<div id=inhoud></div>";
inhoudFunction();
introClickedFunction();
}
And introClicked gets updated with this function
var introClicked = 0;
function introClickedFunction(){
introClicked = introClicked + 1;
}
But once I press the button twice I get nothing back
Save the generated value directly as a custom field of your <button> element.
In the example below, the element is passed to the click handler function as event.target. The function reads the gen_locations field. If it's not set, then it generates the random value and sets it.
window.addEventListener('DOMContentLoaded', _e => {
const locs = ["movie", "park", "garden", "home"];
document.getElementById('inhoud-button1').addEventListener('click', inhoudFunction);
document.getElementById('inhoud-button2').addEventListener('click', inhoudFunction);
function inhoudFunction(event) {
let genlocs = event.target.gen_locations;
if (!genlocs) {
genlocs = []
for (let i = 0; i < 2; i++) {
genlocs.push( locs[Math.floor(Math.random() * locs.length)] );
event.target.gen_locations = genlocs;
}
}
document.getElementById('inhoud').innerHTML = "<h2>Locatie</h2>" + JSON.stringify(genlocs);
}
});
<div id="inhoud"></div>
<button id="inhoud-button1">Inhound 1</button>
<button id="inhoud-button2">Inhound 2</button>
I've cleaned the code by avoiding inline javascript event handlers. Those are bad! :)
Edit: improved to show storing 2 generated randoms at once per button

Check if html tag contains text node

I have a popup modal in Shopify, I'm using text node instead of innerHtml for security concerns. However, everytime I open the popup modal, the text node keeps getting appended to my h1 tag. Is there any way to check if the node already has been appended? (I don't want to use a boolean value to check if text node has been appended)
html:
<h1 id="ProductHeading" class="product__title product__title--template"></h1>
<h2 id="ProductHeadingModal" class="product__title product__title--template product__title--modal"></h2>
javascript:
var title = document.createTextNode(product.title);
// Product heading is an element with h1 tag
var productHeading = document.getElementById("ProductHeading");
if(// how to check if element has no node?) {
productHeading.appendChild(title);
}
the entire javascript block:
window.onload = () => {
if (window.__shgProductInits.length) {
window.__shgProductInits.forEach((ele) => {
let proId = document.getElementById(ele.uuid);
proId.setAttribute('url', ele.productHandle);
proId.style.cursor='pointer';
proId.addEventListener('click', (e) => {
let productHandle = e.target.parentElement.parentElement.parentElement.getAttribute('url');
fetch('/products/'+productHandle+'.js')
.then((res) =>{return res.json()})
.then((product) => {
console.log(product)
var product = product;
document.getElementsByClassName("product-modal")[0].style.display = "block";
var title = document.createTextNode(product.title);
var productHeading = document.getElementById("ProductHeading");
var productHeadingModal = document.getElementById("ProductHeadingModal");
if(!(productHeading.hasChildNodes())) {
productHeading.appendChild(title);
productHeadingModal.appendChild(title);
var price = document.createTextNode("$" + parseInt(product.price).toFixed(2));
document.getElementById("product-price").appendChild(price);
}
document.getElementById("product-image").src = product.images[0];
});
});
});
}
ProductHeading itself is not a node (I think). And checking innerHtml for length doesn't work as it is always 0
Update:
I've added the conditional check, it still returns false everytime I open the modal.
My code:
My browser console:
My website displays:
Inspect element in browser:
A couple of ways:
if (element.firstChild) {
// It has at least one
}
or the hasChildNodes() function:
if (element.hasChildNodes()) {
// It has at least one
}
or the length property of childNodes:
if (element.childNodes.length > 0) { // Or just `if (element.childNodes.length)`
// It has at least one
}
So you can just write this
var title = document.createTextNode(product.title);
// Product heading is an element with h1 tag
var productHeading = document.getElementById("ProductHeading");
if(!(productHeading.hasChildNodes())) {
productHeading.appendChild(title);
}
Referring this answer
if (productHeading.hasChildNodes()) {
}

Function doesn't work when called with addEventListener or onclick, doesn't show up any error msg

I wrote an easy function that should swap between 2 images, this function should fires when clicking on a button but nothing happens on click.
I've tried both addEventListener and onclick method but none in working.
<img id="avatar" src="dog1.jpg" alt="avatar">
<button id="button">change dog</button>
function changeDog() {
var dog = document.getElementById('avatar').scr;
if (dog == "dog1.jpg" ) {
document.getElementById('avatar').scr = "dog2.jpg";
}
else {
document.getElementById('avatar').src = "dog1.jpg";
}
}
var button = document.getElementById('button');
button.addEventListener=('click', changeDog);
I expect that clicking on the button the image with id='avatar' will change source from "dog1.jpg" to "dog2.jpg" and viceversa, but absolutely nothing happens. No error msg is showed. I suspect it may be a dumb mistake cause I'm unexperienced, but I'm struck on this. Thank you all for any help.
You have a few typos in your code. See below
function changeDog() {
var dog = document.getElementById('avatar');
if (dog.src === "dog1.jpg" ) {
dog.src = "dog2.jpg";
}
else {
dog.src = "dog1.jpg";
}
}
var button = document.getElementById('button');
button.addEventListener('click', changeDog);
<img id="avatar" src="dog1.jpg" alt="avatar">
<button id="button">change dog</button>
Also you should decide reading about comparision (using === instead of ==):
https://www.w3schools.com/js/js_comparisons.asp
There are multiple errors in your code. For example, you have written src on some places, and scr on other. Also, you repeat the part of the code again and again.
// Array with all dogs. Makes it easier to add more dogs.
const dogs = [ "dog1.jpg", "dog2.jpg" ];
function changeDog() {
// Get the avatar element
const avatar = document.getElementById('avatar');
// Get current name. Note that the broswer probably have added
// the full url to the image. I use split to break up the string
// in an array, and then use slice(-1) to get the last item
// and then [0] to get the element.
const dog = avatar.src.split('/').slice(-1)[0];
// get the index of the dog
const index = dogs.indexOf( dog );
// set the new src, from the dogs array, with the index + 1;
// If index + 1 is larger than the length of the dogs-array
// the % (remainder-operator) will make sure that the index
// wraps around to 0, so we get the next name.
avatar.src = dogs[ ( index + 1 ) % dogs.length ];
console.log( avatar.src );
}
var button = document.getElementById('button');
button.addEventListener('click', changeDog);
<img id="avatar" src="dog1.jpg" alt="avatar">
<button id="button">change dog</button>
function changeDog() {
const dog = document.getElementById('avatar');
const imgSrc = dog.src === "dog1.jpg" ? "dog2.jpg" : dog.src;
dog.src = imgSrc;
}
const button = document.getElementById('button');
button.addEventListener('click', changeDog);
<img id="avatar" src="dog1.jpg" alt="avatar">
<button id="button">change dog</button>
function changeDog() {
// you create a constant for document.getElementById().src, so do not need it every line
const dog = document.getElementById('avatar').src;
if (dog === "dog1.jpg" ) {
dog = "dog2.jpg";
}
else {
dog = "dog1.jpg";
}
}
const button= document.getElementById("button");
button.addEventListener("click", () => {
changeDog();
}
Updated from var to let/const (new standard), changed your rough equate to an absolute and created a direct call toward the event listener, the call method I have used allows you to perform additional actions after changeDog() also if you so wish. Your original code had a few issues which prevented it from actually running.

How do I replace an item in an array with one that isn't in said array?

So I want to have one of the images in the array change to a question mark. Here's what I have so far.
var icons = new Array ();
icons [0] = { html: "Animals/Ape.png" };
icons [1] = { html: "Animals/Bat.png" };
icons [2] = { html: "Animals/Cow.png" };
icons [3] = { html: "Animals/Emu.png" };
icons [4] = { html: "Animals/Pig.png" };
icons [5] = { html: "Animals/Dog.png" };
icons [6] = { html: "Animals/Rat.png" };
icons [7] = { html: "Animals/Yak.png" };
icons [8] = { html: "Animals/Cat.png" };
function showBack()
{
document.getElementById('table').style.display = "none";
document.getElementById('tableblank').style.display = "block";
icons[0]="Animals/Q.png";
setTimeout(showFront,3000);
}
function showFront()
{
document.getElementById('table').style.display = "block";
document.getElementById('tableblank').style.display = "none";
document.getElementById('speech').style.display = "block";
document.getElementById('typewindow').style.display = "block";
}
I've tried a couple of solutions but I haven't been able to make any work. Thanks for the help :)
if you want to re-assign this object you may do it like that :
icons[0].html = "Animals/Q.png";
I would do something like this...
var icons = [ "Animals/Ape.png",
"Animals/Bat.png",
"Animals/Cow.png" ];
icons[1] = "Animals/Q.png";
document.write(icons[1]);
or if you want to keep an the url as an object...
var oIcons = [{ html:"Animals/Ape.png" },
{html:"Animals/Bat.png"},
{html:"Animals/Cow.png"}];
oIcons[2].html = "Animals/Q.png";
document.write(oIcons[2].html);
So basicly on show back you should have...
icons[0].html="Animals/Q.png";
Considering the code you posted in your comment:
<div id="containerGameplay">
<div id = "table">
<script>
for (i = 0; i < 9 ; i++) {
document.write ("<div class = 'tile'><img src='" + icons[i].html+ "'></div>");
}
</script>
</div>
You are running inline code on your page, which is executed as soon as the browser loads it. To change an image later, you'll need to create a reference to the element you want to change. The easiest way to do this is to give your elements IDs, which would change your code like so:
document.write("<div class='title'><img id='icon_" + i + "' src='" + icons[i].html+ "'></div>");
This will result in the first image (icon[0]) being applied to the element with the ID "icon_0", and so on for each image.
Later, when you want to change an image, you can get a reference to the correct element, and then change the src to that element:
elem = document.getElementById('icon_0');
elem.src = "Animals/Q.png";
Or, following what I believe you were trying to do originally, you can change the array, then set the new source (src):
icons[0].html = "Animals/Q.png";
document.getElementById('icon_0').src = icons[0].html;
They're both the same, but the second example is also storing the value in your array. Keep in mind that there is no automatic data-binding, so simply changing the array does not automatically update the image element.

Categories

Resources