I have following function to calculate time between the start and the end (which are just input fields).
calculateTime() {
if(this.state.start !== '' && this.state.end !== ''){
let time1 = moment(this.state.end, "hh:mm");
let subtract = time1.subtract(this.state.start);
let format = moment(subtract).format("hh:mm");
console.log(format);
return format;
}
return 0;
}
In general the calculation works. The value gets set via a input field and the state gets updated to the entered value. As seen here:
<table>
<thead>
<tr>
<th>Date</th>
<th>Start</th>
<th>End</th>
<th>Time</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input type="date" id="start" name="trip-start"
min="2022-01-01" max="2023-12-31" onChange={this.handleDate} value={this.state.date} />
</td>
<td>
<input type="text" onChange={this.handleStart} placeholder="hh:mm" maxLength={5} />
</td>
<td>
<input type="text" onChange={this.handleEnd} placeholder="hh:mm" maxLength={5} />
</td>
<td>
<p>{this.calculateTime()}</p>
</td>
</tr>
</tbody>
</table>
The function for setting the start state (setting the end value is similar except a other function gets called to update the state)
handleStart(event:any) {
this.setState({
start: event.target.value
});
}
As you can see in the pictures the values are off by 12h
Here it should be 13:01 instead of 01:01
Here it should be 00:01 instead of 12:01
Has anyone an idea how to fix that besides manually adding or removing the 12h?
Here is the working code :
const calculateTime = () => {
if (this.state.start !== "" && this.state.end !== "") {
let time1 = moment(this.state.end, "hh:mm");
let time2 = moment(this.state.start, "hh:mm");
let hoursDiff = time1.diff(time2, "hours");
console.log("Hours:" + hoursDiff);
let minutesDiff = time1.diff(time2, "minutes");
console.log("Minutes:" + minutesDiff);
// let subtract = time1.subtract(time2);
// let format = subtract.format("hh:mm");
// console.log(format);
return `${hoursDiff} : ${minutesDiff}`;
}
return 0;
};
Now, why your code didn't worked is beacuse, you need to wrap your startDate with moment,
let time2 = moment(this.state.start, "hh:mm");
let subtract = time1.subtract(time2);
when trying to do the both hour and mins. operation in single function it's adding locale time as well , I don't see any option to disable that. if you find something like that, you can use your code as well.
I hope this helps, after asking you to edit your question multiple times. :)
Also, looking at your use case, you should consider substracting the date with time , not just time
https://momentjscom.readthedocs.io/en/latest/moment/04-displaying/07-difference/
Related
I have a two on change events that check for the inputted dates. If the date exceeds to the compared date, spits out an alert message. All this happens after a click away from the text box.
//This on change event works perfectly fine
$("td[date1] > input").on("change", function () {
var cur_td = $(this).closest("tr");
var startdate = $(this).val();
var enddate = cur_td.find("td[date2]").text();
var d1 = Date.parse(startdate);
var d2 = Date.parse(enddate);
if (d1 > d2) {
alert("The date exceeds End Date. Please check the date and re-enter it.");
}
});
// This on change event doesn't work...
$("td[date2] > input").on("change", function () {
var cur = $(this).closest("tr");
var str = $(this).val();
var end = cur.find("td[date3]").text(); // Problem here
alert(end); // Returning blank..
var t1 = Date.parse(str);
var t2 = Date.parse(end);
if (t1 > t2) {
alert("The date exceeds End Date. Please check the date and re-enter it.");
}
});
Razor View:
<td date1><input class="start" id=#item.ID type="text" actual="1" value='#(item.Date1 == null ? "" : Convert.ToDateTime(item.Date1).ToString("MM-dd-yyyy"))' readonly="readonly" /></td>
<td date2><input class="end" id=#item.ID type="text" actual="1" value='#(item.Date2== null ? "" : Convert.ToDateTime(item.Date2).ToString("MM-dd-yyyy"))' readonly="readonly" /></td>
<td date3>#Html.DisplayFor(x => item.Date3)</td>
Problem
The first on change event works perfectly fine, however the second one is not doing the same thing.
var end = cur_td.find("td[date3]").text();
alert(end);
This is returning a blank. I don't understand how is it not able to find the td element. They're both the same exact functions comparing different dates.
function update() {
var object_one = $('#start_time');
var object_two = $('#total');
var object_three = $('#end-time');
var my_input = object_one.val();
var my_put = object_three.val();
var my_output = my_put - my_input;
object_two.val(my_output);
}
<th colspan="2"> Monday</th>
<td> <input id="start_time" type="time"></td>
<td> <input id= "end-time" type= "time"></td>
<td> <input id="start_time" type="time"></td>
<td> <input id= "end-time" type= "time"></td>
<td> in</td>
<td>out </td>
<td> in</td>
<td>out </td>
I've already defined the values of start and end time... i just don't how to subtract the times to get my output. I don't know if I'm setting the values correctly and that's why I get NaN as my output. It's a TIMESHEET assignment, so we have to add the time's in each row etc. I'm really new to this, help.
If you take a look at the value of your time inputs, they are strings. You can learn more about this type of time input here. The thing to note is that the value will always be a string in the format HH:MM (24 hour clock). This means it's easy to parse into hours/minutes.
I've made a function for you to do exactly this. You can find it here.
function ParseTime(timeString) {
var timeMatcher = /(\d\d):(\d\d)/;
var result = timeMatcher.exec(timeString);
// The first result (result 0) is the full string,
// the second is the number of hours, the third is the number of minutes.
var hours = Number(result[1]);
var minutes = Number(result[2]);
// returns the time in number of minutes.
return (hours * 60) + minutes;
}
I'm trying to change the values of some input fields only once upon page being loaded. For example submit_date_year should be current year, so 2017 right now.
My HTML
<template name="trip_html">
<table class="table table-striped table-condensed table-hover rsk-tbl vScrollTHead">
<tr>
<td><input class="form-control input-lg" name="submit_date_day" type="text" placeholder="Day"/> </td>
<td><input class="form-control input-lg" name="submit_date_month" type="text" placeholder="Month"/> </td>
<td><input class="form-control input-lg" name="submit_date_year" type="text" placeholder="Year"/> </td>
</tr>
</table>
</template>
My JS
On page load function
Template.trip_html.rendered = function(event, template) {
event.target.submit_date_year.value = 'test'; // DOES NOT WORK
console.log('Template onLoad');
};
However, I cannot use event.target.submit_date_year in that on load function, for some reason...
But it works in events, once I click 'submit' button
Template.trip_html.events({
"submit .add-trip": function(event){
event.preventDefault();
var day = event.target.submit_date_day.value;
var month = event.target.submit_date_month.value;
var year = event.target.submit_date_year.value;
var car = event.target.submit_car.value;
var b = event.target.submit_b.value;
var a = event.target.submit_a.value;
var dist = event.target.submit_dist.value;
if(empty(day) || empty(month) || empty(year) || empty(car) || empty(b) || empty(a) || empty(dist)){
return false;
}
if(!isNumeric(day) || !isNumeric(month) || !isNumeric(year) || !isNumeric(dist)){
return false;
}
if(day.startsWith("0"))
day = day.replace("0", "");
if(month.startsWith("0"))
month = month.replace("0", "");
if(year.startsWith("0"))
year = year.replace("0", "");
console.log(day, month, year, car, a, b, dist);
Meteor.call('addTrip', day, month, year, car, a, b, dist);
event.target.submit_a.value = event.target.submit_b.value;
event.target.submit_b.value = '';
event.target.submit_dist.value = '';
},
Help please!
It does not work because you are passing an event parameter in the onRendered Callback. Therefore, you can't select the DOM element via event.target.
try to give the element a certain class in the markup and replace the line event.target.submit_date_year.value = 'test'; // DOES NOT WORK
with something like:
$('.year-input').val() = 'test';
The html line:
<td><input class="form-control input-lg year-input" name="submit_date_year" type="text" placeholder="Year"/></td>
You can delete the 'event' parameter from the rendered callback now.
Hope, I could help.
The reason it isn't working is because you aren't using the onRendered function properly. You are also trying to access the input using an event object which doesn't exist because there is no event.
Try:
Template.trip_html.onRendered(function () {
$('input[name="submit_date_year"]').val('2017');
});
EDIT
You can just use HTML to achieve this too if you don't need the data to be dynamic.
<input class="form-control input-lg" name="submit_date_year" type="text" placeholder="Year" value="2017"/>
I have a table. This table contains rows and one of those columns in each row is a date. There are two input text boxes above the table; one input box represents the from date and the other represents the to date. Let's say the user only enters in the from date, I would like the table to display every row that contains that date and after. The opposite goes for if the user only enters the date in the TO input field; it would show all rows with dates leading up to that date. Along with if the user has a FROM AND TO date. It would catch the dates with the FROM date and the TO date along with every row that contains a date that is in between those.
What I have completed so far is an input field that will search the entire body of the table and output that row for whichever characters the user has entered.
JQuery
<script>
$("#searchInput").keyup(function () {
//split the current value of searchInput
var data = this.value.split(" ");
//create a jquery object of the rows
var jo = $(".fbody").find("tr");
if (this.value == "") {
jo.show();
return;
}
//hide all the rows
jo.hide();
//Recusively filter the jquery object to get results.
jo.filter(function (i, v) {
var $t = $(this);
for (var d = 0; d < data.length; ++d) {
if ($t.is(":contains('" + data[d] + "')")) {
return true;
}
}
return false;
})
//show the rows that match.
.show();
}).focus(function () {
this.value = "";
$(this).unbind('focus');
})
</script>
HTML
<input id="searchInput" type="text" placeholder="From"/>
<input id="searchInput" type="text" placeholder="To" >
<tbody class="fbody">
<tr>
<td>something</td>
<td>something</td>
<td>4/18/2016</td>
<td>something</td>
</tr>
<tr>
<td>something</td>
<td>something</td>
<td>4/19/2016</td>
<td>something</td>
</tr>
<tr>
<td>something</td>
<td>something</td>
<td>4/20/2016</td>
<td>something</td>
</tr>
</tbody>
Please Help. Thanks.
One big problem with your current code was the duplicate ids the DOM. The remainder of your logic was close, but I simplified it.
The snippet below should work for you. If the dates entered at the top are invalid they will be ignored completely. Note that since we're running on the input event, you're temporarily going to filter out all your rows because it is going to interpret years before they are filled-out to 4 digits. You may want to account for this differently, or potentially use the blur event instead.
$(".searchInput").on("input", function() {
var from = stringToDate($("#searchFrom").val());
var to = stringToDate($("#searchTo").val());
$(".fbody tr").each(function() {
var row = $(this);
var date = stringToDate(row.find("td").eq(2).text());
//show all rows by default
var show = true;
//if from date is valid and row date is less than from date, hide the row
if (from && date < from)
show = false;
//if to date is valid and row date is greater than to date, hide the row
if (to && date > to)
show = false;
if (show)
row.show();
else
row.hide();
});
});
//parse entered date. return NaN if invalid
function stringToDate(s) {
var ret = NaN;
var parts = s.split("/");
date = new Date(parts[2], parts[0], parts[1]);
if (!isNaN(date.getTime())) {
ret = date;
}
return ret;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input id="searchFrom" class="searchInput" type="text" placeholder="From"/>
<input id="searchTo" class="searchInput" type="text" placeholder="To" >
<table class="fbody" border="1">
<tr>
<td>nothing</td>
<td>nothing</td>
<td>4/18/2016</td>
<td>nothing</td>
</tr>
<tr>
<td>nothing</td>
<td>nothing</td>
<td>4/19/2016</td>
<td>nothing</td>
</tr>
<tr>
<td>nothing</td>
<td>nothing</td>
<td>4/20/2016</td>
<td>nothing</td>
</tr>
</table>
I have a series of input boxes in a table with some number of dynamically generated rows as such:
<table id="someDataTable">
<tbody>
<tr>
<td >Some Title</td>
<td >Units</td>
<td >Val/Unit</td>
<td >Value</td>
</tr>
<tr>
<td><input type="text" size="30" /></td>
<td><input type="text" size="14" class="units commas"/></td>
<td><input type="text" size="14" class="value commas"/></td>
<td><input type="text" size="14" readonly="readonly" class="autoTotal"/></td>
</tr>
...
</tbody>
</table>
Now, I have a blur() call to add commas every time an input box is exited to add commas with the nifty Number Formatter plugin, and it simply does this:
<script>
$(".commas").blur(function () {
$(this).parseNumber({ format: "#,###", locale: "us" });
$(this).formatNumber({ format: "#,###", locale: "us" });
});
</script>
And it works beautifully. Now, on the other side, I also have a chunk of code that does the form math automatically on every keystroke. It has a call in initialize() that looks like this:
$(document).on('keyup', '#someDataTable', DoCalculations);
The function it invokes looks like this:
function DoCalculations() {
$(this).find('tr').each(function () {
var tUnits = $(this).find('.units').val();
var tValue = $(this).find('.value').val();
$(this).find('.autoTotal').val(Math.round(tUnits * tValue));
});
}
--
Now, my problem: I need to be able to rip out the commas to do the calculations. I was hoping to be able to use NumberFormatter's parseNumber() function to do this, but it was having a small fit. This was the alternate code in DoCalculations to attempt to accomplish that:
function DoCalculations() {
$(this).find('tr').each(function () {
var tTotal;
var tUnits = $(this).find('.units').val();
var tValue = $(this).find('.value').val();
tUnits = $.parseNumber(tUnits, { format: "#,###", locale: "us" });
tValue = $.parseNumber(tValue, { format: "#,###", locale: "us" });
tTotal = tUnits * tValue;
tTotal = $.formatNumber(tTotal, { format: "#,###", locale: "us" });
$(this).find('.autoTotal').val(tTotal);
});
}
But it comes back with a runtime error in NumberFormatter.js, where it cannot get the property of numberString.indexOf of undefined or null reference. Line 442 to be exact. I'm not sure why though. I originally thought it was because there were empty input boxes, but that turned out to not matter.
At the end of the day, I need to strip out commas.
Removing characters is something that regular expressions excel at:
var tValue = parseFloat($(this).find('.value').val().replace(/,/g, ''));
UPDATE
If val() can be null/undefined, you can add a check like this:
var tValue = $(this).find('.value').val();
tValue = tValue ? parseFloat(tValue.replace(/,/g, '')) : 0;