I have a JSON file which stores an array of picture URLs. I want to rotate through these links, changing the background of a div every 4 seconds.
I'm having no trouble accessing the JSON file or changing the background of the div. However, I can't seem to figure out how to restart at the beginning of the array after every picture has been shown.
How should I approach this problem?
$.getJSON(json, function (data) {
var arr = $.map(data, function (el) { return el; })
, i = 0;
var changeObj = function() {
i++;
var url = 'url("' + arr[i].url + '")';
$this.css({
backgroundImage: url
});
};
setInterval(changeObj, 4000);
});
Here's a demo
Let's assume your have already parsed your JSON into an array of URLs called myPictureArray and you have written a function called swapInNewPicture, which takes a URL of an image as its argument. (I'm not going to write these functions for you.)
var rotatePictures = function (arr) {
var length = arr.length
, i = 0;
setInterval(function () {
i = (i + 1) % length;
swapInNewPicture(arr[i]);
}, 4000)
}
Now, all you have to do is call rotatePictures(myPictureArray) after you finish parsing your JSON.
Use the modulus operation so it wraps around when it reaches the end of the array. Replace:
i++;
with:
i = (i + 1) % arr.length;
This is basically equivalent to:
i++;
if (i == arr.length) {
i = 0;
}
BTW, you can simplify the setInterval call to:
setInterval(changeObj, 4000);
Related
I am trying to write a function that given a list of ids goes to firebase storage and retrieves the download URL for each id and saves the URLs in an array in the same order as the ids array. On testing I have found that the download URLs are returned in a random order. Below is some scaled down code of the aforementioned function.
1) Is there a way to cause the returned URLs to arrive in the correct order?
2) The setTimeout function is used after the loop to wait for 3 seconds otherwise the urlsToDownload array is empty. Is there a more accurate way to wait until all the URLs have been downloaded?
function downloadAll() {
var storageRef = firebase.storage().ref("/stuffToDownload");
var urlsToDownload = [];
var downloadIds = ['1', '2'];
for (var x = 0; x < downloadIds.length; x++) {
var downloadId = dowloadIds[x];
(function(did) {
var storageFileRef = storageRef.child(did);
storageFileRef.getDownloadURL().then(function(url) {
urlsToDownload.push(url);
}).catch(function(error) {
console.log("error");
});
})(downloadId);
}
}
}
setTimeout(function() {
console.log("finished getting file urls", urlsToDownload.length);
var index = 0;
for(index = 0; index < urlsToDownload.length; index++){
console.log(index + " " + urlsToDownload[index]);
}
}, 3000);
}
what you can do is wait for the URL to download then check the length of the urlsToDownload with the length of downloadIds, if matches call a function like below,
storageFileRef.getDownloadURL().then(function(url) {
urlsToDownload.push(url);
if(urlsToDownload.length==downloadIds.length){ //if you have all the files matching with downloadIds then you will get all the download URL
_callConsoleLog()
}
})
var _callConsoleLog=function(){
var index = 0;
for(index = 0; index < urlsToDownload.length; index++){
console.log(index + " " + urlsToDownload[index]);
}
}
I want to cycle through an array and display each element individually, and then remove it. Sort of like this fiddle, but I don't want it to go forever.
I tried using jQuery because I thought it would be easier, but I am clearly missing something. Can anyone help?
Here is my attempt, but it just goes straight to the last element in the array.
var list = [1,2,3,4,5,6];
var length = list.length;
for(i = 0; i < length; i++) {
$('#nums').html(list[i]).delay(750);
}
Oh, and I don't care if it's jQuery or vanilla JavaScript. Either is fine by me.
$(document).ready(function(){
var list = [1,2,3,4,5,6];
var length = list.length;
var i = 0;
var ivl = setInterval( function () {
if (i < length) {
$('#nums').html(list[i]).delay(750);
i++;
}
else {
clearInterval(ivl);
}
}, 750);
});
The (pretty clever) example uses the fact that the modulus operator (%) gives you remainder, which is periodic, so you can use it to cycle through your array by taking the remainder of an infinitely increasing number divided by the length of your list.
If you want it to stop, however, you can just do a check to see if you've finished cycling through the list:
var list = [1, 2, 3, 4, 5, 6];
var length = list.length;
var i = 0;
var finished = false;
function repeat() {
if (!finished) {
document.getElementById('nums').innerHTML = list[i % length];
i++;
if (i === length) {
finished = true;
}
} else {
clearInterval(interval);
}
}
var interval = setInterval(repeat, 750);
<div id="nums"></div>
Late to the party but wouldn't it be better to use setTimeout rather than setInterval just in case the code executed on each iteration takes longer than the interval duration? I mean, I know it's not an issue in this instance but it's just a better/safer way to do this sort of thing.
$(document).ready(function(){
var list = [1,2,3,4,5,6];
var length = list.length;
var i = 0;
(function next(){
if (i < length){
$('#nums').html(list[i++]);
setTimeout(next,750);
}
})();
});
http://jsfiddle.net/zLexhdfp/3/
This question already has answers here:
Detect multiple images load event
(2 answers)
Closed 8 years ago.
I have a simple html page where I want to load a stack of images. And I want to display one of them according to the user's cursor on the screen. Basically I'm trying to do something like this :
http://test.vostrel.net/jquery.reel/example/object-movie-camera-sequence/
I do this in two steps, in the first one I load low resolution images (60 images in less than two seconds) and in the second one when the user click for the first time I swap the low res for the high resolution images (60 images in about 10 seconds).
Those are my two functions :
function loadImages() {
var imagesDOM;
for (var j = 0 ; j < directoriesNumber ; j++) {
imagesDOM = new Array();
for (var i = 1 ; i < imageNumber + 1 ; i++) {
images[i] = imageDirectory[j] + "/" + imageBasename + twoDigits(i) + imageExtension;
}
for (var i = 1 ; i < imageNumber + 1 ; i++) {
imagesDOM[i] = new Image();
imagesDOM[i].id = "image" + j + "_" + i;
imagesDOM[i].src = images[i];
$("#cadre").append(imagesDOM[i]);
}
}
}
function loadImagesHigh() {
for (var j = 0 ; j < directoriesNumber ; j++) {
for (var i = 1 ; i < imageNumber+1 ; i++) {
images[i] = imageDirectoryHigh[j] + "/" + imageBasename + twoDigits(i) + imageExtension;
}
for (var i = 1 ; i < imageNumber+1 ; i++) {
$("#image" + j + "_" + i).attr("src",images[i]);
}
}
}
So question is how can I monitor the downloads of the images on the client side : 4 out of 60 images loaded please wait...
I have checked this :
Is there a way to determine when 4 images have been loaded using JS?
But the src are written in the html.
Solution, thanks to Aaron Digulla, is as simple as adding the following event listener before assigning a value to src:
$(imagesDOM[i]).load(function () {
console.log("loaded");
}
);
Thanks for reading.
Before assigning a value to src, attach an event listener to the image. You'll need two global variables which that contain the total image count and the number of images that have been loaded.
The question Is there a way to determine when 4 images have been loaded using JS? contains several examples how the event listener looks like.
[EDIT] OP finally used
$(imagesDOM[i]).load(function () {console.log("loaded")});
I had to do a similar thing recently and I plumped for manual use of jQuery deferred objects. Here's the principle:
//specify imgs to load and create a jQuery deferred object for each
var
imgs_to_load = ['foo', 'bar', 'foo2', 'bar2'], //etc
dfds = imgs_to_load.map(function() { return new $.Deferred; });
//wait for each img to load and resolve its corresponding deferred
imgs_to_load.forEach(function(filename, i) {
var img = $('<img />', {src: filename+'.jpg'}).on('load', function() {
dfds[i].resolve();
});
});
//when all imgs loaded, do something
$.when.apply(null, dfds).then(function() { alert('all done'); });
So we make a deferred object for every image we wish to load. When the image loads, we manually resolve it, and when all deferreds are resolved we move on.
I have a JSON array(?) of pairs of every state and a value associated with that state, it looks like the following below:
var states = [{"STATE":"AL","AMOUNT":"6"}, {"STATE":"AK","AMOUNT":"3"}]
I need the page to shuffle through them without reloading the page
"AL 6" [wait x seconds] then "AK 3" [wait x seconds] then etc...
I need this to run continuously.
I never use any of these languages but was told that they were my best bet.
Could someone give me some guidance on this please.
Thank you in advance.
Here's a jsfiddle with setInterval execting a function that alternates between each state and displays it in a div:
http://jsfiddle.net/WD5Qj/1/
var states = '[{"STATE":"AL","AMOUNT":"6"}, {"STATE":"AK","AMOUNT":"3"}]';
json = jQuery.parseJSON(states);
var i = 0;
var cycle = function(){
$("#state").html(json[i].STATE + json[i].AMOUNT);
i = (i+1)%json.length;
}
var loop = setInterval(cycle, 500);
Alright, you'd need a function that does the rotation through the array, and a variable for keeping the current state (in both meanings of the word):
var stateIndex = 0;
function rotate() {
stateIndex++;
if(stateIndex >= states.length)
stateIndex = 0;
displayState(states[stateIndex]);
}
And you'd need an interval to perform the rotation:
var stateRotation = window.setInterval(rotate, 3000); // 3000ms = 3 sec
The stateRotation variable is an identifier of your interval. You may use that if you ever want to stop: window.clearInterval(stateRotation);
Now, the above code anticipates a function displayState which takes a state object and displays it. How that would look depends entirely on how you want your state to displayed. In its simplest form, something like this:
function displayState(state) {
$('#state-name').html(state.STATE);
$('#state-amount').html(state.AMOUNT);
}
As per your description, it might perhaps be something more like
$('#state-text').html(state.STATE + ' ' + state.AMOUNT);
var states = [{"STATE":"AL","AMOUNT":"6"}, {"STATE":"AK","AMOUNT":"3"}];
var i = 0;
setInterval(function(){
var array_index = i % states.length;
$('#state').html( states[ array_index ]['STATE'] );
$('#state').html( states[ array_index ]['AMOUNT'] );
i++;
}, 2000);
Here's a fiddle.
function displayNextItem(index){
if (index === states.length)
displayNextItem(0);
$("#someDiv").text(states[index]["STATE"] + " " + states[index]["AMOUNT"]);
setTimeout(function() { displayNextItem(index + 1); }, 1000);
}
And then
displayNextItem(0);
var i = 0, l = states.length, timer, intervalLength = 5000;
timer = setInterval(function(){
if(i >= l){
clearInterval(timer);
}else{
alert(states[i++].STATE);
}
},intervalLength);
This implementation is waiting the AMOUNT number of seconds. If you want constant number of seconds then other answers are better :).
JavaScript:
var states = [{"STATE":"AL","AMOUNT":"6"}, {"STATE":"AK","AMOUNT":"3"}];
function iterate(index) {
var time = states[index].AMOUNT;
// replace the text with new one
$("#output").text(states[index].STATE + " " + time);
setTimeout(function() {
var next = (index + 1) % states.length;
iterate(next);
}, time * 1000);
}
iterate(0);
HERE is the code.
How to set interval or may be timeout through the array, to produce effects for the element every 2 sec for example the 1-st idea is to programm something like this:
for (photoKey in arrBigPhotoes) {
setInterval(function() {
// alert(arrBigPhotoes[photoKey]);
document.getElementById("big_photo").src='/upload/images/'+arrBigPhotoes[photoKey];
}, 2000);
}
But it didn't work properly. May be someone can help me with this task I'll be extremely glad.
I'm also have a jQuery - the resolution may be through this library, but without any plug-ins.
Thanks.
Try something like this -
var photos = ['1.jpg', '2.jpg', '3.jpg'];
var photo_index = 0;
function switchPhoto() {
photo_index = (photo_index + 1) % photos.length;
document.getElementById('big_photo').setAttribute('src', '/upload/images/' + photos[photo_index]);
}
setInterval(switchPhoto, 2000);
You should probably put this inside some kind of document ready event handler
I would suggest you pre-load the images you are trying to display. If the user is on a slow connection, your approach would fail.
var images = new Array();
var counter = 0;
var image = document.createElement("img");
image.onload = function() {
counter++;
};
image.src = <url>;
images.push(image);
The counter is there so that you can determine when all images are properly loaded. Let's say you have six images, then, in your "intervaled" function, you would immediately return if counter < 6.
Your "switcher" function could look this way
var i = 0;
setInterval(function() {
if (counter < 6) return;
i = (i+1) % images.length;
document.getElementById("big_photo").src = images[i].src;
}, 2000);