/*! * UI development toolkit for HTML5 (OpenUI5) * (c) Copyright 2009-2018 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ // Provides control sap.m.DateTimeField. sap.ui.define([ 'sap/ui/model/type/Date', 'sap/ui/model/odata/type/ODataType', './InputBase', 'sap/ui/core/LocaleData', 'sap/ui/core/library', 'sap/ui/core/format/DateFormat', './DateTimeFieldRenderer', "sap/base/util/deepEqual", "sap/base/Log", "sap/ui/thirdparty/jquery", // jQuery Plugin "cursorPos" "sap/ui/dom/jquery/cursorPos" ], function( SimpleDateType, ODataType, InputBase, LocaleData, coreLibrary, DateFormat, DateTimeFieldRenderer, deepEqual, Log, jQuery ) { "use strict"; // shortcut for sap.ui.core.CalendarType var CalendarType = coreLibrary.CalendarType; /** * Constructor for a new sap.m.DateTimeField. * * @param {string} [sId] ID for the new control, generated automatically if no ID is given * @param {object} [mSettings] Initial settings for the new control * * @class * The sap.m.DateTimeField control provides a basic functionality for date/time input controls. * * To be extended by date and time picker controls. For internal use only. * @abstract * * @extends sap.m.InputBase * * @author SAP SE * @version 1.60.23 * * @constructor * @public * @since 1.50.0 * @alias sap.m.DateTimeField * @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel */ var DateTimeField = InputBase.extend("sap.m.DateTimeField", /** @lends sap.m.DateTimeField.prototype */ { metadata: { "abstract" : true, library: "sap.m", properties: { /** * Determines the format, displayed in the input field. */ displayFormat: {type: "string", group: "Appearance", defaultValue: null}, /** * Determines the format of the value property. */ valueFormat: {type: "string", group: "Data", defaultValue: null}, /** * Holds a reference to a JavaScript Date Object. The value (string) * property will be set according to it. Alternatively, if the value * and valueFormat pair properties are supplied instead, * the dateValue will be instantiated according to the parsed * value. * Use dateValue as a helper property to easily obtain the day, month, year, hours, minutes * and seconds of the chosen date and time. Although possible to bind it, the recommendation is not to do it. * When binding is needed, use value property instead. */ dateValue: {type: "object", group: "Data", defaultValue: null}, /** * Holds a reference to a JavaScript Date Object to define the initially focused * date/time when the picker popup is opened. * * Notes: * * @since 1.54 */ initialFocusedDateValue: {type: "object", group: "Data", defaultValue: null} } } }); DateTimeField.prototype.setValue = function (sValue) { sValue = this.validateProperty("value", sValue); // to convert null and undefined to "" var sOldValue = this.getValue(); if (sValue === sOldValue) { return this; } else { this._lastValue = sValue; } // set the property in any case but check validity on output this.setProperty("value", sValue); this._bValid = true; // convert to date object var oDate; if (sValue) { oDate = this._parseValue(sValue); if (!oDate || oDate.getTime() < this._oMinDate.getTime() || oDate.getTime() > this._oMaxDate.getTime()) { this._bValid = false; Log.warning("Value can not be converted to a valid date", this); } } this.setProperty("dateValue", oDate); // do not call InputBase.setValue because the displayed value and the output value might have different pattern if (this.getDomRef()) { // convert to output var sOutputValue; if (oDate) { sOutputValue = this._formatValue(oDate); } else { sOutputValue = sValue; } if (this._$input.val() !== sOutputValue) { this._$input.val(sOutputValue); this._curpos = this._$input.cursorPos(); } } return this; }; DateTimeField.prototype.setDateValue = function (oDate) { if (this._isValidDate(oDate)) { throw new Error("Date must be a JavaScript date object; " + this); } if (deepEqual(this.getDateValue(), oDate)) { return this; } oDate = this._dateValidation(oDate); // convert date object to value var sValue = this._formatValue(oDate, true); if (sValue !== this.getValue()) { this._lastValue = sValue; } // set the property in any case but check validity on output this.setProperty("value", sValue); if (this.getDomRef()) { // convert to output var sOutputValue = this._formatValue(oDate); if (this._$input.val() !== sOutputValue) { this._$input.val(sOutputValue); this._curpos = this._$input.cursorPos(); } } return this; }; DateTimeField.prototype.setValueFormat = function (sValueFormat) { // if valueFormat changes the value must be parsed again this.setProperty("valueFormat", sValueFormat, true); // no rerendering var sValue = this.getValue(); if (sValue) { this._handleDateValidation(this._parseValue(sValue)); } return this; }; DateTimeField.prototype.setDisplayFormat = function (sDisplayFormat) { this.setProperty("displayFormat", sDisplayFormat, true); // no rerendering this.updateDomValue(this._formatValue(this.getDateValue())); this._updateDomPlaceholder(this._getPlaceholder()); return this; }; DateTimeField.prototype.getDisplayFormatType = function () { return null; }; DateTimeField.prototype._dateValidation = function (oDate) { this._bValid = true; this.setProperty("dateValue", oDate); return oDate; }; DateTimeField.prototype._handleDateValidation = function (oDate) { this._bValid = true; this.setProperty("dateValue", oDate); }; DateTimeField.prototype._getPlaceholder = function() { var sPlaceholder = this.getPlaceholder(); if (!sPlaceholder) { sPlaceholder = this._getDisplayFormatPattern(); if (!sPlaceholder) { sPlaceholder = this._getDefaultDisplayStyle(); } if (this._checkStyle(sPlaceholder)) { sPlaceholder = this._getLocaleBasedPattern(sPlaceholder); } } return sPlaceholder; }; DateTimeField.prototype._getLocaleBasedPattern = function (sPlaceholder) { return LocaleData.getInstance( sap.ui.getCore().getConfiguration().getFormatSettings().getFormatLocale() ).getDatePattern(sPlaceholder); }; DateTimeField.prototype._parseValue = function (sValue, bDisplayFormat) { return this._getFormatter(bDisplayFormat).parse(sValue); }; DateTimeField.prototype._formatValue = function (oDate, bValueFormat) { if (oDate) { return this._getFormatter(!bValueFormat).format(oDate); } return ""; }; DateTimeField.prototype._getDefaultDisplayStyle = function () { return "medium"; }; DateTimeField.prototype._getDefaultValueStyle = function () { return "short"; }; DateTimeField.prototype._getFormatter = function (bDisplayFormat) { var sPattern = this._getBoundValueTypePattern(), bRelative = false, // if true strings like "Tomorrow" are parsed fine oFormat, oBinding = this.getBinding("value"), sCalendarType; if (oBinding && oBinding.oType && oBinding.oType.oOutputFormat) { bRelative = !!oBinding.oType.oOutputFormat.oFormatOptions.relative; sCalendarType = oBinding.oType.oOutputFormat.oFormatOptions.calendarType; } /* eslint-disable no-lonely-if */ if (!sPattern) { // not databinding is used -> use given format if (bDisplayFormat) { sPattern = ( this.getDisplayFormat() || this._getDefaultDisplayStyle() ); sCalendarType = this.getDisplayFormatType(); } else { sPattern = ( this.getValueFormat() || this._getDefaultValueStyle() ); sCalendarType = CalendarType.Gregorian; } } if (!sCalendarType) { sCalendarType = sap.ui.getCore().getConfiguration().getCalendarType(); } if (bDisplayFormat) { if (sPattern === this._sUsedDisplayPattern && sCalendarType === this._sUsedDisplayCalendarType) { oFormat = this._oDisplayFormat; } } else { if (sPattern === this._sUsedValuePattern && sCalendarType === this._sUsedValueCalendarType) { oFormat = this._oValueFormat; } } if (oFormat) { return oFormat; } return this._getFormatterInstance(oFormat, sPattern, bRelative, sCalendarType, bDisplayFormat); }; DateTimeField.prototype._getFormatterInstance = function (oFormat, sPattern, bRelative, sCalendarType, bDisplayFormat) { if (this._checkStyle(sPattern)) { oFormat = this._getFormatInstance({style: sPattern, strictParsing: true, relative: bRelative, calendarType: sCalendarType}, bDisplayFormat); } else { oFormat = this._getFormatInstance({pattern: sPattern, strictParsing: true, relative: bRelative, calendarType: sCalendarType}, bDisplayFormat); } if (bDisplayFormat) { this._sUsedDisplayPattern = sPattern; this._sUsedDisplayCalendarType = sCalendarType; this._oDisplayFormat = oFormat; } else { this._sUsedValuePattern = sPattern; this._sUsedValueCalendarType = sCalendarType; this._oValueFormat = oFormat; } return oFormat; }; DateTimeField.prototype._getFormatInstance = function (oArguments, bDisplayFormat) { return DateFormat.getInstance(oArguments); }; DateTimeField.prototype._checkStyle = function (sPattern) { return (sPattern === "short" || sPattern === "medium" || sPattern === "long" || sPattern === "full"); }; DateTimeField.prototype._getDisplayFormatPattern = function () { var sPattern = this._getBoundValueTypePattern(); if (sPattern) { return sPattern; } sPattern = this.getDisplayFormat(); if (this._checkStyle(sPattern)) { sPattern = this._getLocaleBasedPattern(sPattern); } return sPattern; }; DateTimeField.prototype._getBoundValueTypePattern = function () { var oBinding = this.getBinding("value"), oBindingType = oBinding && oBinding.getType && oBinding.getType(); if (oBindingType instanceof SimpleDateType) { return oBindingType.getOutputPattern(); } if (oBindingType instanceof ODataType && oBindingType.oFormat) { return oBindingType.oFormat.oFormatOptions.pattern; } return undefined; }; // Cross frame check for a date should be performed here otherwise setDateValue would fail in OPA tests // because Date object in the test is different than the Date object in the application (due to the iframe). // We can use jQuery.type or this method: // function isValidDate (date) { // return date && Object.prototype.toString.call(date) === "[object Date]" && !isNaN(date); //} DateTimeField.prototype._isValidDate = function (oDate) { return oDate && jQuery.type(oDate) !== "date"; }; /** * Updates the placeholder of the input element with a given valye * @param {string} sValue the new value * @private * @returns void */ DateTimeField.prototype._updateDomPlaceholder = function (sValue) { if (this.getDomRef()) { this._$input.attr("placeholder", sValue); } }; return DateTimeField; });