Jquery: Doing an interval, timout, then interval again - javascript

I'm trying to do a reveal of a list of elements 1 after another in a setInterval for 5 seconds but after the 7th element, i want to wait for 60 seconds, meaning a timeout and continue the interval.
Following is my code, I can get it done but the problem with this code is that it does the timeout repetatively on every 7th element, however, i'm only looking to do it on the 1st 7th occurance and not on all the 7th element.
$(document).ready(function(){
var index=0;
var firstInterval=setInterval(function(){
if(index==7){
$("#love p:hidden:first").fadeIn(2000);
clearInterval(firstInterval);
index=0;
return;
}else{
$("#love p:hidden:first").fadeIn(2000);
index++;
}
var timeout=setTimeout(function(){
$("#love p:hidden:first").fadeIn(2000);
var secondInterval=setInterval(function(){
$("#love p.2nd_batch:hidden:first").fadeIn(2000);
},5000);
clearTimeout(timeout);
},60000);
},5000);
});
Any help would be greatly appreciated. thanks

Does this work for you? http://jsfiddle.net/301hsmom/3/ (watch the bottom right)
$(document).ready(function() {
var index = 1;
var firstInterval = setInterval(function() {
if (index === 7) {
$("#love p").filter(":hidden").filter(":first").fadeIn(2000);
clearInterval(firstInterval);
index = 1;
var timeout = setTimeout(function() {
$("#love p:hidden:first").fadeIn(2000);
var secondInterval = setInterval(function() {
var elem = $("#love p").filter(":hidden");
if (elem) {
elem.filter(":first").fadeIn(2000);
} else {
clearInterval(secondInterval);
}
}, 5000);
}, 60000);
} else {
$("#love p").filter(":hidden").filter(":first").fadeIn(2000);
index++;
}
}, 5000);
});
First, your var index = 0; and looping until index === 7 will run 8 times, rather than the intended 7. To fix this, change one of them to var index = 1; or index === 6.
Secondly, you create a new timeout every 5 seconds within the firstInterval code. You only want this to happen once the first 7 elements have been shown. This is fixed by moving it inside the if (index === 7) { statement so it will execute once 7 elements have been shown.
Another optimization I have applied is changing $("#love p:hidden:first") to $("#love p").filter(":hidden").filter(":first"). According to http://api.jquery.com/first-selector/:
Because :first is a jQuery extension and not part of the CSS specification, queries using :first cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. To achieve the best performance when using :first to select elements, first select the elements using a pure CSS selector, then use .filter(":first").
Changing :hidden is for the same reason. http://api.jquery.com/hidden-selector/.
Now everything works up to the first seven elements (assuming you have at least 7 elements, otherwise you will need to check for the existence of the element in the else within firstIndex). Next, we remove clearTimeout(timeout); as timeout's only run once and do not need to be cleared.
The next thing we do, is because we do not know how many elements there are to display after the first 7, we try to find a hidden element (with var elem = $("#love p").filter(":hidden");) and check for it's existence (using if (elem)). If it exists, we get the first one, and fade it in (elem.filter(":first").fadeIn(2000);), otherwise, we stop looping (clearInterval(secondInterval);).

Related

Slideshow program, why is the last slide showing twice?

All my images are in the html, and it couldn’t be a simpler program.
I just cannot figure out where the repetition comes from:
$(document).ready(function() {
var imgArray = $("#slides img:first-child");
var newCaption;
var nextImg;
var SlideShow = function() {
$("#slide").fadeOut(1000, function() {
if (imgArray.length == 0) {
imgArray = $("#slides img:first-child");
} else {
imgArray = imgArray.next();
}
nextImg = imgArray.attr("src");
newCaption = imgArray.attr("alt");
$("#slide").attr("src", nextImg).fadeIn(1000);
$("#caption").text(newCaption).show(1000);
});
};
var stop = setInterval(SlideShow, 2000);
$("#slide").click(function() {
stop = setInterval();
});
});
The logic is wrong here:
if (imgArray.length == 0) {
imgArray = $("#slides img:first-child");
} else {
imgArray = imgArray.next();
}
Imagine, you’re at the last <img> inside the id="slides" element.
Is imgArray.length == 0?
Of course not.
You’re at the last one, so imgArray contains one element, so its length is 1.
The else part will now get executed and set imgArray to the .next sibling.
But there is no next sibling, because you just were at the last <img>.
So now, imgArray is an empty jQuery object.
No next element exists.
Then you go ahead and get .attr("src") of nothing.
Then you go ahead and get .attr("alt") of nothing.
Both of these result in undefined as documented.
Then, you .fadeIn(1000) the id="slide" element, but, weirdly, also set its src attribute.
What do you think this does?
An <img> cannot contain another <img>, so setting the src of the container that contains all <img>s is meaningless.
And once the setInterval is triggered again, the cycle repeats with a fadeOut.
And only now do you finally check if imgArray even exists, after wrongly assuming that it does, setting src and alt, and doing fade-out animations.
Only now do you set imgArray = $("#slides img:first-child");.
Rubber Duck Debug your code.
This means: go through the execution by hand and try to explain each step.
It repeats at the end, you say, so what happens if imgArray contains the last <img>?
What is the next statement that is executed?
Does it make sense?
Why do you think so?
Use the debugger built into your browser.
You can observe the imgArray expression, or the imgArray.length expression.
Do these expressions always produce the values you expect?
At which point do they no longer do that?
Use console.log debugging.
The single statement console.log({ imgArray, imgArrayLength: imgArray.length, imgArrayNext: imgArray.next() }) may already answer several questions; you can copy-paste it after any one of your statements.
So move the check:
var SlideShow = function(){
$("#slide").fadeOut(1000, function(){
imgArray = imgArray.next();
if (imgArray.length === 0) {
imgArray = $("#slides img:first-child");
}
// Etc.
});
};
Next problem: stop = setInterval();.
stop is never used, other than as an assignment target.
Reassigning some variable doesn’t affect previously assigned objects.
It doesn’t stop the interval.
Stopping the inveral is done with clearInterval(stop);.

Adding increased count to the DOM for every pass

what I'm hoping to achieve is to increase a count and then append that to the DOM on every pass through using each(). What I have at the moment is the final count added at the end. For example.
Say I have 100 divs, for every pass through it should add the new count as it counts it, like so 1,2,3,4,5,6,7... and so on. But at the moment it counts all the objects and just appends 100 at the end. Please can someone point me in the direction to where I'm going wrong?
I've added a very basic version of what I'm hoping to achieve below... also here is a JSbin (I tried jsfiddle but it seems to be down for me) .
$(".toCount").each(function(i){
$("#count").text(i + 1);
});
$('input').on('click',function () {
var len = $(".toCount").length;
var arr = [];
for (var i = 0; i < len; i++ ) {
arr.push(i+1);
}
$('#count').text(arr.join());
});
I don't know what you mean by 1, 2, 3 ... in case that you want to count the elements step by step you can use setInterval function:
$('input').on('click',function () {
var l = $(".toCount").length,
$c = $('#count'),
i = 0;
var t = setInterval(function() {
i++;
$c.text(i);
if (i === l) clearInterval(t);
}, 10);
});
http://jsbin.com/eronel/17/edit
use append();
Insert content, specified by the parameter, to the end of each element in the set of matched elements.
in your case text() is replacing your div's text so u get 100 at the end ..
$("#count").append(i + 1);
Use append
$("#count").append(i + 1);

JavaScript / jQuery or something to change text every some seconds

I need JavaScript or jQuery something to change text every few seconds... without the user doing anything.
Example:
"Welcome" changes to "Salmat datang" changes to "Namaste", etc. after 3 seconds and loops back.
As others have said, setInterval is your friend:
var text = ["Welcome", "Hi", "Sup dude"];
var counter = 0;
var elem = document.getElementById("changeText");
var inst = setInterval(change, 1000);
function change() {
elem.innerHTML = text[counter];
counter++;
if (counter >= text.length) {
counter = 0;
// clearInterval(inst); // uncomment this if you want to stop refreshing after one cycle
}
}
<div id="changeText"></div>
You may take a look at the setInterval method. For example:
window.setInterval(function() {
// this will execute on every 5 seconds
}, 5000);
You can use setInterval to call a function repeatedly. In the function you can change the required text.
The list of texts to change between could be stored in an array, and each time the function is called you can update a variable to contain the current index being used. The value can loop round to 0 when it reaches the end of the array.
See this fiddle for an example.
setInterval(function(){
alert('hello, do you have a beer?');
}, 1000);
where 1000 ms = 1 second.

Where to put this block of script so that this slideshow can move automatically?

I asked a question before on how to make the jQuery Blinds slideshow move automatically and somebody answered on this page (the one with 12 votes):
Is there a way to make this slideshow move automatically?
Seems like the code is working for most people but I can't get it to work for me. I used the original demo file and placed the code at the very bottom of jquery.blinds-0.9.js, right after "})(jQuery);" but still the slideshow isn't moving. What am I doing wrong? I checked the class names and they are correct.
This is that block of script:
var SlideChanger = function(seconds_each) {
var index = -1;
// on the first cycle, index will be set to zero below
var maxindex = ($(".change_link").length) - 1;
// how many total slides are there (count the slide buttons)
var timer = function() {
// this is the function returned by SlideChanger
var logic = function() {
// this is an inner function which uses the
// enclosed values (index and maxindex) to cycle through the slides
if (index == maxindex)
index = 0; // reset to first slide
else
index++; // goto next slide, set index to zero on first cycle
$('.slideshow').blinds_change(index); // this is what changes the slide
setTimeout(logic, 1000 * seconds_each);
// schedule ourself to run in the future
}
logic(); // get the ball rolling
}
return timer; // give caller the function
}
SlideChanger(5)(); // get the function at five seconds per slide and run it
Try wrapping the last line SlideChanger(5)(); in a document.ready, like this:
$(function(){SlideChanger(5)();})
Otherwise $(".change_link").length will prob return 0

Is there a way to make this slideshow move automatically?

This is the slideshow that we used:
http://www.littlewebthings.com/projects/blinds/
and this is the JS file:
http://www.littlewebthings.com/projects/blinds/js/jquery.blinds-0.9.js
However, this slideshow doesn't have a setting that makes it go through each image automatically. You still have to click on the numbers below it to see the images. Does anybody know what to add into the javascript code to make it go through each image automatically?
Thanks!
This solution uses closures and recursion.
var SlideChanger = function(seconds_each) {
var index = -1;
// on the first cycle, index will be set to zero below
var maxindex = ($(".change_link").length) - 1;
// how many total slides are there (count the slide buttons)
var timer = function() {
// this is the function returned by SlideChanger
var logic = function() {
// this is an inner function which uses the
// enclosed values (index and maxindex) to cycle through the slides
if (index == maxindex)
index = 0; // reset to first slide
else
index++; // goto next slide, set index to zero on first cycle
$('.slideshow').blinds_change(index); // this is what changes the slide
setTimeout(logic, 1000 * seconds_each);
// schedule ourself to run in the future
}
logic(); // get the ball rolling
}
return timer; // give caller the function
}
SlideChanger(5)(); // get the function at five seconds per slide and run it
What we are doing here is exposing the inner function timer outside of the function in which it was defined (SlideChanger). This function (timer) has access to the variables defined inside of SlideChanger (index and maxindex).
Now that we have set up the variables in the enclosing environment and a function to return to the caller, we can set up the logical engine in logic. When logic is run, it uses index and maxindex to determine which slide should be shown next, shows the slide, and schedules itself to be run again in the future.
When called, the returning function calls logic to get the ball rolling. Then logic repeats indefinitely by scheduling itself to run in the future each time it is run.
So, to summarize, we call SlideChanger with a numeric argument x. It returns a function that, after being called, will change the slide every x seconds.
Another way to write the same concept.
(function(seconds_each) {
var index = -1;
// on the first cycle, index will be set to zero below
var maxindex = ($(".change_link").length) - 1;
// how many total slides are there (count the slide buttons)
return function() {
// this is the function returned by SlideChanger
var logic = function() {
// this is an inner function which uses the
// enclosed values (index and maxindex) to cycle through the slides
if (index == maxindex)
index = 0; // reset to first slide
else
index++; // goto next slide, set index to zero on first cycle
$('.slideshow').blinds_change(index); // this is what changes the slide
setTimeout(logic, 1000 * seconds_each);
// schedule ourself to run in the future
}
logic(); // get the ball rolling
}
})(5)(); // get the function at five seconds per slide and run it
JavaScript is a nice language with many functional programming constructs such as higher order functions (functions that either create functions or accept functions as parameters) and anonymous functions. For more info see http://www.ibm.com/developerworks/web/library/wa-javascript.html
ecounysis's solution would work but it's unnecessarily complicated. Here's a simpler way using setInterval, modulo, and not wrapping it in an extra function:
function startSlideshow(ms) {
var index = -1;
var count = $(".change_link").length - 1;
return setInterval(function() {
index = (index + 1) % count;
$('.slideshow').blinds_change(index);
}, ms);
}
After a quick scan through the source, I didn't see a built-in API for auto-advancing the slides. However, you could use an alternative slideshow, like this one:
http://jquery.malsup.com/cycle/
All you need is to include a timer on it and call the blinds_change event. That works for me.

Categories

Resources