Basically I have a class counting system that displays the number of classes and displays them in a span element. Below is the code:
$.get('other.html', function(data) {
$('#total').html($('.doc', data).length);
});
This works perfectly, however I'd like a way to have the numbers increasing one by one since the span element contains 0 when the page loads. Here's an example (the numbers increasing on here).
For this I have tried setTimeout and despite this not working anyway, I released it would simply delay the function and then display the end number. I have heard of periodical or something similar being used but could not find this in the example source code.
I am really sorry for more poor phrasing. If you have no idea what I mean then just ask and I'll try rephrase or find a better example.
The key is the function which increases the number should set a setTimeout to call itself, before termination. This way it will always be called again. If you want the option to stop the incrementing, you can add a global variable, and the function will only set a new timeout when that variable is true.
Example:
var doIncrement = true;
var numberToIncrement = 0;
function increment {
numberToIncrement++;
$('#mySpan').text(numberToIncrement);
if (doIncrement) {
setTimeout(increment, 1000);
}
}
You could use the setInterval function that allows you to run code at some time intervals. clearInterval allows to stop the task.
http://jsfiddle.net/d52Pw/
var $totalEl = $('#total');
$.get('other.html', function(data) {
var len = $('.doc', data).length,
count = 0,
int = setInterval(function () {
if (++count === len) {
//when we reach len, we stop the task
clearInterval(int);
}
$totalEl.html(count);
}, 500); //run every 1/2 sec
});
Related
I want to build a simple banner image slider functionality, but instead of sliding, the images are supposed to fade in and out.
It's a Drupal project, so I don't know how many images are going to be used.
The structure is simple enough:
<div class="banner-container">
<!-- potentially a lot of divs with background images -->
</div>
What I want to do is essentially iterate through this "array" of divs let the currently active one fade out and let the one that the array is pointing to at the moment fade in.
I thought I could get it to work like this:
var a = $('#banner-container').children();
while(1) {
a.each(function(){
$('.active').fadeOut(500).removeClass('active');
$(this).fadeIn(500).addClass('.active');
})
}
Obviously there is a lot wrong in my code, I have run into multiple issues, but the one I cannot seem to solve is getting the loop to wait between the iterations. To my knowledge, a traditional loop like foreach could just have some sort of wait function added to the end of it and execute that wait in every loop. But the .each() seems to execute every iteration simultaneously. How can I loop through an array like this (potentially infinitely) and wait like 5 seconds every time?
I read somewhere that the animate functions work asynchronously, and I assume the same goes for CSS transforms, so creating fadeIn, and fadeOut classes and try this with CSS wouldn't work.
You're looking for the setTimeout and setInterval functions: You pass a function into them with a timeout (in milliseconds), and they call the function after that many milliseconds (repeating, in the case of setInterval).
So for instance:
var a = $('#banner-container').children();
var index = 0;
run();
function run() {
a.filter('.active').fadeOut(500).removeClass('active');
a.eq(index).fadeIn(500).addClass('active');
index = (index + 1) % a.length; // Wraps around if it hits the end
setTimeout(run, 1000);
}
That will update the first div, then a second later the next div, and so on.
Live Example:
// Scoping function to avoid creating globals
(function() {
var a = $('#banner-container').children();
var index = 0;
run()
function run() {
a.filter('.active').fadeOut(500).removeClass('active');
a.eq(index).fadeIn(500).addClass('active');
index = (index + 1) % a.length; // Wraps around if it hits the end
setTimeout(run, 1000);
}
})();
#banner-container a {
display: none;
position: absolute;
}
#banner-container {
position: relative;
}
<div id="banner-container">
<a>one</a>
<a>two</a>
<a>three</a>
<a>four</a>
<a>five</a>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
In the above, I've used setTimeout, which only schedules a single callback, because I find I write fewer bugs when the thing I'm calling has to explicitly re-schedule the next call. :-) But you could also use setInterval(run, 1000); which would call run at roughly one-second intervals, until/unless you told it to stop via clearInterval.
you can't use a loop for this because of the nature of javascript, you will have to use recursion instead, something like this untested code should work..
function loopNext(currentIndex){
// set the current index on the first call
if('undefined' === typeof currentIndex) currentIndex=0;
// the group of image divs
var images = $(".imagesDivs");
// if the current index doesn't exist,
// we've looped thru them all, reset the index
if('undefined' === typeof images.eq(currentIndex)) currentIndex=0;
// fade out the previous one and fade in the first one
images.fadeOut('slow', function(){
images.eq(currentIndex).fadeIn('slow');
});
// fade the next one every 3 seconds or so
setTimeout(function(){
loopNext(currentIndex+1);
}, 3000);
}
To start the loop you can just call it without any parameters..
loopNext();
you can use setTimout and go to the next element or start over:
setTimout(function(){
var current = $('.active');
var next = current.next().length > 0 ? current.next() : $('.banner-container > div').first();
current.fadeOut(500).removeClass('active');
next.fadeIn(500).addClass('.active');
},5000);
The problem
I'm trying to simplify a long javascript code and i have a problem with identifying callbacks.
I have a large array with elements to animate on page
[selector, activate interval, hide after]:
things_to_move = [
['.ufo, .chefoven, .sushi', 9900, 2000],
['.hotdog,.pizzaman,.boyballon', 12090, 3600],
(...)
]
Basically, the aim is to to activate each of the selectors every x seconds, and hide them x seconds later, as per the example above.
Current code
After many tries, I ended up with this:
// Activate the element, and set timeout to hide it
var showFun = function(index1) {
$(things_to_move[index1][0]).addClass('move');
setTimeout( function(){hideFun(index1)},things_to_move[index1][2]);
}
// Hide the element
var hideFun = function(index2) {
$(things_to_move[index2][0]).removeClass('move');
}
// Loop through all items and set the interval for each one
for(_A=0; _A < things_to_move.length; _A++) {
setInterval(function(){showFun(_A)}, things_to_move[_A][1]);
}
But of course this doesn't work. Every time the showFun function is called, it takes the value of _A after the loop finished and not the value at which setInterval was set.
Question
So the question is, how can i pass a unique index into the setInterval callback, so the callback knows which array item to use?
Final solution
If anyone is interested, the final solution: Fiddle
The most direct way to solve it is using closures.
Try something like this:
for(_A=0; _A < things_to_move.length; _A++) {
setInterval((function(_innerA){
return function(){ showFun(_innerA); };
})(_A), things_to_move[_A][1]);
}
I'm having some issues with simulating live typing with jQuery. My Javascript is as follows (with a live demo here).
$(document).ready(function () {
var keystrokes = [];
var value = "";
var counter = 0;
window.setInterval(pushKeystrokes, 100);
function pushKeystrokes() {
keystrokes.push({
value: value
});
}
$("#test").keyup(function () {
value = $(this).val();
});
$("#button").click(function () {
$("#test").val("");
$.each(keystrokes, function () {
window.setTimeout(function () {
$("#test").val(keystrokes[counter].value);
}, 100 * counter);
counter++;
});
});
});
This is supposed to wait for input to a text field called test, and as soon as a button is clicked, it should clear that text field and simulate typing the characters the user typed in real-time. For some reason, my call to setTimeout only produces the very last value in the array.
However, if I set Math.random as the value of the text field in the setTimeout instead of keystrokes[counter].value, it seems to update fine every 100 milliseconds as it should. What exactly am I doing wrong? I'm guessing it has something to do with scope.
Edit:
Sorry I wasn't clear. I would like to preserve delays in user action, i.e. waiting a few seconds before typing, typing words at different speeds, etc. Is this still possible?
I've edited the code you posted in your JSBin, modified a few things here and there.
The logic behind the rewritten script is added in the form of comments.
Here's an example
Try this example http://jsbin.com/eVOcOku/4/.
In your example you have additional issue with timeInterval.
There are a few problems you're having here, some to do with unnecessary code, and some to do with the nature of setTimeout
First of all the pushKeyStrokes() function seems dodgy; it only checks every 100 ms? Besides, it's not needed because later you can just go through the string provided by the input once the button is pressed, and you can do that using charAt.
Secondly, you're referring to the value "counter" within your setTimeout function, but by the time that function is called the counter value will have reached the length of the input string; counter++ will already have been called every time before the first call to the character display function is even made!
In any case, I modified your JS Bin; hope it makes sense and let me know if you have any questions:
$(document).ready(function() {
var value = "";
$test = $("#test");
$("#button").click(function() {
value = $test.val();
$test.val("");
for (var i = 0; i < value.length; i++)
{
window.setTimeout(addChar, 100 * i, value.charAt(i));
}
function addChar(char)
{
$test.val($test.val() + char);
}
});
});
I have a button in my page that's looping a series of DIVs and editing them (appending text mostly, nothing serious),
The thing is, the number of DIVs is changing by the user (The user can add or remove them freely),
I'm looping the DIVs via jQuery $.each function:
var DomToEdit = $('.divs_to_edit');
$.each(DomToEdit, function() { $(this).append('text'); ... });
the variable DomToEdit contains somewhat unlimited number of divs, and then I refer to them via the $.each function.
Sometimes while doing the $.each loop the user gets to wait for a couple of secons, and in worse cases the browser is crashing
Is there a way to prevent this? Maybe having the loop "sleep" after 50 DIVs?
Thanks
EDIT: I didn't use the same ID, sorry - it was a flaw in my explanation. I use the same class. :)
The first argument of the function in the .each handler is the index of the current element. you can simply add a check before it, and return false to stop the loop.
$.each(DomToEdit, function(i) { // or DomToEdit.each(function() {
if (i === 50) return false;
..
DomToEdit is a jQuery object, so $.each(DomToEdit, fn) and DomToEdit.each(fn) are equivalent.
A more effective method is to cut off the elements, using .slice(0, 50).
DomToEdit.slice(0, 50).each( function(i) {
..
Add a timer which will execute append 50 div's every 5 seconds and works thru the array of div until it finishes iterating all div.
Below code works on 50 div every 5 seconds.
var DomToEdit = $('#divs_to_edit');
var timer = setInterval( function () { //<-- Create a Timer
$.each(DomToEdit, function(index) { //<-- Iterate thru divs
if (index == 50) return; //<-- Return on 50 for later
$(this).append('text');
});
DomToEdit = DomToEdit.slice(0, 50); //<-- Slice the processed div's
// Clear timer when all elements are processed.
if (DomToEdit.length == 0) {
clearInterval(timer);
}
}, 5000); // <-- Do the steps on every 5 secs
Whenever I think that code can potentially cause a crash, I'll create a self-decementing breaker variable that breaks out of a loop after a certain number of loop cycles.
var breaker = 100;
while(true) {
breaker--;if(breaker<0){console.log("Oh snap batman");break;}
console.log("CRASH");
}
The method could execute alternative code that works around the crash as well. Usually, I just try to fix the code somehow ;)
You could setTimeout to 0 in order to queue the processing of each element into the execution stack (0 makes it just queue without delay):
$.each(DomToEdit, function() {
var elem = $(this);
setTimeout(function() { elem.append('text'); }, 0);
});
You could queue the tasks and then execute tasks
in batches of X every Y milliseconds:
var queue = [];
$.each(DomToEdit, function () {
queue.push( $.proxy( function () {
$(this).append('text');
}, this ));
});
window.setInterval( function(){
var l = 100;
while( queue.length && l-- ) { //Keep executing tasks until there
//is no more or maximum amount of tasks
//executed for this batch is executed
queue.shift()();
}
}, 50 );
The real fix is of course carefully review what you are doing and fix that. $('#divs_to_edit') always returns a single element max so .each doesn't make much sense here for example...
It's possible with an extremely large number of elements, that it would actually be less processor intensive to pull the entire container element as a string and run a Javascript .replace() on it and replace the entire container, than looping through hundreds of thousands of elements?
I know at first glance (due to the title) this looks like one of the "Did you try searching Google before posting?" questions, but I can't seem to find an answer for the specific issue I'm experiencing. Sorry if I'm a noob.... still learning :)
I need to simulate a pause in javascript, but the setTimeout(function_call, timeout) function is not working for me. Reason being... when that setTimeout function is called, it then makes the function call asynchronously.
A little background:
I'm trying to simulate text being typed into a div at randomly timed intervals. I want it to appear as if a person is actually typing a message while the user is viewing the page. Since the timeout is a random interval and the function call is made asynchronously, the text ends up being printed in a random order.
Here is a snippet of what I have thus far:
typeString: function(s)
{
for(var i=0;i<s.length;i++)
{
var c = s.charAt(i);
var temp = setTimeout("MessageType.typeChar('" + c + "')", this.genRandomTime());
}
}
Thanks in advance for your help.
CJAM
UPDATE: By adding the timer delay to a varialbe, it enabled me to offset timeOut for the asynchronous calls. Thank you all for your quick responses. Here is the updated code:
typeString: function(s)
{
var delay = 0;
for(var i=0;i<s.length;i++)
{
var c = s.charAt(i);
setTimeout("GoogleTyper.typeChar('"+c+"')", delay += this.genRandomTime());
}
}
Have you tried cumulatively setting the timeout? Stick a variable outside of your loop and initialize it to 0. Let's call it timeout for now. Add a random amount of time to this variable at the beginning of each iteration of your loop, and make the timeout work off of that. This way, you are ensured that functions are being called in order.
Your problem is you are using one all your times are delayed starting from now - the next timer needs to be fired after the previous. Simply add the previous timer delay to the new timer.
typeString: function(s)
{
var delay = 0;
for(var i=0;i<s.length;i++)
{
var c = s.charAt(i);
delay = delay + this.genRandomTime();
var temp = setTimeout("MessageType.typeChar('" + c + "')", delay );
}
}
Instead of passing to each timer event that character to be displayed, let each event handler grab the next character off of a queue (array, list whatever), so the order is maintained.