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.
Related
I'm making a little clock using getTime(), but the output won't refresh. I have tried this:
<p id="clock"></p>
var i;
for (i=0; i < 5; i++){
var date = getTime;
var time = time.getHour() + ":" + time.getMinute() + ":" + time.getSecond()
getElementById('clock').innerHTML = time;
}
Though it just keeps my tab in a constant state of loading. How do I fix this? Thanks!
Just move your code inside setInterval()
let i = 5;
const timer = setInterval(() => {
var date = getTime;
var time = time.getHour() + ":" + time.getMinute() + ":" + time.getSecond()
getElementById('clock').innerHTML = time;
i--;
if (i < 0) {
clearInterval(timer)
}
}, 1000);
So setInterval() lets your code run asyncrounously, that means it doesnt block the rest of the execution, because it runs "seperately" (I would like to describe it better, but my english skills are lacking).
setInterval runs your code every 1000 ms (as specified) forever, unless you dont clear it with clearInterval(). If you want to make a timer it is quiet useful.
this () => {} is an arrow function. You can also use function(){}, if you want, in this case it makes no difference.
Here is the w3schools reference for setInterval(): https://www.w3schools.com/jsref/met_win_setinterval.asp
and here is the MDN reference to asynchronous javascript: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous
Good luck with your project ;)
I hope this helps
setInterval (function refresh(){
var fecha = new Date();
var hora = fecha.getHours();
var minutos = fecha.getMinutes();
var segundos = fecha.getSeconds();
var textoHora = `
${hora}:${minutos}:${segundos}
`;
document.getElementById('clock').innerHTML = textoHora;
}, 1000);
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 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.
okay so i want if my counter reaches the maximum count, it starts over, with the default counter number which is 0 here is my code:
var picCount = 0; // global
var maxCount = 4;
//Pictures, to add more then 4 pics, add var picFive = "link to image here", var picSix ="bla", you get it.. add in picArray ,picFive and ,picSix
//To change the time delay, change it at the body onload and on the setTimeout
var picOne = "http://screenshots.nl.sftcdn.net/nl/scrn/3342000/3342167/modloader-for-minecraft-02-700x406.jpg"
var picTwo = "http://media.moddb.com/images/downloads/1/31/30912/minecraft_blox.png"
var picThree = "http://www.mupload.nl/img/rl6zeofbb.png"
var picFour = "http://www.mupload.nl/img/rl6zeofbb.png"
var picArray = [picOne, picTwo, picThree, picFour]
//
// gets next picture in array
function nextPic() { // check if adding 1 exceeds number of pics in array
if (picCount.length < maxCount.length) {
picCount = (picCount + 1 < picArray.length) ? picCount + 1 : 5000;
// build the image to write to page using the new pic reference
var build = '<img border="0" src="' + picArray[picCount] + '" width="649">\n';
document.getElementById("imgHolder").innerHTML = build;
// repeat this every 10 seconds.
setTimeout('nextPic()', 10 * 1000) //setTimeout is here
} else {
picCount = (picCount - maxCount < picArray.length) ? picCount + 1 : 5000;
// build the image to write to page using the new pic reference
var build = '<img border="0" src="' + picArray[picCount] + '" width="649">\n';
document.getElementById("imgHolder").innerHTML = build;
// repeat this every 10 seconds.
setTimeout('nextPic()', 10 * 1000) //setTimeout is here
}
}
okay so i hope you guys can help me with this..
That's a lot of messy code.
My fix for an implementation would probably look something like this:
var currentPic = 0;
var picOne = "http://screenshots.nl.sftcdn.net/nl/scrn/3342000/3342167/modloader-for-minecraft-02-700x406.jpg"
var picTwo = "http://media.moddb.com/images/downloads/1/31/30912/minecraft_blox.png"
var picThree = "http://www.mupload.nl/img/rl6zeofbb.png"
var picFour = "http://www.mupload.nl/img/rl6zeofbb.png"
var picArray= [picOne,picTwo,picThree,picFour]
function nextPic() {
if (currentPic < picArray.length) {currentPic++;}
else {currentPic = 0;}
var build='<img border="0" src="'+picArray[currentPic]+'" width="649">';
document.getElementById("imgHolder").innerHTML=build;
// repeat this every 10 seconds.
setTimeout('nextPic()',10 * 1000)//setTimeout is here
}
Despite many other issues which I am sure are present in your code, I believe this line is the cause of your particular problem addressed in the question:
if (picCount.length < maxCount.length) {
maxCount and picCount are just numbers. They do not have a length property. Change it to this:
if (picCount < maxCount) {
var currentPic = 0;
var picArray= ["http://screenshots.nl.sftcdn.net/nl/scrn/3342000/3342167/modloader-for-minecraft-02-700x406.jpg",
"http://media.moddb.com/images/downloads/1/31/30912/minecraft_blox.png",
"http://www.mupload.nl/img/rl6zeofbb.png",
"http://www.mupload.nl/img/rl6zeofbb.png"];
function nextPic() {
(currentPic < picArray.length) ? currentPic++ : currentPic = 0;
var build='<img border="0" src="'+picArray[currentPic]+'" width="649">';
document.getElementById("imgHolder").innerHTML=build;
}
setTimeout('nextPic()',10 * 1000);
I made a few changes that make your code cleaner.
Some tips:
No need to store your image URLs in vars before putting them in the array. Just initialize your array with them.
Don't repeat yourself. Whenever you find yourself using the exact same code in multiple places, you probably need to rethink how you are approaching the problem.
Look up the "ternary operator". In my opinion it makes simple conditional statements easier to read.
No need to use maxCount - the max count will be the length of your picArray.
Although not usually required, try to end all statements with a semicolon.
Don't mind the elitist attitude some people have, but at the same time, try to research as much as you can before asking a question.
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.