UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

421 lines (420 loc) • 18.5 kB
/** * DevExtreme (esm/ui/calendar/ui.calendar.base_view.js) * Version: 23.2.6 * Build date: Wed May 01 2024 * * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ import $ from "../../core/renderer"; import domAdapter from "../../core/dom_adapter"; import eventsEngine from "../../events/core/events_engine"; import { data as elementData } from "../../core/element_data"; import { getPublicElement } from "../../core/element"; import Widget from "../widget/ui.widget"; import coreDateUtils from "../../core/utils/date"; import { extend } from "../../core/utils/extend"; import { noop } from "../../core/utils/common"; import dateSerialization from "../../core/utils/date_serialization"; import messageLocalization from "../../localization/message"; import { addNamespace } from "../../events/utils/index"; import { name as clickEventName } from "../../events/click"; import { start as hoverStartEventName } from "../../events/hover"; var { abstract: abstract } = Widget; var CALENDAR_OTHER_VIEW_CLASS = "dx-calendar-other-view"; var CALENDAR_CELL_CLASS = "dx-calendar-cell"; var CALENDAR_CELL_START_CLASS = "dx-calendar-cell-start"; var CALENDAR_CELL_END_CLASS = "dx-calendar-cell-end"; var CALENDAR_CELL_START_IN_ROW_CLASS = "dx-calendar-cell-start-in-row"; var CALENDAR_CELL_END_IN_ROW_CLASS = "dx-calendar-cell-end-in-row"; var CALENDAR_WEEK_NUMBER_CELL_CLASS = "dx-calendar-week-number-cell"; var CALENDAR_EMPTY_CELL_CLASS = "dx-calendar-empty-cell"; var CALENDAR_TODAY_CLASS = "dx-calendar-today"; var CALENDAR_SELECTED_DATE_CLASS = "dx-calendar-selected-date"; var CALENDAR_CELL_IN_RANGE_CLASS = "dx-calendar-cell-in-range"; var CALENDAR_CELL_RANGE_HOVER_CLASS = "dx-calendar-cell-range-hover"; var CALENDAR_CELL_RANGE_HOVER_START_CLASS = "dx-calendar-cell-range-hover-start"; var CALENDAR_CELL_RANGE_HOVER_END_CLASS = "dx-calendar-cell-range-hover-end"; var CALENDAR_RANGE_START_DATE_CLASS = "dx-calendar-range-start-date"; var CALENDAR_RANGE_END_DATE_CLASS = "dx-calendar-range-end-date"; var CALENDAR_CONTOURED_DATE_CLASS = "dx-calendar-contoured-date"; var NOT_WEEK_CELL_SELECTOR = "td:not(.".concat(CALENDAR_WEEK_NUMBER_CELL_CLASS, ")"); var CALENDAR_DXCLICK_EVENT_NAME = addNamespace(clickEventName, "dxCalendar"); var CALENDAR_DXHOVERSTART_EVENT_NAME = addNamespace(hoverStartEventName, "dxCalendar"); var CALENDAR_DATE_VALUE_KEY = "dxDateValueKey"; var DAY_INTERVAL = 864e5; var BaseView = Widget.inherit({ _getViewName: function() { return "base" }, _getDefaultOptions: function() { return extend(this.callBase(), { date: new Date, focusStateEnabled: false, cellTemplate: null, disabledDates: null, onCellClick: null, onCellHover: null, onWeekNumberClick: null, rowCount: 3, colCount: 4, allowValueSelection: true, _todayDate: () => new Date }) }, _initMarkup: function() { this.callBase(); this._renderImpl() }, _renderImpl: function() { this.$element().append(this._createTable()); this._createDisabledDatesHandler(); this._renderBody(); this._renderContouredDate(); this._renderValue(); this._renderRange(); this._renderEvents() }, _createTable: function() { this._$table = $("<table>"); var localizedWidgetName = messageLocalization.format("dxCalendar-ariaWidgetName"); this.setAria({ label: localizedWidgetName, role: "grid" }, this._$table); return this._$table }, _renderBody: function() { this.$body = $("<tbody>").appendTo(this._$table); var rowData = { cellDate: this._getFirstCellData(), prevCellDate: null }; for (var rowIndex = 0, rowCount = this.option("rowCount"); rowIndex < rowCount; rowIndex++) { rowData.row = this._createRow(); for (var colIndex = 0, colCount = this.option("colCount"); colIndex < colCount; colIndex++) { this._renderCell(rowData, colIndex) } this._renderWeekNumberCell(rowData) } }, _createRow: function() { var row = domAdapter.createElement("tr"); this.setAria("role", "row", $(row)); this.$body.get(0).appendChild(row); return row }, _createCell: function(cellDate, cellIndex) { var cell = domAdapter.createElement("td"); var $cell = $(cell); cell.className = this._getClassNameByDate(cellDate, cellIndex); cell.setAttribute("data-value", dateSerialization.serializeDate(cellDate, coreDateUtils.getShortDateFormat())); elementData(cell, CALENDAR_DATE_VALUE_KEY, cellDate); this.setAria({ role: "gridcell", label: this.getCellAriaLabel(cellDate) }, $cell); return { cell: cell, $cell: $cell } }, _renderCell: function(params, cellIndex) { var { cellDate: cellDate, prevCellDate: prevCellDate, row: row } = params; if (prevCellDate) { coreDateUtils.fixTimezoneGap(prevCellDate, cellDate) } params.prevCellDate = cellDate; var { cell: cell, $cell: $cell } = this._createCell(cellDate, cellIndex); var cellTemplate = this.option("cellTemplate"); $(row).append(cell); if (cellTemplate) { cellTemplate.render(this._prepareCellTemplateData(cellDate, cellIndex, $cell)) } else { cell.innerHTML = this._getCellText(cellDate) } params.cellDate = this._getNextCellData(cellDate) }, _getClassNameByDate: function(cellDate, cellIndex) { var className = CALENDAR_CELL_CLASS; if (this._isTodayCell(cellDate)) { className += " ".concat(CALENDAR_TODAY_CLASS) } if (this._isDateOutOfRange(cellDate) || this.isDateDisabled(cellDate)) { className += " ".concat(CALENDAR_EMPTY_CELL_CLASS) } if (this._isOtherView(cellDate)) { className += " ".concat(CALENDAR_OTHER_VIEW_CLASS) } if ("range" === this.option("selectionMode")) { if (0 === cellIndex) { className += " ".concat(CALENDAR_CELL_START_IN_ROW_CLASS) } if (cellIndex === this.option("colCount") - 1) { className += " ".concat(CALENDAR_CELL_END_IN_ROW_CLASS) } if (this._isStartDayOfMonth(cellDate)) { className += " ".concat(CALENDAR_CELL_START_CLASS) } if (this._isEndDayOfMonth(cellDate)) { className += " ".concat(CALENDAR_CELL_END_CLASS) } } return className }, _prepareCellTemplateData: function(cellDate, cellIndex, $cell) { var isDateCell = cellDate instanceof Date; var text = isDateCell ? this._getCellText(cellDate) : cellDate; var date = isDateCell ? cellDate : void 0; var view = this._getViewName(); return { model: { text: text, date: date, view: view }, container: getPublicElement($cell), index: cellIndex } }, _renderEvents: function() { this._createCellClickAction(); eventsEngine.off(this._$table, CALENDAR_DXCLICK_EVENT_NAME); eventsEngine.on(this._$table, CALENDAR_DXCLICK_EVENT_NAME, NOT_WEEK_CELL_SELECTOR, e => { if (!$(e.currentTarget).hasClass(CALENDAR_EMPTY_CELL_CLASS)) { this._cellClickAction({ event: e, value: $(e.currentTarget).data(CALENDAR_DATE_VALUE_KEY) }) } }); var { selectionMode: selectionMode } = this.option(); eventsEngine.off(this._$table, CALENDAR_DXHOVERSTART_EVENT_NAME); if ("range" === selectionMode) { this._createCellHoverAction(); eventsEngine.on(this._$table, CALENDAR_DXHOVERSTART_EVENT_NAME, NOT_WEEK_CELL_SELECTOR, e => { if (!$(e.currentTarget).hasClass(CALENDAR_EMPTY_CELL_CLASS)) { this._cellHoverAction({ event: e, value: $(e.currentTarget).data(CALENDAR_DATE_VALUE_KEY) }) } }) } if ("single" !== selectionMode) { this._createWeekNumberCellClickAction(); eventsEngine.on(this._$table, CALENDAR_DXCLICK_EVENT_NAME, ".".concat(CALENDAR_WEEK_NUMBER_CELL_CLASS), e => { var $row = $(e.currentTarget).closest("tr"); var firstDateInRow = $row.find(".".concat(CALENDAR_CELL_CLASS)).first().data(CALENDAR_DATE_VALUE_KEY); var lastDateInRow = $row.find(".".concat(CALENDAR_CELL_CLASS)).last().data(CALENDAR_DATE_VALUE_KEY); var rowDates = [...coreDateUtils.getDatesOfInterval(firstDateInRow, lastDateInRow, DAY_INTERVAL), lastDateInRow]; this._weekNumberCellClickAction({ event: e, rowDates: rowDates }) }) } }, _createCellClickAction: function() { this._cellClickAction = this._createActionByOption("onCellClick") }, _createCellHoverAction: function() { this._cellHoverAction = this._createActionByOption("onCellHover") }, _createWeekNumberCellClickAction: function() { this._weekNumberCellClickAction = this._createActionByOption("onWeekNumberClick") }, _createDisabledDatesHandler: function() { var disabledDates = this.option("disabledDates"); this._disabledDatesHandler = Array.isArray(disabledDates) ? this._getDefaultDisabledDatesHandler(disabledDates) : disabledDates || noop }, _getDefaultDisabledDatesHandler: function(disabledDates) { return noop }, _isTodayCell: abstract, _isDateOutOfRange: abstract, isDateDisabled: function(cellDate) { var dateParts = { date: cellDate, view: this._getViewName() }; return this._disabledDatesHandler(dateParts) }, _isOtherView: abstract, _isStartDayOfMonth: abstract, _isEndDayOfMonth: abstract, _getCellText: abstract, _getFirstCellData: abstract, _getNextCellData: abstract, _renderContouredDate: function(contouredDate) { if (!this.option("focusStateEnabled")) { return } contouredDate = contouredDate || this.option("contouredDate"); var $oldContouredCell = this._getContouredCell(); var $newContouredCell = this._getCellByDate(contouredDate); $oldContouredCell.removeClass(CALENDAR_CONTOURED_DATE_CLASS); if (contouredDate) { $newContouredCell.addClass(CALENDAR_CONTOURED_DATE_CLASS) } }, _getContouredCell: function() { return this._$table.find(".".concat(CALENDAR_CONTOURED_DATE_CLASS)) }, _renderValue: function() { if (!this.option("allowValueSelection")) { return } var value = this.option("value"); if (!Array.isArray(value)) { value = [value] } this._updateSelectedClass(value) }, _updateSelectedClass: function(value) { var _this$_$selectedCells; if (this._isRangeMode() && !this._isMonthView()) { return } null === (_this$_$selectedCells = this._$selectedCells) || void 0 === _this$_$selectedCells ? void 0 : _this$_$selectedCells.forEach($cell => { $cell.removeClass(CALENDAR_SELECTED_DATE_CLASS) }); this._$selectedCells = value.map(value => this._getCellByDate(value)); this._$selectedCells.forEach($cell => { $cell.addClass(CALENDAR_SELECTED_DATE_CLASS) }) }, _renderRange: function() { var _this$_$rangeCells, _this$_$hoveredRangeC, _this$_$rangeStartHov, _this$_$rangeEndHover, _this$_$rangeStartDat, _this$_$rangeEndDateC, _this$_$rangeStartDat2, _this$_$rangeEndDateC2; var { allowValueSelection: allowValueSelection, value: value, range: range } = this.option(); if (!allowValueSelection || !this._isRangeMode() || !this._isMonthView()) { return } null === (_this$_$rangeCells = this._$rangeCells) || void 0 === _this$_$rangeCells ? void 0 : _this$_$rangeCells.forEach($cell => { $cell.removeClass(CALENDAR_CELL_IN_RANGE_CLASS) }); null === (_this$_$hoveredRangeC = this._$hoveredRangeCells) || void 0 === _this$_$hoveredRangeC ? void 0 : _this$_$hoveredRangeC.forEach($cell => { $cell.removeClass(CALENDAR_CELL_RANGE_HOVER_CLASS) }); null === (_this$_$rangeStartHov = this._$rangeStartHoverCell) || void 0 === _this$_$rangeStartHov ? void 0 : _this$_$rangeStartHov.removeClass(CALENDAR_CELL_RANGE_HOVER_START_CLASS); null === (_this$_$rangeEndHover = this._$rangeEndHoverCell) || void 0 === _this$_$rangeEndHover ? void 0 : _this$_$rangeEndHover.removeClass(CALENDAR_CELL_RANGE_HOVER_END_CLASS); null === (_this$_$rangeStartDat = this._$rangeStartDateCell) || void 0 === _this$_$rangeStartDat ? void 0 : _this$_$rangeStartDat.removeClass(CALENDAR_RANGE_START_DATE_CLASS); null === (_this$_$rangeEndDateC = this._$rangeEndDateCell) || void 0 === _this$_$rangeEndDateC ? void 0 : _this$_$rangeEndDateC.removeClass(CALENDAR_RANGE_END_DATE_CLASS); this._$rangeCells = range.map(value => this._getCellByDate(value)); this._$rangeStartDateCell = this._getCellByDate(value[0]); this._$rangeEndDateCell = this._getCellByDate(value[1]); this._$rangeCells.forEach($cell => { $cell.addClass(CALENDAR_CELL_IN_RANGE_CLASS) }); null === (_this$_$rangeStartDat2 = this._$rangeStartDateCell) || void 0 === _this$_$rangeStartDat2 ? void 0 : _this$_$rangeStartDat2.addClass(CALENDAR_RANGE_START_DATE_CLASS); null === (_this$_$rangeEndDateC2 = this._$rangeEndDateCell) || void 0 === _this$_$rangeEndDateC2 ? void 0 : _this$_$rangeEndDateC2.addClass(CALENDAR_RANGE_END_DATE_CLASS) }, _renderHoveredRange() { var _this$_$hoveredRangeC2, _this$_$rangeStartHov2, _this$_$rangeEndHover2, _this$_$rangeStartHov3, _this$_$rangeEndHover3; var { allowValueSelection: allowValueSelection, hoveredRange: hoveredRange } = this.option(); if (!allowValueSelection || !this._isRangeMode() || !this._isMonthView()) { return } null === (_this$_$hoveredRangeC2 = this._$hoveredRangeCells) || void 0 === _this$_$hoveredRangeC2 ? void 0 : _this$_$hoveredRangeC2.forEach($cell => { $cell.removeClass(CALENDAR_CELL_RANGE_HOVER_CLASS) }); null === (_this$_$rangeStartHov2 = this._$rangeStartHoverCell) || void 0 === _this$_$rangeStartHov2 ? void 0 : _this$_$rangeStartHov2.removeClass(CALENDAR_CELL_RANGE_HOVER_START_CLASS); null === (_this$_$rangeEndHover2 = this._$rangeEndHoverCell) || void 0 === _this$_$rangeEndHover2 ? void 0 : _this$_$rangeEndHover2.removeClass(CALENDAR_CELL_RANGE_HOVER_END_CLASS); this._$hoveredRangeCells = hoveredRange.map(value => this._getCellByDate(value)); this._$rangeStartHoverCell = this._getCellByDate(hoveredRange[0]); this._$rangeEndHoverCell = this._getCellByDate(hoveredRange[hoveredRange.length - 1]); this._$hoveredRangeCells.forEach($cell => { $cell.addClass(CALENDAR_CELL_RANGE_HOVER_CLASS) }); null === (_this$_$rangeStartHov3 = this._$rangeStartHoverCell) || void 0 === _this$_$rangeStartHov3 ? void 0 : _this$_$rangeStartHov3.addClass(CALENDAR_CELL_RANGE_HOVER_START_CLASS); null === (_this$_$rangeEndHover3 = this._$rangeEndHoverCell) || void 0 === _this$_$rangeEndHover3 ? void 0 : _this$_$rangeEndHover3.addClass(CALENDAR_CELL_RANGE_HOVER_END_CLASS) }, _isMonthView: function() { return "month" === this.option("zoomLevel") }, _isRangeMode: function() { return "range" === this.option("selectionMode") }, getCellAriaLabel: function(date) { return this._getCellText(date) }, _getFirstAvailableDate: function() { var date = this.option("date"); var min = this.option("min"); date = coreDateUtils.getViewFirstCellDate(this._getViewName(), date); return new Date(min && date < min ? min : date) }, _getCellByDate: abstract, isBoundary: abstract, _optionChanged: function(args) { var { name: name, value: value } = args; switch (name) { case "value": this._renderValue(); break; case "range": this._renderRange(); break; case "hoveredRange": this._renderHoveredRange(); break; case "contouredDate": this._renderContouredDate(value); break; case "onCellClick": this._createCellClickAction(); break; case "onCellHover": this._createCellHoverAction(); break; case "min": case "max": case "disabledDates": case "cellTemplate": case "selectionMode": this._invalidate(); break; case "_todayDate": this._renderBody(); break; default: this.callBase(args) } } }); export default BaseView;