// Copyright 2007 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 Input Date Picker implementation. Pairs a * goog.ui.PopupDatePicker with an input element and handles the input from * either. * * @see ../demos/inputdatepicker.html */ goog.provide('goog.ui.InputDatePicker'); goog.require('goog.date.DateTime'); goog.require('goog.dom'); goog.require('goog.i18n.DateTimeParse'); goog.require('goog.string'); goog.require('goog.ui.Component'); goog.require('goog.ui.PopupDatePicker'); /** * Input date picker widget. * * @param {goog.i18n.DateTimeFormat} dateTimeFormatter A formatter instance * used to format the date picker's date for display in the input element. * @param {goog.i18n.DateTimeParse} dateTimeParser A parser instance used to * parse the input element's string as a date to set the picker. * @param {goog.ui.DatePicker=} opt_datePicker Optional DatePicker. This * enables the use of a custom date-picker instance. * @param {goog.dom.DomHelper=} opt_domHelper Optional DOM helper. * @extends {goog.ui.Component} * @constructor */ goog.ui.InputDatePicker = function( dateTimeFormatter, dateTimeParser, opt_datePicker, opt_domHelper) { goog.ui.Component.call(this, opt_domHelper); this.dateTimeFormatter_ = dateTimeFormatter; this.dateTimeParser_ = dateTimeParser; this.popupDatePicker_ = new goog.ui.PopupDatePicker( opt_datePicker, opt_domHelper); this.addChild(this.popupDatePicker_); this.popupDatePicker_.setAllowAutoFocus(false); }; goog.inherits(goog.ui.InputDatePicker, goog.ui.Component); /** * Used to format the date picker's date for display in the input element. * @type {goog.i18n.DateTimeFormat} * @private */ goog.ui.InputDatePicker.prototype.dateTimeFormatter_ = null; /** * Used to parse the input element's string as a date to set the picker. * @type {goog.i18n.DateTimeParse} * @private */ goog.ui.InputDatePicker.prototype.dateTimeParser_ = null; /** * The instance of goog.ui.PopupDatePicker used to pop up and select the date. * @type {goog.ui.PopupDatePicker} * @private */ goog.ui.InputDatePicker.prototype.popupDatePicker_ = null; /** * The element that the PopupDatePicker should be parented to. Defaults to the * body element of the page. * @type {Element} * @private */ goog.ui.InputDatePicker.prototype.popupParentElement_ = null; /** * Returns the PopupDatePicker's internal DatePicker instance. This can be * used to customize the date picker's styling. * * @return {goog.ui.DatePicker} The internal DatePicker instance. */ goog.ui.InputDatePicker.prototype.getDatePicker = function() { return this.popupDatePicker_.getDatePicker(); }; /** * Returns the selected date, if any. Compares the dates from the date picker * and the input field, causing them to be synced if different. * @return {goog.date.Date?} The selected date, if any. */ goog.ui.InputDatePicker.prototype.getDate = function() { // The user expectation is that the date be whatever the input shows. // This method biases towards the input value to conform to that expectation. var inputDate = this.getInputValueAsDate_(); var pickerDate = this.popupDatePicker_.getDate(); if (inputDate && pickerDate) { if (!inputDate.equals(pickerDate)) { this.popupDatePicker_.setDate(inputDate); } } else { this.popupDatePicker_.setDate(null); } return inputDate; }; /** * Sets the selected date. See goog.ui.PopupDatePicker.setDate(). * @param {goog.date.Date?} date The date to set. */ goog.ui.InputDatePicker.prototype.setDate = function(date) { this.popupDatePicker_.setDate(date); }; /** * Sets the value of the input element. This can be overridden to support * alternative types of input setting. * * @param {string} value The value to set. */ goog.ui.InputDatePicker.prototype.setInputValue = function(value) { var el = this.getElement(); if (el.labelInput_) { el.labelInput_.setValue(value); } else { el.value = value; } }; /** * Returns the value of the input element. This can be overridden to support * alternative types of input getting. * * @return {string} The input value. */ goog.ui.InputDatePicker.prototype.getInputValue = function() { var el = this.getElement(); if (el.labelInput_) { return el.labelInput_.getValue(); } else { return el.value; } }; /** * Gets the input element value and attempts to parse it as a date. * * @return {goog.date.Date?} The date object is returned if the parse * is successful, null is returned on failure. * @private */ goog.ui.InputDatePicker.prototype.getInputValueAsDate_ = function() { var value = goog.string.trim(this.getInputValue()); if (value) { var date = new goog.date.DateTime(); // DateTime needed as parse assumes it can call getHours(), getMinutes(), // etc, on the date if hours and minutes aren't defined. if (this.dateTimeParser_.strictParse(value, date) > 0) { return date; } } return null; }; /** * Creates an input element for use with the popup date picker. */ goog.ui.InputDatePicker.prototype.createDom = function() { this.setElementInternal( this.getDomHelper().createDom('input', {'type': 'text'})); this.popupDatePicker_.createDom(); }; /** * Sets the element that the PopupDatePicker should be parented to. If not set, * defaults to the body element of the page. * @param {Element} el The element that the PopupDatePicker should be parented * to. */ goog.ui.InputDatePicker.prototype.setPopupParentElement = function(el) { this.popupParentElement_ = el; }; /** * Called when the DOM for the component is for sure in the document. */ goog.ui.InputDatePicker.prototype.enterDocument = function() { goog.ui.InputDatePicker.superClass_.enterDocument.call(this); var el = this.getElement(); (this.popupParentElement_ || this.getDomHelper().getDocument().body). appendChild(this.popupDatePicker_.getElement()); this.popupDatePicker_.enterDocument(); this.popupDatePicker_.attach(el); // Set the date picker to have the input's initial value, if any. this.popupDatePicker_.setDate(this.getInputValueAsDate_()); var handler = this.getHandler(); handler.listen(this.popupDatePicker_, goog.ui.DatePicker.Events.CHANGE, this.onDateChanged_); handler.listen(this.popupDatePicker_, goog.ui.PopupBase.EventType.SHOW, this.onPopup_); }; /** * Called when the DOM for the component is removed from the document or * when the component no longer is managing the DOM. */ goog.ui.InputDatePicker.prototype.exitDocument = function() { goog.ui.InputDatePicker.superClass_.exitDocument.call(this); var el = this.getElement(); this.popupDatePicker_.detach(el); this.popupDatePicker_.exitDocument(); goog.dom.removeNode(this.popupDatePicker_.getElement()); }; /** @override */ goog.ui.InputDatePicker.prototype.decorateInternal = function(element) { goog.ui.InputDatePicker.superClass_.decorateInternal.call(this, element); this.popupDatePicker_.createDom(); }; /** @override */ goog.ui.InputDatePicker.prototype.disposeInternal = function() { goog.ui.InputDatePicker.superClass_.disposeInternal.call(this); this.popupDatePicker_.dispose(); this.popupDatePicker_ = null; this.popupParentElement_ = null; }; /** * See goog.ui.PopupDatePicker.showPopup(). * @param {Element} element Reference element for displaying the popup -- popup * will appear at the bottom-left corner of this element. */ goog.ui.InputDatePicker.prototype.showForElement = function(element) { this.popupDatePicker_.showPopup(element); }; /** * See goog.ui.PopupDatePicker.hidePopup(). */ goog.ui.InputDatePicker.prototype.hidePopup = function() { this.popupDatePicker_.hidePopup(); }; /** * Event handler for popup date picker popup events. * * @param {goog.events.Event} e popup event. * @private */ goog.ui.InputDatePicker.prototype.onPopup_ = function(e) { this.setDate(this.getInputValueAsDate_()); }; /** * Event handler for date change events. Called when the date changes. * * @param {goog.ui.DatePickerEvent} e Date change event. * @private */ goog.ui.InputDatePicker.prototype.onDateChanged_ = function(e) { this.setInputValue(e.date ? this.dateTimeFormatter_.format(e.date) : ''); };