I needed a simple calendar simple to DatePicker control. The example includes handling of mouse over and click events for showing additional information for each day. Live example at:
http://www.durlabh.com/extJS/example.../calendar.html
You can download the code from:
http://www.durlabh.com/extJS/example...r/calendar.zip
Some of the features are:
* Ability to easily specify the mouse over, color/ content of individual cell based on date
* Resizable
* Fast switching between months
To test, place the files in extJS\examples\Calendar folder. Here is the code if you are having trouble downloading:
Calendar.css
Code:
.ux-cal
{
font-size:11px;
}
.ux-cal .ux-cal-weekday
{
background:#DFECFB url(../../resources/images/default/shared/glass-bg.gif) repeat-x scroll left top;
font-weight:bold;
height:25px;
}
.ux-cal .ux-cal-header
{
background:transparent url(../../resources/images/default/shared/hd-sprite.gif) repeat-x scroll 0 -83px;
height:25px;
}
.ux-cal .ux-cal-header .ux-cal-monthTitle
{
text-align:center;
color:#ffffff;
font-weight:bold;
}
.ux-cal td
{
text-align: center;
vertical-align: middle;
border:solid 1px white;
cursor:pointer;
}
.ux-cal .ux-cal-row td:hover
{
background: #ddecfe;
}
.ux-cal .otherMonth
{
color: #AAAAAA;
}
.ux-cal-weekday td
{
cursor:default;
}
Calendar.js
Code:
Ext.ux.Calendar = function(config) {
Ext.ux.Calendar.superclass.constructor.call(this, config);
this.addEvents({
click: true,
mouseover: true,
mouseout: true
});
};
Ext.ux.Calendar = Ext.extend(Ext.Panel, {
onRender: function(container, position) {
Ext.ux.Calendar.superclass.onRender.apply(this, arguments);
this.createInitialLayout();
this.update();
},
daysOfWeek: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
value: new Date(),
moveMonths: function(months) {
this.value = this.value.add(Date.MONTH, months);
this.update();
},
showPrevMonth: function() {
this.moveMonths(-1);
},
showNextMonth: function() {
this.moveMonths(1);
},
showNavigation: true,
createInitialLayout: function() {
var htmlData = [];
htmlData.push("<table class=\"ux-cal\" width='100%' height='100%' cellspacing='0'>");
htmlData.push("<thead>");
htmlData.push("<tr class='ux-cal-header'>");
htmlData.push("<th><div class='x-date-left'><a href='#'> </a></th>")
htmlData.push("<th colspan='5' class='ux-cal-monthTitle'> </th>");
htmlData.push("<th><div class='x-date-right' style='float:right'><a href='#'> </a></div></th>")
htmlData.push('</th></tr>');
htmlData.push('</thead>');
htmlData.push('<tbody>');
htmlData.push("<tr class='ux-cal-weekday'>");
var daysOfWeek = this.daysOfWeek;
for (var i = 0; i < 7; i++) {
var width = i == 0 || i == 6 ? 15 : 14;
htmlData.push('<td width="' + width + '%">' + daysOfWeek[i] + '</td>');
}
htmlData.push('</tr>');
for (var i = 0; i < 42; i++) {
if (i % 7 == 0) { // First day of week
htmlData.push("<tr class='ux-cal-row'>");
}
htmlData.push("<td> </td>");
if (i % 7 == 6) { // Last day of week
htmlData.push("</tr>");
}
}
htmlData.push('</tbody>');
htmlData.push("</table>");
this.body.update(htmlData.join(""));
var leftNav = this.body.child("div.x-date-left a");
var rightNav = this.body.child("div.x-date-right a");
this.leftClickRpt = new Ext.util.ClickRepeater(leftNav, { handler: this.showPrevMonth, scope: this, preventDefault: true, stopDefault: true });
this.rightClickRpt = new Ext.util.ClickRepeater(rightNav, { handler: this.showNextMonth, scope: this, preventDefault: true, stopDefault: true });
var showNavigation = this.showNavigation;
leftNav.setDisplayed(showNavigation);
rightNav.setDisplayed(showNavigation);
this.calendarHeaderEl = this.body.child('th.ux-cal-monthTitle');
var table = this.body.select('table');
table.on({
mouseover: this.onMouseOver,
mouseout: this.onMouseOut,
click: this.onClick,
scope: this
});
this.cells = this.body.select('tbody td');
},
beforeDestroy: function() {
this.leftClickRpt.destroy();
this.rightClickRpt.destroy();
this.cells.destroy();
Ext.ux.Calendar.superclass.beforeDestroy.apply(this, arguments);
},
onMouseOver: function(e) {
this.processEvent('mouseover', e);
},
onMouseOut: function(e) {
this.fireEvent('mouseout', e, this);
},
onClick: function(e) {
this.processEvent('click', e);
},
processEvent: function(eventName, e) {
var t = e.getTarget();
var o = {};
if (t.tagName == 'TD') {
var cell = t;
var row = t.parentNode;
var rowIndex = row.rowIndex - 2; // Ignore header rows
o = { cellIndex: cell.cellIndex, rowIndex: rowIndex, row: row, cell: cell };
if (rowIndex >= 0) {
o.date = this.startOfCalendar.add(Date.DAY, ((o.rowIndex) * 7) + o.cellIndex);
}
}
this.fireEvent(eventName, o, e);
},
update: function() {
var value = this.value.clearTime();
var startOfCalendar = value.getFirstDateOfMonth();
var endOfCalendar = startOfCalendar.getLastDateOfMonth();
var startWeekDay = Number(startOfCalendar.format("N"));
if (startWeekDay > 0) {
startOfCalendar = startOfCalendar.add(Date.DAY, -startWeekDay);
}
var endWeekDay = Number(endOfCalendar.format("N"));
if (endWeekDay < 6) {
endOfCalendar = endOfCalendar.add(Date.DAY, 6 - endWeekDay);
}
var duration = endOfCalendar - startOfCalendar;
var oneDay = 1000 * 60 * 60 * 24;
duration = duration / oneDay + 1;
endOfCalendar = endOfCalendar.add(Date.DAY, 42 - duration);
var htmlData = [];
var calendarTitle = value.format("F, Y");
this.calendarHeaderEl.update(calendarTitle);
var currentMonth = value.format("m");
var o = { today: new Date().clearTime(), date: startOfCalendar };
var cells = this.cells.elements;
this.startOfCalendar = startOfCalendar;
for (var i = 0; i < 42; i++) {
o.css = o.date.format("m") == currentMonth ? "sameMonth" : "otherMonth";
o.css += " x-unselectable";
o.caption = o.date.format("d");
o.cell = cells[i + 7];
this.formatDay(o);
o.cell.className = o.css;
o.cell.innerHTML = o.caption;
o.date = o.date.add(Date.DAY, 1);
}
},
beforeDestroy: function() {
if (this.rendered) {
Ext.destroy(
this.leftClickRpt,
this.rightClickRpt
);
}
Ext.ux.Calendar.superclass.beforeDestroy.apply(this, arguments);
}
});
Ext.reg('ux-cal', Ext.ux.Calendar);
Sample implementation showing mouse over/ click event handling:
Code:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Calendar Example</title>
<link rel="stylesheet" type="text/css" href="../../resources/css/ext-all.css" />
<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../../ext-all.js"></script>
<script language="javascript" src="calendar.js"></script>
<link rel="stylesheet" type="text/css" href="calendar.css" />
<style>
.ux-cal-highlight { background-color: gray; }
</style>
</head>
<body>
<a href="javascript:emulateAJAX()">Reset calendar data</a>
</body>
<script type="text/javascript">
emulateAJAX = function() {
// Sample data that could have been from AJAX request
homeCalendar.dates = {
'20090614': '14-Jun-2009 Data'
}
if (homeCalendar.rendered) {
homeCalendar.update();
}
};
homeCalendar = new Ext.ux.Calendar({
// Sample data
dates: {
'20090615': 'Test'
},
getData: function(o) {
return this.dates[o.date.format("Ymd")];
},
// Custom formatting based on date
formatDay: function(o) {
var data = this.getData(o);
if (data) {
o.css += " ux-cal-highlight";
o.caption += "*";
}
},
listeners: {
// Sample for click handling
click: function(o) {
if (o.date) {
var data = this.getData(o);
if (data) {
Ext.Msg.alert('Alert', 'Event on ' + o.date.toString() + ":" + data);
} else {
Ext.Msg.alert('Alert', 'No event scheduled on ' + o.date.toString());
}
}
},
// Sample for mouse over handling to show tool-tip
mouseover: function(o) {
if (!o.date) {
this.tooltip.hide();
} else {
var text = o.date.toString();
if (this.tooltip.rendered) {
this.tooltip.body.dom.innerHTML = text;
} else {
this.tooltip.html = text;
}
this.tooltip.show();
}
},
// Adding tool-tip to the calendar
render: function() {
this.tooltip = new Ext.ToolTip({
target: this.body,
showDelay: 20,
trackMouse: true
})
},
destroy: function() {
this.tooltip.destroy();
}
}
});
Ext.QuickTips.init();
var win = new Ext.Window({
height: 300,
width: 300,
layout: 'fit',
items: homeCalendar,
title: 'Calendar'
});
win.show();
</script>
</html>