[483] | 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 | }); |
---|