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