1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621 |
- // Copyright 2006 The Closure Library Authors. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS-IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- /**
- * @fileoverview Date picker implementation.
- *
- * @author eae@google.com (Emil A Eklund)
- * @see ../demos/datepicker.html
- */
- goog.provide('goog.ui.DatePicker');
- goog.provide('goog.ui.DatePicker.Events');
- goog.provide('goog.ui.DatePickerEvent');
- goog.require('goog.a11y.aria');
- goog.require('goog.asserts');
- goog.require('goog.date.Date');
- goog.require('goog.date.DateRange');
- goog.require('goog.date.Interval');
- goog.require('goog.dom');
- goog.require('goog.dom.NodeType');
- goog.require('goog.dom.TagName');
- goog.require('goog.dom.classlist');
- goog.require('goog.events.Event');
- goog.require('goog.events.EventType');
- goog.require('goog.events.KeyHandler');
- goog.require('goog.i18n.DateTimeFormat');
- goog.require('goog.i18n.DateTimePatterns');
- goog.require('goog.i18n.DateTimeSymbols');
- goog.require('goog.style');
- goog.require('goog.ui.Component');
- goog.require('goog.ui.DefaultDatePickerRenderer');
- goog.require('goog.ui.IdGenerator');
- /**
- * DatePicker widget. Allows a single date to be selected from a calendar like
- * view.
- *
- * @param {goog.date.Date|Date=} opt_date Date to initialize the date picker
- * with, defaults to the current date.
- * @param {Object=} opt_dateTimeSymbols Date and time symbols to use.
- * Defaults to goog.i18n.DateTimeSymbols if not set.
- * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper.
- * @param {goog.ui.DatePickerRenderer=} opt_renderer Optional Date picker
- * renderer.
- * @constructor
- * @extends {goog.ui.Component}
- */
- goog.ui.DatePicker = function(
- opt_date, opt_dateTimeSymbols, opt_domHelper, opt_renderer) {
- goog.ui.Component.call(this, opt_domHelper);
- /**
- * Date and time symbols to use.
- * @type {!goog.i18n.DateTimeSymbolsType}
- * @private
- */
- this.symbols_ = /** @type {!goog.i18n.DateTimeSymbolsType} */ (
- opt_dateTimeSymbols || goog.i18n.DateTimeSymbols);
- this.wdayNames_ = this.symbols_.STANDALONESHORTWEEKDAYS;
- // Formatters for the various areas of the picker
- this.i18nDateFormatterDay_ = new goog.i18n.DateTimeFormat('d', this.symbols_);
- this.i18nDateFormatterDay2_ =
- new goog.i18n.DateTimeFormat('dd', this.symbols_);
- this.i18nDateFormatterWeek_ =
- new goog.i18n.DateTimeFormat('w', this.symbols_);
- // Formatter for day grid aria label.
- this.i18nDateFormatterDayAriaLabel_ =
- new goog.i18n.DateTimeFormat('M d', this.symbols_);
- // Previous implementation did not use goog.i18n.DateTimePatterns,
- // so it is likely most developers did not set it.
- // This is why the fallback to a hard-coded string (just in case).
- var patYear = goog.i18n.DateTimePatterns.YEAR_FULL || 'y';
- this.i18nDateFormatterYear_ =
- new goog.i18n.DateTimeFormat(patYear, this.symbols_);
- var patMMMMy = goog.i18n.DateTimePatterns.YEAR_MONTH_FULL || 'MMMM y';
- this.i18nDateFormatterMonthYear_ =
- new goog.i18n.DateTimeFormat(patMMMMy, this.symbols_);
- /**
- * @type {!goog.ui.DatePickerRenderer}
- * @private
- */
- this.renderer_ = opt_renderer ||
- new goog.ui.DefaultDatePickerRenderer(
- this.getBaseCssClass(), this.getDomHelper());
- /**
- * Selected date.
- * @type {goog.date.Date}
- * @private
- */
- this.date_ = new goog.date.Date(opt_date);
- this.date_.setFirstWeekCutOffDay(this.symbols_.FIRSTWEEKCUTOFFDAY);
- this.date_.setFirstDayOfWeek(this.symbols_.FIRSTDAYOFWEEK);
- /**
- * Active month.
- * @type {goog.date.Date}
- * @private
- */
- this.activeMonth_ = this.date_.clone();
- this.activeMonth_.setDate(1);
- /**
- * Class names to apply to the weekday columns.
- * @type {Array<string>}
- * @private
- */
- this.wdayStyles_ = ['', '', '', '', '', '', ''];
- this.wdayStyles_[this.symbols_.WEEKENDRANGE[0]] =
- goog.getCssName(this.getBaseCssClass(), 'wkend-start');
- this.wdayStyles_[this.symbols_.WEEKENDRANGE[1]] =
- goog.getCssName(this.getBaseCssClass(), 'wkend-end');
- /**
- * Object that is being used to cache key handlers.
- * @type {Object}
- * @private
- */
- this.keyHandlers_ = {};
- /**
- * Collection of dates that make up the date picker.
- * @type {!Array<!Array<!goog.date.Date>>}
- * @private
- */
- this.grid_ = [];
- /** @private {Array<!Array<Element>>} */
- this.elTable_;
- /**
- * TODO(tbreisacher): Remove external references to this field,
- * and make it private.
- * @type {Element}
- */
- this.tableBody_;
- /** @private {Element} */
- this.tableFoot_;
- /** @private {Element} */
- this.elYear_;
- /** @private {Element} */
- this.elMonth_;
- /** @private {Element} */
- this.elToday_;
- /** @private {Element} */
- this.elNone_;
- /** @private {Element} */
- this.menu_;
- /** @private {Element} */
- this.menuSelected_;
- /** @private {function(Element)} */
- this.menuCallback_;
- };
- goog.inherits(goog.ui.DatePicker, goog.ui.Component);
- goog.tagUnsealableClass(goog.ui.DatePicker);
- /**
- * Flag indicating if the number of weeks shown should be fixed.
- * @type {boolean}
- * @private
- */
- goog.ui.DatePicker.prototype.showFixedNumWeeks_ = true;
- /**
- * Flag indicating if days from other months should be shown.
- * @type {boolean}
- * @private
- */
- goog.ui.DatePicker.prototype.showOtherMonths_ = true;
- /**
- * Range of dates which are selectable by the user.
- * @type {!goog.date.DateRange}
- * @private
- */
- goog.ui.DatePicker.prototype.userSelectableDateRange_ =
- goog.date.DateRange.allTime();
- /**
- * Flag indicating if extra week(s) always should be added at the end. If not
- * set the extra week is added at the beginning if the number of days shown
- * from the previous month is less then the number from the next month.
- * @type {boolean}
- * @private
- */
- goog.ui.DatePicker.prototype.extraWeekAtEnd_ = true;
- /**
- * Flag indicating if week numbers should be shown.
- * @type {boolean}
- * @private
- */
- goog.ui.DatePicker.prototype.showWeekNum_ = true;
- /**
- * Flag indicating if weekday names should be shown.
- * @type {boolean}
- * @private
- */
- goog.ui.DatePicker.prototype.showWeekdays_ = true;
- /**
- * Flag indicating if none is a valid selection. Also controls if the none
- * button should be shown or not.
- * @type {boolean}
- * @private
- */
- goog.ui.DatePicker.prototype.allowNone_ = true;
- /**
- * Flag indicating if the today button should be shown.
- * @type {boolean}
- * @private
- */
- goog.ui.DatePicker.prototype.showToday_ = true;
- /**
- * Flag indicating if the picker should use a simple navigation menu that only
- * contains controls for navigating to the next and previous month. The default
- * navigation menu contains controls for navigating to the next/previous month,
- * next/previous year, and menus for jumping to specific months and years.
- * @type {boolean}
- * @private
- */
- goog.ui.DatePicker.prototype.simpleNavigation_ = false;
- /**
- * Custom decorator function. Takes a goog.date.Date object, returns a String
- * representing a CSS class or null if no special styling applies
- * @type {Function}
- * @private
- */
- goog.ui.DatePicker.prototype.decoratorFunction_ = null;
- /**
- * Flag indicating if the dates should be printed as a two charater date.
- * @type {boolean}
- * @private
- */
- goog.ui.DatePicker.prototype.longDateFormat_ = false;
- /**
- * Element for navigation row on a datepicker.
- * @type {Element}
- * @private
- */
- goog.ui.DatePicker.prototype.elNavRow_ = null;
- /**
- * Element for the month/year in the navigation row.
- * @type {Element}
- * @private
- */
- goog.ui.DatePicker.prototype.elMonthYear_ = null;
- /**
- * Element for footer row on a datepicker.
- * @type {Element}
- * @private
- */
- goog.ui.DatePicker.prototype.elFootRow_ = null;
- /**
- * Generator for unique table cell IDs.
- * @type {goog.ui.IdGenerator}
- * @private
- */
- goog.ui.DatePicker.prototype.cellIdGenerator_ =
- goog.ui.IdGenerator.getInstance();
- /**
- * Name of base CSS class of datepicker.
- * @type {string}
- * @private
- */
- goog.ui.DatePicker.BASE_CSS_CLASS_ = goog.getCssName('goog-date-picker');
- /**
- * The numbers of years to show before and after the current one in the
- * year pull-down menu. A total of YEAR_MENU_RANGE * 2 + 1 will be shown.
- * Example: for range = 2 and year 2013 => [2011, 2012, 2013, 2014, 2015]
- * @const {number}
- * @private
- */
- goog.ui.DatePicker.YEAR_MENU_RANGE_ = 5;
- /**
- * Constants for event names
- *
- * @const
- */
- goog.ui.DatePicker.Events = {
- CHANGE: 'change',
- CHANGE_ACTIVE_MONTH: 'changeActiveMonth',
- SELECT: 'select'
- };
- /**
- * @deprecated Use isInDocument.
- */
- goog.ui.DatePicker.prototype.isCreated =
- goog.ui.DatePicker.prototype.isInDocument;
- /**
- * @return {number} The first day of week, 0 = Monday, 6 = Sunday.
- */
- goog.ui.DatePicker.prototype.getFirstWeekday = function() {
- return this.activeMonth_.getFirstDayOfWeek();
- };
- /**
- * Returns the class name associated with specified weekday.
- * @param {number} wday The week day number to get the class name for.
- * @return {string} The class name associated with specified weekday.
- */
- goog.ui.DatePicker.prototype.getWeekdayClass = function(wday) {
- return this.wdayStyles_[wday];
- };
- /**
- * @return {boolean} Whether a fixed number of weeks should be showed. If not
- * only weeks for the current month will be shown.
- */
- goog.ui.DatePicker.prototype.getShowFixedNumWeeks = function() {
- return this.showFixedNumWeeks_;
- };
- /**
- * @return {boolean} Whether a days from the previous and/or next month should
- * be shown.
- */
- goog.ui.DatePicker.prototype.getShowOtherMonths = function() {
- return this.showOtherMonths_;
- };
- /**
- * @return {boolean} Whether a the extra week(s) added always should be at the
- * end. Only applicable if a fixed number of weeks are shown.
- */
- goog.ui.DatePicker.prototype.getExtraWeekAtEnd = function() {
- return this.extraWeekAtEnd_;
- };
- /**
- * @return {boolean} Whether week numbers should be shown.
- */
- goog.ui.DatePicker.prototype.getShowWeekNum = function() {
- return this.showWeekNum_;
- };
- /**
- * @return {boolean} Whether weekday names should be shown.
- */
- goog.ui.DatePicker.prototype.getShowWeekdayNames = function() {
- return this.showWeekdays_;
- };
- /**
- * @return {boolean} Whether none is a valid selection.
- */
- goog.ui.DatePicker.prototype.getAllowNone = function() {
- return this.allowNone_;
- };
- /**
- * @return {boolean} Whether the today button should be shown.
- */
- goog.ui.DatePicker.prototype.getShowToday = function() {
- return this.showToday_;
- };
- /**
- * Returns base CSS class. This getter is used to get base CSS class part.
- * All CSS class names in component are created as:
- * goog.getCssName(this.getBaseCssClass(), 'CLASS_NAME')
- * @return {string} Base CSS class.
- */
- goog.ui.DatePicker.prototype.getBaseCssClass = function() {
- return goog.ui.DatePicker.BASE_CSS_CLASS_;
- };
- /**
- * Sets the first day of week
- *
- * @param {number} wday Week day, 0 = Monday, 6 = Sunday.
- */
- goog.ui.DatePicker.prototype.setFirstWeekday = function(wday) {
- this.activeMonth_.setFirstDayOfWeek(wday);
- this.updateCalendarGrid_();
- this.redrawWeekdays_();
- };
- /**
- * Sets class name associated with specified weekday.
- *
- * @param {number} wday Week day, 0 = Monday, 6 = Sunday.
- * @param {string} className Class name.
- */
- goog.ui.DatePicker.prototype.setWeekdayClass = function(wday, className) {
- this.wdayStyles_[wday] = className;
- this.redrawCalendarGrid_();
- };
- /**
- * Sets whether a fixed number of weeks should be showed. If not only weeks
- * for the current month will be showed.
- *
- * @param {boolean} b Whether a fixed number of weeks should be showed.
- */
- goog.ui.DatePicker.prototype.setShowFixedNumWeeks = function(b) {
- this.showFixedNumWeeks_ = b;
- this.updateCalendarGrid_();
- };
- /**
- * Sets whether a days from the previous and/or next month should be shown.
- *
- * @param {boolean} b Whether a days from the previous and/or next month should
- * be shown.
- */
- goog.ui.DatePicker.prototype.setShowOtherMonths = function(b) {
- this.showOtherMonths_ = b;
- this.redrawCalendarGrid_();
- };
- /**
- * Sets the range of dates which may be selected by the user.
- *
- * @param {!goog.date.DateRange} dateRange The range of selectable dates.
- */
- goog.ui.DatePicker.prototype.setUserSelectableDateRange = function(dateRange) {
- this.userSelectableDateRange_ = dateRange;
- };
- /**
- * Gets the range of dates which may be selected by the user.
- *
- * @return {!goog.date.DateRange} The range of selectable dates.
- */
- goog.ui.DatePicker.prototype.getUserSelectableDateRange = function() {
- return this.userSelectableDateRange_;
- };
- /**
- * Determine if a date may be selected by the user.
- *
- * @param {!goog.date.Date} date The date to be tested.
- * @return {boolean} Whether the user may select this date.
- * @private
- */
- goog.ui.DatePicker.prototype.isUserSelectableDate_ = function(date) {
- return this.userSelectableDateRange_.contains(date);
- };
- /**
- * Sets whether the picker should use a simple navigation menu that only
- * contains controls for navigating to the next and previous month. The default
- * navigation menu contains controls for navigating to the next/previous month,
- * next/previous year, and menus for jumping to specific months and years.
- *
- * @param {boolean} b Whether to use a simple navigation menu.
- */
- goog.ui.DatePicker.prototype.setUseSimpleNavigationMenu = function(b) {
- this.simpleNavigation_ = b;
- this.updateNavigationRow_();
- this.updateCalendarGrid_();
- };
- /**
- * Sets whether a the extra week(s) added always should be at the end. Only
- * applicable if a fixed number of weeks are shown.
- *
- * @param {boolean} b Whether a the extra week(s) added always should be at the
- * end.
- */
- goog.ui.DatePicker.prototype.setExtraWeekAtEnd = function(b) {
- this.extraWeekAtEnd_ = b;
- this.updateCalendarGrid_();
- };
- /**
- * Sets whether week numbers should be shown.
- *
- * @param {boolean} b Whether week numbers should be shown.
- */
- goog.ui.DatePicker.prototype.setShowWeekNum = function(b) {
- this.showWeekNum_ = b;
- // The navigation and footer rows may rely on the number of visible columns,
- // so we update them when adding/removing the weeknum column.
- this.updateNavigationRow_();
- this.updateFooterRow_();
- this.updateCalendarGrid_();
- };
- /**
- * Sets whether weekday names should be shown.
- *
- * @param {boolean} b Whether weekday names should be shown.
- */
- goog.ui.DatePicker.prototype.setShowWeekdayNames = function(b) {
- this.showWeekdays_ = b;
- this.redrawWeekdays_();
- this.redrawCalendarGrid_();
- };
- /**
- * Sets whether the picker uses narrow weekday names ('M', 'T', 'W', ...).
- *
- * The default behavior is to use short names ('Mon', 'Tue', 'Wed', ...).
- *
- * @param {boolean} b Whether to use narrow weekday names.
- */
- goog.ui.DatePicker.prototype.setUseNarrowWeekdayNames = function(b) {
- this.wdayNames_ = b ? this.symbols_.STANDALONENARROWWEEKDAYS :
- this.symbols_.STANDALONESHORTWEEKDAYS;
- this.redrawWeekdays_();
- };
- /**
- * Sets whether none is a valid selection.
- *
- * @param {boolean} b Whether none is a valid selection.
- */
- goog.ui.DatePicker.prototype.setAllowNone = function(b) {
- this.allowNone_ = b;
- if (this.elNone_) {
- this.updateTodayAndNone_();
- }
- };
- /**
- * Sets whether the today button should be shown.
- *
- * @param {boolean} b Whether the today button should be shown.
- */
- goog.ui.DatePicker.prototype.setShowToday = function(b) {
- this.showToday_ = b;
- if (this.elToday_) {
- this.updateTodayAndNone_();
- }
- };
- /**
- * Updates the display style of the None and Today buttons as well as hides the
- * table foot if both are hidden.
- * @private
- */
- goog.ui.DatePicker.prototype.updateTodayAndNone_ = function() {
- goog.style.setElementShown(this.elToday_, this.showToday_);
- goog.style.setElementShown(this.elNone_, this.allowNone_);
- goog.style.setElementShown(
- this.tableFoot_, this.showToday_ || this.allowNone_);
- };
- /**
- * Sets the decorator function. The function should have the interface of
- * {string} f({goog.date.Date});
- * and return a String representing a CSS class to decorate the cell
- * corresponding to the date specified.
- *
- * @param {Function} f The decorator function.
- */
- goog.ui.DatePicker.prototype.setDecorator = function(f) {
- this.decoratorFunction_ = f;
- };
- /**
- * Sets whether the date will be printed in long format. In long format, dates
- * such as '1' will be printed as '01'.
- *
- * @param {boolean} b Whethere dates should be printed in long format.
- */
- goog.ui.DatePicker.prototype.setLongDateFormat = function(b) {
- this.longDateFormat_ = b;
- this.redrawCalendarGrid_();
- };
- /**
- * Changes the active month to the previous one.
- */
- goog.ui.DatePicker.prototype.previousMonth = function() {
- this.activeMonth_.add(new goog.date.Interval(goog.date.Interval.MONTHS, -1));
- this.updateCalendarGrid_();
- this.fireChangeActiveMonthEvent_();
- };
- /**
- * Changes the active month to the next one.
- */
- goog.ui.DatePicker.prototype.nextMonth = function() {
- this.activeMonth_.add(new goog.date.Interval(goog.date.Interval.MONTHS, 1));
- this.updateCalendarGrid_();
- this.fireChangeActiveMonthEvent_();
- };
- /**
- * Changes the active year to the previous one.
- */
- goog.ui.DatePicker.prototype.previousYear = function() {
- this.activeMonth_.add(new goog.date.Interval(goog.date.Interval.YEARS, -1));
- this.updateCalendarGrid_();
- this.fireChangeActiveMonthEvent_();
- };
- /**
- * Changes the active year to the next one.
- */
- goog.ui.DatePicker.prototype.nextYear = function() {
- this.activeMonth_.add(new goog.date.Interval(goog.date.Interval.YEARS, 1));
- this.updateCalendarGrid_();
- this.fireChangeActiveMonthEvent_();
- };
- /**
- * Selects the current date.
- */
- goog.ui.DatePicker.prototype.selectToday = function() {
- this.setDate(new goog.date.Date());
- };
- /**
- * Clears the selection.
- */
- goog.ui.DatePicker.prototype.selectNone = function() {
- if (this.allowNone_) {
- this.setDate(null);
- }
- };
- /**
- * @return {!goog.date.Date} The active month displayed.
- */
- goog.ui.DatePicker.prototype.getActiveMonth = function() {
- return this.activeMonth_.clone();
- };
- /**
- * @return {goog.date.Date} The selected date or null if nothing is selected.
- */
- goog.ui.DatePicker.prototype.getDate = function() {
- return this.date_ && this.date_.clone();
- };
- /**
- * @param {number} row The row in the grid.
- * @param {number} col The column in the grid.
- * @return {goog.date.Date} The date in the grid or null if there is none.
- */
- goog.ui.DatePicker.prototype.getDateAt = function(row, col) {
- return this.grid_[row] ?
- this.grid_[row][col] ? this.grid_[row][col].clone() : null :
- null;
- };
- /**
- * Returns a date element given a row and column. In elTable_, the elements that
- * represent dates are 1 indexed because of other elements such as headers.
- * This corrects for the offset and makes the API 0 indexed.
- *
- * @param {number} row The row in the element table.
- * @param {number} col The column in the element table.
- * @return {Element} The element in the grid or null if there is none.
- * @protected
- */
- goog.ui.DatePicker.prototype.getDateElementAt = function(row, col) {
- if (row < 0 || col < 0) {
- return null;
- }
- var adjustedRow = row + 1;
- return this.elTable_[adjustedRow] ?
- this.elTable_[adjustedRow][col + 1] || null :
- null;
- };
- /**
- * Sets the selected date. Will always fire the SELECT event.
- *
- * @param {goog.date.Date|Date} date Date to select or null to select nothing.
- */
- goog.ui.DatePicker.prototype.setDate = function(date) {
- this.setDate_(date, true);
- };
- /**
- * Sets the selected date, and optionally fires the SELECT event based on param.
- *
- * @param {goog.date.Date|Date} date Date to select or null to select nothing.
- * @param {boolean} fireSelection Whether to fire the selection event.
- * @private
- */
- goog.ui.DatePicker.prototype.setDate_ = function(date, fireSelection) {
- // Check if the month has been changed.
- var sameMonth = date == this.date_ ||
- date && this.date_ && date.getFullYear() == this.date_.getFullYear() &&
- date.getMonth() == this.date_.getMonth();
- // Check if the date has been changed.
- var sameDate =
- date == this.date_ || sameMonth && date.getDate() == this.date_.getDate();
- // Set current date to clone of supplied goog.date.Date or Date.
- this.date_ = date && new goog.date.Date(date);
- // Set current month
- if (date) {
- this.activeMonth_.set(this.date_);
- // Set years with two digits to their full year, not 19XX.
- this.activeMonth_.setFullYear(this.date_.getFullYear());
- this.activeMonth_.setDate(1);
- }
- // Update calendar grid even if the date has not changed as even if today is
- // selected another month can be displayed.
- this.updateCalendarGrid_();
- if (fireSelection) {
- // TODO(eae): Standardize selection and change events with other components.
- // Fire select event.
- var selectEvent = new goog.ui.DatePickerEvent(
- goog.ui.DatePicker.Events.SELECT, this, this.date_);
- this.dispatchEvent(selectEvent);
- }
- // Fire change event.
- if (!sameDate) {
- var changeEvent = new goog.ui.DatePickerEvent(
- goog.ui.DatePicker.Events.CHANGE, this, this.date_);
- this.dispatchEvent(changeEvent);
- }
- // Fire change active month event.
- if (!sameMonth) {
- this.fireChangeActiveMonthEvent_();
- }
- };
- /**
- * Updates the navigation row (navigating months and maybe years) in the navRow_
- * element of a created picker.
- * @private
- */
- goog.ui.DatePicker.prototype.updateNavigationRow_ = function() {
- if (!this.elNavRow_) {
- return;
- }
- var row = this.elNavRow_;
- // Clear the navigation row.
- while (row.firstChild) {
- row.removeChild(row.firstChild);
- }
- var fullDateFormat =
- this.symbols_.DATEFORMATS[goog.i18n.DateTimeFormat.Format.FULL_DATE]
- .toLowerCase();
- this.renderer_.renderNavigationRow(
- row, this.simpleNavigation_, this.showWeekNum_, fullDateFormat);
- if (this.simpleNavigation_) {
- this.addPreventDefaultClickHandler_(
- row, goog.getCssName(this.getBaseCssClass(), 'previousMonth'),
- this.previousMonth);
- var previousMonthElement = goog.dom.getElementByClass(
- goog.getCssName(this.getBaseCssClass(), 'previousMonth'), row);
- if (previousMonthElement) {
- // Note: we're hiding the next and previous month buttons from screen
- // readers because keyboard navigation doesn't currently work correctly
- // with them. If that is fixed, we can show the buttons again.
- goog.a11y.aria.setState(
- previousMonthElement, goog.a11y.aria.State.HIDDEN, true);
- previousMonthElement.tabIndex = -1;
- }
- this.addPreventDefaultClickHandler_(
- row, goog.getCssName(this.getBaseCssClass(), 'nextMonth'),
- this.nextMonth);
- var nextMonthElement = goog.dom.getElementByClass(
- goog.getCssName(this.getBaseCssClass(), 'nextMonth'), row);
- if (nextMonthElement) {
- goog.a11y.aria.setState(
- nextMonthElement, goog.a11y.aria.State.HIDDEN, true);
- nextMonthElement.tabIndex = -1;
- }
- this.elMonthYear_ = goog.dom.getElementByClass(
- goog.getCssName(this.getBaseCssClass(), 'monthyear'), row);
- } else {
- this.addPreventDefaultClickHandler_(
- row, goog.getCssName(this.getBaseCssClass(), 'previousMonth'),
- this.previousMonth);
- this.addPreventDefaultClickHandler_(
- row, goog.getCssName(this.getBaseCssClass(), 'nextMonth'),
- this.nextMonth);
- this.addPreventDefaultClickHandler_(
- row, goog.getCssName(this.getBaseCssClass(), 'month'),
- this.showMonthMenu_);
- this.addPreventDefaultClickHandler_(
- row, goog.getCssName(this.getBaseCssClass(), 'previousYear'),
- this.previousYear);
- this.addPreventDefaultClickHandler_(
- row, goog.getCssName(this.getBaseCssClass(), 'nextYear'),
- this.nextYear);
- this.addPreventDefaultClickHandler_(
- row, goog.getCssName(this.getBaseCssClass(), 'year'),
- this.showYearMenu_);
- this.elMonth_ = goog.dom.getElementByClass(
- goog.getCssName(this.getBaseCssClass(), 'month'), row);
- this.elYear_ = goog.dom.getDomHelper().getElementByClass(
- goog.getCssName(this.getBaseCssClass(), 'year'), row);
- }
- };
- /**
- * Setup click handler with prevent default.
- *
- * @param {!Element} parentElement The parent element of the element. This is
- * needed because the element in question might not be in the dom yet.
- * @param {string} cssName The CSS class name of the element to attach a click
- * handler.
- * @param {Function} handlerFunction The click handler function.
- * @private
- */
- goog.ui.DatePicker.prototype.addPreventDefaultClickHandler_ = function(
- parentElement, cssName, handlerFunction) {
- var element = goog.dom.getElementByClass(cssName, parentElement);
- this.getHandler().listen(element, goog.events.EventType.CLICK, function(e) {
- e.preventDefault();
- handlerFunction.call(this, e);
- });
- };
- /**
- * Updates the footer row (with select buttons) in the footRow_ element of a
- * created picker.
- * @private
- */
- goog.ui.DatePicker.prototype.updateFooterRow_ = function() {
- if (!this.elFootRow_) {
- return;
- }
- var row = this.elFootRow_;
- // Clear the footer row.
- goog.dom.removeChildren(row);
- this.renderer_.renderFooterRow(row, this.showWeekNum_);
- this.addPreventDefaultClickHandler_(
- row, goog.getCssName(this.getBaseCssClass(), 'today-btn'),
- this.selectToday);
- this.addPreventDefaultClickHandler_(
- row, goog.getCssName(this.getBaseCssClass(), 'none-btn'),
- this.selectNone);
- this.elToday_ = goog.dom.getElementByClass(
- goog.getCssName(this.getBaseCssClass(), 'today-btn'), row);
- this.elNone_ = goog.dom.getElementByClass(
- goog.getCssName(this.getBaseCssClass(), 'none-btn'), row);
- this.updateTodayAndNone_();
- };
- /** @override */
- goog.ui.DatePicker.prototype.decorateInternal = function(el) {
- goog.ui.DatePicker.superClass_.decorateInternal.call(this, el);
- goog.asserts.assert(el);
- goog.dom.classlist.add(el, this.getBaseCssClass());
- var table = this.dom_.createElement(goog.dom.TagName.TABLE);
- var thead = this.dom_.createElement(goog.dom.TagName.THEAD);
- var tbody = this.dom_.createElement(goog.dom.TagName.TBODY);
- var tfoot = this.dom_.createElement(goog.dom.TagName.TFOOT);
- goog.a11y.aria.setRole(tbody, 'grid');
- tbody.tabIndex = 0;
- // As per comment in colorpicker: table.tBodies and table.tFoot should not be
- // used because of a bug in Safari, hence using an instance variable
- this.tableBody_ = tbody;
- this.tableFoot_ = tfoot;
- var row = this.dom_.createElement(goog.dom.TagName.TR);
- row.className = goog.getCssName(this.getBaseCssClass(), 'head');
- this.elNavRow_ = row;
- this.updateNavigationRow_();
- thead.appendChild(row);
- var cell;
- this.elTable_ = [];
- for (var i = 0; i < 7; i++) {
- row = this.dom_.createElement(goog.dom.TagName.TR);
- this.elTable_[i] = [];
- for (var j = 0; j < 8; j++) {
- cell = this.dom_.createElement(j == 0 || i == 0 ? 'th' : 'td');
- if ((j == 0 || i == 0) && j != i) {
- cell.className = (j == 0) ?
- goog.getCssName(this.getBaseCssClass(), 'week') :
- goog.getCssName(this.getBaseCssClass(), 'wday');
- goog.a11y.aria.setRole(cell, j == 0 ? 'rowheader' : 'columnheader');
- }
- row.appendChild(cell);
- this.elTable_[i][j] = cell;
- }
- tbody.appendChild(row);
- }
- row = this.dom_.createElement(goog.dom.TagName.TR);
- row.className = goog.getCssName(this.getBaseCssClass(), 'foot');
- this.elFootRow_ = row;
- this.updateFooterRow_();
- tfoot.appendChild(row);
- table.cellSpacing = '0';
- table.cellPadding = '0';
- table.appendChild(thead);
- table.appendChild(tbody);
- table.appendChild(tfoot);
- el.appendChild(table);
- this.redrawWeekdays_();
- this.updateCalendarGrid_();
- el.tabIndex = 0;
- };
- /** @override */
- goog.ui.DatePicker.prototype.createDom = function() {
- goog.ui.DatePicker.superClass_.createDom.call(this);
- this.decorateInternal(this.getElement());
- };
- /** @override */
- goog.ui.DatePicker.prototype.enterDocument = function() {
- goog.ui.DatePicker.superClass_.enterDocument.call(this);
- var eh = this.getHandler();
- eh.listen(
- this.tableBody_, goog.events.EventType.CLICK, this.handleGridClick_);
- eh.listen(
- this.getKeyHandlerForElement_(this.getElement()),
- goog.events.KeyHandler.EventType.KEY, this.handleGridKeyPress_);
- };
- /** @override */
- goog.ui.DatePicker.prototype.exitDocument = function() {
- goog.ui.DatePicker.superClass_.exitDocument.call(this);
- this.destroyMenu_();
- for (var uid in this.keyHandlers_) {
- this.keyHandlers_[uid].dispose();
- }
- this.keyHandlers_ = {};
- };
- /**
- * @deprecated Use decorate instead.
- */
- goog.ui.DatePicker.prototype.create = goog.ui.DatePicker.prototype.decorate;
- /** @override */
- goog.ui.DatePicker.prototype.disposeInternal = function() {
- goog.ui.DatePicker.superClass_.disposeInternal.call(this);
- this.elTable_ = null;
- this.tableBody_ = null;
- this.tableFoot_ = null;
- this.elNavRow_ = null;
- this.elFootRow_ = null;
- this.elMonth_ = null;
- this.elMonthYear_ = null;
- this.elYear_ = null;
- this.elToday_ = null;
- this.elNone_ = null;
- };
- /**
- * Click handler for date grid.
- *
- * @param {goog.events.BrowserEvent} event Click event.
- * @private
- */
- goog.ui.DatePicker.prototype.handleGridClick_ = function(event) {
- if (event.target.tagName == goog.dom.TagName.TD) {
- // colIndex/rowIndex is broken in Safari, find position by looping
- var el, x = -2, y = -2; // first col/row is for weekday/weeknum
- for (el = event.target; el; el = el.previousSibling, x++) {
- }
- for (el = event.target.parentNode; el; el = el.previousSibling, y++) {
- }
- var obj = this.grid_[y][x];
- if (this.isUserSelectableDate_(obj)) {
- this.setDate(obj.clone());
- }
- }
- };
- /**
- * Keypress handler for date grid.
- *
- * @param {goog.events.BrowserEvent} event Keypress event.
- * @private
- */
- goog.ui.DatePicker.prototype.handleGridKeyPress_ = function(event) {
- var months, days;
- switch (event.keyCode) {
- case 33: // Page up
- event.preventDefault();
- months = -1;
- break;
- case 34: // Page down
- event.preventDefault();
- months = 1;
- break;
- case 37: // Left
- event.preventDefault();
- days = -1;
- break;
- case 39: // Right
- event.preventDefault();
- days = 1;
- break;
- case 38: // Down
- event.preventDefault();
- days = -7;
- break;
- case 40: // Up
- event.preventDefault();
- days = 7;
- break;
- case 36: // Home
- event.preventDefault();
- this.selectToday();
- case 46: // Delete
- event.preventDefault();
- this.selectNone();
- break;
- case 13: // Enter
- case 32: // Space
- event.preventDefault();
- this.setDate_(this.date_, true /* fireSelection */);
- default:
- return;
- }
- var date;
- if (this.date_) {
- date = this.date_.clone();
- date.add(new goog.date.Interval(0, months, days));
- } else {
- date = this.activeMonth_.clone();
- date.setDate(1);
- }
- if (this.isUserSelectableDate_(date)) {
- this.setDate_(date, false /* fireSelection */);
- }
- };
- /**
- * Click handler for month button. Opens month selection menu.
- *
- * @param {goog.events.BrowserEvent} event Click event.
- * @private
- */
- goog.ui.DatePicker.prototype.showMonthMenu_ = function(event) {
- event.stopPropagation();
- var list = [];
- for (var i = 0; i < 12; i++) {
- list.push(this.symbols_.STANDALONEMONTHS[i]);
- }
- this.createMenu_(
- this.elMonth_, list, this.handleMonthMenuClick_,
- this.symbols_.STANDALONEMONTHS[this.activeMonth_.getMonth()]);
- };
- /**
- * Click handler for year button. Opens year selection menu.
- *
- * @param {goog.events.BrowserEvent} event Click event.
- * @private
- */
- goog.ui.DatePicker.prototype.showYearMenu_ = function(event) {
- event.stopPropagation();
- var list = [];
- var year = this.activeMonth_.getFullYear();
- var loopDate = this.activeMonth_.clone();
- for (var i = -goog.ui.DatePicker.YEAR_MENU_RANGE_;
- i <= goog.ui.DatePicker.YEAR_MENU_RANGE_; i++) {
- loopDate.setFullYear(year + i);
- list.push(this.i18nDateFormatterYear_.format(loopDate));
- }
- this.createMenu_(
- this.elYear_, list, this.handleYearMenuClick_,
- this.i18nDateFormatterYear_.format(this.activeMonth_));
- };
- /**
- * Call back function for month menu.
- *
- * @param {Element} target Selected item.
- * @private
- */
- goog.ui.DatePicker.prototype.handleMonthMenuClick_ = function(target) {
- var itemIndex = Number(target.getAttribute('itemIndex'));
- this.activeMonth_.setMonth(itemIndex);
- this.updateCalendarGrid_();
- if (this.elMonth_.focus) {
- this.elMonth_.focus();
- }
- };
- /**
- * Call back function for year menu.
- *
- * @param {Element} target Selected item.
- * @private
- */
- goog.ui.DatePicker.prototype.handleYearMenuClick_ = function(target) {
- if (target.firstChild.nodeType == goog.dom.NodeType.TEXT) {
- // We use the same technique used for months to get the position of the
- // item in the menu, as the year is not necessarily numeric.
- var itemIndex = Number(target.getAttribute('itemIndex'));
- var year = this.activeMonth_.getFullYear();
- this.activeMonth_.setFullYear(
- year + itemIndex - goog.ui.DatePicker.YEAR_MENU_RANGE_);
- this.updateCalendarGrid_();
- }
- this.elYear_.focus();
- };
- /**
- * Support function for menu creation.
- *
- * @param {Element} srcEl Button to create menu for.
- * @param {Array<string>} items List of items to populate menu with.
- * @param {function(Element)} method Call back method.
- * @param {string} selected Item to mark as selected in menu.
- * @private
- */
- goog.ui.DatePicker.prototype.createMenu_ = function(
- srcEl, items, method, selected) {
- this.destroyMenu_();
- var el = this.dom_.createElement(goog.dom.TagName.DIV);
- el.className = goog.getCssName(this.getBaseCssClass(), 'menu');
- this.menuSelected_ = null;
- var ul = this.dom_.createElement(goog.dom.TagName.UL);
- for (var i = 0; i < items.length; i++) {
- var li = this.dom_.createDom(goog.dom.TagName.LI, null, items[i]);
- li.setAttribute('itemIndex', i);
- if (items[i] == selected) {
- this.menuSelected_ = li;
- }
- ul.appendChild(li);
- }
- el.appendChild(ul);
- srcEl = /** @type {!HTMLElement} */ (srcEl);
- el.style.left = srcEl.offsetLeft + srcEl.parentNode.offsetLeft + 'px';
- el.style.top = srcEl.offsetTop + 'px';
- el.style.width = srcEl.clientWidth + 'px';
- this.elMonth_.parentNode.appendChild(el);
- this.menu_ = el;
- if (!this.menuSelected_) {
- this.menuSelected_ = /** @type {Element} */ (ul.firstChild);
- }
- this.menuSelected_.className =
- goog.getCssName(this.getBaseCssClass(), 'menu-selected');
- this.menuCallback_ = method;
- var eh = this.getHandler();
- eh.listen(this.menu_, goog.events.EventType.CLICK, this.handleMenuClick_);
- eh.listen(
- this.getKeyHandlerForElement_(this.menu_),
- goog.events.KeyHandler.EventType.KEY, this.handleMenuKeyPress_);
- eh.listen(
- this.dom_.getDocument(), goog.events.EventType.CLICK, this.destroyMenu_);
- el.tabIndex = 0;
- el.focus();
- };
- /**
- * Click handler for menu.
- *
- * @param {goog.events.BrowserEvent} event Click event.
- * @private
- */
- goog.ui.DatePicker.prototype.handleMenuClick_ = function(event) {
- event.stopPropagation();
- this.destroyMenu_();
- if (this.menuCallback_) {
- this.menuCallback_(/** @type {Element} */ (event.target));
- }
- };
- /**
- * Keypress handler for menu.
- *
- * @param {goog.events.BrowserEvent} event Keypress event.
- * @private
- */
- goog.ui.DatePicker.prototype.handleMenuKeyPress_ = function(event) {
- // Prevent the grid keypress handler from catching the keypress event.
- event.stopPropagation();
- var el;
- var menuSelected = this.menuSelected_;
- switch (event.keyCode) {
- case 35: // End
- event.preventDefault();
- el = menuSelected.parentNode.lastChild;
- break;
- case 36: // Home
- event.preventDefault();
- el = menuSelected.parentNode.firstChild;
- break;
- case 38: // Up
- event.preventDefault();
- el = menuSelected.previousSibling;
- break;
- case 40: // Down
- event.preventDefault();
- el = menuSelected.nextSibling;
- break;
- case 13: // Enter
- case 9: // Tab
- case 0: // Space
- event.preventDefault();
- this.destroyMenu_();
- this.menuCallback_(menuSelected);
- break;
- }
- if (el && el != menuSelected) {
- menuSelected.className = '';
- el.className = goog.getCssName(this.getBaseCssClass(), 'menu-selected');
- this.menuSelected_ = /** @type {!Element} */ (el);
- }
- };
- /**
- * Support function for menu destruction.
- * @private
- */
- goog.ui.DatePicker.prototype.destroyMenu_ = function() {
- if (this.menu_) {
- var eh = this.getHandler();
- eh.unlisten(this.menu_, goog.events.EventType.CLICK, this.handleMenuClick_);
- eh.unlisten(
- this.getKeyHandlerForElement_(this.menu_),
- goog.events.KeyHandler.EventType.KEY, this.handleMenuKeyPress_);
- eh.unlisten(
- this.dom_.getDocument(), goog.events.EventType.CLICK,
- this.destroyMenu_);
- goog.dom.removeNode(this.menu_);
- delete this.menu_;
- }
- };
- /**
- * Determines the dates/weekdays for the current month and builds an in memory
- * representation of the calendar.
- *
- * @private
- */
- goog.ui.DatePicker.prototype.updateCalendarGrid_ = function() {
- if (!this.getElement()) {
- return;
- }
- var date = this.activeMonth_.clone();
- date.setDate(1);
- // Show year name of select month
- if (this.elMonthYear_) {
- goog.dom.setTextContent(
- this.elMonthYear_, this.i18nDateFormatterMonthYear_.format(date));
- }
- if (this.elMonth_) {
- goog.dom.setTextContent(
- this.elMonth_, this.symbols_.STANDALONEMONTHS[date.getMonth()]);
- }
- if (this.elYear_) {
- goog.dom.setTextContent(
- this.elYear_, this.i18nDateFormatterYear_.format(date));
- }
- var wday = date.getWeekday();
- var days = date.getNumberOfDaysInMonth();
- // Determine how many days to show for previous month
- date.add(new goog.date.Interval(goog.date.Interval.MONTHS, -1));
- date.setDate(date.getNumberOfDaysInMonth() - (wday - 1));
- if (this.showFixedNumWeeks_ && !this.extraWeekAtEnd_ && days + wday < 33) {
- date.add(new goog.date.Interval(goog.date.Interval.DAYS, -7));
- }
- // Create weekday/day grid
- var dayInterval = new goog.date.Interval(goog.date.Interval.DAYS, 1);
- this.grid_ = [];
- for (var y = 0; y < 6; y++) { // Weeks
- this.grid_[y] = [];
- for (var x = 0; x < 7; x++) { // Weekdays
- this.grid_[y][x] = date.clone();
- // Date.add breaks dates before year 100 by adding 1900 to the year
- // value. As a workaround we store the year before the add and reapply it
- // after (with special handling for January 1st).
- var year = date.getFullYear();
- date.add(dayInterval);
- if (date.getMonth() == 0 && date.getDate() == 1) {
- // Increase year on January 1st.
- year++;
- }
- date.setFullYear(year);
- }
- }
- this.redrawCalendarGrid_();
- };
- /**
- * Draws calendar view from in memory representation and applies class names
- * depending on the selection, weekday and whatever the day belongs to the
- * active month or not.
- * @private
- */
- goog.ui.DatePicker.prototype.redrawCalendarGrid_ = function() {
- if (!this.getElement()) {
- return;
- }
- var month = this.activeMonth_.getMonth();
- var today = new goog.date.Date();
- var todayYear = today.getFullYear();
- var todayMonth = today.getMonth();
- var todayDate = today.getDate();
- // Draw calendar week by week, a worst case month has six weeks.
- for (var y = 0; y < 6; y++) {
- // Draw week number, if enabled
- if (this.showWeekNum_) {
- goog.dom.setTextContent(
- this.elTable_[y + 1][0],
- this.i18nDateFormatterWeek_.format(this.grid_[y][0]));
- goog.dom.classlist.set(
- this.elTable_[y + 1][0],
- goog.getCssName(this.getBaseCssClass(), 'week'));
- } else {
- goog.dom.setTextContent(this.elTable_[y + 1][0], '');
- goog.dom.classlist.set(this.elTable_[y + 1][0], '');
- }
- for (var x = 0; x < 7; x++) {
- var o = this.grid_[y][x];
- var el = this.elTable_[y + 1][x + 1];
- // Assign a unique element id (required for setting the active descendant
- // ARIA role) unless already set.
- if (!el.id) {
- el.id = this.cellIdGenerator_.getNextUniqueId();
- }
- goog.asserts.assert(el, 'The table DOM element cannot be null.');
- goog.a11y.aria.setRole(el, 'gridcell');
- // Set the aria label of the grid cell to the month plus the day.
- goog.a11y.aria.setLabel(
- el, this.i18nDateFormatterDayAriaLabel_.format(o));
- var classes = [goog.getCssName(this.getBaseCssClass(), 'date')];
- if (!this.isUserSelectableDate_(o)) {
- classes.push(
- goog.getCssName(this.getBaseCssClass(), 'unavailable-date'));
- }
- if (this.showOtherMonths_ || o.getMonth() == month) {
- // Date belongs to previous or next month
- if (o.getMonth() != month) {
- classes.push(goog.getCssName(this.getBaseCssClass(), 'other-month'));
- }
- // Apply styles set by setWeekdayClass
- var wday = (x + this.activeMonth_.getFirstDayOfWeek() + 7) % 7;
- if (this.wdayStyles_[wday]) {
- classes.push(this.wdayStyles_[wday]);
- }
- // Current date
- if (o.getDate() == todayDate && o.getMonth() == todayMonth &&
- o.getFullYear() == todayYear) {
- classes.push(goog.getCssName(this.getBaseCssClass(), 'today'));
- }
- // Selected date
- if (this.date_ && o.getDate() == this.date_.getDate() &&
- o.getMonth() == this.date_.getMonth() &&
- o.getFullYear() == this.date_.getFullYear()) {
- classes.push(goog.getCssName(this.getBaseCssClass(), 'selected'));
- goog.asserts.assert(
- this.tableBody_, 'The table body DOM element cannot be null');
- goog.a11y.aria.setState(this.tableBody_, 'activedescendant', el.id);
- }
- // Custom decorator
- if (this.decoratorFunction_) {
- var customClass = this.decoratorFunction_(o);
- if (customClass) {
- classes.push(customClass);
- }
- }
- // Set cell text to the date and apply classes.
- var formatedDate = this.longDateFormat_ ?
- this.i18nDateFormatterDay2_.format(o) :
- this.i18nDateFormatterDay_.format(o);
- goog.dom.setTextContent(el, formatedDate);
- // Date belongs to previous or next month and showOtherMonths is false,
- // clear text and classes.
- } else {
- goog.dom.setTextContent(el, '');
- }
- goog.dom.classlist.set(el, classes.join(' '));
- }
- // Hide the either the last one or last two weeks if they contain no days
- // from the active month and the showFixedNumWeeks is false. The first four
- // weeks are always shown as no month has less than 28 days).
- if (y >= 4) {
- var parentEl = /** @type {Element} */ (
- this.elTable_[y + 1][0].parentElement ||
- this.elTable_[y + 1][0].parentNode);
- goog.style.setElementShown(
- parentEl,
- this.grid_[y][0].getMonth() == month || this.showFixedNumWeeks_);
- }
- }
- };
- /**
- * Fires the CHANGE_ACTIVE_MONTH event.
- * @private
- */
- goog.ui.DatePicker.prototype.fireChangeActiveMonthEvent_ = function() {
- var changeMonthEvent = new goog.ui.DatePickerEvent(
- goog.ui.DatePicker.Events.CHANGE_ACTIVE_MONTH, this,
- this.getActiveMonth());
- this.dispatchEvent(changeMonthEvent);
- };
- /**
- * Draw weekday names, if enabled. Start with whatever day has been set as the
- * first day of week.
- * @private
- */
- goog.ui.DatePicker.prototype.redrawWeekdays_ = function() {
- if (!this.getElement()) {
- return;
- }
- if (this.showWeekdays_) {
- for (var x = 0; x < 7; x++) {
- var el = this.elTable_[0][x + 1];
- var wday = (x + this.activeMonth_.getFirstDayOfWeek() + 7) % 7;
- goog.dom.setTextContent(el, this.wdayNames_[(wday + 1) % 7]);
- }
- }
- var parentEl = /** @type {Element} */ (
- this.elTable_[0][0].parentElement || this.elTable_[0][0].parentNode);
- goog.style.setElementShown(parentEl, this.showWeekdays_);
- };
- /**
- * Returns the key handler for an element and caches it so that it can be
- * retrieved at a later point.
- * @param {Element} el The element to get the key handler for.
- * @return {goog.events.KeyHandler} The key handler for the element.
- * @private
- */
- goog.ui.DatePicker.prototype.getKeyHandlerForElement_ = function(el) {
- var uid = goog.getUid(el);
- if (!(uid in this.keyHandlers_)) {
- this.keyHandlers_[uid] = new goog.events.KeyHandler(el);
- }
- return this.keyHandlers_[uid];
- };
- /**
- * Object representing a date picker event.
- *
- * @param {string} type Event type.
- * @param {goog.ui.DatePicker} target Date picker initiating event.
- * @param {goog.date.Date} date Selected date.
- * @constructor
- * @extends {goog.events.Event}
- * @final
- */
- goog.ui.DatePickerEvent = function(type, target, date) {
- goog.events.Event.call(this, type, target);
- /**
- * The selected date
- * @type {goog.date.Date}
- */
- this.date = date;
- };
- goog.inherits(goog.ui.DatePickerEvent, goog.events.Event);
|