UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

1,013 lines (1,012 loc) • 40.5 kB
/** * DevExtreme (esm/ui/calendar/ui.calendar.js) * Version: 21.1.4 * Build date: Mon Jun 21 2021 * * Copyright (c) 2012 - 2021 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import $ from "../../core/renderer"; import Guid from "../../core/guid"; import registerComponent from "../../core/component_registrator"; import { noop } from "../../core/utils/common"; import { isNumeric, isString, isFunction, isDefined, isDate } from "../../core/utils/type"; import { inRange } from "../../core/utils/math"; import { extend } from "../../core/utils/extend"; import Button from "../button"; import Editor from "../editor/editor"; import Swipeable from "../../events/gesture/swipeable"; import Navigator from "./ui.calendar.navigator"; import Views from "./ui.calendar.views"; import { move } from "../../animation/translator"; import browser from "../../core/utils/browser"; import dateUtils from "../../core/utils/date"; import dateSerialization from "../../core/utils/date_serialization"; import devices from "../../core/devices"; import fx from "../../animation/fx"; import { hasWindow } from "../../core/utils/window"; import messageLocalization from "../../localization/message"; import { FunctionTemplate } from "../../core/templates/function_template"; import { isCommandKeyPressed } from "../../events/utils/index"; var CALENDAR_CLASS = "dx-calendar"; var CALENDAR_BODY_CLASS = "dx-calendar-body"; var CALENDAR_CELL_CLASS = "dx-calendar-cell"; var CALENDAR_FOOTER_CLASS = "dx-calendar-footer"; var CALENDAR_TODAY_BUTTON_CLASS = "dx-calendar-today-button"; var CALENDAR_HAS_FOOTER_CLASS = "dx-calendar-with-footer"; var CALENDAR_VIEWS_WRAPPER_CLASS = "dx-calendar-views-wrapper"; var CALENDAR_VIEW_CLASS = "dx-calendar-view"; var FOCUSED_STATE_CLASS = "dx-state-focused"; var ANIMATION_DURATION_SHOW_VIEW = 250; var POP_ANIMATION_FROM = .6; var POP_ANIMATION_TO = 1; var CALENDAR_INPUT_STANDARD_PATTERN = "yyyy-MM-dd"; var CALENDAR_DATE_VALUE_KEY = "dxDateValueKey"; var LEVEL_COMPARE_MAP = { month: 3, year: 2, decade: 1, century: 0 }; var ZOOM_LEVEL = { MONTH: "month", YEAR: "year", DECADE: "decade", CENTURY: "century" }; var isIE11 = browser.msie && parseInt(browser.version) <= 11; var Calendar = Editor.inherit({ _activeStateUnit: "." + CALENDAR_CELL_CLASS, _getDefaultOptions: function() { return extend(this.callBase(), { hoverStateEnabled: true, activeStateEnabled: true, currentDate: new Date, value: null, dateSerializationFormat: void 0, min: new Date(1e3, 0), max: new Date(3e3, 0), firstDayOfWeek: void 0, zoomLevel: ZOOM_LEVEL.MONTH, maxZoomLevel: ZOOM_LEVEL.MONTH, minZoomLevel: ZOOM_LEVEL.CENTURY, showTodayButton: false, cellTemplate: "cell", disabledDates: null, onCellClick: null, onContouredChanged: null, hasFocus: function(element) { return element.hasClass(FOCUSED_STATE_CLASS) }, _todayDate: () => new Date }) }, _defaultOptionsRules: function() { return this.callBase().concat([{ device: function() { return "desktop" === devices.real().deviceType && !devices.isSimulator() }, options: { focusStateEnabled: true } }]) }, _supportedKeys: function() { return extend(this.callBase(), { rightArrow: function(e) { e.preventDefault(); if (isCommandKeyPressed(e)) { this._waitRenderView(1) } else { this._moveCurrentDateByOffset(1 * this._getRtlCorrection()) } }, leftArrow: function(e) { e.preventDefault(); if (isCommandKeyPressed(e)) { this._waitRenderView(-1) } else { this._moveCurrentDateByOffset(-1 * this._getRtlCorrection()) } }, upArrow: function(e) { e.preventDefault(); if (isCommandKeyPressed(e)) { this._navigateUp() } else { if (fx.isAnimating(this._view.$element())) { return } this._moveCurrentDateByOffset(-1 * this._view.option("colCount")) } }, downArrow: function(e) { e.preventDefault(); if (isCommandKeyPressed(e)) { this._navigateDown() } else { if (fx.isAnimating(this._view.$element())) { return } this._moveCurrentDateByOffset(1 * this._view.option("colCount")) } }, home: function(e) { e.preventDefault(); var zoomLevel = this.option("zoomLevel"); var currentDate = this.option("currentDate"); var min = this._dateOption("min"); if (this._view.isDateDisabled(currentDate)) { return } var date = dateUtils.sameView(zoomLevel, currentDate, min) ? min : dateUtils.getViewFirstCellDate(zoomLevel, currentDate); this._moveToClosestAvailableDate(date) }, end: function(e) { e.preventDefault(); var zoomLevel = this.option("zoomLevel"); var currentDate = this.option("currentDate"); var max = this._dateOption("max"); if (this._view.isDateDisabled(currentDate)) { return } var date = dateUtils.sameView(zoomLevel, currentDate, max) ? max : dateUtils.getViewLastCellDate(zoomLevel, currentDate); this._moveToClosestAvailableDate(date) }, pageUp: function(e) { e.preventDefault(); this._waitRenderView(-1 * this._getRtlCorrection()) }, pageDown: function(e) { e.preventDefault(); this._waitRenderView(1 * this._getRtlCorrection()) }, tab: noop, enter: function(e) { if (!this._isMaxZoomLevel()) { this._navigateDown() } else if (!this._view.isDateDisabled(this.option("currentDate"))) { var value = this._updateTimeComponent(this.option("currentDate")); this._dateValue(value, e) } } }) }, _getSerializationFormat: function(optionName) { var value = this.option(optionName || "value"); if (this.option("dateSerializationFormat")) { return this.option("dateSerializationFormat") } if (isNumeric(value)) { return "number" } if (!isString(value)) { return } return dateSerialization.getDateSerializationFormat(value) }, _convertToDate: function(value, optionName) { return dateSerialization.deserializeDate(value) }, _dateValue: function(value, event) { if (event) { if ("keydown" === event.type) { var cellElement = this._view._getContouredCell().get(0); event.target = cellElement } this._saveValueChangeEvent(event) } this._dateOption("value", value) }, _dateOption: function(optionName, optionValue) { if (1 === arguments.length) { return this._convertToDate(this.option(optionName), optionName) } var serializationFormat = this._getSerializationFormat(optionName); this.option(optionName, dateSerialization.serializeDate(optionValue, serializationFormat)) }, _shiftDate: function(zoomLevel, date, offset, reverse) { switch (zoomLevel) { case ZOOM_LEVEL.MONTH: date.setDate(date.getDate() + offset * reverse); break; case ZOOM_LEVEL.YEAR: date.setMonth(date.getMonth() + offset * reverse); break; case ZOOM_LEVEL.DECADE: date.setFullYear(date.getFullYear() + offset * reverse); break; case ZOOM_LEVEL.CENTURY: date.setFullYear(date.getFullYear() + 10 * offset * reverse) } }, _moveCurrentDateByOffset: function(offset) { var baseDate = this.option("currentDate"); var currentDate = new Date(baseDate); var zoomLevel = this.option("zoomLevel"); this._shiftDate(zoomLevel, currentDate, offset, 1); var maxDate = this._getMaxDate(); var minDate = this._getMinDate(); var isDateForwardInNeighborView = this._areDatesInNeighborView(zoomLevel, currentDate, baseDate); var isDateForwardInRange = inRange(currentDate, minDate, maxDate) && isDateForwardInNeighborView; var dateForward = new Date(currentDate); while (isDateForwardInRange) { if (!this._view.isDateDisabled(dateForward)) { currentDate = dateForward; break } this._shiftDate(zoomLevel, dateForward, offset, 1); isDateForwardInNeighborView = this._areDatesInNeighborView(zoomLevel, dateForward, baseDate); isDateForwardInRange = inRange(dateForward, minDate, maxDate) && isDateForwardInNeighborView } if (this._view.isDateDisabled(baseDate) || this._view.isDateDisabled(currentDate)) { this._waitRenderView(offset > 0 ? 1 : -1) } else { this.option("currentDate", currentDate) } }, _areDatesInSameView(zoomLevel, date1, date2) { switch (zoomLevel) { case ZOOM_LEVEL.MONTH: return date1.getMonth() === date2.getMonth(); case ZOOM_LEVEL.YEAR: return date1.getYear() === date2.getYear(); case ZOOM_LEVEL.DECADE: return parseInt(date1.getYear() / 10) === parseInt(date2.getYear() / 10); case ZOOM_LEVEL.CENTURY: return parseInt(date1.getYear() / 100) === parseInt(date2.getYear() / 100) } }, _areDatesInNeighborView(zoomLevel, date1, date2) { switch (zoomLevel) { case ZOOM_LEVEL.MONTH: return (a = date1.getMonth(), b = date2.getMonth(), abs = Math.abs(a - b), Math.min(abs, 12 - abs)) <= 1; case ZOOM_LEVEL.YEAR: return Math.abs(date1.getYear() - date2.getYear()) <= 1; case ZOOM_LEVEL.DECADE: return Math.abs(date1.getYear() - date2.getYear()) <= 10; case ZOOM_LEVEL.CENTURY: return Math.abs(date1.getYear() - date2.getYear()) <= 100 } var a, b, abs }, _moveToClosestAvailableDate: function() { var baseDate = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : this.option("currentDate"); var currentDate = dateUtils.createDate(baseDate); var zoomLevel = this.option("zoomLevel"); var isCurrentDateAvailable = !this._isDateNotAvailable(currentDate); var isDateForwardAvailable = isCurrentDateAvailable; var isDateBackwardAvailable = isCurrentDateAvailable; var isDateForwardInStartView; var isDateBackwardInStartView; var dateForward = dateUtils.createDate(currentDate); var dateBackward = dateUtils.createDate(currentDate); do { if (isDateForwardAvailable) { currentDate = dateForward; break } if (isDateBackwardAvailable) { currentDate = dateBackward; break } this._shiftDate(zoomLevel, dateForward, 1, 1); this._shiftDate(zoomLevel, dateBackward, 1, -1); isDateForwardInStartView = this._areDatesInSameView(zoomLevel, dateForward, baseDate); isDateBackwardInStartView = this._areDatesInSameView(zoomLevel, dateBackward, baseDate); isDateForwardAvailable = isDateForwardInStartView && !this._isDateNotAvailable(dateForward); isDateBackwardAvailable = isDateBackwardInStartView && !this._isDateNotAvailable(dateBackward) } while (isDateForwardInStartView || isDateBackwardInStartView); this.option("currentDate", currentDate) }, _isDateNotAvailable: function(date) { var maxDate = this._getMaxDate(); var minDate = this._getMinDate(); return !inRange(date, minDate, maxDate) || this._view.isDateDisabled(date) }, _init: function() { this.callBase(); this._correctZoomLevel(); this._initCurrentDate(); this._initActions() }, _correctZoomLevel: function() { var minZoomLevel = this.option("minZoomLevel"); var maxZoomLevel = this.option("maxZoomLevel"); var zoomLevel = this.option("zoomLevel"); if (LEVEL_COMPARE_MAP[maxZoomLevel] < LEVEL_COMPARE_MAP[minZoomLevel]) { return } if (LEVEL_COMPARE_MAP[zoomLevel] > LEVEL_COMPARE_MAP[maxZoomLevel]) { this.option("zoomLevel", maxZoomLevel) } else if (LEVEL_COMPARE_MAP[zoomLevel] < LEVEL_COMPARE_MAP[minZoomLevel]) { this.option("zoomLevel", minZoomLevel) } }, _initCurrentDate: function() { var currentDate = this._getNormalizedDate(this._dateOption("value")) || this._getNormalizedDate(this.option("currentDate")); this.option("currentDate", currentDate) }, _getNormalizedDate: function(date) { date = dateUtils.normalizeDate(date, this._getMinDate(), this._getMaxDate()); return isDefined(date) ? this._getDate(date) : date }, _initActions: function() { this._cellClickAction = this._createActionByOption("onCellClick"); this._onContouredChanged = this._createActionByOption("onContouredChanged") }, _initTemplates: function() { this._templateManager.addDefaultTemplates({ cell: new FunctionTemplate((function(options) { var data = options.model; $(options.container).append($("<span>").text(data && data.text || String(data))) })) }); this.callBase() }, _updateCurrentDate: function(date) { if (fx.isAnimating(this._$viewsWrapper)) { fx.stop(this._$viewsWrapper, true) } var min = this._getMinDate(); var max = this._getMaxDate(); if (min > max) { this.option("currentDate", new Date); return } var normalizedDate = this._getNormalizedDate(date); if (date.getTime() !== normalizedDate.getTime()) { this.option("currentDate", dateUtils.createDate(normalizedDate)); return } var offset = this._getViewsOffset(this._view.option("date"), normalizedDate); if (0 !== offset && !this._isMaxZoomLevel() && this._isOtherViewCellClicked) { offset = 0 } if (this._view && 0 !== offset && !this._suppressNavigation) { this._navigate(offset, normalizedDate) } else { this._renderNavigator(); this._setViewContoured(normalizedDate); this._updateAriaId(normalizedDate) } }, _setViewContoured: function(date) { if (this.option("hasFocus")(this._focusTarget())) { this._view.option("contouredDate", date) } }, _getMinDate: function() { if (this.min) { return this.min } this.min = this._dateOption("min") || new Date(1e3, 0); return this.min }, _getMaxDate: function() { if (this.max) { return this.max } this.max = this._dateOption("max") || new Date(3e3, 0); return this.max }, _getViewsOffset: function(startDate, endDate) { var zoomLevel = this.option("zoomLevel"); if (zoomLevel === ZOOM_LEVEL.MONTH) { return this._getMonthsOffset(startDate, endDate) } var zoomCorrection; switch (zoomLevel) { case ZOOM_LEVEL.CENTURY: zoomCorrection = 100; break; case ZOOM_LEVEL.DECADE: zoomCorrection = 10; break; default: zoomCorrection = 1 } return parseInt(endDate.getFullYear() / zoomCorrection) - parseInt(startDate.getFullYear() / zoomCorrection) }, _getMonthsOffset: function(startDate, endDate) { var yearOffset = endDate.getFullYear() - startDate.getFullYear(); var monthOffset = endDate.getMonth() - startDate.getMonth(); return 12 * yearOffset + monthOffset }, _waitRenderView: function(offset) { if (this._alreadyViewRender) { return } this._alreadyViewRender = true; var date = this._getDateByOffset(offset * this._getRtlCorrection()); this._moveToClosestAvailableDate(date); this._waitRenderViewTimeout = setTimeout(() => { this._alreadyViewRender = false }) }, _getRtlCorrection: function() { return this.option("rtlEnabled") ? -1 : 1 }, _getDateByOffset: function(offset, date) { var _date; date = this._getDate(null !== (_date = date) && void 0 !== _date ? _date : this.option("currentDate")); var currentDay = date.getDate(); var difference = dateUtils.getDifferenceInMonth(this.option("zoomLevel")) * offset; date.setDate(1); date.setMonth(date.getMonth() + difference); var lastDay = dateUtils.getLastMonthDate(date).getDate(); date.setDate(currentDay > lastDay ? lastDay : currentDay); return date }, _focusTarget: function() { return this.$element() }, _initMarkup: function() { this._renderSubmitElement(); this.callBase(); var $element = this.$element(); $element.addClass(CALENDAR_CLASS); this._renderBody(); $element.append(this.$body); this._renderViews(); this._renderNavigator(); $element.append(this._navigator.$element()); this._renderSwipeable(); this._renderFooter(); this._updateAriaSelected(); this._updateAriaId(); this._moveToClosestAvailableDate() }, _render: function() { this.callBase(); this._setViewContoured(this.option("currentDate")) }, _renderBody: function() { if (!this._$viewsWrapper) { this.$body = $("<div>").addClass(CALENDAR_BODY_CLASS); this._$viewsWrapper = $("<div>").addClass(CALENDAR_VIEWS_WRAPPER_CLASS); this.$body.append(this._$viewsWrapper) } }, _getKeyboardListeners() { return this.callBase().concat([this._view]) }, _renderViews: function() { this.$element().addClass(CALENDAR_VIEW_CLASS + "-" + this.option("zoomLevel")); var currentDate = this.option("currentDate"); this._view = this._renderSpecificView(currentDate); if (hasWindow()) { var beforeDate = this._getDateByOffset(-1, currentDate); this._beforeView = this._isViewAvailable(beforeDate) ? this._renderSpecificView(beforeDate) : null; var afterDate = this._getDateByOffset(1, currentDate); afterDate.setDate(1); this._afterView = this._isViewAvailable(afterDate) ? this._renderSpecificView(afterDate) : null } this._translateViews() }, _renderSpecificView: function(date) { var specificView = Views[this.option("zoomLevel")]; var $view = $("<div>").appendTo(this._$viewsWrapper); var config = this._viewConfig(date); return this._createComponent($view, specificView, config) }, _viewConfig: function(date) { var disabledDates = this.option("disabledDates"); disabledDates = isFunction(disabledDates) ? this._injectComponent(disabledDates.bind(this)) : disabledDates; return { date: date, min: this._getMinDate(), max: this._getMaxDate(), firstDayOfWeek: this.option("firstDayOfWeek"), value: this._dateOption("value"), tabIndex: void 0, focusStateEnabled: this.option("focusStateEnabled"), hoverStateEnabled: this.option("hoverStateEnabled"), disabledDates: disabledDates, onCellClick: this._cellClickHandler.bind(this), cellTemplate: this._getTemplateByOption("cellTemplate"), allowValueSelection: this._isMaxZoomLevel(), _todayDate: this.option("_todayDate") } }, _injectComponent: function(func) { var that = this; return function(params) { extend(params, { component: that }); return func(params) } }, _isViewAvailable: function(date) { var zoomLevel = this.option("zoomLevel"); var min = dateUtils.getViewMinBoundaryDate(zoomLevel, this._getMinDate()); var max = dateUtils.getViewMaxBoundaryDate(zoomLevel, this._getMaxDate()); return dateUtils.dateInRange(date, min, max) }, _translateViews: function() { move(this._view.$element(), { left: 0, top: 0 }); this._beforeView && move(this._beforeView.$element(), { left: this._getViewPosition(-1), top: 0 }); this._afterView && move(this._afterView.$element(), { left: this._getViewPosition(1), top: 0 }) }, _getViewPosition: function(coefficient) { var rtlCorrection = this.option("rtlEnabled") && !browser.msie ? -1 : 1; return 100 * coefficient * rtlCorrection + "%" }, _cellClickHandler: function(e) { var zoomLevel = this.option("zoomLevel"); var nextView = dateUtils.getViewDown(zoomLevel); var isMaxZoomLevel = this._isMaxZoomLevel(); if (nextView && !isMaxZoomLevel) { this._navigateDown(e.event.currentTarget) } else { var newValue = this._updateTimeComponent(e.value); this._dateValue(newValue, e.event); this._cellClickAction(e) } }, _updateTimeComponent: function(date) { var result = dateUtils.createDate(date); var currentValue = this._dateOption("value"); if (currentValue) { result.setHours(currentValue.getHours()); result.setMinutes(currentValue.getMinutes()); result.setSeconds(currentValue.getSeconds()); result.setMilliseconds(currentValue.getMilliseconds()) } return result }, _isMaxZoomLevel: function() { return this.option("zoomLevel") === this.option("maxZoomLevel") }, _navigateDown: function(cell) { var zoomLevel = this.option("zoomLevel"); if (this._isMaxZoomLevel()) { return } var nextView = dateUtils.getViewDown(zoomLevel); if (!nextView) { return } var newCurrentDate = this._view.option("contouredDate") || this._view.option("date"); if (cell) { newCurrentDate = $(cell).data(CALENDAR_DATE_VALUE_KEY) } this._isOtherViewCellClicked = true; this.option("currentDate", newCurrentDate); this.option("zoomLevel", nextView); this._isOtherViewCellClicked = false; this._renderNavigator(); this._animateShowView(); this._moveToClosestAvailableDate(); this._setViewContoured(this._getNormalizedDate(this.option("currentDate"))) }, _renderNavigator: function() { if (!this._navigator) { this._navigator = new Navigator($("<div>"), this._navigatorConfig()) } this._navigator.option("text", this._view.getNavigatorCaption()); this._updateButtonsVisibility() }, _navigatorConfig: function() { return { text: this._view.getNavigatorCaption(), onClick: this._navigatorClickHandler.bind(this), onCaptionClick: this._navigateUp.bind(this), rtlEnabled: this.option("rtlEnabled") } }, _navigatorClickHandler: function(e) { var currentDate = this._getDateByOffset(e.direction, this.option("currentDate")); this._moveToClosestAvailableDate(currentDate) }, _navigateUp: function() { var zoomLevel = this.option("zoomLevel"); var nextView = dateUtils.getViewUp(zoomLevel); if (!nextView || this._isMinZoomLevel(zoomLevel)) { return } this.option("zoomLevel", nextView); this._renderNavigator(); this._animateShowView(); this._moveToClosestAvailableDate(); this._setViewContoured(this._getNormalizedDate(this.option("currentDate"))) }, _isMinZoomLevel: function(zoomLevel) { var min = this._getMinDate(); var max = this._getMaxDate(); return dateUtils.sameView(zoomLevel, min, max) || this.option("minZoomLevel") === zoomLevel }, _updateButtonsVisibility: function() { this._navigator.toggleButton("next", !isDefined(this._getRequiredView("next"))); this._navigator.toggleButton("prev", !isDefined(this._getRequiredView("prev"))) }, _renderSwipeable: function() { if (!this._swipeable) { this._swipeable = this._createComponent(this.$element(), Swipeable, { onStart: this._swipeStartHandler.bind(this), onUpdated: this._swipeUpdateHandler.bind(this), onEnd: this._swipeEndHandler.bind(this), itemSizeFunc: this._viewWidth.bind(this) }) } }, _swipeStartHandler: function(e) { fx.stop(this._$viewsWrapper, true); e.event.maxLeftOffset = this._getRequiredView("next") ? 1 : 0; e.event.maxRightOffset = this._getRequiredView("prev") ? 1 : 0 }, _getRequiredView: function(name) { var view; var isRtl = this.option("rtlEnabled"); if ("next" === name) { view = isRtl ? this._beforeView : this._afterView } else if ("prev" === name) { view = isRtl ? this._afterView : this._beforeView } return view }, _swipeUpdateHandler: function(e) { var offset = e.event.offset; move(this._$viewsWrapper, { left: offset * this._viewWidth(), top: 0 }); this._updateNavigatorCaption(offset) }, _swipeEndHandler: function(e) { var targetOffset = e.event.targetOffset; var moveOffset = !targetOffset ? 0 : targetOffset / Math.abs(targetOffset); if (0 === moveOffset) { this._animateWrapper(0, ANIMATION_DURATION_SHOW_VIEW); return } var date = this._getDateByOffset(-moveOffset * this._getRtlCorrection()); if (this._isDateInInvalidRange(date)) { if (moveOffset >= 0) { date = new Date(this._getMinDate()) } else { date = new Date(this._getMaxDate()) } } this.option("currentDate", date) }, _viewWidth: function() { if (!this._viewWidthValue) { this._viewWidthValue = this.$element().width() } return this._viewWidthValue }, _updateNavigatorCaption: function(offset) { offset *= this._getRtlCorrection(); var view = this._view; if (offset > .5 && this._beforeView) { view = this._beforeView } else if (offset < -.5 && this._afterView) { view = this._afterView } this._navigator.option("text", view.getNavigatorCaption()) }, _isDateInInvalidRange: function(date) { if (this._view.isBoundary(date)) { return } var min = this._getMinDate(); var max = this._getMaxDate(); var normalizedDate = dateUtils.normalizeDate(date, min, max); return normalizedDate === min || normalizedDate === max }, _renderFooter: function() { var showTodayButton = this.option("showTodayButton"); if (showTodayButton) { var $todayButton = this._createComponent($("<a>"), Button, { focusStateEnabled: false, text: messageLocalization.format("dxCalendar-todayButtonText"), onClick: function(args) { this._toTodayView(args) }.bind(this), integrationOptions: {} }).$element().addClass(CALENDAR_TODAY_BUTTON_CLASS); this._$footer = $("<div>").addClass(CALENDAR_FOOTER_CLASS).append($todayButton); this.$element().append(this._$footer) } this.$element().toggleClass(CALENDAR_HAS_FOOTER_CLASS, showTodayButton) }, _renderSubmitElement: function() { this._$submitElement = $("<input>").attr("type", "hidden").appendTo(this.$element()); this._setSubmitValue(this.option("value")) }, _setSubmitValue: function(value) { var dateValue = this._convertToDate(value); this._getSubmitElement().val(dateSerialization.serializeDate(dateValue, CALENDAR_INPUT_STANDARD_PATTERN)) }, _getSubmitElement: function() { return this._$submitElement }, _animateShowView: function() { fx.stop(this._view.$element(), true); return this._popAnimationView(this._view, POP_ANIMATION_FROM, POP_ANIMATION_TO, ANIMATION_DURATION_SHOW_VIEW).promise() }, _popAnimationView: function(view, from, to, duration) { return fx.animate(view.$element(), { type: "pop", from: { scale: from, opacity: from }, to: { scale: to, opacity: to }, duration: duration }) }, _navigate: function(offset, value) { if (0 !== offset && 1 !== Math.abs(offset) && this._isViewAvailable(value)) { var newView = this._renderSpecificView(value); if (offset > 0) { this._afterView && this._afterView.$element().remove(); this._afterView = newView } else { this._beforeView && this._beforeView.$element().remove(); this._beforeView = newView } this._translateViews() } var rtlCorrection = this._getRtlCorrection(); var offsetSign = offset > 0 ? 1 : offset < 0 ? -1 : 0; var endPosition = -rtlCorrection * offsetSign * this._viewWidth(); var viewsWrapperPosition = this._$viewsWrapper.position().left; if (viewsWrapperPosition !== endPosition) { if (this._preventViewChangeAnimation) { this._wrapperAnimationEndHandler(offset, value) } else { this._animateWrapper(endPosition, ANIMATION_DURATION_SHOW_VIEW).done(this._wrapperAnimationEndHandler.bind(this, offset, value)) } } }, _animateWrapper: function(to, duration) { return fx.animate(this._$viewsWrapper, { type: "slide", from: { left: this._$viewsWrapper.position().left }, to: { left: to }, duration: duration }) }, _getDate(value) { var result = dateUtils.createDate(value); if (isIE11 && isDate(value)) { result.setMilliseconds(0) } return result }, _toTodayView: function(args) { this._saveValueChangeEvent(args.event); var today = new Date; if (this._isMaxZoomLevel()) { this._dateOption("value", today); return } this._preventViewChangeAnimation = true; this.option("zoomLevel", this.option("maxZoomLevel")); this._dateOption("value", today); this._animateShowView(); this._preventViewChangeAnimation = false }, _wrapperAnimationEndHandler: function(offset, newDate) { this._rearrangeViews(offset); this._translateViews(); this._resetLocation(); this._renderNavigator(); this._setViewContoured(newDate); this._updateAriaId(newDate) }, _rearrangeViews: function(offset) { if (0 === offset) { return } var viewOffset; var viewToCreateKey; var viewToRemoveKey; if (offset < 0) { viewOffset = 1; viewToCreateKey = "_beforeView"; viewToRemoveKey = "_afterView" } else { viewOffset = -1; viewToCreateKey = "_afterView"; viewToRemoveKey = "_beforeView" } if (!this[viewToCreateKey]) { return } var destinationDate = this[viewToCreateKey].option("date"); if (this[viewToRemoveKey]) { this[viewToRemoveKey].$element().remove() } if (offset === viewOffset) { this[viewToRemoveKey] = this._view } else { this[viewToRemoveKey] = this._renderSpecificView(this._getDateByOffset(viewOffset, destinationDate)); this._view.$element().remove() } this._view = this[viewToCreateKey]; var dateByOffset = this._getDateByOffset(-viewOffset, destinationDate); this[viewToCreateKey] = this._isViewAvailable(dateByOffset) ? this._renderSpecificView(dateByOffset) : null }, _resetLocation: function() { move(this._$viewsWrapper, { left: 0, top: 0 }) }, _clean: function() { this.callBase(); this._clearViewWidthCache(); delete this._$viewsWrapper; delete this._navigator; delete this._$footer }, _clearViewWidthCache: function() { delete this._viewWidthValue }, _disposeViews: function() { this._view.$element().remove(); this._beforeView && this._beforeView.$element().remove(); this._afterView && this._afterView.$element().remove(); delete this._view; delete this._beforeView; delete this._afterView }, _dispose: function() { clearTimeout(this._waitRenderViewTimeout); this.callBase() }, _refreshViews: function() { this._disposeViews(); this._renderViews() }, _visibilityChanged: function() { this._translateViews() }, _focusInHandler: function() { this.callBase.apply(this, arguments); this._view.option("contouredDate", this.option("currentDate")) }, _focusOutHandler: function() { this.callBase.apply(this, arguments); this._view.option("contouredDate", null) }, _updateViewsValue: function(value) { var newValue = value ? new Date(value) : null; this._view.option("value", newValue); this._beforeView && this._beforeView.option("value", newValue); this._afterView && this._afterView.option("value", newValue) }, _updateAriaSelected: function(value, previousValue) { var _value; value = null !== (_value = value) && void 0 !== _value ? _value : this._dateOption("value"); var $prevSelectedCell = this._view._getCellByDate(previousValue); var $selectedCell = this._view._getCellByDate(value); this.setAria("selected", void 0, $prevSelectedCell); this.setAria("selected", true, $selectedCell); if (value && this.option("currentDate").getTime() === value.getTime()) { this._updateAriaId(value) } }, _updateAriaId: function(value) { var _value2; value = null !== (_value2 = value) && void 0 !== _value2 ? _value2 : this.option("currentDate"); var ariaId = "dx-" + new Guid; var $newCell = this._view._getCellByDate(value); this.setAria("id", ariaId, $newCell); this.setAria("activedescendant", ariaId); this._onContouredChanged(ariaId) }, _suppressingNavigation: function(callback, args) { this._suppressNavigation = true; callback.apply(this, args); delete this._suppressNavigation }, _optionChanged: function(args) { var value = args.value; var previousValue = args.previousValue; switch (args.name) { case "width": this.callBase(args); this._clearViewWidthCache(); break; case "min": case "max": this.min = void 0; this.max = void 0; this._suppressingNavigation(this._updateCurrentDate, [this.option("currentDate")]); this._refreshViews(); this._renderNavigator(); break; case "firstDayOfWeek": this._refreshViews(); this._updateButtonsVisibility(); break; case "currentDate": this.setAria("id", void 0, this._view._getCellByDate(previousValue)); this._updateCurrentDate(value); break; case "zoomLevel": this.$element().removeClass(CALENDAR_VIEW_CLASS + "-" + previousValue); this._correctZoomLevel(); this._refreshViews(); this._renderNavigator(); this._updateAriaId(); break; case "minZoomLevel": case "maxZoomLevel": this._correctZoomLevel(); this._updateButtonsVisibility(); break; case "value": value = this._convertToDate(value); previousValue = this._convertToDate(previousValue); this._updateAriaSelected(value, previousValue); this.option("currentDate", isDefined(value) ? dateUtils.createDate(value) : new Date); this._updateViewsValue(value); this._setSubmitValue(value); this.callBase(args); break; case "onCellClick": this._view.option("onCellClick", value); break; case "onContouredChanged": this._onContouredChanged = this._createActionByOption("onContouredChanged"); break; case "disabledDates": case "dateSerializationFormat": case "cellTemplate": case "showTodayButton": this._invalidate(); break; case "hasFocus": break; case "_todayDate": this._refreshViews(); break; default: this.callBase(args) } } }); registerComponent("dxCalendar", Calendar); export default Calendar;