Does moment.js comparing dates not work properly? - javascript

I am building a datatable and wish to compare a date string that is passed in, to todays date, and then do something based on the outcome (before today, same as today etc etc)
"createdRow": function (row, data, dataIndex) {
var formattedDate = moment().format("DD-MMM-YYYY");
var dateIncoming = moment(data.NextDue, 'DD-MMM-YYYY').format("DD-MMM-YYYY");
if (dateIncoming < formattedDate) {
dateDue = true;
}
if (dateDue === true && data.AssignedToName !== "With Caller") {
$(row).css({ "color": "red" });
}
}
So it is mainly working, but I have one record where the dateDue is 15-03-2017 and the formattedDate is also 15-03-2017, but the css on my row is still activating.
I would normally expect this to happen if a datetime was also involved, and I also have several other values where dateDue is 15-03-2017 and these filter correctly.

You can use isBefore and isAfter to compare moment objects istead of <.
Moreover you need to remove format() since it trasforms moment object in string, so, as stated in the comments, in your code you are comparing strings intead of moment/dates.
Your code will be:
"createdRow": function (row, data, dataIndex) {
var formattedDate = moment();
var dateIncoming = moment(data.NextDue, 'DD-MMM-YYYY');
if (dateIncoming.isBefore(formattedDate)) {
dateDue = true;
}
if (dateDue === true && data.AssignedToName !== "With Caller") {
$(row).css({ "color": "red" });
}
}

Related

I want to filter by a date range using a custom date component for Ag-Grid ReactJS

I want to filter by a date range instead of a single date using the ReactJS ag grid.
Here is my code sample in plnkr
componentDidMount() {
this.picker = flatpickr(this.refs.flatpickr, {
onChange: this.onDateChanged.bind(this),
dateFormat: 'd/m/Y',
mode:'range',
wrap: true,
});
So I have added mode:'range' to use a date range for the flatpickr date component that ag-grid uses in their examples
I want to be able to filter the rows in the plnkr example by using the date range. However, I can only pass in one of the dates (the from date) to the comparator function in the columnDef. If I try to pass in an array of dates, I receive an error since ag-grid is only expecting a single date object and not an array of date objects.
{
field: 'date',
minWidth: 190,
filter: 'agDateColumnFilter',
filterParams: {
comparator: function(filterLocalDateAtMidnight, cellValue) {
var dateAsString = cellValue;
var dateParts = dateAsString.split('/');
var cellDate = new Date(
Number(dateParts[2]),
Number(dateParts[1]) - 1,
Number(dateParts[0])
);
if (filterLocalDateAtMidnight.getTime() === cellDate.getTime()) {
return 0;
}
if (cellDate < filterLocalDateAtMidnight) {
return -1;
}
if (cellDate > filterLocalDateAtMidnight) {
return 1;
}
},
},
},
I suspect I need to overwrite one of the api methods to take in an array of date objects instead of a single date in the column definitions but I cannot seem to do this correctly.

How to change more than one cell background color in fullCalendar

I am changing the cell background color of jan 12 using dayRender. How can I change one more cell background color in same month?
var data=[{
'specialDay':'2017-01-12'
}];
console.log(data)
var $calendar = $('#calendar').fullCalendar({
defaultView: 'month',
dayRender: function (date, cell) {
var today = new Date(data[0].specialDay);
if (date.getDate() === today.getDate() && date.getMonth() === today.getMonth()) {
cell.css("background-color", "red");
}
}
});
http://jsfiddle.net/CYnJY/937/
EDIT Attempt at using a loop, which still isn't working properly:
var data = [{
'name': 'xxx',
'specialDay': [{
'day': '2017-01-12'
}, {
'day': '2017-01-19'
}]
}];
console.log(data)
var $calendar = $('#calendar').fullCalendar({
defaultView: 'month',
dayRender: function(date, cell) {
$.each(data.specialDay, function(index, element) {
alert(element.day)
var today = new Date(data[0].specialDay);
if (date.getDate() === today.getDate() && date.getMonth() === today.getMonth()) {
cell.css("background-color", "red");
}
})
}
});
http://jsfiddle.net/CYnJY/941/
There were a couple of relatively simple things wrong with your attempt, both of which resulted in errors being displayed in the browser console:
I couldn't see any reason for data to be an array. SpecialDay within it is an array and that seemed to be sufficient for your purpose. Then in places you were trying to access data.specialDay, which didn't exist (it would have had to be data[0].specialDay because you had to access the first object of the data array, which then contained the specialDay property).
new Date(data[0].specialDay); The date is actually in the day property of the object(s) within the specialDay array. Putting an array into the Date constructor doesn't make a lot of sense - an array can't be parsed as a date. Ironically, right above it you had alerted element.day, which is what you needed to feed into the array, so you weren't far away from the correct solution to this one.
Here's a working version of the code:
var data = { //data is now an object
'name': 'xxx',
'specialDay': [{
'day': '2017-11-12'
}, {
'day': '2017-11-19'
}]
};
console.log(data)
var $calendar = $('#calendar').fullCalendar({
defaultView: 'month',
dayRender: function(date, cell) {
$.each(data.specialDay, function(index, element) {
//alert(element.day)
var today = new Date(element.day); //put the correct variable into the Date constructor
if (date.getDate() === today.getDate() && date.getMonth() === today.getMonth()) {
cell.css("background-color", "red");
}
})
}
});
See http://jsfiddle.net/CYnJY/947/ for a demo.
One other observation: you are using a very old version of fullCalendar (1.6.1) which is no longer supported. The current version is 3.6.2. I would advise you to upgrade as soon as you can. There may be a small number of changes you need to make, including upgrading your jQuery version, including moment.js etc, but it's all clear in the documentation. This link has a guide to upgrading from version 1.x to 2.0 and above: https://fullcalendar.io/wiki/Upgrading-to-v2/

How to convert an associative array of dates into object in jQuery for flatpickr

I've been trying to figure this out for hours, and not getting anywhere at all.
OK, so I have a database table that saves staff holidays, using a start and an end date, so it's a range. If it's a single day, it will be the same date but normally it's a range.
I am using Flatpickr on my site in order to book a job for a specific date and time, but I need to disable dates that the chosen staff member is NOT available on. When the user selects a staff member, there is an ajax call to the holiday table in the database and fetches any holiday dates, puts them in an array then returns it back to the ajax in JSON. Here's my call ($(this).val() refers to the staff dropdown, and this will run on change):
var staffId = $(this).val();
var dateObj = {};
var parsed;
$.post( '/get-availability', { staff_id: staffId }
).done( function(response) {
if(response.length > 0) {
parsed = JSON.parse(response);
$.each(parsed, function(i, element) {
console.log("i : " + i);
dateObj = { from : element['from'], to : element['to'] };
});
}
The PHP in get-availability is as follows:
$staff_id = $request->get('staff_id');
$staff_entity = $this->getDoctrine()->getManager()->getRepository('AppBundle:Staff')->findOneBy(array('id' => $staff_id));
// get all holidays for the staff member
$holiday_repo = $this->getDoctrine()->getManager()->getRepository('AppBundle:Holiday');
$holidays = $holiday_repo->findBy(array('staff' => $staff_entity));
$result = array();
if(!empty($holidays)) {
$x = 0;
foreach ($holidays as $row) {
$result[$x]['from'] = $row->getStartDate()->format('Y-m-d');
$result[$x]['to'] = $row->getEndDate()->format('Y-m-d');
$x ++;
}
}
return new Response(json_encode($result));
Coming back to the ajax, I need to layout my flatpickr config as follows (the dates are just examples):
disable: [
{
from: "2017-04-01",
to: "2017-06-01"
},
{
from: "2017-09-01",
to: "2017-12-01"
}
]
But my dateObj will get overwritten each time, so it only adds the LAST date range in:
var config = {
disable: [
dateObj
]
};
Basically, I need to know how to correctly adapt the $.each loop in order to get a result like the first example above, but nothing works. So far I've tried:
dateObj += { from : element['from'], to : element['to'] };
dateObj.i = { from : element['from'], to : element['to'] };
Then making it an array and trying:
dateObj[i] = { from : element['from'], to : element['to'] };
JSON.stringify(dateObj)
But every single one fails. I'm hoping someone can help me with this!
OK, in the end I used the DatePeriod() function and passed all the dates back as a single array, rather than in the from and to blocks. Not exactly the most optimised version of doing it but it works.
foreach ($holidays as $row) {
$start_date = new \DateTime($row->getStartDate()->format('Y-m-d'));
$end_date = new \DateTime($row->getEndDate()->format('Y-m-d'));
$date_range = new \DatePeriod($start_date, new \DateInterval('P1D'), $end_date);
foreach($date_range as $date){
$date_array[] = $date->format('Y-m-d');
}
// Add the end date as this is not included in the date period.
$date_array[] = $row->getEndDate()->format('Y-m-d');
}
$date_array then gets encoded and passed back to the Ajax where it is parsed and added to the config of flatpickr.

How can I select the features based on propetry

How can I select the features from the property attributes of the feature ?
Have a look at Array.protoype.filter()
Ok, it's not pretty but it works;)
Create a filter function
function filterBy(element) {
return
element.properties.systemtime_start ==
getMonthFromEpoch(element.properties.systemtime_start);
}
Create a function to filter the month
function getMonthFromEpoch(time) {
var month = 'noMonthSet';
var tMonth = new Date(time).toLocaleDateString('en-US', {month: 'long'});
if (tMonth == 'January') {
month = time;
}
return month
}
Pass the part with the features of your object to the filter
var filterd = yourObject.features.filter(filterBy)
This will return a new array with objects matching to systemstartTime 'January'
One more thing. I would change your naming. Use system_time_start instead of system:time_start. Otherwise you won't be able this property via JS

Ext JS GroupingStore group DateTime column by just date?

I have an Ext GroupingStore on a list of orders. One of the columns is a DateTime. I would like the user to be able to group by the DateTime column and have all days under one group. At the moment, each date, hour, minute and second is one group... not very useful :-)
Any way short of two columns to accomplish this?
You can modify a GroupingView method to accomplish this.
First create the GroupingView object:
var gview = new Ext.grid.GroupingView({
forceFit: true,
groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
});
Then modify the (in fact "private") method:
gview.getGroup = function(v, r, groupRenderer, rowIndex, colIndex, ds){
// colIndex of your date column
if (colIndex == 2) {
// group only by date
return v.format('m.d.Y');
}
else {
// default grouping
var g = groupRenderer ? groupRenderer(v, {}, r, rowIndex, colIndex, ds) : String(v);
if(g === ''){
g = this.cm.config[colIndex].emptyGroupText || this.emptyGroupText;
}
return g;
}
};
Then apply the View to the grid:
var grid = new Ext.grid.GridPanel({
...
view: gview,
...
});
Ah well, a little proof of concept (Click on sort 'Last Updated')
Demo
I think you can specify the date format when you are defining the record type for the store.
It may solve your problem.
Something like
var reader = new Ext.data.JsonReader(
fields:[{
type: 'date',
dateformat: 'd M Y'
},{
.............
..............
},
.............
.............
]
)
var store = new Ext.data.Store({
reader: reader,
data: []
})
Tarnschaf's answer was correct, I just thought I would post my final, modified version of his code for completness. This was how I ended up doing it. Thanks Tarnschaf!
g.view.getGroup = g.view.getGroup.wrap(function(normal,v, r, groupRenderer, rowIndex, colIndex, ds)
{
var cm = g.getColumnModel();
var id=cm.getColumnId(colIndex);
var col=cm.getColumnById(id);
if(col.renderer == formatDateTime)
{
v = (new Date(v)).format('m/d/yy');
groupRenderer = formatDate;
}
return normal(v, r, groupRenderer, rowIndex, colIndex, ds);
});
where g is the GridView. I found that by using g.view.getGroup.wrap I could keep the previous function intact, and only modify the parameters as Tarnschaf's answer did. Also, this method works even if the columns are reordered -- there's no colIndex hard coded in. Furthermore, it automatically applies itself to every column which has a renderer of formatDateTime (my date/time formating function) and switches those to the formatDate groupRenderer so the group headings look cleaner.
Do you actually need to reference the time part of the date? If not, you could use a convert function on the field to call clearTime() on the date object.
In your grid column definition, define a groupRenderer config:
{
groupRenderer : function(v, u, r, row, col, store) {
return //your custom group value
}
}

Categories

Resources