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