javascript value is not updating after onmousevent - javascript

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>

Related

Function executes only once when using onClick event [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";
}

Assigning string to div value from javascript function across pages

I have a web app that outputs the results of a function as a double. The function compares two text documents and returns the percentage indicating the percentage of similarity between the two documents. When the user clicks a Compare button, the function runs and takes the user from the compare.jsp page to the results.jsp page, and displays a loading-bar that is filled in like so:
<div id="levenshtein-distance"
class="ldBar label-center levenshtein-distance"
data-preset="fan"
data-value="${result.percentage}"
data-stroke="">
</div>
This works fine, the fan bar gets the correct percentage. However, I am also trying to color the fan bar using the data-stroke value based on this percentage. I have a simple javascript function to do this, but can't figure out how to pass the value. I've tried running the function in the body tag of the results.jsp page using "onload", but this doesn't work. Here is my JavaScript function:
function barSetLD(percent) {
var red = "red";
var green = "green";
var orange = "orange";
var elem = document.getElementById("levenshtein-distance");
if (percent <= 40.00) {
elem.setAttribute("data-stroke", green);
} else if (percent > 40.00 && percent <= 70.00) {
elem.setAttribute("data-stroke", orange);
} else {
elem.setAttribute("data-stroke", red);
}
}
I've done quite a bit of searching and can't seem to find an example that helped me solve this. Any help is very much appreciated.
////Update:
Trinh, that worked to change the color, thanks! My problem now is that I do, in fact, have multiple 'levenshtein-distance' ids and I am looping through them. So currently everything is being set to the same color. I should have mentioned this initially, sorry. I am comparing multiple pairs of files and outputting the loading-bar for each pair. If you have some idea about how to resolve the looping issue, that would be great, but thanks for the original solution either way! I updated my javascript function as follows:
function barSetLD(percent) {
var red = "red";
var green = "green";
var orange = "orange";
var elem = document.querySelectorAll("[id^=levenshtein-distance]");
for (var i in elem) {
if (percent <= 40.00) {
elem[i].setAttribute("data-stroke", green);
} else if (percent > 40.00 && percent <= 70.00) {
elem[i].setAttribute("data-stroke", orange);
} else {
elem[i].setAttribute("data-stroke", red);
}
}
}
And the full bit of code with the html loop is, and I am now calling the barSetLD(percent) at the very bottom of the page as you suggested:
<c:forEach items="${studentResults}" var="result" varStatus="loop">
<div id="levenshtein-distance"
class="ldBar label-center levenshtein-distance"
data-preset="fan"
data-value="${result.percentage}">
</div>
</c:forEach>
<script type="text/javascript">
barSetLD("${result.percentage}");
</script>
Put your code at the very bottom of the page where all DOM has been loaded. Or at least make sure <div id="levenshtein-distance"/> exist and fully loaded before calling this document.getElementById("levenshtein-distance");. Also double check if you have multiple levenshtein-distance id...

Creating a class based JS instead of id

So I have created this javascript that animates a certain place using it's ID.
The problem is that there are many of those on the site and meaning this I'd have to duplicate this function a lot of times just to replace the x in getElementById("x").
So here is the code I fully done by myself:
var popcount = 0;
var opanumber = 1;
var poptimeout;
function pop() {
if (popcount < 10) {
popcount++;
if (opanumber == 1) {
document.getElementById("nav1").style.opacity = 0;
opanumber = 0;
poptimeout = setTimeout("pop()", 50);
}
else {
document.getElementById("nav1").style.opacity = 1;
opanumber = 1;
poptimeout = setTimeout("pop()", 50);
}
}
else {
popcount = 0;
document.getElementById("nav1").style.opacity = 1;
}
}
function stoppop() {
clearTimeout(poptimeout);
popcount = 0;
document.getElementById("nav1").style.opacity = 1;
}
I would gladly appreciate any information on how I could solve this situation and also any tutorials about using classes and "this".
Something like this; rather than hard code a value into a function it is better to pass the value in so you can reuse the function on more than one thing. In this case you can now call startPop and stopPop with the name of a CSS class.
var popTimeout;
function setOpacity(className, value) {
Array.prototype.forEach.call(
document.getElementsByClassName(className),
function(el) {
el.style.opacity = value;
}
);
}
function pop(className, popCount, opaNumber) {
if (popCount < 10) { //Must be even number so you end on opacity = 1
setOpacity(className, opaNumber);
popTimeout = setTimeout(function() {
pop(className, popCount++, 1-opaNumber);
}, 50);
}
}
function startPop(className) {
pop(className, 0, 0);
}
function stopPop(className) {
clearTimeout(popTimeout);
setOpacity(className, 1);
}
In case you are wondering about the 1 - opaNumber; this is a simpler way of switching a value between 1 and 0. As 1-1=0 and 1-0=1.
Well you started out with recognizing where you have the problem and that's already a good thing :)
To make your code a bit more compact, and get as many things as possible out of the local scope, you could check the following implementation.
It is in a sense a small demo, where I tried adding as much comments as possible.
I edited a bit more after realizing you rather want to use classnames instead of id's :) As a result, I am now rather using the document.querySelectorAll that gives you a bit more freedom.
Now you can call the startPop function with any valid selector. If you want to pop purely on ID, you can use:
startPop('#elementId');
or if you want to go for classes
startPop('.className');
The example itself also add's another function, nl trigger, that shows how you can start / stop the functions.
I also opted to rather use the setInterval method instead of the setTimeout method. Both callback a function after a certain amount of milliseconds, however setInterval you only have to call once.
As an extra change, stopPop also now uses the document.querySelectorAll so you have the same freedom in calling it as the startPop function.
I added 2 more optional parameters in the startPop function, namely total and callback.
Total indicates the maximum times you wish to "blink" the element(s), and the callback provides you with a way to get notified when the popping is over (eg: to update potential elements that started the popping)
I changed it a bit more to allow you to use it for hovering over an element by using the this syntax for inline javascript
'use strict';
function getElements( className ) {
// if it is a string, assume it's a selector like #id or .className
// if not, assume it's an element
return typeof className === "string" ? document.querySelectorAll( className ) : [className];
}
function startPop(className, total, callback) {
// get the element once, and asign a value
var elements = getElements( className ),
current = 0;
var interval = setInterval(function() {
var opacity = ++current % 2;
// (increase current and set style to the left over part after dividing by 2)
elements.forEach(function(elem) { elem.style.opacity = opacity } );
// check if the current value is larger than the total or 10 as a fallback
if (current > (total || 10)) {
// stops the current interval
stopPop(interval, className);
// notifies that the popping is finished (if you add a callback function)
callback && callback();
}
}, 50);
// return the interval so it can be saved and removed at a later time
return interval;
}
function stopPop(interval, className) {
// clear the interval
clearInterval(interval);
// set the opacity to 1 just to be sure ;)
getElements( className ).forEach(function(elem) {
elem.style.opacity = 1;
});
}
function trigger(eventSource, className, maximum) {
// get the source of the click event ( the clicked button )
var source = eventSource.target;
// in case the attribute is there
if (!source.getAttribute('current-interval')) {
// start it & save the current interval
source.setAttribute('current-interval', startPop(className, maximum, function() {
// completed popping ( set the text correct and remove the interval )
source.removeAttribute('current-interval');
source.innerText = 'Start ' + source.innerText.split(' ')[1];
}));
// change the text of the button
source.innerText = 'Stop ' + source.innerText.split(' ')[1];
} else {
// stop it
stopPop(source.getAttribute('current-interval'), className);
// remove the current interval
source.removeAttribute('current-interval');
// reset the text of the button
source.innerText = 'Start ' + source.innerText.split(' ')[1];
}
}
<div class="nav1">
test navigation
</div>
<div class="nav2">
Second nav
</div>
<div class="nav1">
second test navigation
</div>
<div class="nav2">
Second second nav
</div>
<a id="navigation-element-1"
onmouseover="this.interval = startPop( this )"
onmouseout="stopPop( this.interval, this )">Hover me to blink</a>
<button type="button" onclick="trigger( event, '.nav1', 100)">
Start nav1
</button>
<button type="button" onclick="trigger( event, '.nav2', 100)">
Start nav2
</button>
If you do want to take it back to using IDs, then you will need to think about popTimeout if you run this on more than one element at a time.
function setOpacity(id, value) {
document.getElementById(id).style.opacity = value;
}
function runPop(id) {
function pop(id, popCount, opaNumber) {
if (popCount < 10) { //Must be even number so you end on opacity = 1
setOpacity(id, opaNumber);
popTimeout = setTimeout(function() {
pop(id, popCount++, 1-opaNumber);
}, 50);
}
}
var popTimeout;
pop(id, 0, 0);
return function() {
clearTimeout(popTimeout);
setOpacity(id, 1);
}
}
var killPop = [];
function startPop(id) {
killPop[id] = runPop(id);
}
function stopPop(id) {
killPop[id]();
}

Showing random divs images every time page is load

Lets say I have these images gallery, how do i randomly display the images everytime when i reload the page?
http://creativepreviews.com/fiddle/study/20131007/
Let's say the image will display in the background of the DIV, then the following should do it.
// JS
var imgArray = ["img1.jpg", "cat.jpg", "sky.jpg"]
function randomBg() {
x = Math.random()
y = Math.round(x * 10)
if (imgArray[y] != undefined) {
document.getElementById("blah").style.backgroundImage = "url('" + imgArray[y] + "')"
} else {
document.getElementById("blah").style.backgroundImage = "url('default.jpg')"
}
}
...and the HTML.
<script src="test.js"></script>
<body onload="randomBg()">
<div id="blah"></div>
...or you could replace the style.backgroundImage in the JS with innerHTML = <img src=" etc...
You could do something along these lines (not tested)
var grd = $('#grid');
var imgs = grd.children();
imgs.sort(function(){return (Math.round(Math.random()) - 0.5);});
grd.remove('li');
for(var i=0;i < imgs.length;i++) grd.append(imgs[i]);
In essence what we are doing is getting all the li elements in 'grid' into an array, randomizing them, removing them all from 'grid' and then putting them back in again.
If you had supplied a working fiddle rather than a link to the finished article it would be easier to modify it and provide a more complete solution.

Getting images to change in a for loop in javascript

So far I created an array with 11 images, initialized the counter, created a function, created a for loop but here is where I get lost. I looked at examples and tutorial on the internet and I can see the code is seeming simple but I'm not getting something basic here. I don't actually understand how to call the index for the images. Any suggestions. Here is the code.
<script type="text/javascript">
var hammer=new Array("jackhammer0.gif",
"jackhammer1.gif",
"jackhammer2.gif",
"jackhammer3.gif",
"jackhammer4.gif",
"jackhammer5.gif",
"jackhammer6.gif",
"jackhammer7.gif",
"jackhammer8.gif",
"jackhammer9.gif",
"jackhammer10.gif")
var curHammer=0;
var numImg = 11;
function getHammer() {
for (i = 0; i < hammer.length; i++)
{
if (curHammer < hammer.length - 1) {
curHammer = curHammer +1;
hammer[i] = new Image();
hammer[i].src="poses/jackhammer" +(i+1) + ".gif";
var nextHammer = curHammer + 1;
nextHammer=0;
{
}
}
}
}
setTimeout("getHammer()", 5000);
</script>
</head>
<body onload = "getHammer()";>
<img id="jack" name="jack" src = "poses/jackhammer0.gif" width= "100" height ="113" alt = "Man and Jackhammer" /><br/>
<button id="jack" name="jack" onclick="getHammer()">Press button</button>
Following on what Paul, said, here's an example of what should work:
var hammer=["jackhammer0.gif","jackhammer1.gif","jackhammer2.gif","jackhammer3.gif",
"jackhammer4.gif","jackhammer5.gif","jackhammer6.gif","jackhammer7.gif",
"jackhammer8.gif","jackhammer9.gif","jackhammer10.gif"];
var curHammer=0;
function getHammer() {
if (curHammer < hammer.length) {
document.getElementById("jack").src= "poses/" + hammer[curHammer];
curHammer = curHammer + 1;
}
}
setTimeout("getHammer()", 5000);
The big missing element is that you need to call getElementById("jack") to get a reference to the DOM Image so that you can change it's source. If you're using jQuery or most other JS frameworks, just type $("#jack") to accomplish the same.
I don't understand the need for the for loop at all, just increment the index value [curHammer] each time you click, and reset if it passes your max index length (in this case 11).
Pseudo-Code:
currentHammer = -1
hammers = [ "a1.jpg", "a2.jpg", "a3.jpg"]
getHammer()
{
currentHammer = currentHammer + 1;
if(currentHammer > 2)
currentHammer = 0;
image.src = hammers[currentHammer];
}
a) are you just trying to show an animated gif? If so, why not use Adobe's Fireworks and merge all those gifs into a single gif?
b) you know that the way you have it the display is going to go crazy overwriting the gif in a circle right?
c) you might want to put a delay (or not). If so, make the load new gif a separate function and set a timeout to it (or an interval).
Also, you are being redundant. How about just changing the src for the image being displayed?:
var jackHammer = new Array();
for (var i=0;i<11;i++) { //pre-loading the images
jackHammer[i] = new image();
jackHammer[i].src = '/poses/jackHammer'+i.toString()+'.gif';
} //remember that "poses" without the "/" will only work if that folder is under the current called page.
for (var i=0;i<11;i++) { //updating the image on
document.getElementById('jhPoses').src = jackHammer[i].src;
}
on the document itself,
< img id='jhPoses' src='1-pixel-transparent.gif' width='x' height='y' alt='poses' border='0' />

Categories

Resources