I have a game that I am making using only pure javascript. Instead of a GUI, It is more like the old command line games and uses a prompt for input.
One of the main components of it is the Clock, which is expressed in hours, and can be checked with the commmand "time" and tells them the value of the variable "time". Here is the code:
var timestrt = 1;
var timer = setInterval(function(){timestrt++;return timestrt;}, 86000); var time = timestrt;
After testing it, I realized that the clock was not changing. So I set it to 10 seconds instead of 86 to be sure that I was waiting long enough, and it still did not want to work
I know that it is probably caused by the prompt and constant alerts, but I am not sure even where to start for a workaround.
Any ideas?
Edit: is it possible to either
1. retrieve the timer from an external page
2. comparing it to an actual clock in real time or 3. Using a animated gif clock in the background and calculating the location of certain pixels as time?
Don't use the native prompts and dialogs, since they stop the script execution time. Instead use simulated ones, for example jQuery IU has prompts and dialog boxes that do not stop execution. Here is an example of that:
$(function() {
$( "#dialog" ).dialog();
var timestrt = 1;
var timer = setInterval(function(){
timestrt++;
var time = timestrt;
$("#time").text(time);
}, 1000);
});
Here is my workaround:
This code is called before the prompt is started:
function initTime() {
var now = new Date();
stS = now.getSeconds();
stM = now.getMinutes();
stH = now.getHours();
}
This is called after the prompt is done:
function computeTime() {
var now = new Date();
var reS = now.getSeconds();
var reM = now.getMinutes();
var reH = now.getHours();
var elapS = reS - stS;
var elapM = reM - stM;
var elapH = reH - stH;
if (elapM < 0) {
reM = reM + 60;
elapM = reM - stM;
}
if (elapS < 0) {
reS = reS + 60;
elapS = reS - stS;
}
Then I convert it to seconds to make it easier to check against:
var finalH = elapH * 3600;
var finalM = elapM * 60;
var finalS = finalM + elapS + finalH;
And check/change the time variable based on how many sets of 86 seconds has passed:
if (finalS > 86 && finalS < 172) {
time = 1;
}
if (finalS > 172 && finalS < 258) {
time = 2;
}
if (finalS > 258 && finalS < 344) {
time = 3;
}
if (finalS > 344 && finalS < 430) {
time = 4;
}
if (finalS > 430 && finalS < 516) {
time = 5;
}
if (finalS > 516) {
time = 6;
alert('5 A.M.');
alert('A clock is chiming...');
alert('6 A.M.');
playing = false;
alert('Thanks for playing! Goodbye!');
}
And that is my alternative to using a setinterval/timer behind multiple prompts and alerts. The last part probably wasn't needed, but since it answered my original question I included it.
Related
Im wondering what is wrong with this for loop here. I'm trying to make a Pomodoro Study Timer, a study technique that suggests that you break down studying into 25-minute chunks that are followed by 3-5 minute breaks. here I have 2 timers that run in sequence, one after the other. When the first timer reaches zero, the second one starts. For now, i have timers set to 5 seconds and 3 seconds respectively in order to make testing quicker. It all works fine until I put the whole thing into a for loop which then brings some unexpected behaviour. I want to loop the entire function based on user input which informs the code on how many times to loop the counters(this isnt setup yet).
The timers are started by pressing a button on an html page. The button executes the pomo() function at the bottom, which contains a loop that should loop the start() function.
PS, I'm a total ultra noob so apologies if this is just terrible code, I'm really new to this :)
var time25 = 5;
var time5 = 3;
var timeElapsed25 = 0;
var timeElapsed5 = 0; // initializes time elapsed to zero
var time = document.getElementsByClassName("header"); //links to html
time[0].innerHTML = time25; // sets output to html
function convertToMin(s) {
mins = Math.floor(s / 60);
let minsStr = mins.toString();
if (minsStr.length === 1) {
mins = '0' + mins;
}
sec = s % 60;
let secStr = sec.toString();
if (secStr.length === 1) {
sec = '0' + sec;
}
return mins + ':' + sec;
}
function start() {
var timer25 = setInterval(counter25, 1000);
console.log("timer1");
function counter25() {
timeElapsed25++
time[0].innerHTML = convertToMin(time25 - timeElapsed25);
if (timeElapsed25 === time25) {
console.log("timer2")
clearInterval(timer25);
timeElapsed25 = 0;
var timer5 = setInterval(counter5, 1000);
function counter5() { //Counter For 5 minute break
timeElapsed5++;
time[0].innerHTML = convertToMin(time5 - timeElapsed5);
if (timeElapsed5 === time5) {
clearInterval(timer5);
timeElapsed5 = 0;
}
}
}
}
}
function pomo() {
for (j = 0; j < 3; j++) {
start();
}
}
You shouldn't call start() in a loop. setInterval() doesn't wait for the the countdown to complete, it returns immediately, so you're starting all 3 timers at the same time.
What you should do is call start() again when both timers complete. To put a limit on the number of repetitions, use a count parameter, and decrement it each time you call again.
var time25 = 5;
var time5 = 3;
var timeElapsed25 = 0;
var timeElapsed5 = 0; // initializes time elapsed to zero
var time = document.getElementsByClassName("header"); //links to html
time[0].innerHTML = time25; // sets output to html
function pomo() {
start(3);
}
function start(count) {
if (count == 0) { // reached the limit
return;
}
var timer25 = setInterval(counter25, 1000);
console.log("timer1");
function counter25() {
timeElapsed25++
time[0].innerHTML = convertToMin(time25 - timeElapsed25);
if (timeElapsed25 === time25) {
console.log("timer2")
clearInterval(timer25);
timeElapsed25 = 0;
var timer5 = setInterval(counter5, 1000);
function counter5() { //Counter For 5 minute break
timeElapsed5++;
time[0].innerHTML = convertToMin(time5 - timeElapsed5);
if (timeElapsed5 === time5) {
clearInterval(timer5);
timeElapsed5 = 0;
start(count - 1); // Start the next full iteration
}
}
}
}
}
function convertToMin(s) {
mins = Math.floor(s / 60);
let minsStr = mins.toString();
if (minsStr.length === 1) {
mins = '0' + mins;
}
sec = s % 60;
let secStr = sec.toString();
if (secStr.length === 1) {
sec = '0' + sec;
}
return mins + ':' + sec;
}
I've programmed this code (javascript countdown) and I have to put 141 of them on page. Doese anybody know if there is some way(program, script etc) that will do the following:
Change from function cdtd1 to function cdtd2 and var sad1 = new Date(); to var sad2 = new Date(); etc.
var d = new Date();
var n = d.getDay();
if(n == 1 || n == 2 || n == 3 || n == 4 || n == 5){
var timer1;
function cdtd1() {
var sad1 = new Date();
var dolazak1 = new Date(sad1.getFullYear(),sad1.getMonth(),sad1.getDate(),23,00,00);
var timeDiff1 = dolazak1.getTime() - sad1.getTime();
if (timeDiff1 <= 0) {
clearInterval(timer1);
$('#dani1Box').remove();
$('#sati1Box').remove();
$('#minute1Box').remove();
$('#sekunde1Box').remove();
}
var sekunde1 = Math.floor(timeDiff1 / 1000);
var minute1 = Math.floor(sekunde1 / 60);
var sati1 = Math.floor(minute1 / 60);
var dani1 = Math.floor(sati1 / 24);
sati1 %= 24;
minute1 %= 60;
sekunde1 %= 60;
$("#dani1Box").html(dani1);
$("#sati1Box").html('7-Dubrava ' + sati1 + ':');
$("#minute1Box").html(minute1 + ':');
$("#sekunde1Box").html(sekunde1);
timer1 = setTimeout(cdtd1, 1000);
}
$(document).ready(function() {
cdtd1();
});
}
I believe what you are looking for is a javscript looping operation.
for(var i = 1; i <= 141; i++) {
console.log(i);
// put code in here that has to run 141 times modifying the html target elements by using string concatenation
$('#target' + i); // This would be come #target1, #target2, #target3 etc up to 141
}
You ask specifically about the variable renaming which would not be necessary in this case since you are reusing the variable in each pass through the loop.
Since you are working with time information you may want to check out this Javascript library: http://momentjs.com/ and work through some of the information on this specific section: http://momentjs.com/docs/#/durations/
JetBrains Webstorm has great javascript refactoring features, including renaming of objects.
I have found this script online and added my own images into it. The only problem is whenever I try to remove var seconds=Digital.getSeconds() it doesn't work anymore, meaning it stops updating.
However, when I keep the script in its original format, the clock does live update. How do I get the clock to update every minute? I only want the hours and minutes.
Here's the code in such a way that actually works properly (although I still don't like document.images... but it'll do)
var imgs = {}, i;
for( i=0; i<10; i++) {
imgs[i] = new Image();
imgs[i].src = "c"+i+".gif";
}
imgs.blank = new Image(); imgs.blank.src = "cb.gif";
imgs.am = new Image(); imgs.am.src = "cam.gif";
imgs.pm = new Image(); imgs.pm.src = "cpm.gif";
function extract(h,m,s,dn){
document.images.a.src = imgs[Math.floor(h/10) || "blank"].src;
document.images.b.src = imgs[h%10].src;
document.images.d.src = imgs[Math.floor(m/10)].src;
document.images.e.src = imgs[m%10].src;
document.images.g.src = imgs[Math.floor(s/10)].src;
document.images.h.src = imgs[s%10].src;
if( dn=="AM") document.images.j.src = imgs.am.src;
else document.images.j.src = imgs.pm.src;
}
function show3(){
var Digital = new Date(),
h = Digital.getHours(),
m = Digital.getMinutes(),
s = Digital.getSeconds(),
dn = h >= 12 ? "PM" : "AM";
extract( h%12 || 12, m, s, dn)
setTimeout(show3,1000);
}
Now, if you want to get rid of seconds, comment out these lines:
// document.images.g.src = imgs[Math.floor(s/10)].src;
// document.images.h.src = imgs[s%10].src;
And remove the g and h images from your HTML source.
You can't remove the seconds, they're needed to increase minutes every 60 seconds. But you can choose not to display them.
But considering the script, you would have a better result making yourself the script, using setInterval and Date as A1rPun said.
So I made a simple timer in a format like this: MM:SS.MS
You can view it here [removed]
It works fine in chrome, IE, etc. but in Firefox the seconds are like twice as long..
I took a look at some other stopwatches, but I don't quit understand them.
Whats the best way to do it ? Right now I have a 10ms interval which generates the timer.
The function looks like that, I hope it's understandable:
var state = false;
var msTimer = null;
var min = document.getElementById("min");
var sec = document.getElementById("sec");
var ms = document.getElementById("ms");
var minCount = 0;
var secCount = 0;
var msCount = 0;
document.onkeydown = function timer(e) {
if (!e) { e = window.event; }
if (e.keyCode == "32") {
if (state == false) {
state = true;
min.innerHTML = "00";
sec.innerHTML = "00";
ms.innerHTML = "00";
msTimer = window.setInterval(function() {
if (msCount == 99) {
msCount = 0;
secCount++;
// Minutes
if (secCount == 60) {
secCount = 0;
minCount++;
if (minCount <= 9)
{ min.innerHTML = "0" + minCount; }
else
{ min.innerHTML = minCount; }
}
// Seconds
if (secCount <= 9)
{ sec.innerHTML = "0" + secCount; }
else
{ sec.innerHTML = secCount; }
} else { msCount++; }
// Miliseconds
if (msCount <= 9)
{ ms.innerHTML = "0" + msCount; }
else
{ ms.innerHTML = msCount; }
// 1 Hour
if (minCount == 60) {
clearInterval(msTimer);
min.innerHTML = "N0";
sec.innerHTML = "00";
ms.innerHTML = "0B";
state = false;
minCount = 0;
secCount = 0;
msCount = 0;
}
}, 10);
} else if (state == true) {
state = false;
clearInterval(msTimer);
minCount = 0;
secCount = 0;
msCount = 0;
}
}
Thanks for any advices :)
Edit:
And btw, it's much smoother in firefox, if I remove all styles from the timer.
But that can't be the solution..
You shouldn't be relying on the interval of the timer being exactly 10ms. It would be better if you viewed each timer tick as a request to refresh the on-screen timer, but take the measurements from the system clock or something like that.
Then however slow or busy the machine (and JS implementation) is, you'll always see an accurate timer1 - just one which updates less often.
1 This will only be as accurate as the system clock, of course. If Javascript has access to a high-performance timer like .NET's Stopwatch class or Java's System.nanoTime() method, that would be better to use.
Timing in Javascript is not guaranteed. A 10ms interval will only ever be approximately 10ms, most likely it will be delayed a tiny bit each time. The correct way to do a timer in Javascript is to save a starting timestamp upon starting the timer, then each 10ms or so calculate the difference between the starting timestamp and the current time and update an element on the page with the formatted value.
I have a fairly long running (3 to 10 second) function that loads data in the background for a fairly infrequently used part of the page. The question I have is what is the optimal running time per execution and delay time between to ensure that the rest of the page stays fairly interactive, but the loading of the data is not overly delayed by breaking it up?
For example:
var i = 0;
var chunkSize = 10;
var timeout = 1;
var data; //some array
var bigFunction = function() {
var nextStop = chunkSize + i; //find next stop
if (nextStop > data.length) { nextStop = data.length }
for (; i < nextStop; i++) {
doSomethingWithData(data[i]);
}
if (i == data.length) { setTimeout(finalizingFunction, timeout); }
else { setTimeout(bigFunction , timeoutLengthInMs); }
};
bigFunction(); //start it all off
Now, I've done some testing, and a chunkSize that yields about a 100ms execution time and a 1ms timeout seem to yield a pretty responsive UI, but some examples I've seen recommend much larger chunks (~300ms) and longer timeouts (20 to 100 ms). Am I missing some dangers in cutting my function into too many small chunks, or is trial and error a safe way to determine these numbers?
Any timeout value less than roughly 15ms is equivalent - the browser will update the DOM, etc and then execute the timeout. See this and this for more info. I tend to use setTimeout(fn, 0).
I would check the time elapsed instead of guessing numbers, because as Jason pointed out, there will be speed differences between clients:
var data; // some array
var i = 0;
var MAX_ITERS = 20; // in case the system time gets set backwards, etc
var CHECK_TIME_EVERY_N_ITERS = 3; // so that we don't check elapsed time excessively
var TIMEOUT_EVERY_X_MS = 300;
var bigFunction = function () {
var maxI = i + MAX_ITERS;
if (maxI > data.length) { maxI = data.length }
var nextTimeI;
var startTime = (new Date()).getTime(); // ms since 1970
var msElapsed;
while (i < maxI) {
nextTimeI = i + CHECK_TIME_EVERY_N_ITERS;
if (nextTimeI > data.length) { nextTimeI = data.length }
for (; i < nextTimeI; i++) {
doSomethingWithData(data[i]);
}
msElapsed = (new Date()).getTime() - startTime;
if (msElapsed > TIMEOUT_EVERY_X_MS) {
break;
}
}
if (i == data.length) {
setTimeout(finalizingFunction, 0);
} else {
setTimeout(bigFunction , 0);
}
};
bigFunction(); //start it all off
The 1ms timeout is not actually 1 ms. By the time the thread yields, to achieve the 1ms, it probably yielded much more - because the typical thread time-slice is 30ms. Any number of other threads may have executed during the 1ms timeout, which could mean that 200ms went by before you received control again.
Why not just have the 'doSomethingWithData' execute in an entirely different thread?