I need javascript function that runs timer and when timer expired it calls function calllink() that sets new x1 variable witch value is then passed to settimeout duration delay.
For example...here is the code:
var x1 = 5000;
function calllink() {
alert("Delayed " + x1);
x1 = 1000;
}
setTimeout(function() { calllink(); }, x1);
So when running this code it needs to delay first 5seconds then display message:
Delayed 5000 then run again setTimeout and when time expired display message Delayed 1000
I need this for programming epg, so i read xml file, read into variable x1 from xml file for channel duration (endtime - starttime) and then execute this function, when time expired it calls calllink() that then read from xml next program duration (endtime-starttime) and then sets new value of variable x1 that is set to setTimeout x1.
If is this possible to do? I was trying today, and no go. I always getting in delay of 1seconds messages.
UPDATED Question:
Ok...since i need to read epg for 130 channels in my list i put this function in onLoad:
// get epg info for all items
for (var count = 0; count <= max; count++) {
epg(count);
setEPGTimer(count);
}
// set epg
function setEPGTimer(count) {
epg(count);
setTimeout( function() { setEPGTimer(count); }, seconds[count] );
}
and json call that retrieves info about show time, start time, end time and description
// get epg
function epg(count) {
// read epg from url
$.getJSON( "http://mywebsite.com/epg.php?channel=" + epgs[count] + "&type=channel", function( data ) {
var item = [];
$.each( data, function( key, val ) {
if ( typeof (val.epg) != "undefined" && val.epg !== null) {
item.push( "<li class='epg'><b>" + count + ". " + channel[count] + "</b></br>" + val.epg.start1 + " - " + val.epg.title1 + "</li>" );
// make global variable epg description
desc[count] = val.epg.desc1;
// convert start and end time to seconds
var a1 = val.epg.start1.split(':');
var a2 = val.epg.stop1.split(':');
var seconds2 = (+a2[0]) * 60 * 60 + (+a2[1]) * 60;
var seconds1 = (+a1[0]) * 60 * 60 + (+a1[1]) * 60;
var seconds0 = (seconds2 - seconds1);
// check if is not time in minus
if (seconds0 > 0) {
seconds[count] = seconds0;
} else{
seconds[count] = 0;
}
}
});
$( ".jTscroller ul#" + count + " li.epg" ).remove();
$( "<li/>", { "class": "", html: item.join( "" ) }).appendTo( ".jTscroller ul#" + count + ".channels" );
});
}
my max variable have value 130..so I was trying to increase timer variable name to 130 (timer[0], timer[1]....timer[129] and put value of seconds[count] into that timer variable (timer[0] = seconds[0], timer[1] = seconds[1].....timer[129] = seconds[129]).
And then when time is out then calls function epg(count) that retrieves new data info for show and sets variable seconds[count] to new value, refreshed li element with new show name durataion...
So the question is how can I loop 130timers for 130channels and when one or more timers time expire it refresh that channel ul with new values?
You need to additionally add your setTimeout call into your calllink function itself, to make it recursive like this:
var x1 = 5000;
function calllink() {
alert("Delayed " + x1);
x1 = 1000;
setTimeout(function() { calllink(); }, x1);
}
setTimeout(function() { calllink(); }, x1);
Note that you should probably add some kind of conditional so that it won't repeat forever, unless that is what you want it to do.
I think this is want you want:
var x1 = getNextFromXml();
function calllink() {
alert("Delayed " + x1);
x1 = getNextFromXml();
setTimeout(calllink, x1);
};
setTimeout(calllink, x1);
Now you only have to implement the function getNextFromXml.
Related
I've encountered a problem that's driving me crazy for like 10 days now... Basically i have a function that fire (the handleText) and I want to wait the end of that function before running a second one (the handleBackground).
I've tried deferred and promises but I think I don't understand them well because I can't get it to work the way I want.
function handleText(){
//BLAST INIT
var blastedwords = $('.baselineHeader').blast({
delimiter: 'word',
});
//SHUFFLE ORDER IN ARRAY
blastedwords = shuffleAds( blastedwords);
function shuffleAds(arr){
for(var j, x, i = arr.length; i; j = parseInt(Math.random() * i), x = arr[--i], arr[i] = arr[j], arr[j] = x);
return arr;
}
//ADD CLASS TO SPAN CREATED WITH BLAST WITH A RANDOM DELAY
blastedwords.each(function(index) {
var min = 45, max = 100;
var delay = Math.floor(Math.random() * (max - min) + min);
var that = $(this);
var t = setTimeout(function() {
$(that).addClass("test");
}, delay * index);
});
}
function handleBackground(){
$('.baselineHeader').addClass('processed');
}
handleText();
handleBackground();
Right now, handleText start, and handleBackground (my second function that I want to run after the first one is finished) fire at the same time and doesn't wait for handleText to finish.
I want handleText to run and wait for the each loop to give class to every span created with blast.js before running handleBackground.
Can someone help me with this ?
Have a great day folks :)
I'd recommend setting up a global variable totalTime which you can use to add up the inidivual delays. That way you can use another setTimeout to call the function handleBackground() after totalTime has passed.
var totalTime = 0;
blastedwords.each(function(index) {
var min = 45,
max = 100;
var delay = Math.floor(Math.random() * (max - min) + min) * index;
totalTime += delay;
var that = $(this);
var t = setTimeout(function() {
$(that).addClass("test");
}, delay);
});
setTimeout(handleBackground, totalTime);
Define delay outside of your function and each iteration increase the delay so that the next one is a random amout of time after the last one.
var delay = 0;
blastedwords.each(function(index) {
var min = 45, max = 100;
delay += Math.floor(Math.random() * (max - min) + min);
var that = $(this);
var t = setTimeout(function() {
$(that).addClass("test");
}, delay * index);
});
Say I have a function OfInterest, called by functions A and B, and that calls function X and Y. I'm looking for a way of viewing:
OfInterest -- 200 ms total time
X -- 150 ms total time
Y -- 50 ms total time
...such that it includes both the calls to OfInterest by A and B.
In the Chrome profiler, this would be the top-down view zoomed in on OfInterest, except that AFAIK there's no way of including calls to OfInterest from both A + B at the same time. The bottom-up view gets the right total time for OfInterest, but AFAIK there's no way of seeing X + Y in that view.
Is there a way of getting Chrome to spit this out, or using a different profiler such as Firebug to see this?
This github project gives top down tree for jvascript call stat
https://github.com/brucespang/jsprof
When i was looking for a javascript function call profiler i found a small script, which i modified as per my need, this script is very simple it will show statistics of all global functions in that window object though it doesnt list names of nested functions called.
function callLog()
{
var functionPool = {}
for( var func in window )
{
if (typeof(window[func]) === 'function')
{
functionPool[func] = window[func];
(function(){
var functionName = func;
var totalTime= 0;
var noOfTimes =0;
var minTime= 0;
var maxTime =0;
window[functionName] = function(){
var args = [].splice.call(arguments,0);
var startTime = +new Date;
functionPool[functionName].apply(window, args );
var duration = new Date - startTime;
if (duration> maxTime)
maxTime= duration;
if (duration< minTime)
minTime= duration;
totalTime = totalTime + duration;
noOfTimes++ ;
console.log('Executed: ' + functionName + '('+args.join(',')+')' + " Time[" + duration + "ms]"+" Total Time[" + totalTime +"ms]" +" No of Times[" + noOfTimes + "]" + "max Time [" + maxTime+ "ms]" + "min Time [" +minTime +"ms]");
}
})();
}
}
}
I currently got this:
var xnumLow = 3000;
var xnumHigh = 4900;
var ynumLow = 9969;
var ynumHigh = 13900;
var ts = Math.round((new Date()).getTime() / 1000);
for (y=ynumLow; y<ynumLow; y++)
{
for(x=xnumLow; x<xnumHigh; x++)
{
$('#box').append(y + " - " + x);
}
}
Now I would like it to append new whole y "row" every 10 seconds, so they all dont append all in once.
The y "row" is the outer for() loop
How can I do this?
I got:
var refreshId = setInterval(function(){ (...) }, 10000);
But I don't know where to merge this with the above code, in order to work correct.
(function () {
var xnumLow = 3000,
xnumHigh = 4900,
ynumLow = 9969,
ynumHigh = 13900,
currentY = ynumLow,
delay = 500,
displayData = function () {
var out = [],
x;
for (x=xnumLow; x<xnumHigh; x++) {
out.push( currentY + "-" + x );
}
console.log(out.join(",")); //do the append here
currentY++;
if (currentY<ynumHigh) {
window.setTimeout(displayData,delay);
}
};
displayData()
})();
setInterval(function () {
// code that appends a box
}, 10000);
https://developer.mozilla.org/en-US/docs/DOM/window.setInterval
var y = ynumLow;
function addRow()
{
for (x = xnumLow; x < xnumHigh; x++) {
$('#box').append(y + " - " + x);
}
if (y++ < ynumHigh)
refreshId = setTimeout(addRow, 10000);
}
addRow();
edited as Pete suggested for clarity
I would do it something like this:
var xnumLow = 3000;
var xnumHigh = 4900;
var ynumLow = 9969;
var ynumHigh = 13900;
var x, y = ynumLow; //don't forget to declare your variables!
var ts = Math.round((new Date()).getTime() / 1000);
(function addYRow() { //Create a function that adds the X elements
for(x=xnumLow; x<xnumHigh; x++)
{
$('#box').append(y + " - " + x);
}
y++; //don't forget to increment y
if(y < ynumHigh) { //only re-call if we aren't done yet
setTimeout(addYRow, 10000); //Recall the function every 10 seconds.
}
}());
Looking at some of the other answers, it's important to realize that you don't want to set up a bunch of things to happen 10 seconds from a given point (which is what happens if you do a loop calling setTimeout(). Instead, I assume you want to add a row, then wait 10 seconds, then add another row. This can only be achieved by adding a row (usiny, in my case, the addYRow() function), then delaying 10 seconds before re-calling the add-a-row function.
Column Delay:
In response to the question about how to do a 500ms delay in the x row, that's a little tricky, but not too bad. You just have to nest things one more time:
var y = ynumLow; //don't forget to declare your variables!
var ts = Math.round((new Date()).getTime() / 1000);
(function addYRow() { //Create a function that adds the X elements
var x = xnumLow;
(function addXCol() { //Create a function that adds each X element
$('#box').append(y + " - " + x);
x++;
if(x < xnumHigh) { //if x is not done, call addXCol 500ms later
setTimeout(addXCol, 500);
} else {
y++;
if(y < ynumHigh) { //If x is done but y isn't, call addYRow 10 seconds later
setTimeout(addYRow, 10000); //Recall the function every 10 seconds.
}
}
}());
}());
Note that if you want to delay the start of the column/row addition (e.g., if you want to put a 500ms delay between when a row is added and when the first column is added, you'll need to adjust the addXCol() expression creation to look like this:
setTimeout(function addXCol() { //Create a function that adds each X element
//...
}, 500);
This will put that initial delay in. Hope that helps.
Something like this?
var refreshId = setInterval(function(){
$('#box').append(++y + " - " + x);
}, 10000);
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.
Thanks Sean for your help. I have moved the calculation code to its own method as you suggested. After debugging I have realised the problem is something to do with storing values globally. I think I have accidently created closures. I have moved the calculation code into a method named calculate() that is run once so that the values of the variable are set globally. but while the method is running the correct values are set, as soon as the method exits and the move() method is called all the values are set to undefined or 0. In the calculate method I even used a hidden field to set the value ('mills') so that I can pass the interval time to this testTimer = window.setInterval(move,document.getElementById('mills').value,"testTimer"); Code of thecalculate()` method looks like this:-
var duration_equiv_seconds = 0;
var duration_equiv_millsec = 0;
var elapsed_percentage = 0;
var elapsed = 0;
var duration = 0;
// function in one JS file
function calculate () {
duration = document.getElementById('callDuration').value;
elapsed = document.getElementById('callElapsed').value;
duration_equiv_seconds = duration/100;
duration_equiv_millsec = duration_equiv_seconds * 1000;
document.getElementById('mills').value = Number(duration)/100 * 1000 ;
elapsed_percentage = (elapsed/duration) * 100;
display_progress(elapsed_percentage);
var countCalc = 0;
document.getElementById('status_message').innerHTML =" CountCalc = " + countCalc + " duration = " + duration + " elapsed =" + elapsed + " elapsed2Var =" + elapsed2Var +" duration_equiv_seconds = " + duration_equiv_seconds + " duration_equiv_millsec=" + duration_equiv_millsec + "
elapsed_percentage=" + elapsed_percentage; countCalc++; return duration_equiv_millsec; }
function voice_progress (time_interval){
// outer timer
voiceTimer = window.setInterval(function(){
handleDurationElapsedRequest()
// outside
function move(){
var count = 0;
duration = document.getElementById('callDuration').value;
elapsed = document.getElementById('callElapsed').value;
duration_equiv_seconds = duration/100;
duration_equiv_millsec = duration_equiv_seconds * 1000;
elapsed = Number(elapsed) + Number(duration_equiv_seconds);
elapsed_percentage = (elapsed/duration) * 100;
document.getElementById('callElapsed').value = elapsed;
display_progress(elapsed_percentage);
move_bar(elapsed_percentage);
if (elapsed_percentage >= 100){
terminate_timer(testTimer);
}
document.getElementById('status_message').innerHTML =" at the endAt the end" + count + " duration = " + duration + " elapsed =" + elapsed +" duration_equiv_seconds = " + duration_equiv_seconds + " duration_equiv_millsec=" + duration_equiv_millsec + " elapsed_percentage=" + elapsed_percentage;
count++;
return duration_equiv_millsec;
}
var sleepTime = calculate(); // sleep time returns 0
testTimer = window.setInterval(move,document.getElementById('mills').value ,"testTimer");
},time_interval,"voiceTimer"); // end of outer Timer (time_interval = 1500) called from <body onload="voice_progress(1500);">
}
//.................................................................`enter code here`
// in another JS file
// XMLHttpObject is created called, server returns the correct values
function handleDurationElapsedRequest(){
if(xmlHttpObject.readyState==4){
if(xmlHttpObject.status==200){
var resp = xmlHttpObject.responseText;
var respArray = resp.split("-");
document.getElementById('callElapsed').value = respArray[0]; //value set here is 47
document.getElementById('callDuration').value = respArray[1]; // value set here is 240
document.getElementById('mills').value = respArray[1]/100 * 1000 ;
}
}
}
The problem is that you are doing the calculations inside of your callback, so that when you start, all of your variables are still 0.
Pull the time calculation out into its own function, and call that before you call setInterval, and your values will start with the right numbers. (Continue to call it in your callback, of course.)
You also are re-scheduling your setInterval call inside move. This is probably wrong, because it will be re-called every interval, so now you have 2 functions being called on a timer. If you use setTimeout, then you might want to reschedule, but not with setInterval.
You also have the same calculation done twice -- JavaScript is real code, and you should treat it as such; Pull that out into a function you can call.
-- Edit --
Now call calculate() from move() so you don't have the same code in 2 places. ;-)
callDuration and callElapsed are only set from handleDurationElapsedRequest, and only when the request is finished. That's probably why you're getting 0. What exactly are you trying to do here? Is the whole page on line somewhere?
Thanks for help. I have fixed the problem. The problem was I was reading the values 'callDuration' and 'callElapsed' before they were even updated after they have been retrieved from the server. I fixed this by setting a timeout of 1.5 seconds before the code that reads these values is executed ie window.setTimeout("calculate()",1500);
Thanks for the help again.