November 26, 2011

Extending ExtJS 4 DatePicker to highlight marked dates


Hi guys,

So today I want to share with you a little extension that I re-wrote for ExtJS 4 DatePicker component.
I say re-wrote, because this is an advanced form of the solution presented here, except that the other one relates to ExtJS 3 and not as robust.

So the basic idea is to have a marked dates on the calendar, same as you would have on your meeting calendar date picker in outlook. I also wanted the component to show some related tooltips for the marked date, and that meant that the data provider for the component is not strictly dates (as in a String, like the other solution), but rather an Objects that contains some metadata for the date.

Let's start with the data that we wish to be displayed. We want to have the date marked, so we need a Date, and for this example we will use the JS Date object, and for each date we want to display tooltip for a mock percentage and cost. So we're actually talking of an object that might look like this:
{date:new Date(2011, 10, 19), percent: '30%', cost:596}
On the component itself we I've created a config member named "markers". This one will hold the array of objects mentioned above.
config: {
    markers: null
},
In addition I want the JS Date object that is given to the DatePicker to use the same date format that is configured for the DatePicker, so for the sake of that lets override the applyMarkers method and in it apply the DatePicker format on each date. With this process we're actually changing the data within the markers from a simple Array to Associative Array, or a Map if you want, where each cell is defined by the formatted date and in it holds the metadata. This will help us later in marking these dates easily.
applyMarkers: function(markers) {
var formattedMarkers = [],
me = this

var formatDates = function(marker) {
var format = me.format,
eDate = Ext.Date,
formattedDate = eDate.dateFormat(marker.date, format)

formattedMarkers[formattedDate] = {percent: marker.percent, cost:marker.cost};
}

Ext.Array.each(markers, formatDates);

return formattedMarkers;
},
We're getting to the heart of the modification. Here we override the fullUpdate method of the DatePicker since it is the one that is in charge of rendering the cells within the calendar, we will add our own "if" statement to ask if there are dates to be marked, and if so we will find the cells that match the dates on the associative Array and append a tooltip according to marker object data.
For convenience purposes I'm only giving the relevant code part:
fullUpdate: function(date, active) {
...
var markers = this.markers;
...
setCellClass = function(cell) {
...
// If we have a need for highlighted dates, let's find the dates
// and start highlighting them
if (markers) {
formatValue = eDate.dateFormat(current, format);
if (markers[formatValue] != null) {
// Use the highlight-date CSS class for highlighting
cell.className = 'highlight-date';
cell.title = "Percent: " + markers[formatValue]["percent"] + "\n" + "Cost: " + markers[formatValue]["cost"];
}
}
};
...
}
Notice that I'm using a CSS class named "highlight-date" to mark the cells. This class, of course, should be included in your CSS file.
And there you have it. A DatePicker that lets you mark dates and append tooltips for it, here is how you use it:
Ext.create('Flashmattic.component.AdvancedDate', {
markers:[
{date:new Date(2011, 10, 19), percent: '30%', cost:596},
{date:new Date(2011, 10, 10), percent: '10%', cost:45},
{date:new Date(2011, 10, 8), percent: '86%', cost:367}
]
})

Have a great week,
Cheers.

3 comments:

Sergio said...

Hi man, where i can download this component? Thanks.

Flashmattic said...

Here :)
This is the code for it, I haven't uploaded it anywhere. Sorry.

Bijan said...

Hi,
i tried this code but i didnt work as i expect, so if anyone has idea let me know.