UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

448 lines (375 loc) • 16.4 kB
"use strict"; var $ = require("../../core/renderer"), noop = require("../../core/utils/common").noop, isNumeric = require("../../core/utils/type").isNumeric, errors = require("../widget/ui.errors"), dateUtils = require("../../core/utils/date"), extend = require("../../core/utils/extend").extend, registerComponent = require("../../core/component_registrator"), devices = require("../../core/devices"), Widget = require("../widget/ui.widget"), Button = require("../button"), Calendar = require("../calendar"), Popover = require("../popover"), Popup = require("../popup"), publisherMixin = require("./ui.scheduler.publisher_mixin"), dateLocalization = require("../../localization/date"), isDefined = require("../../core/utils/type").isDefined; var ELEMENT_CLASS = "dx-scheduler-navigator", CALENDAR_CLASS = "dx-scheduler-navigator-calendar", NEXT_BUTTON_CLASS = "dx-scheduler-navigator-next", CAPTION_BUTTON_CLASS = "dx-scheduler-navigator-caption", PREVIOUS_BUTTON_CLASS = "dx-scheduler-navigator-previous", CALENDAR_POPOVER_CLASS = "dx-scheduler-navigator-calendar-popover", MONDAY_INDEX = 1; var getDefaultFirstDayOfWeekIndex = function getDefaultFirstDayOfWeekIndex(shift) { return shift ? MONDAY_INDEX : dateLocalization.firstDayOfWeekIndex(); }; var getDateMonthFormat = function getDateMonthFormat(short) { return function (date) { var monthName = dateLocalization.getMonthNames(short ? "abbreviated" : "wide")[date.getMonth()]; return [dateLocalization.format(date, "day"), monthName].join(" "); }; }; var getMonthYearFormat = function getMonthYearFormat(date) { return dateLocalization.getMonthNames("abbreviated")[date.getMonth()] + " " + dateLocalization.format(date, "year"); }; var getCaptionFormat = function getCaptionFormat(short, intervalCount, duration) { var dateMonthFormat = getDateMonthFormat(short); return function (date) { if (intervalCount > 1) { var lastIntervalDate = new Date(date), defaultViewDuration = duration; lastIntervalDate.setDate(date.getDate() + defaultViewDuration - 1); var isDifferentMonthDates = date.getMonth() !== lastIntervalDate.getMonth(), useShortFormat = isDifferentMonthDates || short, firstWeekDateText = dateLocalization.format(date, isDifferentMonthDates ? getDateMonthFormat(useShortFormat) : "d"), lastWeekDateText = dateLocalization.format(lastIntervalDate, getCaptionFormat(useShortFormat)); return firstWeekDateText + "-" + lastWeekDateText; } return [dateMonthFormat(date), dateLocalization.format(date, "year")].join(" "); }; }; var getWeekCaption = function getWeekCaption(date, shift, rejectWeekend) { var firstDayOfWeek = this.option("firstDayOfWeek"), firstDayOfWeekIndex = isDefined(firstDayOfWeek) ? firstDayOfWeek : getDefaultFirstDayOfWeekIndex(shift); if (firstDayOfWeekIndex === 0 && rejectWeekend) firstDayOfWeekIndex = MONDAY_INDEX; var firstWeekDate = dateUtils.getFirstWeekDate(date, firstDayOfWeekIndex), weekendDuration = 2; if (rejectWeekend) { firstWeekDate = dateUtils.normalizeDateByWeek(firstWeekDate, date); } if (firstDayOfWeek >= 6 && rejectWeekend) { firstWeekDate.setDate(firstWeekDate.getDate() + (7 - firstDayOfWeek + 1)); } var lastWeekDate = new Date(firstWeekDate), intervalCount = this.option("intervalCount"); shift = shift || 6; lastWeekDate = new Date(lastWeekDate.setDate(lastWeekDate.getDate() + (intervalCount > 1 ? 7 * (intervalCount - 1) + shift : shift))); if (lastWeekDate.getDay() % 6 === 0 && rejectWeekend) { lastWeekDate.setDate(lastWeekDate.getDate() + weekendDuration); } var isDifferentMonthDates = firstWeekDate.getMonth() !== lastWeekDate.getMonth(), useShortFormat = isDifferentMonthDates || this.option("_useShortDateFormat"), firstWeekDateText = dateLocalization.format(firstWeekDate, isDifferentMonthDates ? getDateMonthFormat(useShortFormat) : "d"), lastWeekDateText = dateLocalization.format(lastWeekDate, getCaptionFormat(useShortFormat)); return firstWeekDateText + "-" + lastWeekDateText; }; var getMonthCaption = function getMonthCaption(date) { if (this.option("intervalCount") > 1) { var firstDate = new Date(date); var lastDate = new Date(firstDate); lastDate.setMonth(lastDate.getMonth() + this.option("intervalCount") - 1); var isSameYear = firstDate.getYear() === lastDate.getYear(), lastDateText = getMonthYearFormat(lastDate), firstDateText = isSameYear ? dateLocalization.getMonthNames("abbreviated")[firstDate.getMonth()] : getMonthYearFormat(firstDate); return firstDateText + "-" + lastDateText; } else { return dateLocalization.format(date, "monthandyear"); } }; var dateGetter = function dateGetter(date, offset) { return new Date(date[this.setter](date[this.getter]() + offset)); }; var getConfig = function getConfig(step) { var agendaDuration; switch (step) { case "day": return { duration: 1 * this.option("intervalCount"), setter: "setDate", getter: "getDate", getDate: dateGetter, getCaption: function getCaption(date) { var format = getCaptionFormat(false, this.option("intervalCount"), this._getConfig().duration); return dateLocalization.format(date, format); } }; case "week": return { duration: 7 * this.option("intervalCount"), setter: "setDate", getter: "getDate", getDate: dateGetter, getCaption: getWeekCaption }; case "workWeek": return { duration: 7 * this.option("intervalCount"), setter: "setDate", getter: "getDate", getDate: dateGetter, getCaption: function getCaption(date) { return getWeekCaption.call(this, date, 4, true); } }; case "month": return { duration: 1 * this.option("intervalCount"), setter: "setMonth", getter: "getMonth", getDate: function getDate(date, offset) { var currentDate = date.getDate(); if (currentDate !== 1 && Math.abs(offset) !== 1) { date.setMonth(date.getMonth() + 1); } date.setDate(1); date = dateGetter.call(this, date, offset); var lastDate = dateUtils.getLastMonthDay(date); date.setDate(currentDate < lastDate ? currentDate : lastDate); return date; }, getCaption: getMonthCaption }; case "agenda": agendaDuration = this.invoke("getAgendaDuration"); agendaDuration = isNumeric(agendaDuration) && agendaDuration > 0 ? agendaDuration : 7; return { duration: agendaDuration, setter: "setDate", getter: "getDate", getDate: dateGetter, getCaption: function getCaption(date) { var format = getCaptionFormat(this.option("_useShortDateFormat")); if (agendaDuration > 1) { var lastDate = new Date(date); lastDate.setDate(lastDate.getDate() + agendaDuration - 1); return dateLocalization.format(date, "d") + "-" + dateLocalization.format(lastDate, format); } else { return dateLocalization.format(date, format); } } }; } }; var SchedulerNavigator = Widget.inherit({ _getDefaultOptions: function _getDefaultOptions() { return extend(this.callBase(), { date: new Date(), step: "day", intervalCount: 1, min: undefined, max: undefined, firstDayOfWeek: undefined, _useShortDateFormat: false }); }, _defaultOptionsRules: function _defaultOptionsRules() { return this.callBase().concat([{ device: function device() { return !devices.real().generic || devices.isSimulator(); }, options: { _useShortDateFormat: true } }]); }, _optionChanged: function _optionChanged(args) { switch (args.name) { case "step": case "date": case "intervalCount": this._updateButtonsState(); this._renderCaption(); this._setCalendarOption("value", this.option("date")); break; case "min": case "max": this._updateButtonsState(); this._setCalendarOption(args.name, args.value); break; case "firstDayOfWeek": this._setCalendarOption(args.name, args.value); break; case "tabIndex": case "focusStateEnabled": this._next.option(args.name, args.value); this._caption.option(args.name, args.value); this._prev.option(args.name, args.value); this._setCalendarOption(args.name, args.value); this.callBase(args); break; case "_useShortDateFormat": break; default: this.callBase(args); } }, _init: function _init() { this.callBase(); this.$element().addClass(ELEMENT_CLASS); this._initButtons(); }, _initButtons: function _initButtons() { var $next = $("<div>").addClass(NEXT_BUTTON_CLASS); this._next = this._createComponent($next, Button, { icon: "chevronnext", onClick: this._updateCurrentDate.bind(this, 1), focusStateEnabled: this.option("focusStateEnabled"), tabIndex: this.option("tabIndex"), integrationOptions: {} }); var $caption = $("<div>").addClass(CAPTION_BUTTON_CLASS); this._caption = this._createComponent($caption, Button, { focusStateEnabled: this.option("focusStateEnabled"), tabIndex: this.option("tabIndex"), integrationOptions: {} }); var $prev = $("<div>").addClass(PREVIOUS_BUTTON_CLASS); this._prev = this._createComponent($prev, Button, { icon: "chevronprev", onClick: this._updateCurrentDate.bind(this, -1), focusStateEnabled: this.option("focusStateEnabled"), tabIndex: this.option("tabIndex"), integrationOptions: {} }); this.setAria("label", "Next period", $next); this.setAria("label", "Previous period", $prev); this._updateButtonsState(); this.$element().append($prev, $caption, $next); }, _updateButtonsState: function _updateButtonsState() { var min = this.option("min"), max = this.option("max"); min = min ? dateUtils.trimTime(min) : min; max = max ? dateUtils.trimTime(max) : max; this._prev.option("disabled", min && this._getNextDate(-1) < min); this._next.option("disabled", max && this._getNextDate(1) > max); }, _updateCurrentDate: function _updateCurrentDate(direction) { var date = this._getNextDate(direction); dateUtils.normalizeDate(date, this.option("min"), this.option("max")); this.notifyObserver("currentDateUpdated", date); }, _getNextDate: function _getNextDate(direction) { var stepConfig = this._getConfig(), offset = stepConfig.duration * direction, date = stepConfig.getDate(new Date(this.option("date")), offset); return date; }, _renderFocusTarget: noop, _initMarkup: function _initMarkup() { this.callBase(); this._renderCaption(); }, _render: function _render() { this.callBase(); this._renderPopover(); this._renderCaptionKeys(); }, _renderPopover: function _renderPopover() { var overlayType = !devices.current().generic ? Popup : Popover; var popoverContainer = $("<div>").addClass(CALENDAR_POPOVER_CLASS); this._popover = this._createComponent(popoverContainer, overlayType, { onContentReady: this._popoverContentReadyHandler.bind(this), defaultOptionsRules: [{ device: function device() { return !devices.current().generic; }, options: { fullScreen: true, showCloseButton: false, toolbarItems: [{ shortcut: "cancel" }] } }, { device: function device() { return devices.current().generic; }, options: { target: this._caption.$element() } }] }); this._popover.$element().appendTo(this.$element()); }, _popoverContentReadyHandler: function _popoverContentReadyHandler() { this._calendar = this._createComponent($("<div>"), Calendar, this._calendarOptions()); this._calendar.$element().addClass(CALENDAR_CLASS); this._popover.$content().append(this._calendar.$element()); }, _calendarOptions: function _calendarOptions() { return { min: this.option("min"), max: this.option("max"), firstDayOfWeek: this.option("firstDayOfWeek"), value: this.option("date"), focusStateEnabled: this.option("focusStateEnabled"), onValueChanged: function (e) { if (!this.option("visible")) return; this.notifyObserver("currentDateUpdated", e.value); this._popover.hide(); }.bind(this), hasFocus: function hasFocus() { return true; }, tabIndex: null, _keyboardProcessor: this._calendarKeyboardProcessor }; }, _renderCaption: function _renderCaption() { var date = this.option("date"), caption = this._getConfig().getCaption.call(this, date); this._caption.option({ text: caption, onClick: function () { this._popover.toggle(); }.bind(this) }); }, _renderCaptionKeys: function _renderCaptionKeys() { if (!this.option("focusStateEnabled") || this.option("disabled")) { return; } this._calendarKeyboardProcessor = this._caption._keyboardProcessor.attachChildProcessor(); this._setCalendarOption("_keyboardProcessor", this._calendarKeyboardProcessor); var that = this, executeHandler = function executeHandler() { if (that._popover.$content().is(":hidden")) { that._popover.show(); } else { return true; } }, tabHandler = function tabHandler() { that._popover.hide(); }; this._caption.registerKeyHandler("enter", executeHandler); this._caption.registerKeyHandler("space", executeHandler); this._caption.registerKeyHandler("tab", tabHandler); }, _setCalendarOption: function _setCalendarOption(name, value) { if (this._calendar) { this._calendar.option(name, value); } }, _getConfig: function _getConfig() { var step = this.option("step"), config = getConfig.call(this, step); if (!config) { throw errors.Error("E1033", step); } return config; } }).include(publisherMixin); registerComponent("dxSchedulerNavigator", SchedulerNavigator); module.exports = SchedulerNavigator;