Javascript simple image slider - javascript

I would like to have a simple picture slider. That slider should be in the header of the website and should switch between a small delay. I want it simple and named the pictures 1.jpg, 2.jpg and so on and they are in the folder "bilder".
I have tried a bit and here is my result:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<script type="text/javascript">
function picture_slider(){
setInterval( switch_picture(), 3000 );
return false;
}
function switch_picture() {
for ( var i = 1; i < 7 ; i++ ) {
var pfad = "bilder/" + i + ".jpg";
document.getElementById("bild").src = pfad;
i++;
};
return false;
}
</script>
</head>
<body onload="picture_slider();">
<img id="bild" src="" />
</body>
</html>
I guess, that I did something wrong, because my browser is showing only one picture and is not switching.

jsBin demo
On every loop you're iterating (for loop) over all your images, resulting in the latest one. Also use only switch_picture (instead of switch_picture()).
P.S: create an 0.jpg image for this counter:
function picture_slider(){
setInterval( switch_picture, 2000 ); // corrected removing "()"
}
var bild = document.getElementById("bild")
var i = 0; // Start from image 0.jpg
function switch_picture() { // don't iterate a loop in here!
bild.src = "bilder/"+ (i++ % 7) +".jpg";
}

I found something here: Stackoverflow Link
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<script type="text/javascript">
var i = 0;
var images = [ "1", "2", "3", "4", "5", "6", "7"]
function picture_slider(){
setInterval( switch_picture, 2000 );
}
function switch_picture() {
i++;
if ( i >= images.length ) {
i = 0;
};
var bild = document.getElementById("bild");
bild.src = "bilder/" + images[i] + ".jpg";
}
</script>
</head>
<body onload="picture_slider();">
<img id="bild" src="" />
</body>
</html>

// 1. images need to store in an Array
const images = [
"img/pic-1.jpg",
"img/pic-2.jpg",
"img/pic-3.jpg",
"img/pic-4.jpg",
"img/pic-5.jpg",
"img/pic-6.jpg",
"img/pic-7.jpg"
];
// 7. getElementById by calling, store globally (do not call inside loop/setInterval performance will loose)
const imgElement= document.getElementById("slider-image");
// 2. set initial value for array index
let imgIndex = 0;
// 3. create setInterval()
const sliderInterval = setInterval(() => {
// 6. check condition if length is finished then start again from 0
if (imgIndex >= images.length) { // use >= because index start from 0 and length start from 1, if use just > then last element will be undefined
imgIndex = 0;
}
// 5. testing
// console.log(imgIndex);
// 9. Dynamically change image src
const imgUrl = images[imgIndex];
imgElement.setAttribute('src', imgUrl);
// 4. increase value by 1
imgIndex++;
}, 1000);

Related

Undifined error after switching through images in Javascript

I am trying to create a website with one picture in the middle that changes after a given time. However after running through the loop once, no picture is shown for a short while and my console shows:
Shortly after, it switches through the images again. But having the image dissapear for a short while is a no go.
My Javascript looks like this:
var allPictures = new Array();
var index = 0;
allPictures[0] = "imgA.jpg";
allPictures[1] = "imgB.jpg";
allPictures[2] = "imgC.jpg";
addEventListener("load",() => {
setInterval( function() {
changeImage()
}, 500);
});
function changeImage() {
document.getElementById("galleryPicture").src = allPictures[index];
if (index < allPictures.length) {
index += 1;
} else if (index >= allPictures.length) {
index = 0;
}
}
My HTML looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="main.css">
<title>Website</title>
</head>
<body>
<script src="pictureSwapScript.js"></script>
<div class="galleryPicture">
<img id= "galleryPicture" src="imgA.jpg">
</div>
</body>
</html>
The problem is the condition used to increment index, it will get outside the boundaries of the array.
Replace it with
if (index >= allPictures.length - 1) {
index = 0;
} else {
index += 1;
}
There are other minute improvements that can benefit your code, among which the most obvious to me is replacing:
setInterval( function() {
changeImage()
}, 500);
with just
setInterval(changeImage, 500);
Below code solves your usecase.
function changeImage() {
if (index < allPictures.length - 1) {
index += 1;
} else if (index >= allPictures.length - 1) {
index = 0;
}
document.getElementById("galleryPicture").src = allPictures[index];
}
You were trying to compare index value with length, index always starts from 0. Hence you will have to decrease length by 1 because length starts from 1

My automatic image slider only shows the first two images

My automatic image slider only shows the first two images of the images array while tere are three images. I can't figure out why it is not working properly, I hope someone might know what is going wrong.
var images = [];
var i = 0;
//image array
images[0] = 'https://placeimg.com/900/600/animals?t=1515065784396';
images[1] = 'https://placeimg.com/900/600/animals?t=1515065867693';
images[2] = 'https://placeimg.com/900/600/animals?t=1515065784396';
function changeImage() {
"use strict";
document.getElementById("slider").src = images[i];
if (i < images.length - 1) {
i += 1;
} else {
i = 0;
}
setInterval(changeImage, 2000);
}
window.onload = changeImage;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> Automatic Image Slider </title>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<img id="slider">
</body>
</html>
Here it is! I've modified your code so that it now will work, pay attention not to reinitialize the interval at every changeImage() call ;)
//image array
var images = [];
images[0] = 'https://placeimg.com/900/600/animals?t=1515065784396';
images[1] = 'https://placeimg.com/900/600/animals?t=1515065867693';
images[2] = 'https://placeimg.com/900/600/animals?t=1515065784397';
var i = -1;
function changeImage() {
"use strict";
++i;
if (i >= images.length) {
i = 0;
}
document.getElementById("slider").src = images[i];
}
setInterval(changeImage, 2000);
window.onload = changeImage;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title> Automatic Image Slider </title>
<link rel="stylesheet" href="style.css">
<script src="script.js"></script>
</head>
<body>
<img id="slider">
</body>
</html>
images.length = 3
but
images.length - 1 = 2
so
(i < images.length - 1)
this condition work inly for i = 0 and i = 1
use this condition instead
(i < images.length)
Actually, your code works with a little bug. Note that your first and last image is the same.
And the huge bug of your code is that you are creating a new interval at each changeImage call, so the last image is being placed but fastly replaced for the first image.
Remove the setInterval(changeImage, 2000) from the changeImage function and call it like this:
window.onload = function() {
changeImage();
setInterval(changeImage, 2000)
}
Because your condition if (i < images.length - 1) is true only for 0 an 1
If you do if (i<=images.length-1) you will get all the three images

Javascript - clearInterval not working when multiple setInterval

I got some problem with setInterval & clearInterval.
In my code, I set multiple intervals, and when count reduce to 0, stop the execution.
Like below:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0" charset="utf-8">
</head>
<body>
<body>
<script type="text/javascript">
for (var i=0; i<4; i++){
var count = 100;
var IntervalID = window.setInterval((function(){ // closure
var timeoutID = IntervalID; // temp
var countTemp = count; // temp
var id = i;
return function(){
countTemp --;
console.log(id + " " + countTemp);
// do something here
if ( countTemp == 0 ){
clearInterval(timeoutID); // stop the execution
console.log(id + " stop");
}
}
})(), 20);
}
</script>
</body>
</html>
After the console appear the stop message "x stop", all element stop except the last element(id:3), it still going.
I try to write my code in another form:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0" charset="utf-8">
</head>
<body>
<script type="text/javascript">
for (var i=0; i<4; i++){
doSomething(i);
}
function doSomething(id){
var count = 100;
var IntervalID = window.setInterval((function(){ // closure
var timeoutID = IntervalID; // temp
var countTemp = count; // temp
return function(){
countTemp --;
console.log(id + " " + countTemp);
// do something here
if ( countTemp == 0 ){
clearInterval(timeoutID); // stop the execution
console.log(id + " stop");
}
}
})(), 20);
}
</script>
</body>
</html>
But this time, all elements don't stop.
I have two questions:
1. What is difference between these two code?
2. How to make the code work fine?
Edit:
If you just want to make the code work, only change one line in the second snippet:
clearInterval(timeoutID); // stop the execution
to
clearInterval(IntervalID); // stop the execution
But other people's answer can solve what I confuse at this problem.
The problem is that the correct IntervalID is not being captured in your closure, by the time your closure runs, window.setInterval hasn't returned the id as the assignment expression has not finished yet.
A simple trick can be used with an object, since they are passed to functions by reference in JavaScript
I have modified the loop to accomplish this
for (var i=0; i < 4; i++){
var count = 100;
var args = { id: i, counter: count };
var IntervalID = window.setInterval((function(args){ // closure
return function(){
args.counter--;
console.log(args.id + " " + args.counter)
if ( args.counter == 0 ){
clearInterval(args.IntervalID); // stop the execution
console.log(args.id + " stop");
}
}.bind(args);
})(args), 20);
// by now the correct IntervalID will be captured
// as the assignment expression has finished executing
args.IntervalID = IntervalID;
}

Uncaught TypeError: Cannot set property 'innerHTML' of null

I get this error: "Uncaught TypeError: Cannot set property 'innerHTML' of null". I can't find the fault in my code. I don't use CSS now, nor jQuery.
Here is my HTML code:
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!--<script src="js/banner_test_script.js" language="javascript" type="text/javascript"></script>-->
</head>
<body>
<div id="ban"></div>
<script src="js/banner_test_script.js"></script>
</body>
</html>
And here is my JavaScript code:
window.onload = function what()
{
var myTimery = setInterval(function() {
myTimer();
}, 1000);
var imgn = 0;
function myTimer()
{
if (imgn === 0)
{
var d = "../../download.jpg";
imgn++;
}
else if (imgn === 1)
{
var d = "../../images.jpg";
imgn++;
}
else if (imgn === 2)
{
var d = "../../images1.jpg";
resetImgn();
}
var p = '<img src="' + d + '"></img>';
document.getElementById("ban").innerHTML = "lol";
document.writeln(p);
console.log(document.getElementById('ban') + "1");
console.log(document.getElementById("ban") + "2");
}
;
function resetImgn()
{
imgn = 0;
}
;
/*
function myTimer()
{
for (i = 0; i < 200; i++)
{
document.writeln(i);
}
}
;
*/
};
If you use document.write (or document.writeln) after the initial parsing of the page (which you do, because you're using it in a timer), that implicitly does a document.open, which wipes out the existing page entirely (and the replaces it with what you write). So your elements no longer exist when you try to look them up.
It's not clear to me what your document.writeln(p) is meant to do, but if you remove it, you'll stop wiping out your element, and document.getElementById should be able to find it.
If your goal is to have the image markup in p written to the ban element, then:
document.getElementById("bad").innerHTML = p;
...and removing document.writeln will do it.
Side note: That setInterval line can be just: var myTimery = setInterval(myTimer, 1000); Functions are first-class objects.
Side note 2: You seem to be cycling between imgn 0, 1, 2, then back to 0. You have somewhat complicated logic for doing it. Just FYI, there's a handy trick using the % operator you can use:
imgn = (imgn + 1) % 3;
Assuming you start with 0, the next will be 1, then 2, then 0, then 1...

Rotating URLs within an Iframe

I have 10 different urls that I want to feed into an iframe src attribute that I would also like to rotate say every 5 seconds between all the 10 urls within the iframe.
Unsure how to do this using javascript/best approach?
Sorry, should've mentioned that I am using IE6.
Thanks.
<iframe id="rotator" src="http://...first"></iframe>
<script>
// start when the page is loaded
window.onload = function() {
var urls = [
"http://...first",
"http://...second",
// ....
"http://...tenth" // no ,!!
];
var index = 1;
var el = document.getElementById("rotator");
setTimeout(function rotate() {
if ( index === urls.length ) {
index = 0;
}
el.src = urls[index];
index = index + 1;
// continue rotating iframes
setTimeout(rotate, 5000);
}, 5000); // 5000ms = 5s
};
</script>
Javascript (place in window.onload)
var urls = ['http://www.stackoverflow.com', 'http://www.google.com'];
var pos = 0;
next();
setInterval(next, 5000); // every 5 seconds
function next()
{
if(pos == urls.length) pos = 0; // reset the counter
document.getElementById('rotate').src = urls[pos];
pos++;
}
HTML
<iframe id="rotate"></iframe>
There are many ways, so best is up for debate. Take a look at setInterval() since you mentioned JavaScript. I'd write a method that got the iframe on the page by it's id attribute, getElementById() and changed the src attribute to the next URL in the array of URLs.
<!doctype html>
<html>
<body>
<iframe id="foo"></iframe>
<script>
(function() {
var e = document.getElementById('foo'),
f = function( el, url ) {
el.src = url;
},
urls = [
'http://www.msn.com/',
'http://www.mtv.com/'
],
i = 0,
l = urls.length;
(function rotation() {
if ( i != l-1 ) {
i++
} else {
i = 0;
}
f( e, urls[i] );
setTimeout( arguments.callee, 5000 );
})();
})();
</script>
</body>
</html>
Is there a reason to reload the iframes every time they rotate in? I might load all the iframes upfront and simply rotate through their display if this particular project was concerned with quality of experience.
Hi I assume you would want to load the page completely before starting the timer to load the next URL, otherwise you would end up showing the next URL before the existing page even shows up (depending on your internet speed).
Secondly you said you want to rotate the URLS.
Below is the tested code for this:
<html>
<head>
<title></title>
<style type="text/css">
</style>
<script type="text/javascript">
var urls = [
"http://www.google.com"
,"http://www.yahoo.com"
,"http://www.ajaxian.com"
,"http://www.ebay.com"
];
function showUrl(idx) {
alert(idx + " Showing " + urls[idx]);
var f = document.getElementById("f");
// call the next load after 5 seconds only after
// this iframe loads
f.onload = function() {
var next = ++idx % urls.length;
setTimeout(function(){
showUrl(next);
}, 5000);
}
// set the src
f.src = urls[idx];
}
</script>
</head>
<body onload="showUrl(0)" class="app-chrome">
<iframe id="f" src="about:blank"></iframe>
</body>
</html>
Adding a more compact version: (Works in IE6, FF, Opera, Chromium)
<script type="text/javascript">
window.onload = (function(urls, interval) {
var idx = 0;
var bAttached = false;
return function showUrl() {
var f = document.getElementById("f");
var onLoad = function() { // loading only after previous page loads
idx = ++idx % urls.length; // rotation
setTimeout(showUrl, interval);
}
if(! bAttached) {
if(navigator.userAgent.indexOf("MSIE") !== -1) {
f.attachEvent("onload", onLoad);
bAttached = true;
}else {
f.onload = onLoad;
}
bAttached = true;
}
f.src = urls[idx];
};
})([
"http://www.google.com" ,"http://www.yahoo.com" ,
"http://www.sun.com" ,"http://www.ebay.com"
], 5000
);
</script>
I am not going to do it all for you but an example as requested:
Using Jquery for ease.
Code:
<script type="text/javascript">
//sets a var to 0//
var MyInt = 0
//sets some URLS//
var url1 = 'http://UR1L.com';
var url2 = 'http://URL2.com';
var url3 = 'http://URL3.com';
function RunEveryTenSecs {
// Increases var by 1//
MyInt + 1;
//Checks var value if 1 runs if not goes to next//
if (MyInt == 1) {
$('#MyElementID').html('<iframe src="' + url1+ '"></iframe>');
}
if (MyInt == 2) {
$('#MyElementID').html('<iframe src="' + url2+ '"></iframe>');
}
if (MyInt == 3) {
$('#MyElementID').html('<iframe src="' + url3+ '"></iframe>');
MyInt = 0;
}
}
window.setTimeout(RunEveryTenSecs, 10000);
</script>
HTML:
<div id="MyElementID">
IFRAME WILL GO HERE.
</div>
It may not be the neatest there are other ways to do it but it is something simple and easy to understand. The URL's dont have to be seperate but it will make changing them in the future easier.

Categories

Resources