src/cm/media/js/lib/yui/yui3-3.15.0/build/calendar/calendar-debug.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 YUI.add('calendar', function (Y, NAME) {
       
     2 
       
     3 /**
       
     4  * The Calendar component is a UI widget that allows users
       
     5  * to view dates in a two-dimensional month grid, as well as
       
     6  * to select one or more dates, or ranges of dates. Calendar
       
     7  * is generated dynamically and relies on the developer to
       
     8  * provide for a progressive enhancement alternative.
       
     9  *
       
    10  *
       
    11  * @module calendar
       
    12  */
       
    13 
       
    14 var getCN             = Y.ClassNameManager.getClassName,
       
    15     CALENDAR          = 'calendar',
       
    16     KEY_DOWN          = 40,
       
    17     KEY_UP            = 38,
       
    18     KEY_LEFT          = 37,
       
    19     KEY_RIGHT         = 39,
       
    20     KEY_ENTER         = 13,
       
    21     KEY_SPACE         = 32,
       
    22     CAL_DAY_SELECTED  = getCN(CALENDAR, 'day-selected'),
       
    23     CAL_DAY_HILITED   = getCN(CALENDAR, 'day-highlighted'),
       
    24     CAL_DAY           = getCN(CALENDAR, 'day'),
       
    25     CAL_PREVMONTH_DAY = getCN(CALENDAR, 'prevmonth-day'),
       
    26     CAL_NEXTMONTH_DAY = getCN(CALENDAR, 'nextmonth-day'),
       
    27     CAL_GRID          = getCN(CALENDAR, 'grid'),
       
    28     ydate             = Y.DataType.Date,
       
    29     CAL_PANE          = getCN(CALENDAR, 'pane'),
       
    30     os                = Y.UA.os;
       
    31 
       
    32 /** Create a calendar view to represent a single or multiple
       
    33     * month range of dates, rendered as a grid with date and
       
    34     * weekday labels.
       
    35     *
       
    36     * @class Calendar
       
    37     * @extends CalendarBase
       
    38     * @param config {Object} Configuration object (see Configuration attributes)
       
    39     * @constructor
       
    40     */
       
    41 function Calendar() {
       
    42     Calendar.superclass.constructor.apply ( this, arguments );
       
    43 }
       
    44 
       
    45 Y.Calendar = Y.extend(Calendar, Y.CalendarBase, {
       
    46 
       
    47     _keyEvents: [],
       
    48 
       
    49     _highlightedDateNode: null,
       
    50 
       
    51     /**
       
    52      * A property tracking the last selected date on the calendar, for the
       
    53      * purposes of multiple selection.
       
    54      *
       
    55      * @property _lastSelectedDate
       
    56      * @type Date
       
    57      * @default null
       
    58      * @private
       
    59      */
       
    60     _lastSelectedDate: null,
       
    61 
       
    62     /**
       
    63      * Designated initializer. Activates the navigation plugin for the calendar.
       
    64      *
       
    65      * @method initializer
       
    66      */
       
    67     initializer : function () {
       
    68         this.plug(Y.Plugin.CalendarNavigator);
       
    69 
       
    70         this._keyEvents = [];
       
    71         this._highlightedDateNode = null;
       
    72         this._lastSelectedDate = null;
       
    73     },
       
    74 
       
    75     /**
       
    76      * Overrides the _bindCalendarEvents placeholder in CalendarBase
       
    77      * and binds calendar events during bindUI stage.
       
    78      * @method _bindCalendarEvents
       
    79      * @protected
       
    80      */
       
    81     _bindCalendarEvents : function () {
       
    82         var contentBox = this.get('contentBox'),
       
    83             pane       = contentBox.one("." + CAL_PANE);
       
    84 
       
    85         pane.on("selectstart", this._preventSelectionStart);
       
    86         pane.delegate("click", this._clickCalendar, "." + CAL_DAY + ", ." + CAL_PREVMONTH_DAY + ", ." + CAL_NEXTMONTH_DAY, this);
       
    87         pane.delegate("keydown", this._keydownCalendar, "." + CAL_GRID, this);
       
    88         pane.delegate("focus", this._focusCalendarGrid, "." + CAL_GRID, this);
       
    89         pane.delegate("focus", this._focusCalendarCell, "." + CAL_DAY, this);
       
    90         pane.delegate("blur", this._blurCalendarGrid, "." + CAL_GRID + ",." + CAL_DAY, this);
       
    91 
       
    92 
       
    93         this.after(['minimumDateChange', 'maximumDateChange'], this._afterCustomRendererChange);
       
    94     },
       
    95 
       
    96     /**
       
    97      * Prevents text selection if it is started within the calendar pane
       
    98      * @method _preventSelectionStart
       
    99      * @param event {Event} The selectstart event
       
   100      * @protected
       
   101      */
       
   102     _preventSelectionStart : function (event) {
       
   103         event.preventDefault();
       
   104     },
       
   105 
       
   106     /**
       
   107      * Highlights a specific date node with keyboard highlight class
       
   108      * @method _highlightDateNode
       
   109      * @param oDate {Date} Date corresponding the node to be highlighted
       
   110      * @protected
       
   111      */
       
   112     _highlightDateNode : function (oDate) {
       
   113         this._unhighlightCurrentDateNode();
       
   114         var newNode = this._dateToNode(oDate);
       
   115         newNode.focus();
       
   116         newNode.addClass(CAL_DAY_HILITED);
       
   117     },
       
   118 
       
   119     /**
       
   120      * Unhighlights a specific date node currently highlighted with keyboard highlight class
       
   121      * @method _unhighlightCurrentDateNode
       
   122      * @protected
       
   123      */
       
   124     _unhighlightCurrentDateNode : function () {
       
   125         var allHilitedNodes = this.get("contentBox").all("." + CAL_DAY_HILITED);
       
   126         if (allHilitedNodes) {
       
   127             allHilitedNodes.removeClass(CAL_DAY_HILITED);
       
   128         }
       
   129     },
       
   130 
       
   131     /**
       
   132      * Returns the grid number for a specific calendar grid (for multi-grid templates)
       
   133      * @method _getGridNumber
       
   134      * @param gridNode {Node} Node corresponding to a specific grid
       
   135      * @protected
       
   136      */
       
   137     _getGridNumber : function (gridNode) {
       
   138         var idParts = gridNode.get("id").split("_").reverse();
       
   139 
       
   140         return parseInt(idParts[0], 10);
       
   141     },
       
   142 
       
   143     /**
       
   144      * Handler for loss of focus of calendar grid
       
   145      * @method _blurCalendarGrid
       
   146      * @protected
       
   147      */
       
   148     _blurCalendarGrid : function () {
       
   149         this._unhighlightCurrentDateNode();
       
   150     },
       
   151 
       
   152 
       
   153     /**
       
   154      * Handler for gain of focus of calendar cell
       
   155      * @method _focusCalendarCell
       
   156      * @protected
       
   157      */
       
   158     _focusCalendarCell : function (ev) {
       
   159         this._highlightedDateNode = ev.target;
       
   160         ev.stopPropagation();
       
   161     },
       
   162 
       
   163     /**
       
   164      * Handler for gain of focus of calendar grid
       
   165      * @method _focusCalendarGrid
       
   166      * @protected
       
   167      */
       
   168     _focusCalendarGrid : function () {
       
   169         this._unhighlightCurrentDateNode();
       
   170         this._highlightedDateNode = null;
       
   171     },
       
   172 
       
   173     /**
       
   174      * Handler for keyboard press on a calendar grid
       
   175      * @method _keydownCalendar
       
   176      * @protected
       
   177      */
       
   178     _keydownCalendar : function (ev) {
       
   179         var gridNum = this._getGridNumber(ev.target),
       
   180             curDate = !this._highlightedDateNode ? null : this._nodeToDate(this._highlightedDateNode),
       
   181             keyCode = ev.keyCode,
       
   182             dayNum = 0,
       
   183             dir = '',
       
   184             selMode,
       
   185             newDate,
       
   186             startDate,
       
   187             endDate,
       
   188             lastPaneDate;
       
   189 
       
   190         switch(keyCode) {
       
   191             case KEY_DOWN:
       
   192                 dayNum = 7;
       
   193                 dir = 's';
       
   194                 break;
       
   195             case KEY_UP:
       
   196                 dayNum = -7;
       
   197                 dir = 'n';
       
   198                 break;
       
   199             case KEY_LEFT:
       
   200                 dayNum = -1;
       
   201                 dir = 'w';
       
   202                 break;
       
   203             case KEY_RIGHT:
       
   204                 dayNum = 1;
       
   205                 dir = 'e';
       
   206                 break;
       
   207             case KEY_SPACE: case KEY_ENTER:
       
   208                 ev.preventDefault();
       
   209                 if (this._highlightedDateNode) {
       
   210                     selMode = this.get("selectionMode");
       
   211                     if (selMode === "single" && !this._highlightedDateNode.hasClass(CAL_DAY_SELECTED)) {
       
   212                             this._clearSelection(true);
       
   213                             this._addDateToSelection(curDate);
       
   214                     } else if (selMode === "multiple" || selMode === "multiple-sticky") {
       
   215                         if (this._highlightedDateNode.hasClass(CAL_DAY_SELECTED)) {
       
   216                             this._removeDateFromSelection(curDate);
       
   217                         } else {
       
   218                             this._addDateToSelection(curDate);
       
   219                         }
       
   220                     }
       
   221                 }
       
   222                 break;
       
   223         }
       
   224 
       
   225 
       
   226         if (keyCode === KEY_DOWN || keyCode === KEY_UP || keyCode === KEY_LEFT || keyCode === KEY_RIGHT) {
       
   227 
       
   228             if (!curDate) {
       
   229                 curDate = ydate.addMonths(this.get("date"), gridNum);
       
   230                 dayNum = 0;
       
   231             }
       
   232 
       
   233             ev.preventDefault();
       
   234 
       
   235             newDate = ydate.addDays(curDate, dayNum);
       
   236             startDate = this.get("date");
       
   237             endDate = ydate.addMonths(this.get("date"), this._paneNumber - 1);
       
   238             lastPaneDate = new Date(endDate);
       
   239             endDate.setDate(ydate.daysInMonth(endDate));
       
   240 
       
   241             if (ydate.isInRange(newDate, startDate, endDate)) {
       
   242 /*
       
   243                 var paneShift = (newDate.getMonth() - curDate.getMonth()) % 10;
       
   244 
       
   245                 if (paneShift != 0) {
       
   246                     var newGridNum = gridNum + paneShift,
       
   247                             contentBox = this.get('contentBox'),
       
   248                             newPane = contentBox.one("#" + this._calendarId + "_pane_" + newGridNum);
       
   249                             newPane.focus();
       
   250                 }
       
   251 */
       
   252                 this._highlightDateNode(newDate);
       
   253             } else if (ydate.isGreater(startDate, newDate)) {
       
   254                 if (!ydate.isGreaterOrEqual(this.get("minimumDate"), startDate)) {
       
   255                     this.set("date", ydate.addMonths(startDate, -1));
       
   256                     this._highlightDateNode(newDate);
       
   257                 }
       
   258             } else if (ydate.isGreater(newDate, endDate)) {
       
   259                 if (!ydate.isGreaterOrEqual(lastPaneDate, this.get("maximumDate"))) {
       
   260                     this.set("date", ydate.addMonths(startDate, 1));
       
   261                     this._highlightDateNode(newDate);
       
   262                 }
       
   263             }
       
   264         }
       
   265     },
       
   266 
       
   267     /**
       
   268      * Handles the calendar clicks based on selection mode.
       
   269      * @method _clickCalendar
       
   270      * @param {Event} ev A click event
       
   271      * @private
       
   272      */
       
   273     _clickCalendar : function (ev) {
       
   274         var clickedCell = ev.currentTarget,
       
   275             clickedCellIsDay = clickedCell.hasClass(CAL_DAY) &&
       
   276                                 !clickedCell.hasClass(CAL_PREVMONTH_DAY) &&
       
   277                                 !clickedCell.hasClass(CAL_NEXTMONTH_DAY),
       
   278 
       
   279         clickedCellIsSelected = clickedCell.hasClass(CAL_DAY_SELECTED),
       
   280         selectedDate;
       
   281 
       
   282         switch (this.get("selectionMode")) {
       
   283             case("single"):
       
   284                 if (clickedCellIsDay) {
       
   285                     if (!clickedCellIsSelected) {
       
   286                         this._clearSelection(true);
       
   287                         this._addDateToSelection(this._nodeToDate(clickedCell));
       
   288                     }
       
   289                 }
       
   290                 break;
       
   291             case("multiple-sticky"):
       
   292                 if (clickedCellIsDay) {
       
   293                     if (clickedCellIsSelected) {
       
   294                         this._removeDateFromSelection(this._nodeToDate(clickedCell));
       
   295                     } else {
       
   296                         this._addDateToSelection(this._nodeToDate(clickedCell));
       
   297                     }
       
   298                 }
       
   299                 break;
       
   300             case("multiple"):
       
   301                 if (clickedCellIsDay) {
       
   302                     if (!ev.metaKey && !ev.ctrlKey && !ev.shiftKey) {
       
   303                         this._clearSelection(true);
       
   304                         this._lastSelectedDate = this._nodeToDate(clickedCell);
       
   305                         this._addDateToSelection(this._lastSelectedDate);
       
   306                     } else if (((os === 'macintosh' && ev.metaKey) || (os !== 'macintosh' && ev.ctrlKey)) && !ev.shiftKey) {
       
   307                         if (clickedCellIsSelected) {
       
   308                             this._removeDateFromSelection(this._nodeToDate(clickedCell));
       
   309                             this._lastSelectedDate = null;
       
   310                         } else {
       
   311                             this._lastSelectedDate = this._nodeToDate(clickedCell);
       
   312                             this._addDateToSelection(this._lastSelectedDate);
       
   313                         }
       
   314                     } else if (((os === 'macintosh' && ev.metaKey) || (os !== 'macintosh' && ev.ctrlKey)) && ev.shiftKey) {
       
   315                         if (this._lastSelectedDate) {
       
   316                             selectedDate = this._nodeToDate(clickedCell);
       
   317                             this._addDateRangeToSelection(selectedDate, this._lastSelectedDate);
       
   318                             this._lastSelectedDate = selectedDate;
       
   319                         } else {
       
   320                             this._lastSelectedDate = this._nodeToDate(clickedCell);
       
   321                             this._addDateToSelection(this._lastSelectedDate);
       
   322                         }
       
   323                     } else if (ev.shiftKey) {
       
   324                         if (this._lastSelectedDate) {
       
   325                             selectedDate = this._nodeToDate(clickedCell);
       
   326                             this._clearSelection(true);
       
   327                             this._addDateRangeToSelection(selectedDate, this._lastSelectedDate);
       
   328                             this._lastSelectedDate = selectedDate;
       
   329                         } else {
       
   330                             this._clearSelection(true);
       
   331                             this._lastSelectedDate = this._nodeToDate(clickedCell);
       
   332                             this._addDateToSelection(this._lastSelectedDate);
       
   333                         }
       
   334                     }
       
   335                 }
       
   336                 break;
       
   337         }
       
   338 
       
   339         if (clickedCellIsDay) {
       
   340             /**
       
   341             * Fired when a specific date cell in the calendar is clicked. The event carries a
       
   342             * payload which includes a `cell` property corresponding to the node of the actual
       
   343             * date cell, and a `date` property, with the `Date` that was clicked.
       
   344             *
       
   345             * @event dateClick
       
   346             */
       
   347             this.fire("dateClick", {cell: clickedCell, date: this._nodeToDate(clickedCell)});
       
   348         } else if (clickedCell.hasClass(CAL_PREVMONTH_DAY)) {
       
   349             /**
       
   350             * Fired when any of the previous month's days displayed before the calendar grid
       
   351             * are clicked.
       
   352             *
       
   353             * @event prevMonthClick
       
   354             */
       
   355             this.fire("prevMonthClick");
       
   356         } else if (clickedCell.hasClass(CAL_NEXTMONTH_DAY)) {
       
   357             /**
       
   358             * Fired when any of the next month's days displayed after the calendar grid
       
   359             * are clicked.
       
   360             *
       
   361             * @event nextMonthClick
       
   362             */
       
   363             this.fire("nextMonthClick");
       
   364         }
       
   365     },
       
   366 
       
   367     /**
       
   368      * Overrides CalendarBase.prototype._canBeSelected to disable
       
   369      * nodes earlier than minimumDate and later than maximumDate
       
   370      * @method _canBeSelected
       
   371      * @private
       
   372      */
       
   373     _canBeSelected : function (date) {
       
   374         var minDate = this.get('minimumDate'),
       
   375             maxDate = this.get('maximumDate');
       
   376 
       
   377         if ((minDate && !ydate.isGreaterOrEqual(date, minDate)) ||
       
   378             (maxDate &&  ydate.isGreater(date, maxDate))) {
       
   379             return false;
       
   380         }
       
   381 
       
   382         return Calendar.superclass._canBeSelected.call(this, date);
       
   383     },
       
   384 
       
   385     /**
       
   386      * Overrides CalendarBase.prototype._renderCustomRules to disable
       
   387      * nodes earlier than minimumDate and later than maximumDate
       
   388      * @method _renderCustomRules
       
   389      * @private
       
   390      */
       
   391     _renderCustomRules: function () {
       
   392         Calendar.superclass._renderCustomRules.call(this);
       
   393 
       
   394         var minDate = this.get('minimumDate'),
       
   395             maxDate = this.get('maximumDate'),
       
   396             dates = [],
       
   397             i, l,
       
   398             paneDate,
       
   399             paneNum;
       
   400 
       
   401         if (!minDate && !maxDate) {
       
   402             return;
       
   403         }
       
   404 
       
   405         for (paneNum = 0; paneNum < this._paneNumber; paneNum++) {
       
   406             paneDate = ydate.addMonths(this.get("date"), paneNum);
       
   407             dates = dates.concat(ydate.listOfDatesInMonth(paneDate));
       
   408         }
       
   409 
       
   410         if (minDate) {
       
   411             for (i = 0, l = dates.length; i < l; i++) {
       
   412                 if (!ydate.isGreaterOrEqual(dates[i], minDate)) {
       
   413                     this._disableDate(dates[i]);
       
   414                 } else {
       
   415                     break;
       
   416                 }
       
   417             }
       
   418         }
       
   419 
       
   420         if (maxDate) {
       
   421             for (i = dates.length - 1; i >= 0; i--) {
       
   422                 if (ydate.isGreater(dates[i], maxDate)) {
       
   423                     this._disableDate(dates[i]);
       
   424                 } else {
       
   425                     break;
       
   426                 }
       
   427             }
       
   428         }
       
   429     },
       
   430 
       
   431     /**
       
   432      * Subtracts one month from the current calendar view.
       
   433      * @method subtractMonth
       
   434      * @return {Calendar} A reference to this object
       
   435      * @chainable
       
   436      */
       
   437     subtractMonth : function (e) {
       
   438         this.set("date", ydate.addMonths(this.get("date"), -1));
       
   439         if (e) {
       
   440             e.halt();
       
   441         }
       
   442         return this;
       
   443     },
       
   444 
       
   445     /**
       
   446      * Subtracts one year from the current calendar view.
       
   447      * @method subtractYear
       
   448      * @return {Calendar} A reference to this object
       
   449      * @chainable
       
   450      */
       
   451     subtractYear : function (e) {
       
   452         this.set("date", ydate.addYears(this.get("date"), -1));
       
   453         if (e) {
       
   454             e.halt();
       
   455         }
       
   456         return this;
       
   457     },
       
   458 
       
   459     /**
       
   460      * Adds one month to the current calendar view.
       
   461      * @method addMonth
       
   462      * @return {Calendar} A reference to this object
       
   463      * @chainable
       
   464      */
       
   465     addMonth : function (e) {
       
   466         this.set("date", ydate.addMonths(this.get("date"), 1));
       
   467         if (e) {
       
   468             e.halt();
       
   469         }
       
   470         return this;
       
   471     },
       
   472 
       
   473     /**
       
   474      * Adds one year to the current calendar view.
       
   475      * @method addYear
       
   476      * @return {Calendar} A reference to this object
       
   477      * @chainable
       
   478      */
       
   479     addYear : function (e) {
       
   480         this.set("date", ydate.addYears(this.get("date"), 1));
       
   481         if (e) {
       
   482             e.halt();
       
   483         }
       
   484         return this;
       
   485     }
       
   486 }, {
       
   487     /**
       
   488     * The identity of the widget.
       
   489     *
       
   490     * @property NAME
       
   491     * @type String
       
   492     * @default 'calendar'
       
   493     * @readOnly
       
   494     * @protected
       
   495     * @static
       
   496     */
       
   497     NAME: "calendar",
       
   498 
       
   499     /**
       
   500     * Static property used to define the default attribute configuration of
       
   501     * the Widget.
       
   502     *
       
   503     * @property ATTRS
       
   504     * @type {Object}
       
   505     * @protected
       
   506     * @static
       
   507     */
       
   508     ATTRS: {
       
   509 
       
   510         /**
       
   511          * A setting specifying the type of selection the calendar allows.
       
   512          * Possible values include:
       
   513          * <ul>
       
   514          *   <li>`single` - One date at a time</li>
       
   515          *   <li>`multiple-sticky` - Multiple dates, selected one at a time (the dates "stick"). This option
       
   516          *   is appropriate for mobile devices, where function keys from the keyboard are not available.</li>
       
   517          *   <li>`multiple` - Multiple dates, selected with Ctrl/Meta keys for additional single
       
   518          *   dates, and Shift key for date ranges.</li>
       
   519          *
       
   520          * @attribute selectionMode
       
   521          * @type String
       
   522          * @default single
       
   523          */
       
   524         selectionMode: {
       
   525             value: "single"
       
   526         },
       
   527 
       
   528         /**
       
   529          * The date corresponding to the current calendar view. Always
       
   530          * normalized to the first of the month that contains the date
       
   531          * at assignment time. Used as the first date visible in the
       
   532          * calendar.
       
   533          *
       
   534          * @attribute date
       
   535          * @type Date
       
   536          * @default Today's date as set on the user's computer.
       
   537          */
       
   538         date: {
       
   539             value: new Date(),
       
   540             lazyAdd: false,
       
   541             setter: function (val) {
       
   542 
       
   543                 var newDate    = this._normalizeDate(val),
       
   544                     newEndDate = ydate.addMonths(newDate, this._paneNumber - 1),
       
   545                     minDate    = this.get("minimumDate"),
       
   546                     maxDate    = this.get("maximumDate");
       
   547 
       
   548                 if ((!minDate || ydate.isGreaterOrEqual(newDate, minDate)) &&
       
   549                     (!maxDate || ydate.isGreaterOrEqual(maxDate, newEndDate))
       
   550                 ) {
       
   551                     return newDate;
       
   552                 } else if (minDate && ydate.isGreater(minDate, newDate)) {
       
   553                     return this._normalizeDate(minDate);
       
   554                 } else if (maxDate && ydate.isGreater(newEndDate, maxDate)) {
       
   555                     return ydate.addMonths(this._normalizeDate(maxDate), 1 - this._paneNumber);
       
   556                 }
       
   557             }
       
   558         },
       
   559 
       
   560         /**
       
   561          * Unless minimumDate is null, it will not be possible to display and select dates earlier than this one.
       
   562          *
       
   563          * @attribute minimumDate
       
   564          * @type Date
       
   565          * @default null
       
   566          */
       
   567         minimumDate: {
       
   568             value: null,
       
   569             setter: function (val) {
       
   570                 if (Y.Lang.isDate(val)) {
       
   571                     var curDate = this.get('date'),
       
   572                         newMin  = this._normalizeTime(val);
       
   573                     if (curDate && !ydate.isGreaterOrEqual(curDate, newMin)) {
       
   574                         this.set('date', val);
       
   575                     }
       
   576                     return newMin;
       
   577                 } else {
       
   578                     return null;
       
   579                 }
       
   580             }
       
   581         },
       
   582 
       
   583         /**
       
   584          * Unless maximumDate is null, it will not be possible to display and select dates later than this one.
       
   585          *
       
   586          * @attribute maximumDate
       
   587          * @type Date
       
   588          * @default null
       
   589          */
       
   590         maximumDate: {
       
   591             value: null,
       
   592             setter: function (val) {
       
   593                 if (Y.Lang.isDate(val)) {
       
   594                     var curDate = this.get('date');
       
   595 
       
   596                     if (curDate && !ydate.isGreaterOrEqual(val, ydate.addMonths(curDate, this._paneNumber - 1))) {
       
   597                         this.set('date', ydate.addMonths(this._normalizeDate(val), 1 - this._paneNumber));
       
   598                     }
       
   599 
       
   600                     return this._normalizeTime(val);
       
   601                 } else {
       
   602                     return null;
       
   603                 }
       
   604             }
       
   605         }
       
   606     }
       
   607 });
       
   608 
       
   609 
       
   610 }, '@VERSION@', {"requires": ["calendar-base", "calendarnavigator"], "skinnable": true});