123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- // 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.dom.InputType');
- goog.require('goog.dom.TagName');
- goog.require('goog.i18n.DateTimeParse');
- goog.require('goog.string');
- goog.require('goog.ui.Component');
- goog.require('goog.ui.DatePicker');
- /** @suppress {extraRequire} */
- goog.require('goog.ui.LabelInput');
- goog.require('goog.ui.PopupBase');
- 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);
- goog.tagUnsealableClass(goog.ui.InputDatePicker);
- /**
- * 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 PopupDatePicker instance.
- *
- * @return {goog.ui.PopupDatePicker} Popup instance.
- */
- goog.ui.InputDatePicker.prototype.getPopupDatePicker = function() {
- return this.popupDatePicker_;
- };
- /**
- * 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.DateTime} 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_) {
- var labelInput = /** @type {goog.ui.LabelInput} */ (el.labelInput_);
- 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_) {
- var labelInput = /** @type {goog.ui.LabelInput} */ (el.labelInput_);
- return labelInput.getValue();
- } else {
- return el.value;
- }
- };
- /**
- * Sets the value of the input element from date object.
- *
- * @param {?goog.date.Date} date The value to set.
- * @private
- */
- goog.ui.InputDatePicker.prototype.setInputValueAsDate_ = function(date) {
- this.setInputValue(date ? this.dateTimeFormatter_.format(date) : '');
- };
- /**
- * Gets the input element value and attempts to parse it as a date.
- *
- * @return {goog.date.DateTime} 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) {
- // Parser with YYYY format string will interpret 1 as year 1 A.D.
- // However, datepicker.setDate() method will change it into 1901.
- // Same is true for any other pattern when number entered by user is
- // different from number of digits in the pattern. (YY and 1 will be 1AD).
- // See i18n/datetimeparse.js
- // Conversion happens in goog.date.Date/DateTime constructor
- // when it calls new Date(year...). See ui/datepicker.js.
- return date;
- }
- }
- return null;
- };
- /**
- * Creates an input element for use with the popup date picker.
- * @override
- */
- goog.ui.InputDatePicker.prototype.createDom = function() {
- this.setElementInternal(
- this.getDomHelper().createDom(
- goog.dom.TagName.INPUT, {'type': goog.dom.InputType.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;
- };
- /** @override */
- goog.ui.InputDatePicker.prototype.enterDocument = function() {
- // this.popupDatePicker_ has been added as a child even though it isn't really
- // a child (since its root element is not within InputDatePicker's DOM tree).
- // The PopupDatePicker will have its enterDocument method called as a result
- // of calling the superClass's enterDocument method. The PopupDatePicker needs
- // to be attached to the document *before* calling enterDocument so that when
- // PopupDatePicker decorates its element as a DatePicker, the element will be
- // in the document and enterDocument will be called for the DatePicker. Having
- // the PopupDatePicker's element in the document before calling enterDocument
- // will ensure that the event handlers for DatePicker are attached.
- //
- // An alternative could be to stop adding popupDatePicker_ as a child and
- // instead keep a reference to it and sync some event handlers, etc. but
- // appending the element to the document before calling enterDocument is a
- // less intrusive option.
- //
- // See cl/100837907 for more context and the discussion around this decision.
- (this.popupParentElement_ || this.getDomHelper().getDocument().body)
- .appendChild(this.popupDatePicker_.getElement());
- goog.ui.InputDatePicker.superClass_.enterDocument.call(this);
- var el = this.getElement();
- 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_);
- };
- /** @override */
- 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) {
- var inputValueAsDate = this.getInputValueAsDate_();
- this.setDate(inputValueAsDate);
- // don't overwrite the input value with empty date if input is not valid
- if (inputValueAsDate) {
- this.setInputValueAsDate_(this.getDatePicker().getDate());
- }
- };
- /**
- * 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.setInputValueAsDate_(e.date);
- };
|