Function executes only once when using onClick event [javascript] - javascript

I am trying to randomly change background image of a div (#reaction-background) after every click of a button (#angry) with onclick event.
However, the background image only changes once after clicking the button.
HTML:
<div class="btn-list">
<a id="angry">ANGRY</a>
<div id="reaction-background"></div>
Javascript:
// array of pictures
var fileNamesReactions = [
"angry1.jpg",
"angry2.jpg",
"angry3.jpg",
"angry4.jpg",
"angry5.jpg"
];
// random reaction index
var randomIndexReaction = Math.floor(Math.random() * fileNamesReactions.length);
// randomize pictures
document.getElementById("angry").onclick = function() {
document.getElementById("reaction-background").style.background = "url(./img/reactions/angry/" + fileNamesReactions[randomIndexReaction] + ")";
document.getElementById("reaction-background").style.backgroundRepeat = "no-repeat";
document.getElementById("reaction-background").style.backgroundSize = "contain";
}

Your click event handler is, in fact, running every time you click. The problem is that you are only generating a random number once, before any clicks happen and so you set the background image once and further clicks just set the same image over and over.
You need to move the random generator inside of the click callback so that a new random number is generated upon each click.
Also, don't use the onclick property of the element to set up the callback. While this approach works, it's outdated and you should use the more robust and standard .addEventListener() method to set up events.
In addition, do your styling in CSS as much as possible and use CSS classes.
Putting it all together:
// array of pictures
var fileNamesReactions = [
"angry1.jpg",
"angry2.jpg",
"angry3.jpg",
"angry4.jpg",
"angry5.jpg"
];
// Get your DOM references that you'll use repeatedly just once:
let backgroundElement = document.getElementById("reaction-background");
// randomize pictures
document.getElementById("angry").addEventListener("click", function() {
// You have to get a new random each time the click occurs.
var random = Math.floor(Math.random() * fileNamesReactions.length);
backgroundElement.style.background = "url(./img/reactions/angry/" + fileNamesReactions[random] + ")";
console.log(backgroundElement.style.background);
});
/* Use CSS classes as much as possible as they make code much simpler */
#reaction-background {
background-size:"contain";
background-repeat:"no-repeat";
}
<div class="btn-list">
<a id="angry">ANGRY</a>
<div id="reaction-background"></div>
</div>

Move the random number statement inside the onclick method so that it generate a new number on every click. Please find code below:
// array of pictures
var fileNamesReactions = [
"angry1.jpg",
"angry2.jpg",
"angry3.jpg",
"angry4.jpg",
"angry5.jpg"
];
// randomize pictures
document.getElementById("angry").onclick = function() {
// random reaction index
var randomIndexReaction = Math.floor(Math.random() * fileNamesReactions.length);
document.getElementById("reaction-background").style.background = "url(./img/reactions/angry/" + fileNamesReactions[randomIndexReaction] + ")";
document.getElementById("reaction-background").style.backgroundRepeat = "no-repeat";
document.getElementById("reaction-background").style.backgroundSize = "contain";
}

Related

Prevent createElement from creating multiple identical images

I am going to try and be as thorough as possible on this so stick with me.
My program takes user input entered on a form. This input goes through a range of if statements that will set variables to true, these variables that are set to true will then use createElement to create img inside predetermined divs. There will always be at least one img created, and up to 4 imgs at the most. This is all completed by a button click.
I learned createElement will continuously createElement with each button click posting the img right next to the original img and will do this infinitely or until the page is reloaded.
My solution was to create a counter that incremented each time the button was clicked. That took care of any extra createElements. Then I thought if the user first entered a large number that will create 2 separate and individual images say... image 1 and image 2 (which is desired), then if the user enters a lower number that only creates image 1, then image 2 would still be posted (unwanted). Of course a page refresh would clear the images created and avoid this.
So I'm not quite sure what to do...
Ideally when the button is pressed a second time then all old createElements would be cleared, and all new createElements would populate.
I removed the counter for the purpose of this question
poster__#'s are the called id's...
const movieTime = 30;
var userTimeAvailable = 25;
const button = document.getElementById("calculate");
button.onclick = function calculateTime() {
if (userTimeAvailable < movieTime) {
console.log(
"You have enough time to watch " +
Math.round((userTimeAvailable / movieTime) * 100) +
"% of the movie."
);
displayMoviePoster1 = true;
}
moviePosterGenerator();
}
function moviePosterGenerator() {
if (displayMoviePoster1 === true) {
var par = document.getElementById("poster__2");
var theatricalMoviePoster = document.createElement("img");
theatricalMoviePoster.src = "imgURL";
par.appendChild(theatricalMoviePoster);
}
}
<button class="button" id="calculate">calculate</button>
<div class="movie-poster__container" id="posters">
<div class="movie-poster" id="poster__1"></div>
<div class="movie-poster" id="poster__2"></div>
<div class="movie-poster" id="poster__3"></div>
<div class="movie-poster" id="poster__4"></div>
</div>

javascript value is not updating after onmousevent

I use 1 span tag at the moment.
<span onmouseover="numberOne()" onclick="imgNumber(); return false" onmouseout="noHoverOne()" class="img1 img" id="new-img"> </span>
The span has a "deafult" image, when the mouse goes on the span, another image will be shown, when the mouse leaves the span, the default image will be shown again.
now the javascript:
function numberOne() {
var random2 = Math.floor((Math.random() * 3) + 1);
var random3 = Math.floor((Math.random() * 3) + 1);
do {
var random = Math.floor((Math.random() * 3) + 1);
} while (random === numberOne.last);
numberOne.last = random;
Random numbers are made here. So every time you leave the span and go on the span, there will be a different image.
if (random == 2) {
document.getElementById('new-img').style = "background-image: url('http://web-stars.nl/molgeld.jpg');";
} else if ((random==random2)==random3) {
document.getElementById('new-img').style = "background-image: url('http://web-stars.nl/vrijstelling.jpg');";
} else {
document.getElementById('new-img').style = "background-image: url('http://web-stars.nl/haspel.jpg');";
}
These are the images that will be shown depending on the number
return random;
}
var value = numberOne();
function imgNumber() {
document.getElementById('demo').innerHTML = value;
}
imgNumber();
This is where I am stuck. Before I even have touched the span tag with my mouse, there is already a random number and when I go with the mouse on the span tag, it shows a different image but not a different number. I want to use this number somehow to create a new level for my game. The game is influenced by the chosen image.
So there is a lot going on and it's pretty messy. So please, I would love to hear any kind of constructive feedback.
[EDIT] I will keep the JSfiddle up to date, but there is an error in the preview, it won't display anything. It's still useful Jsfiddle
use a wrapper function where you can call both imgNumber and numberOne
function mouseHover() {
var value = numberOne()
imgNumber(value)
}
function imgNumber(value) {
document.getElementById('demo').innerHTML = value;
}
<span onmouseover="mouseHover()" onclick="imgNumber(); return false" onmouseout="noHoverOne()" class="img1 img" id="new-img"> </span>
Your code is a bit illogical. It seems you want to randomly assign an image to an element background and get a different element each time. So put the image URLs in an array and randomly grab one, ensuring it's different to the last. This means you can add or reduce the images you want to display just by modifying the images array.
Also put all your data in an object rather than using globals, it's just neater. And give your functions names that tell you what they do.
E.g.
var imageData = {
pix: ['http://web-stars.nl/molgeld.jpg',
'http://web-stars.nl/vrijstelling.jpg',
'http://web-stars.nl/haspel.jpg'
],
random: null
}
function changeImage(el) {
// limit do loop just in case data is bad
// Infinite loops are bad...
var len = imageData.pix.length;
var i = len;
do {
var random = Math.random() * len | 0;
} while (i-- && imageData.random == random)
imageData.random = random;
el.style.backgroundImage = imageData.pix[random];
console.log(random, imageData.pix[random]);
}
function updateImageRef() {
document.getElementById('imageRef').textContent = imageData.random;
}
<div id="imageDiv" onmouseover="changeImage(this)" onclick="updateImageRef()">Image div</div>
<div id="imageRef"><div>

Javascript memory card game last card not flipping

Hi I have a memory game that has a demo here.
https://kuochye.github.io/memorygame/
I have a issue with the last card not flipping over and can't figure out why.
document.querySelectorAll(".flip-container").forEach(card => card.classList.add("clicked"));
setTimeout(function () {
document.querySelectorAll(".flip-container").forEach(card =>
card.classList.remove("clicked"));
}, 30000);
^ This was what I did to show the cards for 30 secs before it flips down. But somehow the last card is not showing.
// Build single card
var buildCardNode = function (index, value, isRevealed, width, height) {
var flipContainer = document.createElement("li");
var flipper = document.createElement("div");
var front = document.createElement("a");
var back = document.createElement("a");
flipContainer.index = index;
flipContainer.style.width = width;
flipContainer.style.height = height;
flipContainer.classList.add("flip-container");
if (isRevealed) {
flipContainer.classList.add("clicked");
}
flipper.classList.add("flipper");
front.classList.add("front");
front.setAttribute("href", "#");
back.classList.add("back");
back.classList.add("card-" + value);
back.setAttribute("href", "#");
flipper.appendChild(front);
flipper.appendChild(back);
flipContainer.appendChild(flipper);
flipContainer.addEventListener('click', handleFlipCard);
document.querySelectorAll(".flip-container").forEach(card => card.classList.add("clicked"));
setTimeout(function () {
document.querySelectorAll(".flip-container").forEach(card =>
card.classList.remove("clicked"));
}, 30000);
return flipContainer;
};
What you're doing is looking for every card that has already been added and flipping it. That would be fine, but you're doing it before adding each card to the document. So for each card added it finds every card added previously and flips it.
You want to be doing one of two things instead:
a. Flip all cards after they have been added to the document (by moving that first piece of code out of buildCardNode function to where it is called from).
b. Flip each card directly before it is added to the document (instead of using document.querySelectorAll.forEach, you use flipContainer.classList.add/remove).

Show / Hide images randomly using jQuery

I want to create a function that grabs all the instances of an image class on the page. As default these will be hidden, then randomly after a certain interval show one of those images (can be any image). Then the function will rerun and show another image. (whilst hiding the image that was shown on the first run through.
I've got to this stage with the function (not currently working)
(function randomShow() {
var showDiv = $('.show'),
el = showDiv.eq(Math.floor(Math.random() * showDiv.length));
el.show().delay(2000).show(randomShow);
})();
Thanks
I put together a jsFiddle using divs in place of images to demonstrate (pure js):
http://jsfiddle.net/oogley_boogley/az9gd8wf/
the script:
var divs = document.getElementsByClassName('square');
var arrLength = divs.length;
var randomNumberLimit;
var interval_speed = 1000;
setInterval(function(){
randomNumberLimit = Math.floor((Math.random() * arrLength) + 1);
for(i=0;i<arrLength;i++){
var matchingDiv = divs[i];
if(matchingDiv.id == randomNumberLimit){
matchingDiv.setAttribute("class","showing square blue");
}
if(matchingDiv.id != randomNumberLimit){
matchingDiv.setAttribute("class","hiding square blue");
}
}
}, interval_speed);

choose image in array and continue

First time JavaScript coder here.
Trying to solve this so that an image is displayed when the appropriate button for that image is clicked and then the function continues to show the other image in the Array and loops.
For instance if the banner is displaying image 4 and the user clicks on the button for image 2, then the banner should display image 2 and then rotate to show image 3 and continue looping.
Here is the code:
var i = 0;
var baners = new Array();
baners.push('banner1.jpg');
baners.push('banner2.jpg');
baners.push('banner3.jpg');
baners.push('banner4.jpg');
baners.push('banner5.jpg');
function swapImage(){
var img = document.getElementById("banner");
img.src = baners[i];
if (i<(baners.length-1)){i++;
}else{
i=0;
}
setTimeout('swapImage()', 2000);
}
function button1 (){
var img = document.getElementById("banner");
img.src = baners[0]
}
I am unsure if it is possible to make one global function for the 5 buttons.
Thank you!
I am unsure if it is possible to make one global function for the 5 buttons.
Yes. Use something like this:
function buttonClicked(number) {
var img = document.getElementById("banner");
img.src = baners[number]
i = number; // set current loop position
}
then call buttonClicked(0) from button1, buttonClicked(1) from button2 and so on. If you want to automatically attach the handlers to the button using a for-loop, check out JavaScript closure inside loops – simple practical example.

Categories

Resources