1 | define([ |
---|
2 | "dojo/_base/array", // array.map |
---|
3 | "dojo/date", |
---|
4 | "dojo/date/locale", |
---|
5 | "dojo/_base/declare", // declare |
---|
6 | "dojo/dom-attr", // domAttr.get |
---|
7 | "dojo/dom-class", // domClass.add domClass.contains domClass.remove domClass.toggle |
---|
8 | "dojo/_base/kernel", // kernel.deprecated |
---|
9 | "dojo/keys", // keys |
---|
10 | "dojo/_base/lang", // lang.hitch |
---|
11 | "dojo/on", |
---|
12 | "dojo/sniff", // has("ie") |
---|
13 | "./CalendarLite", |
---|
14 | "./_Widget", |
---|
15 | "./_CssStateMixin", |
---|
16 | "./_TemplatedMixin", |
---|
17 | "./form/DropDownButton" |
---|
18 | ], function(array, date, local, declare, domAttr, domClass, kernel, keys, lang, on, has, CalendarLite, _Widget, _CssStateMixin, _TemplatedMixin, DropDownButton){ |
---|
19 | |
---|
20 | // module: |
---|
21 | // dijit/Calendar |
---|
22 | |
---|
23 | // _Widget for deprecated methods like setAttribute() |
---|
24 | var Calendar = declare("dijit.Calendar", [CalendarLite, _Widget, _CssStateMixin], { |
---|
25 | // summary: |
---|
26 | // A simple GUI for choosing a date in the context of a monthly calendar. |
---|
27 | // |
---|
28 | // description: |
---|
29 | // See CalendarLite for general description. Calendar extends CalendarLite, adding: |
---|
30 | // |
---|
31 | // - month drop down list |
---|
32 | // - keyboard navigation |
---|
33 | // - CSS classes for hover/mousepress on date, month, and year nodes |
---|
34 | // - support of deprecated methods (will be removed in 2.0) |
---|
35 | |
---|
36 | // Set node classes for various mouse events, see dijit._CssStateMixin for more details |
---|
37 | cssStateNodes: { |
---|
38 | "decrementMonth": "dijitCalendarArrow", |
---|
39 | "incrementMonth": "dijitCalendarArrow", |
---|
40 | "previousYearLabelNode": "dijitCalendarPreviousYear", |
---|
41 | "nextYearLabelNode": "dijitCalendarNextYear" |
---|
42 | }, |
---|
43 | |
---|
44 | setValue: function(/*Date*/ value){ |
---|
45 | // summary: |
---|
46 | // Deprecated. Use set('value', ...) instead. |
---|
47 | // tags: |
---|
48 | // deprecated |
---|
49 | kernel.deprecated("dijit.Calendar:setValue() is deprecated. Use set('value', ...) instead.", "", "2.0"); |
---|
50 | this.set('value', value); |
---|
51 | }, |
---|
52 | |
---|
53 | _createMonthWidget: function(){ |
---|
54 | // summary: |
---|
55 | // Creates the drop down button that displays the current month and lets user pick a new one |
---|
56 | |
---|
57 | return new Calendar._MonthDropDownButton({ |
---|
58 | id: this.id + "_mddb", |
---|
59 | tabIndex: -1, |
---|
60 | onMonthSelect: lang.hitch(this, "_onMonthSelect"), |
---|
61 | lang: this.lang, |
---|
62 | dateLocaleModule: this.dateLocaleModule |
---|
63 | }, this.monthNode); |
---|
64 | }, |
---|
65 | |
---|
66 | postCreate: function(){ |
---|
67 | this.inherited(arguments); |
---|
68 | |
---|
69 | // Events specific to Calendar, not used in CalendarLite |
---|
70 | this.own( |
---|
71 | on(this.domNode, "keydown", lang.hitch(this, "_onKeyDown")), |
---|
72 | on(this.dateRowsNode, "mouseover", lang.hitch(this, "_onDayMouseOver")), |
---|
73 | on(this.dateRowsNode, "mouseout", lang.hitch(this, "_onDayMouseOut")), |
---|
74 | on(this.dateRowsNode, "mousedown", lang.hitch(this, "_onDayMouseDown")), |
---|
75 | on(this.dateRowsNode, "mouseup", lang.hitch(this, "_onDayMouseUp")) |
---|
76 | ); |
---|
77 | }, |
---|
78 | |
---|
79 | _onMonthSelect: function(/*Number*/ newMonth){ |
---|
80 | // summary: |
---|
81 | // Handler for when user selects a month from the drop down list |
---|
82 | // tags: |
---|
83 | // protected |
---|
84 | |
---|
85 | // move to selected month, bounding by the number of days in the month |
---|
86 | // (ex: jan 31 --> feb 28, not feb 31) |
---|
87 | var date = new this.dateClassObj(this.currentFocus); |
---|
88 | date.setDate(1); |
---|
89 | date.setMonth(newMonth); |
---|
90 | var daysInMonth = this.dateModule.getDaysInMonth(date); |
---|
91 | var currentDate = this.currentFocus.getDate(); |
---|
92 | date.setDate(Math.min(currentDate, daysInMonth)); |
---|
93 | this._setCurrentFocusAttr(date); |
---|
94 | }, |
---|
95 | |
---|
96 | _onDayMouseOver: function(/*Event*/ evt){ |
---|
97 | // summary: |
---|
98 | // Handler for mouse over events on days, sets hovered style |
---|
99 | // tags: |
---|
100 | // protected |
---|
101 | |
---|
102 | // event can occur on <td> or the <span> inside the td, |
---|
103 | // set node to the <td>. |
---|
104 | var node = |
---|
105 | domClass.contains(evt.target, "dijitCalendarDateLabel") ? |
---|
106 | evt.target.parentNode : |
---|
107 | evt.target; |
---|
108 | |
---|
109 | if(node && ( |
---|
110 | (node.dijitDateValue && !domClass.contains(node, "dijitCalendarDisabledDate")) |
---|
111 | || node == this.previousYearLabelNode || node == this.nextYearLabelNode |
---|
112 | )){ |
---|
113 | domClass.add(node, "dijitCalendarHoveredDate"); |
---|
114 | this._currentNode = node; |
---|
115 | } |
---|
116 | }, |
---|
117 | |
---|
118 | _onDayMouseOut: function(/*Event*/ evt){ |
---|
119 | // summary: |
---|
120 | // Handler for mouse out events on days, clears hovered style |
---|
121 | // tags: |
---|
122 | // protected |
---|
123 | |
---|
124 | if(!this._currentNode){ |
---|
125 | return; |
---|
126 | } |
---|
127 | |
---|
128 | // if mouse out occurs moving from <td> to <span> inside <td>, ignore it |
---|
129 | if(evt.relatedTarget && evt.relatedTarget.parentNode == this._currentNode){ |
---|
130 | return; |
---|
131 | } |
---|
132 | var cls = "dijitCalendarHoveredDate"; |
---|
133 | if(domClass.contains(this._currentNode, "dijitCalendarActiveDate")){ |
---|
134 | cls += " dijitCalendarActiveDate"; |
---|
135 | } |
---|
136 | domClass.remove(this._currentNode, cls); |
---|
137 | this._currentNode = null; |
---|
138 | }, |
---|
139 | |
---|
140 | _onDayMouseDown: function(/*Event*/ evt){ |
---|
141 | var node = evt.target.parentNode; |
---|
142 | if(node && node.dijitDateValue && !domClass.contains(node, "dijitCalendarDisabledDate")){ |
---|
143 | domClass.add(node, "dijitCalendarActiveDate"); |
---|
144 | this._currentNode = node; |
---|
145 | } |
---|
146 | }, |
---|
147 | |
---|
148 | _onDayMouseUp: function(/*Event*/ evt){ |
---|
149 | var node = evt.target.parentNode; |
---|
150 | if(node && node.dijitDateValue){ |
---|
151 | domClass.remove(node, "dijitCalendarActiveDate"); |
---|
152 | } |
---|
153 | }, |
---|
154 | |
---|
155 | handleKey: function(/*Event*/ evt){ |
---|
156 | // summary: |
---|
157 | // Provides keyboard navigation of calendar. |
---|
158 | // description: |
---|
159 | // Called from _onKeyDown() to handle keydown on a stand alone Calendar, |
---|
160 | // and also from `dijit/form/_DateTimeTextBox` to pass a keydown event |
---|
161 | // from the `dijit/form/DateTextBox` to be handled in this widget |
---|
162 | // returns: |
---|
163 | // False if the key was recognized as a navigation key, |
---|
164 | // to indicate that the event was handled by Calendar and shouldn't be propagated |
---|
165 | // tags: |
---|
166 | // protected |
---|
167 | var increment = -1, |
---|
168 | interval, |
---|
169 | newValue = this.currentFocus; |
---|
170 | switch(evt.keyCode){ |
---|
171 | case keys.RIGHT_ARROW: |
---|
172 | increment = 1; |
---|
173 | //fallthrough... |
---|
174 | case keys.LEFT_ARROW: |
---|
175 | interval = "day"; |
---|
176 | if(!this.isLeftToRight()){ |
---|
177 | increment *= -1; |
---|
178 | } |
---|
179 | break; |
---|
180 | case keys.DOWN_ARROW: |
---|
181 | increment = 1; |
---|
182 | //fallthrough... |
---|
183 | case keys.UP_ARROW: |
---|
184 | interval = "week"; |
---|
185 | break; |
---|
186 | case keys.PAGE_DOWN: |
---|
187 | increment = 1; |
---|
188 | //fallthrough... |
---|
189 | case keys.PAGE_UP: |
---|
190 | interval = evt.ctrlKey || evt.altKey ? "year" : "month"; |
---|
191 | break; |
---|
192 | case keys.END: |
---|
193 | // go to the next month |
---|
194 | newValue = this.dateModule.add(newValue, "month", 1); |
---|
195 | // subtract a day from the result when we're done |
---|
196 | interval = "day"; |
---|
197 | //fallthrough... |
---|
198 | case keys.HOME: |
---|
199 | newValue = new this.dateClassObj(newValue); |
---|
200 | newValue.setDate(1); |
---|
201 | break; |
---|
202 | default: |
---|
203 | return true; |
---|
204 | } |
---|
205 | |
---|
206 | if(interval){ |
---|
207 | newValue = this.dateModule.add(newValue, interval, increment); |
---|
208 | } |
---|
209 | |
---|
210 | this._setCurrentFocusAttr(newValue); |
---|
211 | |
---|
212 | return false; |
---|
213 | }, |
---|
214 | |
---|
215 | _onKeyDown: function(/*Event*/ evt){ |
---|
216 | // summary: |
---|
217 | // For handling keydown events on a stand alone calendar |
---|
218 | if(!this.handleKey(evt)){ |
---|
219 | evt.stopPropagation(); |
---|
220 | evt.preventDefault(); |
---|
221 | } |
---|
222 | }, |
---|
223 | |
---|
224 | onValueSelected: function(/*Date*/ /*===== date =====*/){ |
---|
225 | // summary: |
---|
226 | // Deprecated. Notification that a date cell was selected. It may be the same as the previous value. |
---|
227 | // description: |
---|
228 | // Formerly used by `dijit/form/_DateTimeTextBox` (and thus `dijit/form/DateTextBox`) |
---|
229 | // to get notification when the user has clicked a date. Now onExecute() (above) is used. |
---|
230 | // tags: |
---|
231 | // protected |
---|
232 | }, |
---|
233 | |
---|
234 | onChange: function(value){ |
---|
235 | this.onValueSelected(value); // remove in 2.0 |
---|
236 | }, |
---|
237 | |
---|
238 | getClassForDate: function(/*===== dateObject, locale =====*/){ |
---|
239 | // summary: |
---|
240 | // May be overridden to return CSS classes to associate with the date entry for the given dateObject, |
---|
241 | // for example to indicate a holiday in specified locale. |
---|
242 | // dateObject: Date |
---|
243 | // locale: String? |
---|
244 | // tags: |
---|
245 | // extension |
---|
246 | |
---|
247 | /*===== |
---|
248 | return ""; // String |
---|
249 | =====*/ |
---|
250 | } |
---|
251 | }); |
---|
252 | |
---|
253 | Calendar._MonthDropDownButton = declare("dijit.Calendar._MonthDropDownButton", DropDownButton, { |
---|
254 | // summary: |
---|
255 | // DropDownButton for the current month. Displays name of current month |
---|
256 | // and a list of month names in the drop down |
---|
257 | |
---|
258 | onMonthSelect: function(){ |
---|
259 | }, |
---|
260 | |
---|
261 | postCreate: function(){ |
---|
262 | this.inherited(arguments); |
---|
263 | this.dropDown = new Calendar._MonthDropDown({ |
---|
264 | id: this.id + "_mdd", //do not change this id because it is referenced in the template |
---|
265 | onChange: this.onMonthSelect |
---|
266 | }); |
---|
267 | }, |
---|
268 | _setMonthAttr: function(month){ |
---|
269 | // summary: |
---|
270 | // Set the current month to display as a label |
---|
271 | var monthNames = this.dateLocaleModule.getNames('months', 'wide', 'standAlone', this.lang, month); |
---|
272 | this.dropDown.set("months", monthNames); |
---|
273 | |
---|
274 | // Set name of current month and also fill in spacer element with all the month names |
---|
275 | // (invisible) so that the maximum width will affect layout. But not on IE6 because then |
---|
276 | // the center <TH> overlaps the right <TH> (due to a browser bug). |
---|
277 | this.containerNode.innerHTML = |
---|
278 | (has("ie") == 6 ? "" : "<div class='dijitSpacer'>" + this.dropDown.domNode.innerHTML + "</div>") + |
---|
279 | "<div class='dijitCalendarMonthLabel dijitCalendarCurrentMonthLabel'>" + monthNames[month.getMonth()] + "</div>"; |
---|
280 | } |
---|
281 | }); |
---|
282 | |
---|
283 | Calendar._MonthDropDown = declare("dijit.Calendar._MonthDropDown", [_Widget, _TemplatedMixin], { |
---|
284 | // summary: |
---|
285 | // The list-of-months drop down from the MonthDropDownButton |
---|
286 | |
---|
287 | // months: String[] |
---|
288 | // List of names of months, possibly w/some undefined entries for Hebrew leap months |
---|
289 | // (ex: ["January", "February", undefined, "April", ...]) |
---|
290 | months: [], |
---|
291 | |
---|
292 | templateString: "<div class='dijitCalendarMonthMenu dijitMenu' " + |
---|
293 | "data-dojo-attach-event='onclick:_onClick,onmouseover:_onMenuHover,onmouseout:_onMenuHover'></div>", |
---|
294 | |
---|
295 | _setMonthsAttr: function(/*String[]*/ months){ |
---|
296 | this.domNode.innerHTML = array.map(months,function(month, idx){ |
---|
297 | return month ? "<div class='dijitCalendarMonthLabel' month='" + idx + "'>" + month + "</div>" : ""; |
---|
298 | }).join(""); |
---|
299 | }, |
---|
300 | |
---|
301 | _onClick: function(/*Event*/ evt){ |
---|
302 | this.onChange(domAttr.get(evt.target, "month")); |
---|
303 | }, |
---|
304 | |
---|
305 | onChange: function(/*Number*/ /*===== month =====*/){ |
---|
306 | // summary: |
---|
307 | // Callback when month is selected from drop down |
---|
308 | }, |
---|
309 | |
---|
310 | _onMenuHover: function(evt){ |
---|
311 | domClass.toggle(evt.target, "dijitCalendarMonthLabelHover", evt.type == "mouseover"); |
---|
312 | } |
---|
313 | }); |
---|
314 | |
---|
315 | return Calendar; |
---|
316 | }); |
---|