I have a javascript function being called this way
do_work();
setTimeout(do_some_other_work);
do_work();
setTimeout(do_some_other_work);
do_work();
How do i output the total time spent in this case ?
You can use global variables: one with the starting time (to compare later), and one that gets incremented by do_work() and do_some_other_work() using a function that checks if the counter is at the desired number and then calculates the time difference.
So, something like:
var start = new Date(), call_counter = 0;
Then at the end of do_work() and do_some_other_work():
incrementCounter();
And have:
function incrementCounter() {
if ( ++call_counter == 5 ) {
console.log( ((new Date()) - start) );
}
}
Related
The question: How to update element at every 10th Second, i.e., like at 12:30:10, 12:31:10, etc
The following technically works and does as I need, but how am I supposed to do this in the right way? That is, optimally, in terms of code and execution time?
setInterval(function(){
var now = new Date();
if (now.getSeconds() == 10) {
$('#jama').load('jama.php');
}
},1000);
The Problem: I think what you're asking is: To check every for every tenth second, i.e., 12:30:10 is a tenth second, but check every ten seconds (12:30:13, 12:30:23, etc.) is not.
The Solution: In that case, use setTimeout(), running it every second, to find the tenth second, and when you find the tenth second, then just setInterval() as you're doing now.
The Advantage: What's the advantage? Once you find the tenth second, you can change setInterval()'s delay from 1000 to 60000, since we know the next tenth second will be 60 seconds away. This reduces how often the code needs to check, and it also removes the now() object and the unnecessary checking.
The Code: Working demo below.
var myinterval = false;
function findTenthSecond() {
if(!myinterval) {
findTenthSecond_async();
}
}
function findTenthSecond_async() {
setTimeout(function(){
var now = new Date();
console.log("Check second: " + now.getSeconds() + "|");
if (now.getSeconds() == 10) {
myinterval = true;
// your code is here
setInterval(function(){
console.log ("Load jama.php");
$('#jama').load('jama.php');
},60000); // updated the second count to 60 seconds
} else {
findTenthSecond();
}
}, 1000);
}
findTenthSecond();
So in short, the app that i'm developing is a bus timetable app using Meteor, as a practice project.
inside my body.js, I have an interval that runs every second, to fetch the current time and compare to items in a collection.
To show relevant times, I have added an isActive boolean, whenever the current time = sartTime of the collection, it sets it to true, and that is working fine.
But when I do the same thing for endTime and try to set it to false, so I can hide that timeslot, it just doesn't work. Even consoles don't show up. What am I missing? I have recently just started doing meteor, so excuse the redundancies.
Worth noting that the times that I'm comparing to are times imported from an CSV file, so they have to be in the 00:00 AM/PM format.
Thank you guys so much for your time.
Body.js code:
Template.Body.onCreated(function appBodyOnCreated() {
Meteor.setInterval(() => {
var h = (new Date()).getHours();
const m = ((new Date()).getMinutes() <10?'0':'') + ((new Date()).getMinutes());
var ampm = h >= 12 ? ' PM' : ' AM';
ampmReac.set(ampm);
if (h > 12) {
h -= 12;
} else if (h === 0) {
h = 12;
}
const timeAsAString = `${h}${m}`;
const timeAsAStringFormat = `${h}:${m}`;
whatTimeIsItString.set(timeAsAStringFormat + ampm); // convert to a string
const timeAsANumber = parseInt(timeAsAString); // convert to a number
whatTimeIsIt.set(timeAsANumber); // update our reactive variable
if (Timetables.findOne({TimeStart: whatTimeIsItString.get()}).TimeStart == whatTimeIsItString.get())
{
var nowTimetable = Timetables.findOne({TimeStart: whatTimeIsItString.get() });
Timetables.update({_id : nowTimetable._id },{$set:{isActive : true}});
console.log('I am inside the START statement');
}
else if (Timetables.findOne({TimeEnd: whatTimeIsItString.get()}).TimeEnd == whatTimeIsItString.get())
{
var nowTimetable = Timetables.findOne({TimeEnd: whatTimeIsItString.get() });
Timetables.update({_id : nowTimetable._id },{$set:{isActive : false}});
console.log('I am inside the END statement');
}
}, 1000); //reactivate this function every second
});
})
Very probably it is just that your if / else blocks does what you ask it:
It tries to find a document in Timetables, with specified TimeStart. If so, it makes this document as "active".
If no document is previously found, i.e. there is no timeslot which TimeStart is equal to current time, then it tries to find a document with specified TimeEnd.
But your else if block is executed only if the previous if block does not find anything.
Therefore if you have a next timeslot which starts when your current timeslot ends, your if block gets executed for that next timeslot, but the else if block is never executed to de-activate your current timeslot.
An easy solution would be to transform your else if block in an independent if block, so that it is tested whether the previous one (i.e. TimeStart) finds something or not.
Ok so I got it to work eventually. My problem was that it was never going to the second IF statement.
What I have done is set up a whole new Meteor.interval(() >) function, and placed that second IF in there, as is.
I think the problem was that it was it checks the first IF statement and gets stuck there, no matter what the outcome of the parameters is.
Right now I am working on a timesheet where users can set their in time, their out time, and how long they've been at lunch. Then I use a function that subtracts the in time & the lunch from their out time to figure out their hours, plus possible overtime. What I want is to have javascript set the value of the overtime field to '' (aka null) if the amount of time they were at work is 8 hours or less.
My code for checking overtime is this:
// Return difference between two times in hh:mm[am/pm] format as hh:mm
function checkOvertime(timein, timeout, away) {
// Small helper function to pad single digits
function z(n){return (n<10?'0':'') + n;}
// Get difference in minutes
var subtotal = daytimeStringToMins(timeout) - daytimeStringToMins(timein) - timeStringToMins(away);
var regularhours = '08:00';
if (subtotal > timeStringToMins(regularhours)) {var overtime = daytimeStringToMins(timeout) - daytimeStringToMins(timein) - timeStringToMins(away) - timeStringToMins(regularhours);}
else {var overtime = '0';}
return z(overtime/60 | 0) + ':' + z(overtime % 60);
}
and then in my calculation function I have this:
if (checkOvertime(timein, timeout, away).value == '00:00') {
document.getElementById("date-1-overtime").value = '';
} else {
document.getElementById("date-1-overtime").value = checkOvertime(timein, timeout, away);
}
So if a person is at work for 8 hours, then the "date-1-overtime" field says "00:00" but I would like it to put nothing in there so the sheet prints out more cleanly.
I think maybe I am confusing the difference between strings and integers in the calculation functions but I'm not sure, hopefully someone could help me!
I think you should change this method to use regular expressions to extract the appropriate parts of the input and then use parseint to get the value in a numeric form.
Convert that to minutes and if the minutes are less than or equal to 480 (8 * 60), return the actual string.
Also, you can't really assign a null value to an html param. null is not the same as 0. null is essentially, undefined.
You should return the number of minutes worked overtime from your function and use 0 for overtime if the user didn't work overtime.
I am trying to use multiple stop watch timer by using anchor tag.I have successfully done but I am not able to add a functionality like if I clicked first timer,It will start timer from zero,when I clicked second one,first timer's value will be zero and second one will start timer from zero.I am giving my working code below :
JS:
var digit=0;
var hrs = 0;
var min=0;
var time;
var timer_is_on=0;
var id;
function timer(id){
//[Old] - this should be placed after you increment digit
// document.getElementById("secs").innerHTML = digit
//alert("I am testing value"+id);
//[New]
// get the numerical value for seconds,minutes,hours
digit = parseInt(document.getElementById("secs"+id).innerHTML);
min = parseInt(document.getElementById("mins"+id).innerHTML);
hrs = parseInt(document.getElementById("hrs"+id).innerHTML);
// increment;
digit=digit+1;
if(digit>"59"){
min = parseInt(min)+1;
// why is this code here
var count = min.toString().length;
digit=0;
}
// [old] checking if second is greater than 59 and incrementing hours
// if(digit>"59"){
// [new] check if minute is greater than 59
if(min > "59"){
hrs=parseInt(hrs)+1;
digit=0;
min=0; // minute should be reset as well
}
// set the values after all processing is done
document.getElementById("secs"+id).innerHTML = format(digit);
document.getElementById("mins"+id).innerHTML= format(min);
document.getElementById("hrs"+id).innerHTML=format(hrs);
}
function activate(id){
if(!timer_is_on){
timer_is_on=1;
// time = setTimeout("timer()",1000) will only call it once , use setInterval instead
time=setInterval("timer("+id+")",1000);
}
else {
timer_is_on=0;
clearInterval(time); // clear the timer when the user presses the button again and reset timer_is_on
}
return id;
}
// left pad zero if it is less than 9
function format(time){
if(time > 9)
return time;
else return "0"+time;
}
And The HTML code I have used are :
Click here to start the timer
<span id="hrs1" >00</span>:<span id="mins1" >00</span>:<span id="secs1">00</span></strong>
<br/>
Click here to start the timer
<span id="hrs2" >00</span>:<span id="mins2" >00</span>:<span id="secs2">00</span>
Here is my working js fiddle demo : http://jsfiddle.net/EPtFW/1/
as you are using same method activate() to start second timer, it will make first timer as zero if timer already running.
Solution is "you have to maintain multiple unique timer ids for multiple timers"
For Example, let's say you have T1 and T2 timers to start time;
var timerMap={};
timerMap[createUniqueId for T1] = setInterval();
timerMap[createUniqueId for T2] = setInterval();
to clear timers
clearInterval(timerMap[createUniqueId for T1]);
clearInterval(timerMap[createUniqueId for T2]);
In your case, you have to have createUniqueId and adding to timerMap should be in activate() method. they will work independently.
I'm attempted to add leading zeros to the seconds value and I keep running into errors. I've tried a number of selected solutions posted here and can't seem to make it work.
I'm pulling values from the spans because those values are coming from the database.
var timer = $('.timer');
$('.prev-button,.next-button').hide();
setInterval(function () {
var m = $('.min', timer),
s = $('.sec', timer);
if (m.length == 0 && parseInt(s.html()) <= 0) {
timer.html('Proceed to the Next Slide');
$('.prev-button,.next-button').fadeIn();
}
if (parseInt(s.html()) <= 0) {
m.html(parseInt(m.html() - 1));
s.html(60);
}
if (parseInt(s.html()) < 10) {
$('.sec').prepend(0)
}
if (parseInt(m.html()) <= 0) {
timer.html('Time remaining for this slide - <span class="sec">59</span> seconds')
}
s.html(parseInt(s.html() -1));
}, 1000);
http://jsfiddle.net/certainstrings/a2uJ2/1/
I've modified your Fiddle to make it work. http://jsfiddle.net/a2uJ2/3/
You should store the time in javascript int vars instead of reading it from the html elements every time. This causes maintainability problem as you are attaching logic to the layout of your html document.
I haven't fixed all your code but i've created two variables that are used to perform the calculations instead.
Couple of things: You'd be better off registering a start time, and comparing against that inside the interval function. Timers are not guaranteed to be precise, but will instead trigger on or after the interval you specify. If the computer's busy, the timer might be late.
Also, if you're using parseInt, always, always specify a radix argument (the number base). If you don't, the string "08" will will be parsed to "0" because a leading zero is intepreted as an octal (base-8). So use parseInt(string, 10) to parse to a normal base-10 number.
As for adding the leading zero, I'd say you should keep a couple variable for total amount of seconds, rather than reading/writing to the elements all the time.
Updated you jsfiddle
var duration, startTime, interval;
duration = parseInt($(".min").text(), 10) * 60 + parseInt($(".sec").text(), 10);
startTime = (new Date()).getTime();
function countDown() {
var elapsed, remaining, m, s;
elapsed = ((new Date()).getTime() - startTime) / 1000;
remaining = duration - elapsed;
if(remaining <= 0) {
clearInterval(interval);
$(".timer").text('Proceed to the Next Slide');
$('.prev-button,.next-button').fadeIn();
} else {
m = String(Math.round(remaining / 60));
s = String(Math.round(remaining % 60));
if( s < 10 ) {
s = "0" + s;
}
$(".min").text(m);
$(".sec").text(s);
}
}
interval = setInterval(countDown, 500);
This is just a minimal change from you code. I'd probably do something fundamentally different to keep the markup and JS as separate as possible, and so on and so forth, but this works too.
try it like this:
if (parseInt(s.html()) < 10) {
$('.sec').val('0' + $('.sec').val());
}
You're going to need to treat the value as a string rather than as an int. JavaScript is pretty aggressive about converting things that look like numbers into numbers, and that's what's happening here.