blob: a80d08aa2bbb49c78664e6657986d82fe88c2edb [file] [log] [blame]
/*
Copyright (c) 2004-2005, The Dojo Foundation
All Rights Reserved.
Licensed under the Academic Free License version 2.1 or above OR the
modified BSD license. For more information on Dojo licensing, see:
http://dojotoolkit.org/community/licensing.shtml
*/
dojo.provide("dojo.widget.html.DatePicker");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.HtmlWidget");
dojo.require("dojo.widget.DatePicker");
dojo.require("dojo.event.*");
dojo.require("dojo.html");
/*
Some assumptions:
- I'm planning on always showing 42 days at a time, and we can scroll by week,
not just by month or year
- To get a sense of what month to highlight, I basically initialize on the
first Saturday of each month, since that will be either the first of two or
the second of three months being partially displayed, and then I work forwards
and backwards from that point.
Currently, I assume that dates are stored in the RFC 3339 format,
because I find it to be most human readable and easy to parse
http://www.faqs.org/rfcs/rfc3339.html: 2005-06-30T08:05:00-07:00
FIXME: scroll by week not yet implemented
*/
dojo.widget.html.DatePicker = function(){
dojo.widget.DatePicker.call(this);
dojo.widget.HtmlWidget.call(this);
var _this = this;
// today's date, JS Date object
this.today = "";
// selected date, JS Date object
this.date = "";
// rfc 3339 date
this.storedDate = "";
// date currently selected in the UI, stored in year, month, date in the format that will be actually displayed
this.currentDate = {};
// stored in year, month, date in the format that will be actually displayed
this.firstSaturday = {};
this.classNames = {
previous: "previousMonth",
current: "currentMonth",
next: "nextMonth",
currentDate: "currentDate",
selectedDate: "selectedItem"
}
this.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlDatePicker.html");
this.templateCssPath = dojo.uri.dojoUri("src/widget/templates/HtmlDatePicker.css");
this.fillInTemplate = function(){
this.initData();
this.initUI();
}
this.initData = function() {
this.today = new Date();
if(this.storedDate && (this.storedDate.split("-").length > 2)) {
this.date = dojo.widget.DatePicker.util.fromRfcDate(this.storedDate);
} else {
this.date = this.today;
}
// calendar math is simplified if time is set to 0
this.today.setHours(0);
this.date.setHours(0);
var month = this.date.getMonth();
var tempSaturday = dojo.widget.DatePicker.util.initFirstSaturday(this.date.getMonth().toString(), this.date.getFullYear());
this.firstSaturday.year = tempSaturday.year;
this.firstSaturday.month = tempSaturday.month;
this.firstSaturday.date = tempSaturday.date;
}
this.setDate = function(rfcDate) {
this.storedDate = rfcDate;
}
this.initUI = function() {
this.selectedIsUsed = false;
this.currentIsUsed = false;
var currentClassName = "";
var previousDate = new Date();
var calendarNodes = this.calendarDatesContainerNode.getElementsByTagName("td");
var currentCalendarNode;
// set hours of date such that there is no chance of rounding error due to
// time change in local time zones
previousDate.setHours(8);
var nextDate = new Date(this.firstSaturday.year, this.firstSaturday.month, this.firstSaturday.date, 8);
if(this.firstSaturday.date < 7) {
// this means there are days to show from the previous month
var dayInWeek = 6;
for (var i=this.firstSaturday.date; i>0; i--) {
currentCalendarNode = calendarNodes.item(dayInWeek);
currentCalendarNode.innerHTML = nextDate.getDate();
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
dayInWeek--;
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, false);
}
for(var i=dayInWeek; i>-1; i--) {
currentCalendarNode = calendarNodes.item(i);
currentCalendarNode.innerHTML = nextDate.getDate();
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "previous"));
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, false);
}
} else {
nextDate.setDate(1);
for(var i=0; i<7; i++) {
currentCalendarNode = calendarNodes.item(i);
currentCalendarNode.innerHTML = i + 1;
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, true);
}
}
previousDate.setDate(this.firstSaturday.date);
previousDate.setMonth(this.firstSaturday.month);
previousDate.setFullYear(this.firstSaturday.year);
nextDate = this.incrementDate(previousDate, true);
var count = 7;
currentCalendarNode = calendarNodes.item(count);
while((nextDate.getMonth() == previousDate.getMonth()) && (count<42)) {
currentCalendarNode.innerHTML = nextDate.getDate();
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "current"));
currentCalendarNode = calendarNodes.item(++count);
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, true);
}
while(count < 42) {
currentCalendarNode.innerHTML = nextDate.getDate();
dojo.html.setClass(currentCalendarNode, this.getDateClassName(nextDate, "next"));
currentCalendarNode = calendarNodes.item(++count);
previousDate = nextDate;
nextDate = this.incrementDate(nextDate, true);
}
this.setMonthLabel(this.firstSaturday.month);
this.setYearLabels(this.firstSaturday.year);
}
this.incrementDate = function(date, bool) {
// bool: true to increase, false to decrease
var time = date.getTime();
var increment = 1000 * 60 * 60 * 24;
time = (bool) ? (time + increment) : (time - increment);
var returnDate = new Date();
returnDate.setTime(time);
return returnDate;
}
this.incrementWeek = function(date, bool) {
dojo.unimplemented('dojo.widget.html.DatePicker.incrementWeek');
}
this.incrementMonth = function(date, bool) {
dojo.unimplemented('dojo.widget.html.DatePicker.incrementMonth');
}
this.incrementYear = function(date, bool) {
dojo.unimplemented('dojo.widget.html.DatePicker.incrementYear');
}
this.onIncrementDate = function(evt) {
dojo.unimplemented('dojo.widget.html.DatePicker.onIncrementDate');
}
this.onIncrementWeek = function(evt) {
// FIXME: should make a call to incrementWeek when that is implemented
evt.stopPropagation();
dojo.unimplemented('dojo.widget.html.DatePicker.onIncrementWeek');
switch(evt.target) {
case this.increaseWeekNode:
break;
case this.decreaseWeekNode:
break;
}
}
this.onIncrementMonth = function(evt) {
// FIXME: should make a call to incrementMonth when that is implemented
evt.stopPropagation();
var month = this.firstSaturday.month;
var year = this.firstSaturday.year;
switch(evt.currentTarget) {
case this.increaseMonthNode:
if(month < 11) {
month++;
} else {
month = 0;
year++;
this.setYearLabels(year);
}
break;
case this.decreaseMonthNode:
if(month > 0) {
month--;
} else {
month = 11;
year--;
this.setYearLabels(year);
}
break;
case this.increaseMonthNode.getElementsByTagName("img").item(0):
if(month < 11) {
month++;
} else {
month = 0;
year++;
this.setYearLabels(year);
}
break;
case this.decreaseMonthNode.getElementsByTagName("img").item(0):
if(month > 0) {
month--;
} else {
month = 11;
year--;
this.setYearLabels(year);
}
break;
}
var tempSaturday = dojo.widget.DatePicker.util.initFirstSaturday(month.toString(), year);
this.firstSaturday.year = tempSaturday.year;
this.firstSaturday.month = tempSaturday.month;
this.firstSaturday.date = tempSaturday.date;
this.initUI();
}
this.onIncrementYear = function(evt) {
// FIXME: should make a call to incrementYear when that is implemented
evt.stopPropagation();
var year = this.firstSaturday.year;
switch(evt.target) {
case this.nextYearLabelNode:
year++;
break;
case this.previousYearLabelNode:
year--;
break;
}
var tempSaturday = dojo.widget.DatePicker.util.initFirstSaturday(this.firstSaturday.month.toString(), year);
this.firstSaturday.year = tempSaturday.year;
this.firstSaturday.month = tempSaturday.month;
this.firstSaturday.date = tempSaturday.date;
this.initUI();
}
this.setMonthLabel = function(monthIndex) {
this.monthLabelNode.innerHTML = this.months[monthIndex];
}
this.setYearLabels = function(year) {
this.previousYearLabelNode.innerHTML = year - 1;
this.currentYearLabelNode.innerHTML = year;
this.nextYearLabelNode.innerHTML = year + 1;
}
this.getDateClassName = function(date, monthState) {
var currentClassName = this.classNames[monthState];
if ((!this.selectedIsUsed) && (date.getDate() == this.date.getDate()) && (date.getMonth() == this.date.getMonth()) && (date.getFullYear() == this.date.getFullYear())) {
currentClassName = this.classNames.selectedDate + " " + currentClassName;
this.selectedIsUsed = 1;
}
if((!this.currentIsUsed) && (date.getDate() == this.today.getDate()) && (date.getMonth() == this.today.getMonth()) && (date.getFullYear() == this.today.getFullYear())) {
currentClassName = currentClassName + " " + this.classNames.currentDate;
this.currentIsUsed = 1;
}
return currentClassName;
}
this.onClick = function(evt) {
dojo.event.browser.stopEvent(evt)
}
this.onSetDate = function(evt) {
dojo.event.browser.stopEvent(evt);
this.selectedIsUsed = 0;
this.todayIsUsed = 0;
var month = this.firstSaturday.month;
var year = this.firstSaturday.year;
if (dojo.html.hasClass(evt.target, this.classNames["next"])) {
month = ++month % 12;
// if month is now == 0, add a year
year = (month==0) ? ++year : year;
} else if (dojo.html.hasClass(evt.target, this.classNames["previous"])) {
month = --month % 12;
// if month is now == 0, add a year
year = (month==11) ? --year : year;
}
this.date = new Date(year, month, evt.target.innerHTML);
this.setDate(dojo.widget.DatePicker.util.toRfcDate(this.date));
this.initUI();
}
}
dojo.inherits(dojo.widget.html.DatePicker, dojo.widget.HtmlWidget);