| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642 |
- /**
- * DevExtreme (ui/date_box/ui.date_box.base.js)
- * Version: 19.1.16
- * Build date: Tue Oct 18 2022
- *
- * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
- * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
- */
- "use strict";
- var windowUtils = require("../../core/utils/window");
- var window = windowUtils.getWindow();
- var registerComponent = require("../../core/component_registrator");
- var typeUtils = require("../../core/utils/type");
- var dom = require("../../core/utils/dom");
- var each = require("../../core/utils/iterator").each;
- var compareVersions = require("../../core/utils/version").compare;
- var extend = require("../../core/utils/extend").extend;
- var support = require("../../core/utils/support");
- var devices = require("../../core/devices");
- var config = require("../../core/config");
- var dateUtils = require("../../core/utils/date");
- var uiDateUtils = require("./ui.date_utils");
- var dateSerialization = require("../../core/utils/date_serialization");
- var DropDownEditor = require("../drop_down_editor/ui.drop_down_editor");
- var dateLocalization = require("../../localization/date");
- var messageLocalization = require("../../localization/message");
- var DATEBOX_CLASS = "dx-datebox";
- var DX_AUTO_WIDTH_CLASS = "dx-auto-width";
- var DATEBOX_WRAPPER_CLASS = "dx-datebox-wrapper";
- var PICKER_TYPE = {
- calendar: "calendar",
- rollers: "rollers",
- list: "list",
- "native": "native"
- };
- var TYPE = {
- date: "date",
- datetime: "datetime",
- time: "time"
- };
- var STRATEGY_NAME = {
- calendar: "Calendar",
- dateView: "DateView",
- "native": "Native",
- calendarWithTime: "CalendarWithTime",
- list: "List"
- };
- var STRATEGY_CLASSES = {
- Calendar: require("./ui.date_box.strategy.calendar"),
- DateView: require("./ui.date_box.strategy.date_view"),
- Native: require("./ui.date_box.strategy.native"),
- CalendarWithTime: require("./ui.date_box.strategy.calendar_with_time"),
- List: require("./ui.date_box.strategy.list")
- };
- var isRealWidthSet = function($element) {
- var explicitWidth = $element[0].style.width;
- if (explicitWidth && "auto" !== explicitWidth && "inherit" !== explicitWidth) {
- return true
- }
- return false
- };
- var DateBox = DropDownEditor.inherit({
- _supportedKeys: function() {
- return extend(this.callBase(), this._strategy.supportedKeys())
- },
- _setDeprecatedOptions: function() {
- this.callBase();
- extend(this._deprecatedOptions, {
- maxZoomLevel: {
- since: "18.1",
- alias: "calendarOptions.maxZoomLevel"
- },
- minZoomLevel: {
- since: "18.1",
- alias: "calendarOptions.minZoomLevel"
- }
- })
- },
- _renderButtonContainers: function() {
- this.callBase.apply(this, arguments);
- this._strategy.customizeButtons()
- },
- _getDefaultOptions: function() {
- return extend(this.callBase(), {
- type: "date",
- showAnalogClock: true,
- value: null,
- dateSerializationFormat: void 0,
- min: void 0,
- max: void 0,
- displayFormat: null,
- interval: 30,
- disabledDates: null,
- maxZoomLevel: "month",
- minZoomLevel: "century",
- pickerType: PICKER_TYPE.calendar,
- invalidDateMessage: messageLocalization.format("dxDateBox-validation-datetime"),
- dateOutOfRangeMessage: messageLocalization.format("validation-range"),
- applyButtonText: messageLocalization.format("OK"),
- adaptivityEnabled: false,
- calendarOptions: {},
- useHiddenSubmitElement: true
- })
- },
- _defaultOptionsRules: function() {
- return this.callBase().concat([{
- device: {
- platform: "ios"
- },
- options: {
- showPopupTitle: true
- }
- }, {
- device: {
- platform: "android"
- },
- options: {
- buttonsLocation: "bottom after"
- }
- }, {
- device: function() {
- var realDevice = devices.real();
- var platform = realDevice.platform;
- return "ios" === platform || "android" === platform
- },
- options: {
- pickerType: PICKER_TYPE.native
- }
- }, {
- device: function(_device) {
- return "win" === _device.platform && _device.version && 8 === _device.version[0]
- },
- options: {
- buttonsLocation: "bottom after"
- }
- }, {
- device: function(_device2) {
- return "win" === _device2.platform && _device2.version && 10 === _device2.version[0]
- },
- options: {
- buttonsLocation: "bottom center"
- }
- }, {
- device: function(currentDevice) {
- var realDevice = devices.real();
- var platform = realDevice.platform;
- var version = realDevice.version;
- var isPhone = realDevice.phone;
- return "generic" === platform && "desktop" !== currentDevice.deviceType || "win" === platform && isPhone || "android" === platform && compareVersions(version, [4, 4]) < 0
- },
- options: {
- pickerType: PICKER_TYPE.rollers
- }
- }, {
- device: {
- platform: "generic",
- deviceType: "desktop"
- },
- options: {
- buttonsLocation: "bottom after"
- }
- }])
- },
- _initOptions: function(options) {
- this._userOptions = extend({}, options);
- this.callBase(options);
- this._updatePickerOptions()
- },
- _updatePickerOptions: function() {
- var pickerType = this.option("pickerType");
- var type = this.option("type");
- if (pickerType === PICKER_TYPE.list && (type === TYPE.datetime || type === TYPE.date)) {
- pickerType = PICKER_TYPE.calendar
- }
- if (type === TYPE.time && pickerType === PICKER_TYPE.calendar) {
- pickerType = PICKER_TYPE.list
- }
- this.option("showDropDownButton", "generic" !== devices.real().platform || pickerType !== PICKER_TYPE.native);
- this._pickerType = pickerType
- },
- _init: function() {
- this._initStrategy();
- this.option(extend({}, this._strategy.getDefaultOptions(), this._userOptions));
- delete this._userOptions;
- this._skipCustomValidation = false;
- this.callBase()
- },
- _toLowerCaseFirstLetter: function(string) {
- return string.charAt(0).toLowerCase() + string.substr(1)
- },
- _initStrategy: function() {
- var strategyName = this._getStrategyName(this._getFormatType());
- var strategy = STRATEGY_CLASSES[strategyName];
- if (!(this._strategy && this._strategy.NAME === strategyName)) {
- this._strategy = new strategy(this)
- }
- },
- _getFormatType: function() {
- var currentType = this.option("type");
- var isTime = /h|m|s/g.test(currentType);
- var isDate = /d|M|Y/g.test(currentType);
- var type = "";
- if (isDate) {
- type += TYPE.date
- }
- if (isTime) {
- type += TYPE.time
- }
- return type
- },
- _getStrategyName: function(type) {
- var pickerType = this._pickerType;
- if (pickerType === PICKER_TYPE.rollers) {
- return STRATEGY_NAME.dateView
- } else {
- if (pickerType === PICKER_TYPE.native) {
- return STRATEGY_NAME.native
- }
- }
- if (type === TYPE.date) {
- return STRATEGY_NAME.calendar
- }
- if (type === TYPE.datetime) {
- return STRATEGY_NAME.calendarWithTime
- }
- return STRATEGY_NAME.list
- },
- _initMarkup: function() {
- this.$element().addClass(DATEBOX_CLASS);
- this.callBase();
- this._refreshFormatClass();
- this._refreshPickerTypeClass();
- this._strategy.renderInputMinMax(this._input())
- },
- _render: function() {
- this.callBase();
- this._updateSize()
- },
- _renderDimensions: function() {
- this.callBase();
- this.$element().toggleClass(DX_AUTO_WIDTH_CLASS, !this.option("width"))
- },
- _refreshFormatClass: function() {
- var $element = this.$element();
- each(TYPE, function(_, item) {
- $element.removeClass(DATEBOX_CLASS + "-" + item)
- });
- $element.addClass(DATEBOX_CLASS + "-" + this.option("type"))
- },
- _refreshPickerTypeClass: function() {
- var $element = this.$element();
- each(PICKER_TYPE, function(_, item) {
- $element.removeClass(DATEBOX_CLASS + "-" + item)
- });
- $element.addClass(DATEBOX_CLASS + "-" + this._pickerType)
- },
- _updateSize: function() {
- var $element = this.$element();
- var widthOption = this.option("width");
- var isWidthSet = typeUtils.isDefined(widthOption) || isRealWidthSet($element) && !this._isSizeUpdatable;
- var pickerType = this._pickerType;
- var shouldCalculateWidth = pickerType !== PICKER_TYPE.rollers && "generic" === devices.current().platform;
- if (!windowUtils.hasWindow() || isWidthSet || !(shouldCalculateWidth && $element.is(":visible"))) {
- return
- }
- var format = this._strategy.getDisplayFormat(this.option("displayFormat"));
- var longestValue = dateLocalization.format(uiDateUtils.getLongestDate(format, dateLocalization.getMonthNames(), dateLocalization.getDayNames()), format);
- $element.width(this._calculateWidth(longestValue));
- this._isSizeUpdatable = true
- },
- _calculateWidth: function(value) {
- var IE_ROUNDING_ERROR = 10;
- var NATIVE_BUTTONS_WIDTH = 48;
- var $input = this._input();
- var $longestValueElement = dom.createTextElementHiddenCopy($input, value);
- $longestValueElement.appendTo(this.$element());
- var elementWidth = parseFloat(window.getComputedStyle($longestValueElement.get(0)).width);
- var rightPadding = parseFloat(window.getComputedStyle($input.get(0)).paddingRight);
- var leftPadding = parseFloat(window.getComputedStyle($input.get(0)).paddingLeft);
- var beforeButtonsWidth = this._$beforeButtonsContainer ? parseFloat(window.getComputedStyle(this._$beforeButtonsContainer.get(0)).width) : 0;
- var afterButtonsWidth = this._$afterButtonsContainer ? parseFloat(window.getComputedStyle(this._$afterButtonsContainer.get(0)).width) : 0;
- var width = elementWidth + rightPadding + leftPadding + IE_ROUNDING_ERROR + beforeButtonsWidth + afterButtonsWidth + ("text" !== $input.prop("type") ? NATIVE_BUTTONS_WIDTH : 0);
- $longestValueElement.remove();
- return width
- },
- _attachChildKeyboardEvents: function() {
- this._strategy.attachKeyboardEvents(this._keyboardProcessor)
- },
- _renderPopup: function() {
- this.callBase();
- this._popup._wrapper().addClass(DATEBOX_WRAPPER_CLASS);
- this._renderPopupWrapper()
- },
- _popupConfig: function() {
- var popupConfig = this.callBase();
- return extend(this._strategy.popupConfig(popupConfig), {
- title: this._getPopupTitle(),
- dragEnabled: false
- })
- },
- _renderPopupWrapper: function() {
- if (!this._popup) {
- return
- }
- var $element = this.$element();
- var classPostfixes = extend({}, TYPE, PICKER_TYPE);
- each(classPostfixes, function(_, item) {
- $element.removeClass(DATEBOX_WRAPPER_CLASS + "-" + item)
- }.bind(this));
- this._popup._wrapper().addClass(DATEBOX_WRAPPER_CLASS + "-" + this.option("type")).addClass(DATEBOX_WRAPPER_CLASS + "-" + this._pickerType)
- },
- _renderPopupContent: function() {
- this.callBase();
- this._strategy.renderPopupContent()
- },
- _getFirstPopupElement: function() {
- return this._strategy.getFirstPopupElement() || this.callBase()
- },
- _getLastPopupElement: function() {
- return this._strategy.getLastPopupElement() || this.callBase()
- },
- _popupShowingHandler: function() {
- this.callBase();
- this._strategy.popupShowingHandler()
- },
- _popupHiddenHandler: function() {
- this.callBase();
- this._strategy.popupHiddenHandler()
- },
- _visibilityChanged: function(visible) {
- if (visible) {
- this._updateSize()
- }
- },
- _clearValueHandler: function(e) {
- this.option("text", "");
- this.callBase(e)
- },
- _readOnlyPropValue: function() {
- if (this._pickerType === PICKER_TYPE.rollers) {
- return true
- }
- var platform = devices.real().platform;
- var isCustomValueDisabled = this._isNativeType() && ("ios" === platform || "android" === platform);
- if (isCustomValueDisabled) {
- return this.option("readOnly")
- }
- return this.callBase()
- },
- _isClearButtonVisible: function() {
- return this.callBase() && !this._isNativeType()
- },
- _renderValue: function() {
- var value = this.dateOption("value");
- this.option("text", this._getDisplayedText(value));
- this._strategy.renderValue();
- return this.callBase()
- },
- _setSubmitValue: function() {
- var value = this.dateOption("value");
- var dateSerializationFormat = this.option("dateSerializationFormat");
- var submitFormat = uiDateUtils.SUBMIT_FORMATS_MAP[this.option("type")];
- var submitValue = dateSerializationFormat ? dateSerialization.serializeDate(value, dateSerializationFormat) : uiDateUtils.toStandardDateFormat(value, submitFormat);
- this._getSubmitElement().val(submitValue)
- },
- _getDisplayedText: function(value) {
- var mode = this.option("mode");
- var displayedText;
- if ("text" === mode) {
- var displayFormat = this._strategy.getDisplayFormat(this.option("displayFormat"));
- displayedText = dateLocalization.format(value, displayFormat)
- } else {
- var format = this._getFormatByMode(mode);
- if (format) {
- displayedText = dateLocalization.format(value, format)
- } else {
- displayedText = uiDateUtils.toStandardDateFormat(value, mode)
- }
- }
- return displayedText
- },
- _getFormatByMode: function(mode) {
- return support.inputType(mode) ? null : uiDateUtils.FORMATS_MAP[mode]
- },
- _valueChangeEventHandler: function(e) {
- var text = this.option("text");
- var currentValue = this.dateOption("value");
- if (text === this._getDisplayedText(currentValue)) {
- this._validateValue(currentValue);
- return
- }
- var parsedDate = this._getParsedDate(text);
- var value = currentValue || this._getDateByDefault();
- var type = this.option("type");
- var newValue = uiDateUtils.mergeDates(value, parsedDate, type);
- var date = parsedDate && "time" === type ? newValue : parsedDate;
- if (this._applyInternalValidation(date)) {
- var displayedText = this._getDisplayedText(newValue);
- if (value && newValue && value.getTime() === newValue.getTime() && displayedText !== text) {
- this._renderValue()
- } else {
- this.dateValue(newValue, e)
- }
- }
- this._applyCustomValidation(newValue)
- },
- _getDateByDefault: function() {
- return this._strategy.useCurrentDateByDefault() && this._strategy.getDefaultDate()
- },
- _getParsedDate: function(text) {
- var displayFormat = this._strategy.getDisplayFormat(this.option("displayFormat"));
- var parsedText = this._strategy.getParsedText(text, displayFormat);
- return typeUtils.isDefined(parsedText) ? parsedText : void 0
- },
- _validateValue: function(value) {
- var internalResult = this._applyInternalValidation(value);
- var customResult = !this._skipCustomValidation ? this._applyCustomValidation(value) : true;
- this._skipCustomValidation = false;
- return internalResult && customResult
- },
- _applyInternalValidation: function(value) {
- var text = this.option("text");
- var hasText = !!text && null !== value;
- var isDate = !!value && typeUtils.isDate(value) && !isNaN(value.getTime());
- var isDateInRange = isDate && dateUtils.dateInRange(value, this.dateOption("min"), this.dateOption("max"), this.option("type"));
- var isValid = !hasText && !value || isDateInRange;
- var validationMessage = "";
- if (!isDate) {
- validationMessage = this.option("invalidDateMessage")
- } else {
- if (!isDateInRange) {
- validationMessage = this.option("dateOutOfRangeMessage")
- }
- }
- this.option({
- isValid: isValid,
- validationError: isValid ? null : {
- editorSpecific: true,
- message: validationMessage
- }
- });
- return isValid
- },
- _applyCustomValidation: function(value) {
- this.validationRequest.fire({
- editor: this,
- value: this._serializeDate(value)
- });
- return this.option("isValid")
- },
- _isValueChanged: function(newValue) {
- var oldValue = this.dateOption("value");
- var oldTime = oldValue && oldValue.getTime();
- var newTime = newValue && newValue.getTime();
- return oldTime !== newTime
- },
- _isTextChanged: function(newValue) {
- var oldText = this.option("text");
- var newText = newValue && this._getDisplayedText(newValue) || "";
- return oldText !== newText
- },
- _renderProps: function() {
- this.callBase();
- this._input().attr("autocomplete", "off")
- },
- _renderOpenedState: function() {
- if (!this._isNativeType()) {
- this.callBase()
- }
- if (this._strategy.isAdaptivityChanged()) {
- this._refreshStrategy()
- }
- this._strategy.renderOpenedState()
- },
- _getPopupTitle: function() {
- var placeholder = this.option("placeholder");
- if (placeholder) {
- return placeholder
- }
- var type = this.option("type");
- if (type === TYPE.time) {
- return messageLocalization.format("dxDateBox-simulatedDataPickerTitleTime")
- }
- if (type === TYPE.date || type === TYPE.datetime) {
- return messageLocalization.format("dxDateBox-simulatedDataPickerTitleDate")
- }
- return ""
- },
- _renderPlaceholder: function() {
- this._popup && this._popup.option("title", this._getPopupTitle());
- this.callBase()
- },
- _refreshStrategy: function() {
- this._strategy.dispose();
- this._initStrategy();
- this.option(this._strategy.getDefaultOptions());
- this._refresh()
- },
- _applyButtonHandler: function(e) {
- var value = this._strategy.getValue();
- if (this._applyInternalValidation(value)) {
- this.dateValue(value, e.event)
- }
- this.callBase()
- },
- _dispose: function() {
- this._strategy && this._strategy.dispose();
- this.callBase()
- },
- _isNativeType: function() {
- return this._pickerType === PICKER_TYPE.native
- },
- _optionChanged: function(args) {
- switch (args.name) {
- case "showClearButton":
- case "buttons":
- this.callBase.apply(this, arguments);
- this._updateSize();
- break;
- case "pickerType":
- this._updatePickerOptions({
- pickerType: args.value
- });
- this._refreshStrategy();
- this._refreshPickerTypeClass();
- this._invalidate();
- break;
- case "type":
- this._updatePickerOptions({
- format: args.value
- });
- this._refreshStrategy();
- this._refreshFormatClass();
- this._renderPopupWrapper();
- this._updateSize();
- break;
- case "placeholder":
- this._renderPlaceholder();
- break;
- case "min":
- case "max":
- if (this.option("isValid")) {
- this._applyInternalValidation(this.dateOption("value"))
- } else {
- this._validateValue(this.dateOption("value"))
- }
- this._invalidate();
- break;
- case "dateSerializationFormat":
- case "interval":
- case "disabledDates":
- case "calendarOptions":
- case "minZoomLevel":
- case "maxZoomLevel":
- this._invalidate();
- break;
- case "displayFormat":
- this.option("text", this._getDisplayedText(this.dateOption("value")));
- this._renderInputValue();
- break;
- case "formatWidthCalculator":
- break;
- case "closeOnValueChange":
- var applyValueMode = args.value ? "instantly" : "useButtons";
- this.option("applyValueMode", applyValueMode);
- break;
- case "applyValueMode":
- this._suppressDeprecatedWarnings();
- this.option("closeOnValueChange", "instantly" === args.value);
- this._resumeDeprecatedWarnings();
- this.callBase.apply(this, arguments);
- break;
- case "text":
- this._strategy.textChangedHandler(args.value);
- this.callBase.apply(this, arguments);
- break;
- case "isValid":
- this.callBase.apply(this, arguments);
- this._updateSize();
- break;
- case "showDropDownButton":
- this._updateSize();
- break;
- case "readOnly":
- this.callBase.apply(this, arguments);
- this._updateSize();
- break;
- case "invalidDateMessage":
- case "dateOutOfRangeMessage":
- case "adaptivityEnabled":
- case "showAnalogClock":
- break;
- default:
- this.callBase.apply(this, arguments)
- }
- },
- _getSerializationFormat: function() {
- var value = this.option("value");
- if (this.option("dateSerializationFormat") && config().forceIsoDateParsing) {
- return this.option("dateSerializationFormat")
- }
- if (typeUtils.isNumeric(value)) {
- return "number"
- }
- if (!typeUtils.isString(value)) {
- return
- }
- return dateSerialization.getDateSerializationFormat(value)
- },
- _updateValue: function(value) {
- this.callBase();
- this._validateValue(value || this.dateOption("value"))
- },
- dateValue: function(value, dxEvent) {
- var isValueChanged = this._isValueChanged(value);
- if (isValueChanged && dxEvent) {
- this._saveValueChangeEvent(dxEvent)
- }
- if (!isValueChanged && this._isTextChanged(value)) {
- this._updateValue(value)
- }
- return this.dateOption("value", value)
- },
- dateOption: function(optionName, value) {
- if (1 === arguments.length) {
- return dateSerialization.deserializeDate(this.option(optionName))
- }
- this.option(optionName, this._serializeDate(value))
- },
- _serializeDate: function(date) {
- var serializationFormat = this._getSerializationFormat();
- return dateSerialization.serializeDate(date, serializationFormat)
- },
- reset: function() {
- var defaultOptions = this._getDefaultOptions();
- this._skipCustomValidation = defaultOptions.value === this.dateOption("value");
- this.callBase();
- this._updateValue(this.dateOption("value"))
- }
- });
- registerComponent("dxDateBox", DateBox);
- module.exports = DateBox;
|