<script>
var train_arrivals = [
'00:10',
'00:15',
'00:23',
'00:35',
'00:43',
'00:58',
'01:05',
'01:13',
'01:20',
'01:37',
'01:48',
'02:15',
'02:25',
'02:40',
'02:55',
'03:00',
'03:09',
'03:21',
'03:37',
'03:52',
'04:15',
'04:30',
'04:44',
'04:58',
'05:16',
'05:31',
'05:49',
'06:00',
'06:26',
'06:56',
'08:06',
'07:24',
'07:43',
'07:58',
'08:06',
'08:13',
'08:28',
'08:43',
'08:58',
'09:05',
'09:13',
'09:28',
'09:43',
'09:58',
'10:05',
'10:38',
'11:00',
'11:38',
'12:38',
'13:38',
'14:38',
'15:38',
'16:00',
'16:39',
'17:00',
'17:06',
'17:27',
'17:57',
'20:20',
'20:45',
'21:50',
'23:25',
'23:30',
'23:48'
];
$(function() {
var today = new Date();
var now = moment([today.getFullYear(), today.getMonth(), today.getMinutes(), today.getHours(), today.getMinutes()]);
var setted = '';
var count = 1;
for (var i=0; i<train_arrivals.length; i++){
var entry = train_arrivals[i];
time = entry.split(":");
var arrival = moment([today.getFullYear(), today.getMonth(), today.getMinutes(), time[0], time[1]]);
diff = arrival.diff(now, 'minutes');
if (!setted && diff > 0) {
$("#arrival_list").append($("<li id="+count+" style='font-size: x-large' class='bg-success'>").text(diff + ' min '));
setted = count;
} else
$("#arrival_list").append($("<li id="+count+" class='bg-info'>").text(diff + ' min'));
if (setted && count >= setted + 2) break;
if (!setted && count > 1)
$('#'+count).remove();
count++;
}
});
</script>
I have this code for this little web app http://nexttrain.elvismdev.com/
The idea is to show next train arrival to the station due the train arrivals times given at the beginning of the code, the value inside the green row is the first next train approaching to the station, after it are two more train arrivals showing up, and back from it, should show the how many times ago the last train was there. I can't figure it out what is wrong over there that I am getting the wrong value with that so long minutes left, when it should show only a short time period.
If somebody could just look at my code and point me what could I be missing, In real I am not so much proficient in javascript, and time calculations always drive me crazy with issues like this.
Also I am using moment.js
Instead of adding <ul> elements to the DOM (Document Object Model) and then deleting them again, why not try this approach: First find the nearest future departure time, and then work backwards and get the time immediately before that. Add the previous time to the DOM as a <ul>, and then add the nearest future time. Something like this:
var train_arrivals = [
'00:10',
'00:15',
'00:23',
'00:35',
'00:43',
'00:58',
'01:05',
'01:13',
'01:20',
'01:37',
'01:48',
'02:15',
'02:25',
'02:40',
'02:55',
'03:00',
'03:09',
'03:21',
'03:37',
'03:52',
'04:15',
'04:30',
'04:44',
'04:58',
'05:16',
'05:31',
'05:49',
'06:00',
'06:26',
'06:56',
'08:06',
'07:24',
'07:43',
'07:58',
'08:06',
'08:13',
'08:28',
'08:43',
'08:58',
'09:05',
'09:13',
'09:28',
'09:43',
'09:58',
'10:05',
'10:38',
'11:00',
'11:38',
'12:38',
'13:38',
'14:38',
'15:38',
'16:00',
'16:39',
'17:00',
'17:06',
'17:27',
'17:57',
'20:20',
'20:45',
'21:50',
'23:25',
'23:30',
'23:48'
];
$(function() {
var today = moment();
var todayString = today.format("YYYY-MM-DD");
var now = today;
var setted = '';
var count = 1;
for (var i=0; i<train_arrivals.length; i++){
var entry = train_arrivals[i];
var arrival = moment(todayString + ' ' + entry);
diff = arrival.diff(now, 'minutes');
if (!setted && diff > 0) {
if (i > 0) {
var prevEntry = train_arrivals[i - 1];
var prevArrival = moment(todayString + ' ' + prevEntry);
var prevDiff = prevArrival.diff(now, 'minutes');
$("#arrival_list").append($("<li id="+count+" class='bg-info'>").text(prevDiff + ' min'));
}
$("#arrival_list").append($("<li id="+count+" style='font-size: x-large' class='bg-success'>").text(diff + ' min '));
setted = count;
}
else if (diff > 0){
$("#arrival_list").append($("<li id="+count+" class='bg-info'>").text(diff + ' min'));
}
if (setted && count >= setted + 2) break;
count++;
}
});
Here's a working jsFiddle: http://jsfiddle.net/W84Gm/1/
Related
I'm trying to display Open or Closed based on a shift (two Shifts daily) using Javascript. I want to be able to use that data which is stored within a span and then determine if the business is open or closed and display that. for me only one shift is working during second shift its displaying We are now closed.
Might be something better to do the same but only in HTML.
any other suggestion is appreciated.
Here is the code I have so far:
function isOpen(timeRangeEl, date) {
var day = '' + date.getDay();
var hhmm = ('0' + date.getHours()).slice(-2) + ':' + ('0' + date.getMinutes()).slice(-2);
var days = timeRangeEl.getAttribute('data-days');
var openTime = timeRangeEl.getAttribute('data-open');
var closeTime = timeRangeEl.getAttribute('data-close');
return days.indexOf(day) >= 0 && openTime <= hhmm && hhmm < closeTime;
}
function openClose() {
var date = new Date();
var display = document.getElementById('open-display');
var els = display.getElementsByClassName('timerange');
var anyActive = false;
for (var i = 0; i < els.length; i++) {
if (isOpen(els[i], date)) {
anyActive = true;
els[i].className = els[i].className.replace(/ *inactive\b/g, '');
} else if (els[i].className.indexOf('inactive') < 0) {
els[i].className += ' inactive';
}
}
if (anyActive) {
display.className = 'open';
} else {
display.className = 'closed';
}
}
setInterval(openClose, 5000);
openClose();
#open-display.open > .timerange.inactive,
#open-display.open > .timerange2.inactive,
#open-display.open .days {
display: none;
}
#open-display.open > .openclosed::before {
content: 'We are now Open';
}
#open-display.closed > .openclosed::before {
content: 'We are now Closed';
}
<div class="text">
<h3>Working Hours</h3>
<div id="open-display">
<div class="openclosed"></div>
<div class="timerange" data-days="1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31" data-open="12:30" data-close="15:30"><span class="days">Noon</span> 12:30pm - 3:30pm</div>
<div class="timerange2" data-days="1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31" data-open="18:00" data-close="00:30"><span class="days">Dine</span> 6:00pm - 12:30am</div>
</div>
</div>
Successfully done after trying and doing trial and error method.
This is my Javascript code to increment in minutes in interval 1
fillMinutes = function () {
var table = widget.find('.timepicker-minutes table'),
currentMinute = viewDate.clone().startOf('h'),
html = [],
row = $('<tr>'),
step = options.stepping === 1 ? 5 : options.stepping;
while (viewDate.isSame(currentMinute, 'h')) {
if (currentMinute.minute() % (step * 4) === 0) {
row = $('<tr>');
html.push(row);
}
row.append('<td data-action="selectMinute" class="minute' + (!isValid(currentMinute, 'm') ? ' disabled' : '') + '">' + currentMinute.format('mm') + '</td>');
currentMinute.add(step, 'm');
}
table.empty().append(html);
}
I want to modify this to increment in 15 minutes interval.
Can someone help me on this.
The option for stepping is what I believe you want, like this:
<script type="text/javascript">
$(function () {
$('#yourTimePickerElement').datetimepicker({
stepping: 15
});
});
</script>
Here is the documentation for stepping:
stepping
Default: 1
Number of minutes the up/down arrow's will move the minutes value in the time picker
Bootstrap 3 Datepicker documentation
incrementMinutes: function () {
var newDate = date.clone().add(15, 'm');
if (isValid(newDate, 'm')) {
setValue(newDate);
}
}
decrementMinutes: function () {
var newDate = date.clone().subtract(15, 'm');
if (isValid(newDate, 'm')) {
setValue(newDate);
}
}
I am dealing with the following puzzle and I cannot understand why it is happening.
I have the following [I believe to be] equivalent pieces of javascript code, but one does not work as expected (notice the Console.Log):
Updates the UI a single time, then unexpectantly stops updating : http://jsfiddle.net/silentwarrior/1m0v6oj1/
jQuery(function () {
var isWorking = true;
if (isWorking) {
var timeEnd = 1431220406000; // generated from php
var timeNow = 1431210557000; // generated from php
var counter = 1;
var t = "";
setInterval(function () {
try {
var c = timeEnd - timeNow - counter;
console.log(c);
var d = new Date(c);
if (c <= 1) {
window.location.href = window.location.href;
return;
}
t = "";
if (d.getHours() > 0) {
t += d.getHours() + "h ";
}
if (d.getMinutes() > 0) {
t += d.getMinutes() + "m ";
}
t += d.getSeconds();
jQuery("#factory_start_prod").val("Working ... " + t + "s left");
counter = counter + 1;
} catch (e) {
}
}, 1000);
}
});
Updates the UI constantly as expected: http://jsfiddle.net/silentwarrior/n3gkum2e/
jQuery(function () {
var isWorking = true;
if (isWorking) {
var timeEnd = 1431220406000;
var timeNow = 1431210557000;
var counter = 1;
var t = "";
setInterval(function () {
try {
var c = timeEnd - Date.now();
console.log(c);
var d = new Date(c);
if (c <= 1) {
window.location.href = window.location.href;
return;
}
t = "";
if (d.getHours() > 0) {
t += d.getHours() + "h ";
}
if (d.getMinutes() > 0) {
t += d.getMinutes() + "m ";
}
t += d.getSeconds();
jQuery("#factory_start_prod").val("Working ... " + t + "s left");
counter = counter + 1;
} catch (e) {
}
}, 1000);
}
});
The only difference from each other is that, the one that works uses Date.now() to get the current timestamp, while the other one uses a pre-built time stamp.
Why would one example update the text in the input correctly while the other wouldn't?
PS: it is important to me to use generated timestamps instead of Date.now() in order to not depend on the users system when calculating the time left.
Your first example is working, however with each iteration you are only subtracting 1 from the timestamp value, which is equivalent to 1ms. Hence the value never appears to change unless you wait a really long time. You need to increment the counter by 1000 on each iteration for a second to be counted:
counter = counter + 1000;
Updated fiddle
In my project, users can add timecode in and out points for their project, and the project automatically figures out the total duration of the timecode. But I want to add a function that will take all the available timecode durations, convert them to seconds, add them together, then convert the final number back to timecode and put it in a text input.
This is my code, but I keep getting syntax errors:
function timeToSeconds(t) {
var tc = t.split(':');
return parseInt(tc[0])*3600 + parseInt(tc[1])*60 + parseInt(tc[2]);
}
function tcDuration(tcin, tcout) {
function z(n){return (n<10?'0':'') + n;}
var duration = timeToSeconds(tcout) - timeToSeconds(tcin);
var hoursmins = Math.floor(duration / 60);
return z(Math.floor(hoursmins/60)) + ':' + z(hoursmins % 60) + ':' + z(duration % 60);
}
// Run this function every time a film_tc_out cell is changed
function film_tc_Duration() {
if (document.getElementById("film_tc_in").value == '') {var film_tc_in = '00:00:00';} else { var film_tc_in = document.getElementById("film_tc_in").value;}
if (document.getElementById("film_tc_out").value == '') {var film_tc_out = '00:00:00';} else { var film_tc_out = document.getElementById("film_tc_out").value;}
document.getElementById("film_tc_duration").value = tcDuration(film_tc_in, film_tc_out);
}
// Run this function every time a src_tc_out cell is changed
function src_tc_Duration() {
if (document.getElementById("src_tc_in").value == '') {var src_tc_in = '00:00:00';} else { var src_tc_in = document.getElementById("src_tc_in").value;}
if (document.getElementById("src_tc_out").value == '') {var src_tc_out = '00:00:00';} else { var src_tc_out = document.getElementById("src_tc_out").value;}
document.getElementById("src_tc_duration").value = tcDuration(src_tc_in, src_tc_out);
}
// Run this function every time a src_wd_out cell is changed
function src_wd_Duration() {
if (document.getElementById("src_wd_in").value == '') {var src_wd_in = '00:00:00';} else { var src_wd_in = document.getElementById("src_wd_in").value;}
if (document.getElementById("src_wd_out").value == '') {var src_wd_out = '00:00:00';} else { var src_wd_out = document.getElementById("src_wd_out").value;}
document.getElementById("src_wd_duration").value = tcDuration(src_wd_in, src_wd_out);
}
function total_tc_Duration() {
var val = document.getElementsByClassName('.asset_src_tc_duration');
var total_tc = 0;
var v;
for (var i = 0; i < val.length; i++) {
v = timeToSeconds(val[i]);
if (!isNaN(v)) total_tc += v;
}
return (total_tc);
}
function updateAssetTimecode() {
document.getElementById("timecode_total").value = total_tc_Duration();
}
Update: I've rewritten the For Loop to see if that helps - it currently gives me an answer now, although the answer is always "0". It's not spitting out any errors but it seems to think the variable val isn't a number?
Your tcDuration function won't work like you expect. You don't subtract the already calculated hours before doing the minutes calculation and the same with seconds.
function tcDuration(tcin, tcout) {
function z(n){return (n<10?'0':'') + n;}
var duration = timeToSeconds(tcout) - timeToSeconds(tcin);
var hoursmins = Math.floor(duration / 60);
return z(Math.floor(hoursmins / 60)) + ":" + z(hoursmins % 60) + ":" + z(duration % 60);
}
I have this countdown timer script:
<script language="JavaScript" src="http://scripts.hashemian.com/js/countdown.js"></script>
function calcage(secs, num1, num2) {
s = ((Math.floor(secs/num1))%num2).toString();
if (LeadingZero && s.length < 2)
s = "0" + s;
return "<b>" + s + "</b>";
}
function CountBack(secs) {
if (secs < 0) {
document.getElementById("cntdwn").innerHTML = FinishMessage;
return;
}
DisplayStr = DisplayFormat.replace(/%%D%%/g, calcage(secs,86400,100000));
DisplayStr = DisplayStr.replace(/%%H%%/g, calcage(secs,3600,24));
DisplayStr = DisplayStr.replace(/%%M%%/g, calcage(secs,60,60));
DisplayStr = DisplayStr.replace(/%%S%%/g, calcage(secs,1,60));
document.getElementById("cntdwn").innerHTML = DisplayStr;
if (CountActive)
setTimeout("CountBack(" + (secs+CountStepper) + ")", SetTimeOutPeriod);
}
function putspan(backcolor, forecolor) {
document.write("<span id='cntdwn' style='background-color:" + backcolor +
"; color:" + forecolor + "'></span>");
}
if (typeof(BackColor)=="undefined")
BackColor = "white";
if (typeof(ForeColor)=="undefined")
ForeColor= "black";
if (typeof(TargetDate)=="undefined")
TargetDate = "12/27/2012 1:36 PM";
if (typeof(DisplayFormat)=="undefined")
DisplayFormat = "%%D%% Days, %%H%% Hours, %%M%% Minutes, %%S%% Seconds.";
if (typeof(CountActive)=="undefined")
CountActive = true;
if (typeof(FinishMessage)=="undefined")
FinishMessage = "";
if (typeof(CountStepper)!="number")
CountStepper = -1;
if (typeof(LeadingZero)=="undefined")
LeadingZero = true;
CountStepper = Math.ceil(CountStepper);
if (CountStepper == 0)
CountActive = false;
var SetTimeOutPeriod = (Math.abs(CountStepper)-1)*1000 + 990;
putspan(BackColor, ForeColor);
var dthen = new Date(TargetDate);
var dnow = new Date();
if(CountStepper>0)
ddiff = new Date(dnow-dthen);
else
ddiff = new Date(dthen-dnow);
gsecs = Math.floor(ddiff.valueOf()/1000);
CountBack(gsecs);
I want to make it so once the timer reaches 0, it adds 2 days to the original date and resets itself.
Here is what I came up with:
CountStepper = Math.ceil(CountStepper);
if (CountStepper == 0)
CountActive = true;
var SetTimeOutPeriod = (Math.abs(targetdate)-1)*2000 + 990;
putspan(BackColor, ForeColor);
var dthen = new Date(TargetDate);
var dnow = new Date();
if(CountStepper>0)
CountBack(gsecs);
But it doesn't seem to be working. Any help or tips on how to fix this?
There are two ways to do repeating time-based events in Javascript. The first approach, which you're trying, is to do a timeout, then invoke another timeout from within the first timeout's callback (and then that timeout invokes another timeout from its callback, and so on and so forth).
That basic approach totally works (and I imagine if you do a bit of debugging you can get it to work for you), but there's also an alternate approach: setInterval.
setInterval runs the same code over and over again, every timeout period. If you did something like:
window.setInterval((putspan, Math.abs(targetdate)-1)*2000 + 990)
it should also solve your problem.
As a side note, using eval-ed code (javascript inside a string) is a terrible idea for many reasons. I recommend using functions instead (like I did with putspan in my example). You can use jQuery's proxy or Underscore's bind to "fix" arguments in place, like so:
var putspanWithColor = $.proxy(putspan, this, BackColor, ForeColor);
window.setInterval(putspanWithColor, Math.abs(targetdate)-1)*2000 + 990)