Adding leading zeros to a Javascript timer - javascript

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.

Related

Update Element at every 10th Second, i.e., like at 12:30:10, 12:31:10, etc

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();

How to create number suffixes such as "100K" without having to be repetitive?

I've been having a problem that when my auto clicker in my clicker game goes fast enough to get to 200 thousand, it starts to lag, and then it doesn't function properly, or as fast.
Is there a way to make 100 thousand turn into 100K, and 101 thousand turn into 101K without being repetitive?
I tried this with my original code, and realized putting up to 1000 suffixes into each function would be a little too hard:
if (number >= 100000) {
document.getElementById(ID).innerHTML = "100K"
}
if (number >= 101000) {
document.getElementById(ID).innerHTML = "101K"
}
and on and on.
I don't want multiple if statements!
This would work, but it would take up way too much space, and I know there is an easier way to it, but I just couldn't find it. Can anyone provide a way to do this?
Try separating the job of formatting your number into a different function.
SUFFIXES = 'KMBTqQsSOND' // or whatever you'd like them to be
function getSuffixedNumber(num) {
var power = Math.floor(Math.log10(num));
var index = Math.floor(power / 3);
num = Math.round(num / Math.pow(10, (index * 3))); // first 3 digits of the number
return num + (SUFFIXES[index - 1] || ''); // default to no suffix if we get an out of bounds index
}
You can call the function like this: var x = getSuffixedNumber(101000), the value of x will be "101K".

Collection Boolean isn't being set to false - Meteor

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.

Why is this not a clear integer type and how to make it clear?

I have this code:
wallboard.data.Timer = function () {
$("div[data-value]").each(function () {
var time = $(this).attr("data-value");
if (time > 0) {
time += 1000;
$(this).attr("data-value", time).text(TimeToText(time));
}
});
}
The function TimeToText() simply takes a millisecond value and output it as hour:seconds (00:00).
The attribute data-value contains a millisecond value and is stores in the variable time.
This is my "debug" output:
var time = $(this).attr("data-value"); time = 4376
if (time > 0) { is true as 4376 is larger than 0
time += 1000; after this "time" is 43761000 - her it starts concatenating the text "4376" and "1000" and this is the proof that the JavaScript engine thinks time is a string type.
How do I make it clear that time should be an integer type?
var time = $(this).attr("data-value");
var timeInt = parseInt(time) + 1000;
You can use coercion trough the unary +, or just wrap it in a parseInt with a base of 10.
wallboard.data.Timer = function () {
$("div[data-value]").each(function () {
var time = parseInt($(this).attr("data-value"), 10);
if (time > 0) {
time += 1000;
$(this).attr("data-value", time).text(TimeToText(time));
}
});
}
Also, you could have searched for "javascript string to number" and you would find billions of results.
EDIT: Why not interpret numeric strings as numbers automatically? Because that would be a very unpleasant deviation from the convention: in JS you try to modify as little as possible your outputs. If you then wanted to actually concatenate two numeric strings together, you'd have to do lots of hacks to do it:
Instead of var a = "1000" + "10" to get "100010", you would have to do something like this
var a = ["1000", "zz10"].join(""); // note the "zz", so it's not plain numeric.
a = a.replace("zz", ""); // replace "zz" with nothing.
// now `a` would be "100010"
You need to convert the string retrieved with attr() into a number, e.g.
var time = +($(this).attr("data-value"));
You can use unary plus operator to convert the string attribute value to a number(you can also use parseInt())
var time = +$(this).attr("data-value");
You should convert the string to integer before adding it with 1000.
var time = parseInt($(this).attr("data-value"));

Javascript value set null if value equals nothing

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.

Categories

Resources