JavaScript: Toggling Between 2 Images Not Working, Using setInterval - javascript

New to JS. I am trying to toggle between showing two images, dragon.svg, and dragon1.svg, every 1 second starting on page load, and running indefinitely. However, my image only changes once, and then keeps running every second but not following the rules of my if/else statement.
My suspicion is that the function is not changing the value of a global variable called dragonDiv each time it runs, so each time it runs, it is using the original value of the dragonDiv variable.
On the HTML, I have a div with the image inside, like this:
<body onload="changeDragon();">
<div id="dragonarea">
<img src="images/dragon.svg"/>
</div>
</body>
And then I have this JS, which should change the image to dragon1.svg if it is currently dragon.svg, and vice versa, every 1 second.
function changeDragon() {
changeInterval = setInterval(dragonColorChange, 1000);
}
let dragonDiv = document.getElementById('dragonarea');
console.log(dragonDiv.innerHTML); // Correctly logs <img src="images/dragon.svg"/>
function dragonColorChange() {
if (dragonDiv.innerHTML = '<img src="images/dragon.svg">') {
dragonDiv.innerHTML = '<img src="images/dragon1.svg">';
console.log(dragonDiv.innerHTML) // Correctly logs <img src="images/dragon1.svg"/>
} else {
dragonDiv.innerHTML = '<img src="images/dragon.svg">';
console.log(dragonDiv.innerHTML) // Never makes it to this point
}
}
As noted above, the console log tells me that it is correctly changing the image the first time, but after that, it seems like it is again taking the original value of dragonDiv (with the dragon.svg image) and running the function on that innerHTML again (so changing it to dragon1.svg again), rather than updating the innerHTML after running the function once as I'm telling it to do and forcing it to the else statement.
I tried putting the dragonDiv variable inside the dragonColorChange function as well as outside as a global variable. I tried using document.getElementById('dragonarea').src instead of replacing the entire innerHTML of the div tag. I tried using === instead of just =. I tried various other things for about 4 hours and I can't figure out how to get it to keep looping through the if/else statements.
Any mistakes I'm making in my code?

Apart from the typo (= is assignment, == or == is comparison) you have several improvements you can make
Use addEventListener
Change src, not innerHTML, waste of DOM rendering
I suggest a data-attribute
let changeInterval;
let dragonImage;
window.addEventListener("load", function() {
dragonImage = document.getElementById("dragonImage");
changeInterval = setInterval(dragonColorChange, 1000);
})
function dragonColorChange() {
const toggle = dragonImage.dataset.toggle
const src = toggle === "0" ? "images/dragon1.svg" : "images/dragon.svg";
dragonImage.src = src;
dragonImage.dataset.toggle = toggle === "0" ? "1" : "0";
}
<div id="dragonarea">
<img id="dragonImage" data-toggle="0" src="images/dragon.svg" />
</div>

Typo I guess, use === or == for comparison.
Also, onload function on body had different quotes [”] (when I copied and pasted on jsfiddle, it didn't work) instead of ["]
function changeDragon() {
changeInterval = setInterval(dragonColorChange, 1000);
}
let dragonDiv = document.getElementById('dragonarea');
/* console.log(dragonDiv.innerHTML); // Correctly logs <img src="images/dragon.svg"/> */
function dragonColorChange() {
if (dragonDiv.innerHTML === '<img src="images/dragon.svg">') {
dragonDiv.innerHTML = '<img src="images/dragon1.svg">';
console.log(dragonDiv.innerHTML) // Correctly logs <img src="images/dragon1.svg"/>
} else {
dragonDiv.innerHTML = '<img src="images/dragon.svg">';
console.log(dragonDiv.innerHTML) // Never makes it to this point
}
}
<body onload="changeDragon();">
<div id="dragonarea">
<img src="images/dragon.svg" />
</div>
</body>

Here I compare and change the image.src directly, instead of the div's innerHTML, as others have suggested already.
HTML:
<body onload="changeDragon();">
<div id="dragonarea">
<img id="dragon-image" src="images/dragon.svg"/>
</div>
</body>
JavaScript:
function changeDragon() {
changeInterval = setInterval(dragonColorChange, 1000);
}
let dragonImage = document.getElementById('dragon-image');
function dragonColorChange() {
if (dragonImage.src === 'images/dragon.svg') {
dragonImage.src = 'images/dragon1.svg';
} else {
dragonImage.src = 'images/dragon.svg';
}
}

As others have said you need the ===.
Here's one way to do it and keep the variable scoped to the function. I'm using .getAttribute("src") instead of just .src since it gets the relative url path.
Note that dragonColorChange isn't being passed into setInterval. It's the function returned by calling dragonColorChange.
const changeDragon = function () {
changeInterval = setInterval(dragonColorChange(), 1000);
};
function dragonColorChange() {
let dragonImg = document.querySelector('#dragonarea img');
return function () {
dragonImg.src = dragonImg.getAttribute("src") === "images/dragon.svg" ? "images/dragon1.svg" : "images/dragon.svg";
}
}

In the if condition there is a typo. Instead of comparison with == or === there is assignment operator which will assign rather than compare. Try changing that to comparison.

Related

How to set a JS variable from a CSS style

I've made a bunch of JavaScript functions to show, hide and populate various elements on a zooming menu. All seem to working except for one which I need the function to only run if a CSS setting is a specific value (width of 195%). I am very new to JavaScript so there may be more than one issue here.
<script>
function zoomShowF2() {
var widthNow = document.getElementById('svg1').style.width;
if widthNow = '195%' {
document.getElementById('zoomTitle').style.display = 'flex';
else
document.getElementById('zoomTitle').style.display = 'none';
}}</script>
You need to use comparison operators write the if statement as follows
if (widthNow == '195%') {
as the single = is assigning the value not comparing it
There are a few issues with your syntax:
function zoomShowF2() {
var widthNow = document.getElementById('svg1').style.width;
if (widthNow === '195%') {
document.getElementById('zoomTitle').style.display = 'flex';
} else {
document.getElementById('zoomTitle').style.display = 'none';
}
}
Thanks everyone. It works now with a combination of the changes suggested. I assume my curly braces are all in 'tidy' positions?
EDIT. I've adjusted the curly brace positions to as per Ed's layout.
Thanks all!
Your code does not called when the element changes it size or width. You must put all your code inside window.onresize event.
var displayOutput = document.getElementById("display-option");
function reportWindowSize() {
displayOutput.text = document.getElementById("element-to-check").style.width;
}
window.onresize = reportWindowSize;
<p id="element-to-check">Resize the browser window to fire the <code>resize</code> event.</p>
<p>Display: <span id="display-option"></span></p>

Array image looping in JavaScript

I have been trying to loop traffic light images in JavaScript. I'm not sure what to do, can someone give advice.
A slight modification to your code. Here is a working sample.
I removed the dvi.count counter as it creates more confusion, We need to maintain the counters outside the function. I changed the logic to pass around the index of the image in the array starting from 0.
var image = new Array("red.jpg", "redamber.jpg", "green.jpg", "amber.jpg");
var timeout;
function stopIt() {
clearTimeout(timeout);
}
function changeimage (images, index) {
var dvi = document.getElementById(images);
if(image.length <= index)
index = 0;
dvi.src = image[index];
dvi.alt = image[index];
timeout = setTimeout('changeimage("' + images + '",' + (index + 1) + ')', 1000);
}
<body onload="changeimage('changer',0)">
<div>
<img src="t1" alt="test1" id="changer" />
</div>
</body>
I have made 3 changes to your code
Fixed the typeo div.count to dvi.count
Corrected the indenting and braces round the if statement (Not strictly necessary, but makes the code way more readable)
Replaced your nasty use of a string parameter in setTimeout to be a function reference
function changeimage(images){
var dvi=document.getElementById(images);
if(!dvi.count || dvi.count == image.length ){
dvi.count=0;
}
dvi.src=image[dvi.count];
dvi.alt=image[dvi.count];
dvi.count=dvi.count+1;
timeout=setTimeout(function(){
changeimage(images);
},3500);
}
Live example: https://jsfiddle.net/Lofug2hf/1/

Javascript: Return original innerHTML on mouseout

I am sorry for this very basic question. I am very new to javascript and learning it.
I am stuck with one easy problem-
This is what i am trying to do-
I have a header that has some innertext
<h1 id="bd" onmouseover="fun1()" onmouseout="fun2()"> sample</h1>
I am chaging innerHTML of this header on mouseover like this-
function fun1()
{
document.getElementById("bd").innerHTML="a";
}
well on mouseout i do the same but for getting original innerHTML for this header tag.
function fun2()
{
document.getElementById("bd").innerHTML=document.getElementById("bd").innerHTML;
}
But onmouseout function shows me changed innerHTML, that is a in this case.
How do i get original innerHTML sample again onmouseout?
I want this to be done in javascript.
I tried another way more
function fun1()
{
document.getElementById("bd").innerHTML="a";
}
function fun3()
{
var ds=document.getElementById("bd").innerHTML;
alert(ds);
}
function fun2()
{
document.getElementById("bd").innerHTML=fun3();
}
but it is not working also.
A very generic version would be the following:
First change your markup a bit:
<h1 id="bd" onmouseover="fun1(this)" onmouseout="fun2(this)"> sample</h1>
This way you don't need to look up your element again in your callback function. This works then for more than one element you mouse over. Then you go:
function fun1(elm) {
if (!fun1.cache) fun1.cache = {}; // extend your function with a cache
fun1.cache[elm.id] = elm.innerHTML; // write into cache -> fun1.cache.bd
elm.innerHTML = 'a';
}
function fun2(elm) {
if (fun1.cache && fun1.cache[elm.id]) { // see if cache exists and...
elm.innerHTML = fun1.cache[elm.id]; // read from it
}
}
This way you build a caching system that doesn't need an extra global variable but stays closer to your function.
The next step would be to use only one function and send the new value as a parameter. Create something like a toggle function:
<h1 id="bd" onmouseover="fun(this, 'a')" onmouseout="fun(this)"> sample</h1>
and then your function:
function fun(elm, newValue) {
if (!fun.cache) fun.cache = {};
var value = newValue || fun.cache[elm.id]; // no newValue means recover old value
fun.cache[elm.id] = elm.innerHTML; // alway save the old value
elm.innerHTML = value;
}
If you need more explanations about this and creating Objects just leave a comment to this answer and I'll come back with more details...
Good luck!!
Store the first innerHtml in a global variable ,and use this variable to backup the first innerHtml.
var oldInner = '';
function fun1()
{
oldInner = document.getElementById("bd").innerHTML;
document.getElementById("bd").innerHTML="a";
}
function fun2()
{
document.getElementById("bd").innerHTML=oldInner;
}
You'll need to store the original value somehow:
var originalInnerHTML = "";
function fun1()
{
originalInnerHTML = document.getElementById("bd").innerHTML;
document.getElementById("bd").innerHTML="a";
}
function fun2()
{
document.getElementById("bd").innerHTML=originalInnerHTML
}
Currently you just get the existing innerHTML and set it as the new innerHTML - it's always going to be the same. So this line never changes anything:
document.getElementById("bd").innerHTML=document.getElementById("bd").innerHTML;
once you have changed the innerhtml of an element, old data is gone
In order to get the old data you first need to have it store in some other place.
For ex : on mouseover you can first copy the original html to a hidden div, and upon mouseout you can again copy from the hidden div to the main div.
hope this helps.
A very easy implementation will be to have the two text you want to display in the div. so you have:
<h1 id="bd">
<span id='sample1'>sample1</span>
<span id='sample2' style='display: none'>a</span>
</h1>
var el = document.getElementById("bd");
el.onmouseover = function() {
document.getElementById("sample1").setAttribute("style", "display: none");
document.getElementById("sample2").setAttribute("style", "");
}
el.onmouseout = function() {
document.getElementById("sample2").setAttribute("style", "display: none");
document.getElementById("sample1").setAttribute("style", "");
}

Inner HTML if statement not recognizing a div tag

I tested the following code in IE, Chrome, and Firefox and it does not work in any of them. I have read several questions about similar problems but they have not offered solutions that fix my example.
I am trying to create a pause/play button that interfaces with JWplayer (I also want it to interface with flowplayer, once I get the button working) and the image will change depending on which image is currently there. I also have a stop button that stops the player completely and changes the image of the pause/play button to pause.
Here is my current code:
<script type="text/javascript">
function changeimg()
{
var obj = document.getElementById('image1');
var imgtag1 = '<img src=\'PLAY.png\'>';
var imgtag2 = '<img src=\'PAUSE.png\'>';
if(obj.innerHTML == imgtag2)
{obj.innerHTML = imgtag1;}
else
{obj.innerHTML = imgtag2;}
return;
}
function playimg()
{
document.getElementById('image1').innerHTML = '<img src=\'PLAY.png\'>';
return;
}
</script>
<div id="image1" href="#" onclick="changeimg(); jwplayer('mediaspace1').play(); jwplayer('mediaspace2').play(); jwplayer('mediaspace3').play(); jwplayer('mediaspace4').play();"><img src='PLAY.png'></div>
<div href="#" onclick="playimg(); jwplayer('mediaspace1').stop(); jwplayer('mediaspace2').stop(); jwplayer('mediaspace3').stop(); jwplayer('mediaspace4').stop();"><img src='STOP.png'></div>
The play/pause function works, and the first div WILL change into the pause img (so the javascript is going through) and it WILL change back into play if I click on the second div (stop function - triggers playimg() ) but it will not change back into the play image if I click on the pause button again.
For security reasons I can't link the website, but any help would be appreciated
It looks like all you really want to change is the SRC of the IMG tag, not necessarily the entire innerHTML. As machineghost mentions in his comment, there may be whitespace added or other changes to the full HTML that may make your comparison come out as false.
However, you could check if obj.src == "PLAY.png" and set the SRC attribute directly. Something like this:
function changeimg()
{
var obj = document.getElementById('image1');
var img1 = 'PLAY.png';
var img2 = 'PAUSE.png';
if(obj.src == img2)
{obj.src = img1;}
else
{obj.src = img2;}
return;
}
I think the innerhtml you are replacing in changeimg() is affecting the whole obj element, which is a div. So, if(obj.innerHTML == imgtag2) will return false since the div innerhtml is not imgtag2, but the next time you are going to call changeimg(), "obj" will be undefined because you replaced its innerhtml with an HTML code that doesn't have an id: {obj.innerHTML = imgtag2;}
Check the console to see if there's any javascript error, which it should, at if(obj.innerHTML == imgtag2)
rgds.
Just check whether PLAY is present or not and then change innerHTML according to it
function changeimg()
{
var obj = document.getElementById('image1');
var imgtag1 = '<img src=\'PLAY.png\'>';
var imgtag2 = '<img src=\'PAUSE.png\'>';
if(obj.innerHTML.indexOf('PLAY') != -1)
{obj.innerHTML = imgtag2;}
else
{obj.innerHTML = imgtag1;}
return;
}

I can't get my image slideshow to work using JavaScript

I am trying to create a simple image slideshow type thing with the Javascript code below, but what it is doing is displaying the first image in the webpage with everything else, then after 5 seconds clearing the page and displaying the same image, then again every 5 seconds except it doesn't clear the page anymore.
The JavaScript:
var waiPics=new Array();
waiPics[0]='images/path.jpg';
waiPics[1]='images/gorse.jpg';
waiPics[2]='images/stream.jpg';
waiPics[3]='images/pines.jpg';
waiPics[4]='images/stump.jpg';
var time;
function timeUp() {
delete document.write();
nextPic();
}
function nextPic() {
var picNum=0;
if (picNum = waiPics.length) {
picNum=0;
}
else {
picNum++;
}
document.write('<img src="'+waiPics[picNum]+'" title="Waipahihi" alt="Waipahihi">');
time=setTimeout("timeUp()",5000);
}
The HTML:
<script type="text/javascript">
<!-- Begin
nextPic();
// End -->
</script>
Im not very experienced with Javascript, so thanks in advance for the help.
picNum will always be zero because it is declared inside a function and will set to zero every time the function is called. Even if you fix this, your condition is wrong:
if (picNum = waiPics.length) {
The conditional should be:
if (picNum === waiPics.length) {
The single = sign assigns the length to picNum, then converts to a boolean. The array length is nonzero, so it becomes true value. It then resets to zero every time.
Consider using JSLint to check your code for errors and to suggest improvements. It flagged the issue:
"Expected a conditional expression and instead saw an assignment."
if (picNum = waiPics.length) {
In fact, after using JSLint on your code and examining its suggestions, I would use something more like this:
// New array creation syntax
var waiPics = ['images/path.jpg', 'images/gorse.jpg', 'images/stream.jpg', 'images/pines.jpg', 'images/stump.jpg'];
var picNum = 0; // Declare outside inner function so its value is preserved
var myDiv = document.getElementById("ssdiv"); // Get a div element to insert picture into
function nextPic() {
if (picNum === waiPics.length) { // Proper comparison
picNum = 0;
} else {
picNum += 1;
}
// Set picture into div element without evil document.write
myDiv.innerHTML = '<img src="' + waiPics[picNum] + '" title="Waipahihi" alt="Waipahihi">';
// No longer need timeUp; also don't use eval syntax
setTimeout(nextPic, 5000);
}
Assigning innerHTML avoids various problems with document.write and also does not require your page to refresh to change slideshow images. Also note other comments.
You need to use the comparison operator ('==') instead of assigning ('=') here:
//if (picNum = waiPics.length) {
if (picNum == waiPics.length) {
have a look at this example...
http://jsfiddle.net/DaveAlger/eNxuJ/1/
to get your own slideshow working, copy and paste the following html into any text file and save it as slides.html
you can add any number of <img> elements inside the <div class="slideshow">
enjoy!
<html>
<body>
<div class="slideshow">
<img src="http://davealger.info/i/1.jpg" />
<img src="http://davealger.info/i/2.bmp" />
<img src="http://davealger.info/i/3.png" />
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
$(function(){
$('.slideshow img:gt(0)').hide();
setInterval(function(){$('.slideshow :first-child').fadeOut(2000).next('img').fadeIn(2000).end().appendTo('.slideshow');}, 4000);
});
</script>
<style>
.slideshow { position:relative; }
.slideshow img { position:absolute; left:0; top:0; }
</style>
</body>
</html>

Categories

Resources