source: Dev/branches/rest-dojo-ui/client/dojox/widget/Calendar.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 26.6 KB
Line 
1dojo.provide("dojox.widget.Calendar");
2dojo.experimental("dojox.widget.Calendar");
3
4dojo.require("dijit._Widget");
5dojo.require("dijit._Templated");
6dojo.require("dijit._Container");
7dojo.require("dijit.typematic");
8
9dojo.require("dojo.date");
10dojo.require("dojo.date.locale");
11
12dojo.declare("dojox.widget._CalendarBase", [dijit._Widget, dijit._Templated, dijit._Container], {
13        // summary:
14        //              The Root class for all _Calendar extensions
15
16        // templateString: String
17        //              The template to be used to construct the widget.
18        templateString: dojo.cache("dojox.widget","Calendar/Calendar.html"),
19
20        // _views: Array
21        //              The list of mixin views available on this calendar.
22        _views: null,
23
24        // useFx: Boolean
25        //              Specifies if visual effects should be applied to the widget.
26        //              The default behavior of the widget does not contain any effects.
27        //              The dojox.widget.CalendarFx package is needed for these.
28        useFx: true,
29
30        // widgetsInTemplate: Boolean
31        //              This widget is a container of other widgets, so this is true.
32        widgetsInTemplate: true,
33
34        // value: Date
35        //              The currently selected Date
36        value: new Date(),
37
38        constraints: null,
39
40        // footerFormat: String
41        //              The date format of the date displayed in the footer.    Can be
42        //              'short', 'medium', and 'long'
43        footerFormat: "medium",
44
45        constructor: function(){
46                this._views = [];
47                this.value = new Date();
48        },
49
50        postMixInProperties: function(){
51                var c = this.constraints;
52                if(c){
53                        var fromISO = dojo.date.stamp.fromISOString;
54                        if(typeof c.min == "string"){
55                                c.min = fromISO(c.min);
56                        }
57                        if(typeof c.max == "string"){
58                                c.max = fromISO(c.max);
59                        }
60                }
61                this.value = this.parseInitialValue(this.value);
62        },
63
64        parseInitialValue: function(value){
65                if (!value || value === -1){
66                        return new Date();
67                }else if(value.getFullYear){
68                        return value;
69                }else if (!isNaN(value)) {
70                        if (typeof this.value == "string") {
71                                value = parseInt(value);
72                        }
73                        value = this._makeDate(value);
74                }
75                return value;
76        },
77
78        _makeDate: function(value){
79                return value;//new Date(value);
80        },
81
82        postCreate: function(){
83                // summary:
84                //              Instantiates the mixin views
85
86                this.displayMonth = new Date(this.get('value'));
87
88                if(this._isInvalidDate(this.displayMonth)){
89                        this.displayMonth = new Date();
90                }
91
92                var mixin = {
93                        parent: this,
94                        _getValueAttr: dojo.hitch(this, function(){return new Date(this._internalValue || this.value);}),
95                        _getDisplayMonthAttr: dojo.hitch(this, function(){return new Date(this.displayMonth);}),
96                        _getConstraintsAttr: dojo.hitch(this, function(){return this.constraints;}),
97                        getLang: dojo.hitch(this, function(){return this.lang;}),
98                        isDisabledDate: dojo.hitch(this, this.isDisabledDate),
99                        getClassForDate: dojo.hitch(this, this.getClassForDate),
100                        addFx: this.useFx ? dojo.hitch(this, this.addFx) : function(){}
101                };
102
103                //Add the mixed in views.
104                dojo.forEach(this._views, function(widgetType){
105                        var widget = new widgetType(mixin, dojo.create('div'));
106                        this.addChild(widget);
107
108                        var header = widget.getHeader();
109                        if(header){
110                        //place the views's header node in the header of the main widget
111                                this.header.appendChild(header);
112
113                                //hide the header node of the widget
114                                dojo.style(header, "display", "none");
115                        }
116                        //Hide all views
117                        dojo.style(widget.domNode, "visibility", "hidden");
118
119                        //Listen for the values in a view to be selected
120                        dojo.connect(widget, "onValueSelected", this, "_onDateSelected");
121                        widget.set("value", this.get('value'));
122                }, this);
123
124                if(this._views.length < 2){
125                        dojo.style(this.header, "cursor", "auto");
126                }
127
128                this.inherited(arguments);
129
130                // Cache the list of children widgets.
131                this._children = this.getChildren();
132
133                this._currentChild = 0;
134
135                //Populate the footer with today's date.
136                var today = new Date();
137
138                this.footer.innerHTML = "Today: "
139                        + dojo.date.locale.format(today, {
140                                formatLength:this.footerFormat,
141                                selector:'date',
142                                locale:this.lang});
143
144                dojo.connect(this.footer, "onclick", this, "goToToday");
145
146                var first = this._children[0];
147
148                dojo.style(first.domNode, "top", "0px");
149                dojo.style(first.domNode, "visibility", "visible");
150
151                var header = first.getHeader();
152                if(header){
153                        dojo.style(first.getHeader(), "display", "");
154                }
155
156                dojo[first.useHeader ? "removeClass" : "addClass"](this.container, "no-header");
157
158                first.onDisplay();
159
160                var _this = this;
161
162                var typematic = function(nodeProp, dateProp, adj){
163                        dijit.typematic.addMouseListener(_this[nodeProp], _this, function(count){
164                                if(count >= 0){ _this._adjustDisplay(dateProp, adj);}
165                        }, 0.8, 500);
166                };
167                typematic("incrementMonth", "month", 1);
168                typematic("decrementMonth", "month", -1);
169                this._updateTitleStyle();
170        },
171
172        addFx: function(query, fromNode){
173                // Stub function than can be overridden to add effects.
174        },
175
176        _isInvalidDate: function(/*Date*/ value){
177                // summary:
178                //              Runs various tests on the value, checking for invalid conditions
179                // tags:
180                //              private
181                return !value || isNaN(value) || typeof value != "object" || value.toString() == this._invalidDate;
182        },
183
184        _setValueAttr: function(/*Date*/ value){
185                // summary:
186                //              Set the current date and update the UI. If the date is disabled, the selection will
187                //              not change, but the display will change to the corresponding month.
188                if(!value){
189                        value = new Date();
190                }
191                if(!value["getFullYear"]){
192                        value = dojo.date.stamp.fromISOString(value + "");
193                }
194                if(this._isInvalidDate(value)){
195                        return false;
196                }
197                if(!this.value || dojo.date.compare(value, this.value)){
198                        value = new Date(value);
199                        this.displayMonth = new Date(value);
200                        this._internalValue = value;
201                        if(!this.isDisabledDate(value, this.lang) && this._currentChild == 0){
202                                this.value = value;
203                                this.onChange(value);
204                        }
205                        if (this._children && this._children.length > 0) {
206                                this._children[this._currentChild].set("value", this.value);
207                        }
208                        return true;
209                }
210                return false;
211        },
212
213        isDisabledDate: function(/*Date*/date, /*String?*/locale){
214                // summary:
215                //              May be overridden to disable certain dates in the calendar e.g. `isDisabledDate=dojo.date.locale.isWeekend`
216                var c = this.constraints;
217                var compare = dojo.date.compare;
218                return c && (c.min && (compare(c.min, date, "date") > 0) ||
219                                                        (c.max && compare(c.max, date, "date") < 0));
220        },
221
222        onValueSelected: function(/*Date*/date){
223                // summary:
224                //              A date cell was selected. It may be the same as the previous value.
225        },
226
227        _onDateSelected: function(date, formattedValue, force){
228                this.displayMonth = date;
229
230                this.set("value", date)
231                //Only change the selected value if it was chosen from the
232                //first child.
233                if(!this._transitionVert(-1)){
234                        if(!formattedValue && formattedValue !== 0){
235                                formattedValue = this.get('value');
236                        }
237                        this.onValueSelected(formattedValue);
238                }
239
240        },
241
242        onChange: function(/*Date*/date){
243                // summary:
244                //              Called only when the selected date has changed
245        },
246
247        onHeaderClick: function(e){
248                // summary:
249                //      Transitions to the next view.
250                this._transitionVert(1);
251        },
252
253        goToToday: function(){
254                this.set("value", new Date());
255                this.onValueSelected(this.get('value'));
256        },
257
258        _transitionVert: function(/*Number*/direction){
259                // summary:
260                //              Animates the views to show one and hide another, in a
261                //              vertical direction.
262                //              If 'direction' is 1, then the views slide upwards.
263                //              If 'direction' is -1, the views slide downwards.
264                var curWidget = this._children[this._currentChild];
265                var nextWidget = this._children[this._currentChild + direction];
266                if(!nextWidget){return false;}
267
268                dojo.style(nextWidget.domNode, "visibility", "visible");
269
270                var height = dojo.style(this.containerNode, "height");
271                nextWidget.set("value", this.displayMonth);
272
273                if(curWidget.header){
274                        dojo.style(curWidget.header, "display", "none");
275                }
276                if(nextWidget.header){
277                        dojo.style(nextWidget.header, "display", "");
278                }
279                dojo.style(nextWidget.domNode, "top", (height * -1) + "px");
280                dojo.style(nextWidget.domNode, "visibility", "visible");
281
282                this._currentChild += direction;
283
284                var height1 = height * direction;
285                var height2 = 0;
286                dojo.style(nextWidget.domNode, "top", (height1 * -1) + "px");
287
288                // summary: Slides two nodes vertically.
289                var anim1 = dojo.animateProperty({
290                        node: curWidget.domNode,
291                        properties: {top: height1},
292                        onEnd: function(){
293                                dojo.style(curWidget.domNode, "visibility", "hidden");
294                        }
295                });
296                var anim2 = dojo.animateProperty({
297                        node: nextWidget.domNode,
298                        properties: {top: height2},
299                        onEnd: function(){
300                                nextWidget.onDisplay();
301                        }
302                });
303
304                dojo[nextWidget.useHeader ? "removeClass" : "addClass"](this.container, "no-header");
305
306                anim1.play();
307                anim2.play();
308                curWidget.onBeforeUnDisplay()
309                nextWidget.onBeforeDisplay();
310
311                this._updateTitleStyle();
312                return true;
313        },
314
315        _updateTitleStyle: function(){
316                dojo[this._currentChild < this._children.length -1 ? "addClass" : "removeClass"](this.header, "navToPanel");
317        },
318
319        _slideTable: function(/*String*/widget, /*Number*/direction, /*Function*/callback){
320                // summary:
321                //              Animates the horizontal sliding of a table.
322                var table = widget.domNode;
323
324                //Clone the existing table
325                var newTable = table.cloneNode(true);
326                var left = dojo.style(table, "width");
327
328                table.parentNode.appendChild(newTable);
329
330                //Place the existing node either to the left or the right of the new node,
331                //depending on which direction it is to slide.
332                dojo.style(table, "left", (left * direction) + "px");
333
334                //Call the function that generally populates the new cloned node with new data.
335                //It may also attach event listeners.
336                callback();
337
338                //Animate the two nodes.
339                var anim1 = dojo.animateProperty({node: newTable, properties:{left: left * direction * -1}, duration: 500, onEnd: function(){
340                        newTable.parentNode.removeChild(newTable);
341                }});
342                var anim2 = dojo.animateProperty({node: table, properties:{left: 0}, duration: 500});
343
344                anim1.play();
345                anim2.play();
346        },
347
348        _addView: function(view){
349                //Insert the view at the start of the array.
350                this._views.push(view);
351        },
352
353        getClassForDate: function(/*Date*/dateObject, /*String?*/locale){
354                // summary:
355                //              May be overridden to return CSS classes to associate with the date entry for the given dateObject,
356                //              for example to indicate a holiday in specified locale.
357
358/*=====
359                return ""; // String
360=====*/
361        },
362
363        _adjustDisplay: function(/*String*/part, /*int*/amount, noSlide){
364                // summary:
365                //              This function overrides the base function defined in dijit.Calendar.
366                //              It changes the displayed years, months and days depending on the inputs.
367                var child = this._children[this._currentChild];
368
369                var month = this.displayMonth = child.adjustDate(this.displayMonth, amount);
370
371                this._slideTable(child, amount, function(){
372                        child.set("value", month);
373                });
374        }
375});
376
377dojo.declare("dojox.widget._CalendarView", dijit._Widget, {
378        // summary:
379        //              Base implementation for all view mixins.
380        //              All calendar views should extend this widget.
381        headerClass: "",
382
383        useHeader: true,
384
385        cloneClass: function(clazz, n, before){
386                // summary:
387                //              Clones all nodes with the class 'clazz' in a widget
388                var template = dojo.query(clazz, this.domNode)[0];
389                var i;
390                if(!before){
391                        for(i = 0; i < n; i++){
392                                template.parentNode.appendChild(template.cloneNode(true));
393                        }
394                }else{
395                        var bNode = dojo.query(clazz, this.domNode)[0];
396                        for(i = 0; i < n; i++){
397                                template.parentNode.insertBefore(template.cloneNode(true), bNode);
398                        }
399                }
400        },
401
402        _setText: function(node, text){
403                // summary:
404                //              Sets the text inside a node
405                if(node.innerHTML != text){
406                        dojo.empty(node);
407                        node.appendChild(dojo.doc.createTextNode(text));
408                }
409        },
410
411        getHeader: function(){
412                // summary:
413                //              Returns the header node of a view. If none exists,
414                //              an empty DIV is created and returned.
415                return this.header || (this.header = this.header = dojo.create("span", { "class":this.headerClass }));
416        },
417
418        onValueSelected: function(date){
419                //Stub function called when a date is selected
420        },
421
422        adjustDate: function(date, amount){
423                // summary:
424                //              Adds or subtracts values from a date.
425                //              The unit, e.g. "day", "month" or "year", is
426                //              specified in the "datePart" property of the
427                //              calendar view mixin.
428                return dojo.date.add(date, this.datePart, amount);
429        },
430
431        onDisplay: function(){
432                // summary:
433                //              Stub function that can be used to tell a view when it is shown.
434        },
435
436        onBeforeDisplay: function(){
437                // summary:
438                //              Stub function that can be used to tell a view it is about to be shown.
439        },
440
441        onBeforeUnDisplay: function(){
442                // summary:
443                //              Stub function that can be used to tell
444                //              a view when it is no longer shown.
445        }
446});
447
448dojo.declare("dojox.widget._CalendarDay", null, {
449        // summary:
450        //              Mixin for the dojox.widget.Calendar which provides
451        //              the standard day-view. A single month is shown at a time.
452        parent: null,
453
454        constructor: function(){
455                this._addView(dojox.widget._CalendarDayView);
456        }
457});
458
459dojo.declare("dojox.widget._CalendarDayView", [dojox.widget._CalendarView, dijit._Templated], {
460        // summary: View class for the dojox.widget.Calendar.
461        //              Adds a view showing every day of a single month to the calendar.
462        //              This should not be mixed in directly with dojox.widget._CalendarBase.
463        //              Instead, use dojox.widget._CalendarDay
464
465        // templateString: String
466        //              The template to be used to construct the widget.
467        templateString: dojo.cache("dojox.widget","Calendar/CalendarDay.html"),
468
469        // datePart: String
470        //              Specifies how much to increment the displayed date when the user
471        //              clicks the array button to increment of decrement the view.
472        datePart: "month",
473
474        // dayWidth: String
475        //              Specifies the type of day name to display.      "narrow" causes just one letter to be shown.
476        dayWidth: "narrow",
477
478        postCreate: function(){
479                // summary:
480                //              Constructs the calendar view.
481                this.cloneClass(".dijitCalendarDayLabelTemplate", 6);
482                this.cloneClass(".dijitCalendarDateTemplate", 6);
483
484                // now make 6 week rows
485                this.cloneClass(".dijitCalendarWeekTemplate", 5);
486
487                // insert localized day names in the header
488                var dayNames = dojo.date.locale.getNames('days', this.dayWidth, 'standAlone', this.getLang());
489                var dayOffset = dojo.cldr.supplemental.getFirstDayOfWeek(this.getLang());
490
491                // Set the text of the day labels.
492                dojo.query(".dijitCalendarDayLabel", this.domNode).forEach(function(label, i){
493                        this._setText(label, dayNames[(i + dayOffset) % 7]);
494                }, this);
495        },
496
497        onDisplay: function(){
498                if(!this._addedFx){
499                // Add visual effects to the view, if any has been specified.
500                        this._addedFx = true;
501                        this.addFx(".dijitCalendarDateTemplate div", this.domNode);
502                }
503        },
504
505        _onDayClick: function(e){
506                // summary:
507                //              Executed when a day value is clicked.
508
509                // If the user somehow clicked the TR, rather than a
510                // cell, ignore it.
511                if(typeof(e.target._date) == "undefined"){return;}
512
513                var date = new Date(this.get("displayMonth"));
514
515                var p = e.target.parentNode;
516                var c = "dijitCalendar";
517                var d = dojo.hasClass(p, c + "PreviousMonth") ? -1 :
518                                                        (dojo.hasClass(p, c + "NextMonth") ? 1 : 0);
519                if(d){date = dojo.date.add(date, "month", d)}
520                date.setDate(e.target._date);
521
522                // If the day is disabled, ignore it
523                if(this.isDisabledDate(date)){
524                        dojo.stopEvent(e);
525                        return;
526                }
527                this.parent._onDateSelected(date);
528        },
529
530        _setValueAttr: function(value){
531                //Change the day values
532                this._populateDays();
533        },
534
535        _populateDays: function(){
536                // summary:
537                //              Fills the days of the current month.
538
539                var currentDate = new Date(this.get("displayMonth"));
540                currentDate.setDate(1);
541                var firstDay = currentDate.getDay();
542                var daysInMonth = dojo.date.getDaysInMonth(currentDate);
543                var daysInPreviousMonth = dojo.date.getDaysInMonth(dojo.date.add(currentDate, "month", -1));
544                var today = new Date();
545                var selected = this.get('value');
546
547                var dayOffset = dojo.cldr.supplemental.getFirstDayOfWeek(this.getLang());
548                if(dayOffset > firstDay){ dayOffset -= 7; }
549
550                var compareDate = dojo.date.compare;
551                var templateCls = ".dijitCalendarDateTemplate";
552                var selectedCls = "dijitCalendarSelectedDate";
553
554                var oldDate = this._lastDate;
555                var redrawRequired = oldDate == null
556                                || oldDate.getMonth() != currentDate.getMonth()
557                                || oldDate.getFullYear() != currentDate.getFullYear();
558                this._lastDate = currentDate;
559
560                // If still showing the same month, it's much faster to not redraw,
561                // and just change the selected date.
562                if(!redrawRequired){
563                        dojo.query(templateCls, this.domNode)
564                                        .removeClass(selectedCls)
565                                        .filter(function(node){
566                                                return node.className.indexOf("dijitCalendarCurrent") > -1
567                                                                        && node._date == selected.getDate();
568                                        })
569                                        .addClass(selectedCls);
570                        return;
571                }
572
573                // Iterate through dates in the calendar and fill in date numbers and style info
574                dojo.query(templateCls, this.domNode).forEach(function(template, i){
575                        i += dayOffset;
576                        var date = new Date(currentDate);
577                        var number, clazz = "dijitCalendar", adj = 0;
578
579                        if(i < firstDay){
580                                number = daysInPreviousMonth - firstDay + i + 1;
581                                adj = -1;
582                                clazz += "Previous";
583                        }else if(i >= (firstDay + daysInMonth)){
584                                number = i - firstDay - daysInMonth + 1;
585                                adj = 1;
586                                clazz += "Next";
587                        }else{
588                                number = i - firstDay + 1;
589                                clazz += "Current";
590                        }
591
592                        if(adj){
593                                date = dojo.date.add(date, "month", adj);
594                        }
595                        date.setDate(number);
596
597                        if(!compareDate(date, today, "date")){
598                                clazz = "dijitCalendarCurrentDate " + clazz;
599                        }
600
601                        if(!compareDate(date, selected, "date")
602                                        && !compareDate(date, selected, "month")
603                                        && !compareDate(date, selected, "year") ){
604                                clazz = selectedCls + " " + clazz;
605                        }
606
607                        if(this.isDisabledDate(date, this.getLang())){
608                                clazz = " dijitCalendarDisabledDate " + clazz;
609                        }
610
611                        var clazz2 = this.getClassForDate(date, this.getLang());
612                        if(clazz2){
613                                clazz = clazz2 + " " + clazz;
614                        }
615
616                        template.className = clazz + "Month dijitCalendarDateTemplate";
617                        template.dijitDateValue = date.valueOf();
618                        var label = dojo.query(".dijitCalendarDateLabel", template)[0];
619
620                        this._setText(label, date.getDate());
621
622                        label._date = label.parentNode._date = date.getDate();
623                }, this);
624
625                // Fill in localized month name
626                var monthNames = dojo.date.locale.getNames('months', 'wide', 'standAlone', this.getLang());
627                this._setText(this.monthLabelNode, monthNames[currentDate.getMonth()]);
628                this._setText(this.yearLabelNode, currentDate.getFullYear());
629        }
630});
631
632
633dojo.declare("dojox.widget._CalendarMonthYear", null, {
634        // summary:
635        //              Mixin class for adding a view listing all 12
636        //              months of the year to the dojox.widget._CalendarBase
637
638        constructor: function(){
639                // summary:
640                //              Adds a dojox.widget._CalendarMonthView view to the calendar widget.
641                this._addView(dojox.widget._CalendarMonthYearView);
642        }
643});
644
645dojo.declare("dojox.widget._CalendarMonthYearView", [dojox.widget._CalendarView, dijit._Templated], {
646        // summary:
647        //              A Calendar view listing the 12 months of the year
648
649        // templateString: String
650        //              The template to be used to construct the widget.
651        templateString: dojo.cache("dojox.widget","Calendar/CalendarMonthYear.html"),
652
653        // datePart: String
654        //              Specifies how much to increment the displayed date when the user
655        //              clicks the array button to increment of decrement the view.
656        datePart: "year",
657
658        // displayedYears: Number
659        //              The number of years to display at once.
660        displayedYears: 10,
661
662        useHeader: false,
663
664        postCreate: function(){
665                this.cloneClass(".dojoxCal-MY-G-Template", 5, ".dojoxCal-MY-btns");
666                this.monthContainer = this.yearContainer = this.myContainer;
667
668                var yClass = "dojoxCalendarYearLabel";
669                var dClass = "dojoxCalendarDecrease";
670                var iClass = "dojoxCalendarIncrease";
671
672                dojo.query("." + yClass, this.myContainer).forEach(function(node, idx){
673                        var clazz = iClass;
674                        switch(idx){
675                                case 0:
676                                        clazz = dClass;
677                                case 1:
678                                        dojo.removeClass(node, yClass);
679                                        dojo.addClass(node, clazz);
680                                        break;
681                        }
682                });
683                // Get the year increment and decrement buttons.
684                this._decBtn = dojo.query('.' + dClass, this.myContainer)[0];
685                this._incBtn = dojo.query('.' + iClass, this.myContainer)[0];
686
687                dojo.query(".dojoxCal-MY-M-Template", this.domNode)
688                        .filter(function(item){
689                                return item.cellIndex == 1;
690                        })
691                        .addClass("dojoxCal-MY-M-last");
692
693                dojo.connect(this, "onBeforeDisplay", dojo.hitch(this, function(){
694                        this._cachedDate = new Date(this.get("value").getTime());
695                        this._populateYears(this._cachedDate.getFullYear());
696                        this._populateMonths();
697                        this._updateSelectedMonth();
698                        this._updateSelectedYear();
699                }));
700
701                dojo.connect(this, "_populateYears", dojo.hitch(this, function(){
702                        this._updateSelectedYear();
703                }));
704                dojo.connect(this, "_populateMonths", dojo.hitch(this, function(){
705                        this._updateSelectedMonth();
706                }));
707
708                this._cachedDate = this.get("value");
709
710                this._populateYears();
711                this._populateMonths();
712
713                // Add visual effects to the view, if any have been mixed in
714                this.addFx(".dojoxCalendarMonthLabel,.dojoxCalendarYearLabel ", this.myContainer);
715        },
716
717        _setValueAttr: function(value){
718                if (value && value.getFullYear()) {
719                        this._populateYears(value.getFullYear());
720                }
721        },
722
723        getHeader: function(){
724                return null;
725        },
726
727        _getMonthNames: function(format){
728                // summary:
729                //              Returns localized month names
730                this._monthNames        = this._monthNames || dojo.date.locale.getNames('months', format, 'standAlone', this.getLang());
731                return this._monthNames;
732        },
733
734        _populateMonths: function(){
735                // summary:
736                //              Populate the month names using the localized values.
737                var monthNames = this._getMonthNames('abbr');
738                dojo.query(".dojoxCalendarMonthLabel", this.monthContainer).forEach(dojo.hitch(this, function(node, cnt){
739                        this._setText(node, monthNames[cnt]);
740                }));
741                var constraints = this.get('constraints');
742
743                if(constraints){
744                        var date = new Date();
745                        date.setFullYear(this._year);
746                        var min = -1, max = 12;
747                        if(constraints.min){
748                                var minY = constraints.min.getFullYear();
749                                if(minY > this._year){
750                                        min = 12;
751                                }else if(minY == this._year){
752                                        min = constraints.min.getMonth();
753                                }
754                        }
755                        if(constraints.max){
756                                var maxY = constraints.max.getFullYear();
757                                if(maxY < this._year){
758                                        max = -1;
759                                }else if(maxY == this._year){
760                                        max = constraints.max.getMonth();
761                                }
762                        }
763
764                        dojo.query(".dojoxCalendarMonthLabel", this.monthContainer)
765                                .forEach(dojo.hitch(this, function(node, cnt){
766                                        dojo[(cnt < min || cnt > max) ? "addClass" : "removeClass"]
767                                                (node, 'dijitCalendarDisabledDate');
768                        }));
769                }
770
771                var h = this.getHeader();
772                if(h){
773                        this._setText(this.getHeader(), this.get("value").getFullYear());
774                }
775        },
776
777        _populateYears: function(year){
778                // summary:
779                //              Fills the list of years with a range of 12 numbers, with the current year
780                //              being the 6th number.
781                var constraints = this.get('constraints');
782                var dispYear = year || this.get("value").getFullYear();
783                var firstYear = dispYear - Math.floor(this.displayedYears/2);
784                var min = constraints && constraints.min ? constraints.min.getFullYear() : firstYear -10000;
785                firstYear = Math.max(min, firstYear);
786
787                // summary: Writes the years to display to the view
788                this._displayedYear = dispYear;
789
790                var yearLabels = dojo.query(".dojoxCalendarYearLabel", this.yearContainer);
791
792                var max = constraints && constraints.max ? constraints.max.getFullYear() - firstYear :  yearLabels.length;
793                var disabledClass = 'dijitCalendarDisabledDate';
794
795                yearLabels.forEach(dojo.hitch(this, function(node, cnt){
796                        if(cnt <= max){
797                                this._setText(node, firstYear + cnt);
798                                dojo.removeClass(node, disabledClass);
799                        }else{
800                                dojo.addClass(node, disabledClass);
801                        }
802                }));
803
804                if(this._incBtn){
805                        dojo[max < yearLabels.length ? "addClass" : "removeClass"](this._incBtn, disabledClass);
806                }
807                if(this._decBtn){
808                        dojo[min >= firstYear ? "addClass" : "removeClass"](this._decBtn, disabledClass);
809                }
810
811                var h = this.getHeader();
812                if(h){
813                        this._setText(this.getHeader(), firstYear + " - " + (firstYear + 11));
814                }
815        },
816
817        _updateSelectedYear: function(){
818                this._year = String((this._cachedDate || this.get("value")).getFullYear());
819                this._updateSelectedNode(".dojoxCalendarYearLabel", dojo.hitch(this, function(node, idx){
820                        return this._year !== null && node.innerHTML == this._year;
821                }));
822        },
823
824        _updateSelectedMonth: function(){
825                var month = (this._cachedDate || this.get("value")).getMonth();
826                this._month = month;
827                this._updateSelectedNode(".dojoxCalendarMonthLabel", function(node, idx){
828                        return idx == month;
829                });
830        },
831
832        _updateSelectedNode: function(query, filter){
833                var sel = "dijitCalendarSelectedDate";
834                dojo.query(query, this.domNode)
835                        .forEach(function(node, idx, array){
836                                dojo[filter(node, idx, array) ? "addClass" : "removeClass"](node.parentNode, sel);
837                });
838                var selMonth = dojo.query('.dojoxCal-MY-M-Template div', this.myContainer)
839                        .filter(function(node){
840                                return dojo.hasClass(node.parentNode, sel);
841                })[0];
842                if(!selMonth){return;}
843                var disabled = dojo.hasClass(selMonth, 'dijitCalendarDisabledDate');
844
845                dojo[disabled ? 'addClass' : 'removeClass'](this.okBtn, "dijitDisabled");
846        },
847
848        onClick: function(evt){
849                // summary:
850                //              Handles clicks on month names
851                var clazz;
852                var _this = this;
853                var sel = "dijitCalendarSelectedDate";
854                function hc(c){
855                        return dojo.hasClass(evt.target, c);
856                }
857
858                if(hc('dijitCalendarDisabledDate')){
859                        dojo.stopEvent(evt);
860                        return false;
861                }
862
863                if(hc("dojoxCalendarMonthLabel")){
864                        clazz = "dojoxCal-MY-M-Template";
865                        this._month = evt.target.parentNode.cellIndex + (evt.target.parentNode.parentNode.rowIndex * 2);
866                        this._cachedDate.setMonth(this._month);
867                        this._updateSelectedMonth();
868                }else if(hc( "dojoxCalendarYearLabel")){
869                        clazz = "dojoxCal-MY-Y-Template";
870                        this._year = Number(evt.target.innerHTML);
871                        this._cachedDate.setYear(this._year);
872                        this._populateMonths();
873                        this._updateSelectedYear();
874                }else if(hc("dojoxCalendarDecrease")){
875                        this._populateYears(this._displayedYear - 10);
876                        return true;
877                }else if(hc("dojoxCalendarIncrease")){
878                        this._populateYears(this._displayedYear + 10);
879                        return true;
880                }else{
881                        return true;
882                }
883                dojo.stopEvent(evt);
884                return false;
885        },
886
887        onOk: function(evt){
888                dojo.stopEvent(evt);
889                if(dojo.hasClass(this.okBtn, "dijitDisabled")){
890                        return false;
891                }
892                this.onValueSelected(this._cachedDate);
893                return false;
894        },
895
896        onCancel: function(evt){
897                dojo.stopEvent(evt);
898                this.onValueSelected(this.get("value"));
899                return false;
900        }
901});
902
903dojo.declare("dojox.widget.Calendar2Pane",
904        [dojox.widget._CalendarBase,
905         dojox.widget._CalendarDay,
906         dojox.widget._CalendarMonthYear], {
907                // summary: A Calendar withtwo panes, the second one
908                //               containing both month and year
909         }
910);
911
912dojo.declare("dojox.widget.Calendar",
913        [dojox.widget._CalendarBase,
914         dojox.widget._CalendarDay,
915         dojox.widget._CalendarMonthYear], {
916                // summary: The standard Calendar. It includes day and month/year views.
917                //      No visual effects are included.
918         }
919);
920
921dojo.declare("dojox.widget.DailyCalendar",
922        [dojox.widget._CalendarBase,
923         dojox.widget._CalendarDay], {
924                // summary: A calendar withonly a daily view.
925                _makeDate: function(value){
926                        var now = new Date();
927                        now.setDate(value);
928                        return now;
929                }
930         }
931
932);
933
934dojo.declare("dojox.widget.MonthAndYearlyCalendar",
935        [dojox.widget._CalendarBase,
936         dojox.widget._CalendarMonthYear], {
937                // summary: A calendar withonly a daily view.
938         }
939);
Note: See TracBrowser for help on using the repository browser.