Why is Javascript function not being called? - javascript

First Question on this site so I hope I do this right! I have a javascript function that I want to display an image (image1.jpg) when the page is loaded, and then every 2 seconds change the image by going through the loop. However only the first image is showing so it seems the JS function is not being called. Can anyone tell me if I am doing something wrong here because it looks fine to me so can't understand why it won't work. Thanks
<html>
<head>
<script type="text/javascript">
function displayImages(){
var images = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
var i = 1;
if(i>images.length-1){
this.src=images[0];
i=1;
}else{
this.src=images[i];
i++;
}
setTimeout("displayImages()", 2000);
}
</script>
</head>
<body onload="displayImages();">
<img id="myButton" src="image1.jpg" />
</body>
</html>

You need to move the line
var i = 1;
outside the displayImages -function or it will start from one each time!
EDIT: But using a global variable is not considered good practice, so you could use closures instead. Also as noted in other answers, you are referencing this which does not refer to the image object, so I corrected that as well as simplified the logic a bit:
<script type="text/javascript">
function displayImages( i ){
var images = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
var img = document.getElementById('myButton');
img.src = images[i];
i = (i+1) % images.length;
setTimeout( function() { displayImages(i); }, 2000 );
}
</script>
<body onload="displayImages(0);">

You need the value of i to be available at each call, it can be kept in a closure using something like:
var displayImages = (function() {
var i = 0;
var images = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
return function() {
document.getElementById('myButton').src = images[i++ % images.length];
setTimeout(displayImages, 2000);
}
}());
Also, since this isn't set by the call, it will default to the global/window object, so you need to get a reference to the image. That too could be held in a closure.

There are a couple of issues here that are stopping this from working.
First the var i = 1; needs to be moved outside the function to make the increment work. Also note that the first item in an array is 0, not 1.
Second you're using this to refer to change the image's src, but this is not a reference to the image. The best thing to do is use here is document.getElementById instead.
var i, button;
i = 0;
button = document.getElementById('myButton');
function displayImages() {
var images = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
if (i > images.length - 1){
button.src = images[0];
i = 0;
}
else{
button.src = images[i];
i++;
}
setTimeout(displayImages, 2000);
}
There's still some room for improvement and optimisation, but this should work.

You are reinitializing value of i every time, so change the following:
function displayImages(){
var images = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
if(!displayImages.i || displayImages.i >= images.length) displayImages.i = 0;
document.getElementById('myButton').src = images[displayImages.i];
displayImages.i++;
setTimeout(displayImages, 2000);
}
Functions are objects in JS and because of this:
you can pass them by reference and not as a string improving performance and readability
you can add fields and even methods to a function object like I did with displayImages.i
EDIT: I've realized that there was one more issue src was not being set for button.
Now I've fixed this and also made other improvements.
Here is the fiddle http://jsfiddle.net/aD4Kj/3/ Only image URLs changed to actually show something.

<script type="text/javascript">
var i = 1;
function displayImages(){
.......
........
Just make "i" Global. so that whenever displayImages being called it will not redefined to 1.

<html>
<head>
<script type="text/javascript">
var i = 1;
function displayImages() {
var images = ['img1.jpg', 'img2.jpg', 'img3.jpg'];
i++;
if (i > images.length - 1) {
i = 0;
}
$('#myButton').attr('src', images[i]);
setTimeout(displayImages, 2000);
}
</script></head>
<body onload="displayImages();">
<img id="myButton" src="img1.jpg" height="150px" width="150px"/>
</body>
</html>
Make i global.

here your are using displayImages() recursively and variable for index i. e i assign as local variable in function displayImages() , you need to assign it global variable i.e outside of the function also initialize it from i=0 as array index always start from 0,
your code become
var i = 0; // assign i global
function displayImages(){
var images = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
if(i>images.length-1){
document.getElementById('myButton').src=images[0]; //get img by id
i=0; // to get first image
}
else{
document.getElementById('myButton').src=images[i]; //get img by id
i++;
}
setTimeout("displayImages()", 2000);
}

Related

javascript/html: Second onclick attribute

I have an image - image1.png. When I click a button the first time, I want it to change to image2.png. When I click the button for a second time, I want it to change to another image, image3.png.
So far I've got it to change to image2 perfectly, was easy enough. I'm just stuck finding a way to change it a second time.
HTML:
<img id="image" src="image1.png"/>
<button onclick=changeImage()>Click me!</button>
JavaScript:
function changeImage(){
document.getElementById("image").src="image2.png";
}
I'm aware I can change the image source with HTML within the button code, but I believe it'll be cleaner with a JS function. I'm open to all solutions though.
You'll need a counter to bump up the image number. Just set the maxCounter variable to the highest image number you plan to use.
Also, note that this code removes the inline HTML event handler, which is a very outdated way of hooking HTML up to JavaScript. It is not recommended because it actually creates a global wrapper function around your callback code and doesn't follow the W3C DOM Level 2 event handling standards. It also doesn't follow the "separation of concerns" methodology for web development. It's must better to use .addEventListener to hook up your DOM elements to events.
// Wait until the document is fully loaded...,
window.addEventListener("load", function(){
// Now, it's safe to scan the DOM for the elements needed
var b = document.getElementById("btnChange");
var i = document.getElementById("image");
var imgCounter = 2; // Initial value to start with
var maxCounter = 3; // Maximum value used
// Wire the button up to a click event handler:
b.addEventListener("click", function(){
// If we haven't reached the last image yet...
if(imgCounter <= maxCounter){
i.src = "image" + imgCounter + ".png";
console.log(i.src);
imgCounter++;
}
});
}); // End of window.addEventListener()
<img id="image" src="image1.png">
<button id="btnChange">Click me!</button>
For achieve your scenario we have to use of counter flag to assign a next image. so we can go throw it.
We can make it more simple
var cnt=1;
function changeImage(){
cnt++;
document.getElementById("image").src= = "image" + cnt + ".png";
}
try this
function changeImage(){
var img = document.getElementById("image");
img.src = img.src == 'image1.png' ? "image2.png" : "image3.png";
}
Just use an if statement to determine what the image's source currently is, like so:
function changeImage(){
var imageSource = document.getElementById("image").src;
if (imageSource == "image1.png"){
imageSource = "image2.png";
}
else if (imageSource == "image2.png"){
imageSource = "image3.png";
}
else {
imageSource = "image1.png";
}
}
This should make the image rotate between 3 different image files (image1.png, image2.png and image3.png). Bear in mind this will only work if you have a finite number of image files that you want to rotate through, otherwise you'd be better off using counters.
Hope this helps.
Check the below code if you make it as a cyclic:
JS
var imgArray = ["image1.png", "image2.png", "image3.png"];
function changeImage(){
var img = document.getElementById("image").src.split("/"),
src = img[img.length-1];
idx = imgArray.indexOf(src);
if(idx == imgArray.length - 1) {
idx = 0;
}
else{
idx++;
}
document.getElementById("image").src = imgArray[idx];
}
html
<button onclick=changeImage();>Click me!</button>
function changeImage(){
document.getElementById("image").attr("src","image2.png");
}

Change image in button on click

I've got a button with an image inside that I want to swap when clicked. I got that part working, but now I also want it to change back to the original image when clicked again.
The code I'm using:
<button onClick="action();">click me<img src="images/image1.png" width="16px" id="ImageButton1"></button>
And the Javascript:
function action() {
swapImage('images/image2.png');
};
var swapImage = function(src) {
document.getElementById("ImageButton1").src = src;
}
Thanks in advance!
While you could use a global variable, you don't need to. When you use setAttribute/getAttribute, you add something that appears as an attrib in the HTML. You also need to be aware that adding a global simply adds the variable to the window or the navigator or the document object (I don't remember which).
You can also add it to the object itself (i.e as a variable that isn't visible if the html is viewed, but is visible if you view the html element as an object in the debugger and look at it's properties.)
Here's two alternatives. 1 stores the alternative image in a way that will cause it to visible in the html, the other doesn't.
<!DOCTYPE html>
<html>
<head>
<script>
function byId(e){return document.getElementById(e);}
window.addEventListener('load', mInit, false);
function mInit()
{
var tgt = byId('ImageButton1');
tgt.secondSource = 'images/image2.png';
}
function byId(e){return document.getElementById(e);}
function action()
{
var tgt = byId('ImageButton1');
var tmp = tgt.src;
tgt.src = tgt.secondSource;
tgt.secondSource = tmp;
};
function action2()
{
var tgt = byId('imgBtn1');
var tmp = tgt.src;
tgt.src = tgt.getAttribute('src2');
tgt.setAttribute('src2', tmp);
}
</script>
<style>
</style>
</head>
<body>
<button onClick="action();">click me<img src="images/image1.png" width="16px" id="ImageButton1"></button>
<br>
<button onClick="action2();">click me<img id='imgBtn1' src="images/image1.png" src2='images/image2.png' width="16px"></button>
</body>
</html>
You need to store the old value in a global variable.
For example:
var globalVarPreviousImgSrc;
var swapImage = function(src)
{
var imgBut = document.getElementById("ImageButton1");
globalVarPreviousImgSrc = imgBut.src;
imgBut.src = src;
}
Then in the action method you can check if it was equal to the old value
function action()
{
if(globalVarPreviousImgSrc != 'images/image2.png')
{
swapImage('images/image2.png');
}else{
swapImage(globalVarPreviousImgSrc);
}
}
It's not a good idea to use global variables in javascripts use a closure or object literal. You can do something like using a closure
(function(){
var clickCounter = 0;
var imgSrc1 = "src to first image";
var imgSrc2 = "src to second image"
functions swapImage (src)
{
var imgBut = document.getElementById("ImageButton1");
imgBut.src = src;
}
function action()
{
if(clickCounter === 1)
{
swapImage(imgSrc1);
--clickCounter;
}else{
swapImage(imgSrc2);
++clickCounter;
}
}
})();
(I haven't run this code though)
This nice w3documentation gives you best practices.
Check this a working example just copy paste and run-
HTML
<button onClick="action();">click me<img src="http://dummyimage.com/200x200/000000/fff.gif&text=Image+1" width="200px" id="ImageButton1"></button>
JAVASCRIPT
<script>
function action()
{
if(document.getElementById("ImageButton1").src == 'http://dummyimage.com/200x200/000000/fff.gif&text=Image+1' )
document.getElementById("ImageButton1").src = 'http://dummyimage.com/200x200/dec4ce/fff.gif&text=Image+2';
else
document.getElementById("ImageButton1").src = 'http://dummyimage.com/200x200/000000/fff.gif&text=Image+1';
}
</script>
Check this working example - http://jsfiddle.net/QVRUG/4/

JavaScript Photo Slider

I'm working on making a JS script that will go in the header div and display a few pictures. I looked into JQuery Cycle, but it was out of my league. The code I wrote below freezes the browser, should I be using the for loop with the timer var?
<script type="text/JavaScript" language="JavaScript">
var timer;
for (timer = 0; timer < 11; timer++) {
if (timer = 0) {
document.write('<img src="images/one.png">');
}
if (timer = 5) {
document.write('<img src="images/two.png">');
}
if (timer = 10) {
document.write('<img src="images/three.png">');
}
}
</script>
Thanks!
Assuming you want a script to rotate images and not just write them to the page as your code will do, you can use something like this:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div id="target"></div>
<script>
var ary = ["images/one.png","images/two.png","images/three.png"];
var target = document.getElementById("target");
setInterval(function(){
target.innerHTML = "<img src=\""+ary[0]+"\" />";
ary.push(ary.shift());
},2000);
</script>
</body>
</html>
Of course the above code has no effects (like fading) which jQuery will give yous, but it also doesn't require loading the entire jQuery library for something so basic.
How about just running the script after the page loads?
<script>
// in <head> //
function load() {
var headDiv = document.getElementById("head");
var images = ["images/one.png", "images/two.png"];
for(var i = 0; i<images.length; i++) {
image = document.createElement("img");
image.src = images[i];
headDiv.appendChild(image);
}
}
</script>
Then use <body onload="load();"> to run the script.
Edit
To add in a delay loading images, I rewrote the code:
<script>
// in <head> //
var displayOnLoad = true; // Set to true to load the first image when the script runs, otherwise set to false to delay before loading the first image
var delay = 2.5; // seconds to delay between loading images
function loadImage(url) {
image = document.createElement("img");
image.src = images[i];
headDiv.appendChild(image);
}
function load() {
var headDiv = document.getElementById("head");
var images = ["images/one.png", "images/two.png"];
for(var i = 0; i<images.length; i++) {
setTimeout(loadImage(images[i]), (i+displayOnLoad)*(delay*1000));
}
}
</script>
Set displayOnLoad = false; if you want to wait the specified delay before loading the first image. The delay is set in seconds. I recommend waiting over a single second between images, as they may take some time to download (depending on the user's internet speed).
As with the first snippet, I haven't tested the code, so please tell me if an error occurs, and I will take a look.
Since you used the jquery tag on your question, I assume you are OK with using jQuery. In which case, you can do something like this:
In your static HTML, include the img tag and set its id to something (in my example, it's set to myImg) and set its src attribute to the first image, e.g.:
<img id="myImg" src="images/one.png">
Next, use jQuery to delay execution of your script until the page has finished loading, then use setTimeout to create a further delay so that the user can actually spend a few seconds looking at the image before it changes:
<script>
var imgTimeoutMsecs = 5000; // Five seconds between image cycles
$(function() {
// Document is ready
setTimeout(function() {
// We will get here after the first timer expires.
// Change the image src property of the existing img element.
$("#myImg").prop("src", "images/two.png");
setTimeout(function() {
// We will get here after the second, nested, timer expires.
// Again, change the image src property of the existing img element.
$("#myImg").prop("src", "images/three.png");
}, imgTimeoutMsecs);
}, imgTimeoutMsecs);
});
</script>
Of course, that approach doesn't scale very well, so if you are using more than three images total, you want to modify the approach to something like this:
var imgTimeoutMsecs = 5000; // Five seconds between image cycles
// Array of img src attributes.
var images = [
"images/one.png",
"images/two.png",
"images/three.png",
"images/four.png",
"images/five.png",
];
// Index into images array.
var iCurrentImage = 0;
function cycleImage() {
// Increment to the next image, or wrap around.
if (iCurrentImage >= images.length) {
iCurrentImage = 0;
}
else {
iCurrentImage += 1;
}
$("#myImg").prop("src", images[iCurrentImage]);
// Reset the timer.
setTimeout(cycleImages, imgTimeoutMsecs);
}
$(function() {
// Document is ready.
// Cycle images for as long as the page is loaded.
setTimeout(cycleImages, imgTimeoutMsecs);
});
There are many improvements that can be made to that example. For instance, you could slightly simplify this code by using setInterval instead of setTimer.
The code you've provided simply iterates through the for loop, writing the images to the browser as it does so. I suggest you take a look at JavaScript setTimeout function.
JS Timing

How to create a rotating thumbnails functionality in jQuery?

Basically I need the thumbnails to rotate every time the user hovers over an image. Here is my failed attempt:
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript">
$(function() {
$('img').hover(function() {
theImage = $(this).attr('id');
otherImages = $(this).attr('class').split('#');
rotateThumbs(otherImages, theImage);
}, function() {
//
});
});
function rotateThumbs(otherImages, theImage) {
for (i=0; i < otherImages.length; i++) {
setInterval($('#'+theImage).attr('src', otherImages[i]), 1000);
}
}
</script>
<img id="myImage" src="http://www.google.com/images/logos/ps_logo2.png" class="http://www.google.com/images/logos/ps_logo2.png#http://l.yimg.com/a/i/ww/met/yahoo_logo_us_061509.png#http://dogandcat.com/images/cat2.jpg" width="174" height="130" />
Does anyone know how this may be accomplished?
Some issues here.
setInterval requires a function reference as it's first argument, but you are executing code that returns a jQuery object.
setInterval executes the first function repeatedly at the specified interval. Is that what you are trying to do? Swap images every second?
Depending on how you correct the first issue, you could run into an issue where i is otherImages.length and thus the src is set to undefined.
Assuming you worked around issue 3, you will have the problem that the image swaps will happen imperceptibly fast and it will appear as though the last image is always displayed.
Instead, don't use a loop. Increment a counter each time a new image is displayed. Try this:
function rotateThumbs(otherImages, theImage) {
var i = 0;
var interval = setInterval(function() {
$('#'+theImage).attr('src', otherImages[i++]);
if (i >= otherImages.length) {
clearInterval(interval);
}
}, 1000);
}
I've implemented a fully-functional example here. This addresses some of the issues that #gilly3 notes, but uses closures instead of an incrementing counter to keep track of the current image:
$(function() {
$('img').hover(function() {
// declaring these variables here will preserve
// the references in the function called by setInterval
var $img = $(this),
imageList = $img.attr('class').split('#'),
intervalId;
// start the cycle
intervalId = window.setInterval(function() {
var next = imageList.pop();
if (next) {
$img.attr('src', next);
} else {
// stop the cycle
intervalId = window.clearInterval(intervalId);
}
}, 1000);
}, function() {});
});
As you can see, using a closure is much easier when you declare the function passed to setInterval inline, rather than as a separate, named function. You could still have a rotateThumbs function if you wanted, but you might need to do some more work to ensure that the variables were being passed properly.
Edit: I made an updated version that continues to cycle as long as the mouse is hovering.
I have adjusted the answer for Sam, taking pre-loading the image into account, so that you won't have a possible deplay at the first rotation.
function rotateThumbs(otherImages, theImage) {
if(!$('#'+theImage).data('setup')){
$('#'+theImage).data('setup', true); // do not double pre-loading images
var $body = $('body');
for(var j = 0; j < otherImages.length; j++){
$body.append($('<img/>').attr('src', otherImages[j])
.css('display', 'none'));
}
}
var i= 0;
setInterval(function(){
$('#'+theImage).attr('src', otherImages[i++]);
if(i >= otherImages.length){i = 0}
}, 1000);
}

How to use .html() with a timer in jQuery?

I want to replace the contents of a div with the values found in an array. I want to keep each value within the div for 3 seconds each. Here's my code so far:
var images = ['a.jpg', 'b.jpg', 'c.jpg'];
for (i = 0; i < images.length; i++) {
$('#slideShow').html("<img src='../"+images[i]+"' alt='' />");
}
This of course changes the images so fast that the human eye only sees one image being in the div at all times. I want to keep each image for 3 seconds before the next .html() is done on the div. How to do this?
Try this:
images = ["a.jpg", "b.jpg", "c.jpg"];
function change(i){
if(!images[i]){return false}
else{
$("#slideShow").src=images[i];
setTimeout( function(){ change(i+1) }, 3000);
}
}
change(0);
Haven't tested it but it should work.
This answer assumes that you want to loop. If not, comment and I'll rewrite.
<script>
var images = ['a.jpg', 'b.jpg', 'c.jpg'];
var curimage = 0;
function changeImage() {
$('#slideShow').html("<img src='../"+images[curimage]+"' alt='' />");
curimage++;
if (curimage > images.length) curimage = 0;
}
changeImage();
window.setInterval(changeImage, 3000);
</script>
I have tested this answer.

Categories