/* Copyright (c) 2004-2006, 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.DatePicker"); dojo.require("dojo.date.common"); dojo.require("dojo.date.format"); dojo.require("dojo.date.serialize"); dojo.require("dojo.widget.*"); dojo.require("dojo.widget.HtmlWidget"); dojo.require("dojo.event.*"); dojo.require("dojo.dom"); dojo.require("dojo.html.style"); dojo.widget.defineWidget( "dojo.widget.DatePicker", dojo.widget.HtmlWidget, { /* summary: Base class for a stand-alone DatePicker widget which makes it easy to select a date, or switch by month and/or year. description: A stand-alone DatePicker widget that makes it easy to select a date, or increment by week, month, and/or year. It is designed to be used on its own, or inside of other widgets to (see dojo.widget.DropdownDatePicker) or other similar combination widgets. Dates attributes passed in the `RFC 3339` format: http://www.faqs.org/rfcs/rfc3339.html (2005-06-30T08:05:00-07:00) so that they are serializable and locale-independent. usage: var datePicker = dojo.widget.createWidget("DatePicker", {}, dojo.byId("datePickerNode"));
*/ //start attributes // value: String|Date // form value property if =='today' will be today's date value: "", // name: String // name of the form element name: "", // displayWeeks: Integer // total weeks to display default displayWeeks: 6, // adjustWeeks: Boolean // if true, weekly size of calendar changes to acomodate the month if false, 42 day format is used adjustWeeks: false, // startDate: String|Date // first available date in the calendar set startDate: "1492-10-12", // endDate: String|Date // last available date in the calendar set endDate: "2941-10-12", // weekStartsOn: Integer // adjusts the first day of the week 0==Sunday..6==Saturday weekStartsOn: "", // storedDate: String // deprecated use value instead storedDate: "", // staticDisplay: Boolean // disable all incremental controls, must pick a date in the current display staticDisplay: false, // dayWidth: String // how to render the names of the days in the header. see dojo.date.getDayNames dayWidth: 'narrow', classNames: { // summary: // stores a list of class names that may be overriden // TODO: this is not good; can't be adjusted via markup, etc. since it's an array previous: "previousMonth", disabledPrevious: "previousMonthDisabled", current: "currentMonth", disabledCurrent: "currentMonthDisabled", next: "nextMonth", disabledNext: "nextMonthDisabled", currentDate: "currentDate", selectedDate: "selectedItem" }, templatePath: dojo.uri.dojoUri("src/widget/templates/DatePicker.html"), templateCssPath: dojo.uri.dojoUri("src/widget/templates/DatePicker.css"), postMixInProperties: function(){ // summary: see dojo.widget.DomWidget dojo.widget.DatePicker.superclass.postMixInProperties.apply(this, arguments); if(this.storedDate){ dojo.deprecated("dojo.widget.DatePicker", "use 'value' instead of 'storedDate'", "0.5"); this.value=this.storedDate; } this.startDate = dojo.date.fromRfc3339(this.startDate); this.endDate = dojo.date.fromRfc3339(this.endDate); this.startDate.setHours(0,0,0,0); //adjust startDate to be exactly midnight this.endDate.setHours(24,0,0,-1); //adjusting endDate to be a fraction of a second before midnight if(!this.weekStartsOn){ this.weekStartsOn=dojo.date.getFirstDayOfWeek(this.lang); } this.today = new Date(); this.today.setHours(0,0,0,0); if(typeof(this.value)=='string'&&this.value.toLowerCase()=='today'){ this.value = new Date(); }else if(this.value && (typeof this.value=="string") && (this.value.split("-").length > 2)) { this.value = dojo.date.fromRfc3339(this.value); this.value.setHours(0,0,0,0); } }, fillInTemplate: function(args, frag) { // summary: see dojo.widget.DomWidget dojo.widget.DatePicker.superclass.fillInTemplate.apply(this, arguments); // Copy style info from input node to output node var source = this.getFragNodeRef(frag); dojo.html.copyStyle(this.domNode, source); this.weekTemplate = dojo.dom.removeNode(this.calendarWeekTemplate); this._preInitUI(this.value ? this.value : this.today, false, true); //init UI with date selected ONLY if user supplies one // Insert localized day names in the template var dayLabels = dojo.lang.unnest(dojo.date.getNames('days', this.dayWidth, 'standAlone', this.lang)); //if we dont use unnest, we risk modifying the dayLabels array inside of dojo.date and screwing up other calendars on the page if(this.weekStartsOn > 0){ //adjust dayLabels for different first day of week. ie: Monday or Thursday instead of Sunday for(var i=0;ithis.endDate){ dateObj = new Date((dateObj days){ this._preInitUI(this.startDate,true,false); nextDate = new Date(this.firstDay); } this.curMonth = new Date(nextDate); this.curMonth.setDate(nextDate.getDate()+6); this.curMonth.setDate(1); var curClass = (nextDate.getMonth() == this.curMonth.getMonth())?'current':'previous'; } if(initUI){ this._initUI(days); } }, _initUI: function(days) { dojo.dom.removeChildren(this.calendarDatesContainerNode); for(var i=0;ithis.endDate){ incWeek = incMonth = incYear = false; } if(decMonth && add(d,DAY,-1)this.endDate){ incMonth = incYear = false; } if(decYear && add(d2,YEAR,-1)this.endDate){ incYear = false; } } function enableControl(node, enabled){ dojo.html.setVisibility(node, enabled ? '' : 'hidden'); } enableControl(this.decreaseWeekNode,decWeek); enableControl(this.increaseWeekNode,incWeek); enableControl(this.decreaseMonthNode,decMonth); enableControl(this.increaseMonthNode,incMonth); enableControl(this.previousYearLabelNode,decYear); enableControl(this.nextYearLabelNode,incYear); }, _incrementWeek: function(evt) { var d = new Date(this.firstDay); switch(evt.target) { case this.increaseWeekNode.getElementsByTagName("img").item(0): case this.increaseWeekNode: var tmpDate = dojo.date.add(d, dojo.date.dateParts.WEEK, 1); if(tmpDate < this.endDate){ d = dojo.date.add(d, dojo.date.dateParts.WEEK, 1); } break; case this.decreaseWeekNode.getElementsByTagName("img").item(0): case this.decreaseWeekNode: if(d >= this.startDate){ d = dojo.date.add(d, dojo.date.dateParts.WEEK, -1); } break; } this._preInitUI(d,true,true); }, _incrementMonth: function(evt) { var d = new Date(this.curMonth); var tmpDate = new Date(this.firstDay); switch(evt.currentTarget) { case this.increaseMonthNode.getElementsByTagName("img").item(0): case this.increaseMonthNode: tmpDate = dojo.date.add(tmpDate, dojo.date.dateParts.DAY, this.displayWeeks*7); if(tmpDate < this.endDate){ d = dojo.date.add(d, dojo.date.dateParts.MONTH, 1); }else{ var revertToEndDate = true; } break; case this.decreaseMonthNode.getElementsByTagName("img").item(0): case this.decreaseMonthNode: if(tmpDate > this.startDate){ d = dojo.date.add(d, dojo.date.dateParts.MONTH, -1); }else{ var revertToStartDate = true; } break; } if(revertToStartDate){ d = new Date(this.startDate); }else if(revertToEndDate){ d = new Date(this.endDate); } this._preInitUI(d,false,true); }, _incrementYear: function(evt) { var year = this.curMonth.getFullYear(); var tmpDate = new Date(this.firstDay); switch(evt.target) { case this.nextYearLabelNode: tmpDate = dojo.date.add(tmpDate, dojo.date.dateParts.YEAR, 1); if(tmpDatethis.startDate){ year--; }else{ var revertToStartDate = true; } break; } var d; if(revertToStartDate){ d = new Date(this.startDate); }else if(revertToEndDate){ d = new Date(this.endDate); }else{ d = new Date(year, this.curMonth.getMonth(), 1); } this._preInitUI(d,false,true); }, onIncrementWeek: function(/*Event*/evt) { // summary: handler for increment week event evt.stopPropagation(); if(!this.staticDisplay){ this._incrementWeek(evt); } }, onIncrementWeekPressed: function(event) { // DOJO accessibility for Alfresco WCM: ALF-11956 if(null != event){ event.stopPropagation(); if((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))){ this.onIncrementWeek(event); } } }, onIncrementMonth: function(/*Event*/evt) { // summary: handler for increment month event evt.stopPropagation(); if(!this.staticDisplay){ this._incrementMonth(evt); } }, onIncrementMonthPressed: function(event) { // DOJO accessibility for Alfresco WCM: ALF-11956 if(null != event){ event.stopPropagation(); if((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))){ this.onIncrementMonth(event); } } }, onIncrementYear: function(/*Event*/evt) { // summary: handler for increment year event evt.stopPropagation(); if(!this.staticDisplay){ this._incrementYear(evt); } }, onIncrementYearPressed: function(event) { // DOJO accessibility for Alfresco WCM: ALF-11956 if(null != event){ event.stopPropagation(); if((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))){ this.onIncrementYear(event); } } }, _setMonthLabel: function(monthIndex) { this.monthLabelNode.innerHTML = dojo.date.getNames('months', 'wide', 'standAlone', this.lang)[monthIndex]; }, _setYearLabels: function(year) { var y = year - 1; var that = this; function f(n){ that[n+"YearLabelNode"].innerHTML = dojo.date.format(new Date(y++, 0), {formatLength:'yearOnly', locale:that.lang}); } f("previous"); f("current"); f("next"); }, _getDateClassName: function(date, monthState) { var currentClassName = this.classNames[monthState]; //we use Number comparisons because 2 dateObjects never seem to equal each other otherwise if ((!this.selectedIsUsed && this.value) && (Number(date) == Number(this.value))) { currentClassName = this.classNames.selectedDate + " " + currentClassName; this.selectedIsUsed = true; } if((!this.currentIsUsed) && (Number(date) == Number(this.today))) { currentClassName = currentClassName + " " + this.classNames.currentDate; this.currentIsUsed = true; } return currentClassName; }, onClick: function(/*Event*/evt) { //summary: the click event handler dojo.event.browser.stopEvent(evt); }, _handleUiClick: function(/*Event*/evt) { // DOJO accessibility for Alfresco WCM: ALF-11956 var selectedDate = this._getSelectDayMonthAndYear(evt); if(null == selectedDate){ return; } this.clickedNode = evt.target; this.setDate(new Date(selectedDate.year, selectedDate.month, evt.target.innerHTML)); }, _getSelectDayMonthAndYear: function(evt) { // DOJO accessibility for Alfresco WCM: ALF-11956 var eventTarget = evt.target; if(eventTarget.nodeType != dojo.dom.ELEMENT_NODE){eventTarget = eventTarget.parentNode;} if(null != evt.preventDefault){ dojo.event.browser.stopEvent(evt); } this.selectedIsUsed = this.todayIsUsed = false; var month = this.curMonth.getMonth(); var year = this.curMonth.getFullYear(); if(dojo.html.hasClass(eventTarget, this.classNames["disabledPrevious"])||dojo.html.hasClass(eventTarget, this.classNames["disabledCurrent"])||dojo.html.hasClass(eventTarget, this.classNames["disabledNext"])){ return null; //this date is disabled... ignore it }else if (dojo.html.hasClass(eventTarget, this.classNames["next"])) { month = ++month % 12; if(month===0){++year;} } else if (dojo.html.hasClass(eventTarget, this.classNames["previous"])) { month = --month % 12; if(month==11){--year;} } return {"day": eventTarget.innerHTML, "month": month, "year": year}; }, _handleUiPress: function(event) { // DOJO accessibility for Alfresco WCM: ALF-11956 if(null != event){ event.stopPropagation(); if((13 == event.keyCode) || (32 == event.keyCode) || ((null != event.charCode) && (32 == event.charCode))){ this._handleUiClick(event); } } }, onValueChanged: function(/*Date*/date) { //summary: the set date event handler }, _isDisabledDate: function(dateObj){ if(dateObjthis.endDate){ return true; } return this.isDisabledDate(dateObj, this.lang); }, isDisabledDate: function(/*Date*/dateObj, /*String?*/locale){ // summary: // May be overridden to disable certain dates in the calendar e.g. isDisabledDate=dojo.date.isWeekend return false; // Boolean }, _initFirstDay: function(/*Date*/dateObj, /*Boolean*/adj){ //adj: false for first day of month, true for first day of week adjusted by startOfWeek var d = new Date(dateObj); if(!adj){d.setDate(1);} d.setDate(d.getDate()-this._getAdjustedDay(d,this.weekStartsOn)); d.setHours(0,0,0,0); return d; // Date }, _getAdjustedDay: function(/*Date*/dateObj){ //summary: used to adjust date.getDay() values to the new values based on the current first day of the week value var days = [0,1,2,3,4,5,6]; if(this.weekStartsOn>0){ for(var i=0;i