UNPKG

@eclipse-scout/core

Version:
311 lines (265 loc) 9.68 kB
/* * Copyright (c) 2010, 2024 BSI Business Systems Integration AG * * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 */ import {Calendar, DateRange, dates, HtmlComponent, InitModelOf, Planner, PlannerDisplayMode, scout, scrollbars, Widget, YearPanelEventMap, YearPanelModel} from '../index'; import $ from 'jquery'; export class YearPanel extends Widget implements YearPanelModel { declare model: YearPanelModel; declare eventMap: YearPanelEventMap; declare self: YearPanel; $yearTitle: JQuery; $yearList: JQuery; selectedDate: Date; displayMode: PlannerDisplayMode; // we must use Planner.DisplayMode (extends Calendar.DisplayMode) here because YearPanel must work for calendar and planner. alwaysSelectFirstDay: boolean; yearRendered: boolean; viewRange: DateRange; protected override _init(model: InitModelOf<this>) { super._init(model); // If true, it is only possible to select the first day of a range, depending on the selected mode // day mode: every day may be selected // week, work week, calendar week mode: only first day of week may be selected // year, month mode: only first day of month may be selected this.alwaysSelectFirstDay = model.alwaysSelectFirstDay; } protected override _render() { this.$container = this.$parent.appendDiv('year-panel-container'); this.htmlComp = HtmlComponent.install(this.$container, this.session); this.$yearTitle = this.$container.appendDiv('year-panel-title'); this.$yearList = this.$container.appendDiv('year-panel-list'); } renderContent() { this.removeContent(); this._drawYear(); this._installScrollbars({ axis: 'y', nativeScrollbars: false, hybridScrollbars: false }); this.yearRendered = true; this._colorYear(); } override get$Scrollable(): JQuery { return this.$yearList; } removeContent() { this._uninstallScrollbars(); this.$yearList.empty(); this.yearRendered = false; } protected override _remove() { this.removeContent(); super._remove(); } protected _drawYear() { let first: Date, month: number, $month: JQuery, day: Date, $day: JQuery, year = this.selectedDate.getFullYear(); // append 3 years this.$yearTitle .data('year', year) .empty(); this.$yearTitle.appendDiv('year-title-item', (year - 1) + '') .data('year-diff', -1) .on('click', this._onYearClick.bind(this)); this.$yearTitle.appendDiv('year-title-item selected', year + ''); this.$yearTitle.appendDiv('year-title-item', (year + 1) + '') .data('year-diff', +1) .on('click', this._onYearClick.bind(this)); // add months and days for (month = 0; month < 12; month++) { first = new Date(year, month, 1); $month = this.$yearList.appendDiv('year-month').attr('data-title', this._format(first, 'MMMM')); for (let d = 1; d <= 31; d++) { day = new Date(year, month, d); // stop if day is already out of range if (day.getMonth() !== month) { break; } // add div per day $day = $month.appendDiv('year-day', d + '').data('date', day); if (day.getDay() === 0 || day.getDay() === 6) { $day.addClass('weekend'); } // first day has margin depending on weekday if (d === 1) { $day.css('margin-left', ((day.getDay() + 6) % 7) * $day.outerWidth()); } } } // bind events for days divs $('.year-day', this.$yearList) .on('click', this._onYearDayClick.bind(this)) .on('mouseenter', this._onYearHoverIn.bind(this)) .on('mouseleave', this._onYearHoverOut.bind(this)); // update scrollbar scrollbars.update(this.$yearList); } protected _colorYear() { if (!this.yearRendered) { return; } // remove color information $('.year-day.year-range, .year-day.year-range-day', this.$yearList).removeClass('year-range year-range-day'); // loop all days and colorize based on range and selected let yearPanel: YearPanel = this, $day, date; $('.year-day', this.$yearList).each(function() { $day = $(this); date = $day.data('date') as Date; if (yearPanel.displayMode !== Calendar.DisplayMode.DAY && date >= yearPanel.viewRange.from && date < yearPanel.viewRange.to) { $day.addClass('year-range'); } if (dates.isSameDay(date, yearPanel.selectedDate)) { $day.addClass('year-range-day'); } }); // selected has to be visible day this._scrollYear(); } /** @internal */ _scrollYear() { let top, halfMonth, halfYear, $day = $('.year-range-day', this.$yearList), $month = $day.parent(), $year = $day.parent().parent(); if (!$month[0]) { return; } top = $month[0].offsetTop; halfMonth = $month.outerHeight() / 2; halfYear = $year.outerHeight() / 2; this.$yearList.animateAVCSD('scrollTop', top + halfMonth - halfYear, () => scrollbars.update(this.$yearList)); } protected _format(date: Date, pattern: string): string { return dates.format(date, this.session.locale, pattern); } selectDate(date: Date) { this.selectedDate = date; if (this.rendered) { // If year shown and changed, redraw year if (!date || date.getFullYear() !== this.$yearTitle.data('year')) { this.renderContent(); } this._colorYear(); } } setDisplayMode(displayMode: PlannerDisplayMode) { if (displayMode === this.displayMode) { return; } this._setProperty('displayMode', displayMode); if (this.rendered) { this._colorYear(); } } setViewRange(viewRange: DateRange) { if (viewRange === this.viewRange) { return; } this._setProperty('viewRange', viewRange); if (this.rendered) { this._colorYear(); } } /* -- events ---------------------------------------- */ protected _onYearClick(event: JQuery.ClickEvent) { let displayMode = Planner.DisplayMode, diff = $(event.target).data('year-diff'), year = this.selectedDate.getFullYear(), month = this.selectedDate.getMonth(), date = this.selectedDate.getDate(), newDate = new Date(year + diff, month, date), oldWeek, newWeek, weekDiff; if (this.alwaysSelectFirstDay) { // find date based on mode if (scout.isOneOf(this.displayMode, displayMode.WEEK, displayMode.WORK_WEEK, displayMode.CALENDAR_WEEK)) { oldWeek = dates.weekInYear(this.selectedDate); newWeek = dates.weekInYear(newDate); weekDiff = oldWeek - newWeek; // shift new selection that week in year does not change and the new selection is a monday. newDate = dates.shift(newDate, 0, 0, weekDiff * 7); newDate = dates.shiftToNextOrPrevMonday(newDate, 0); } else if (scout.isOneOf(this.displayMode, displayMode.MONTH, displayMode.YEAR)) { // set to first day of month newDate = new Date(year + diff, month, 1); } } this.selectedDate = newDate; this.trigger('dateSelect', { date: this.selectedDate }); } protected _onYearDayClick(event: JQuery.ClickEvent) { this.selectedDate = $('.year-hover-day', this.$yearList).data('date'); if (this.selectedDate) { this.trigger('dateSelect', { date: this.selectedDate }); } } protected _onYearHoverIn(event: JQuery.MouseEnterEvent) { let $day = $(event.target), date1 = $day.data('date'), year = date1.getFullYear(), month = date1.getMonth(), date = date1.getDate(), day = (date1.getDay() + 6) % 7, startHover, endHover, $day2, date2; // find hover based on mode if (this.displayMode === Calendar.DisplayMode.DAY) { startHover = new Date(year, month, date); endHover = new Date(year, month, date); } else if (this.displayMode === Calendar.DisplayMode.WEEK) { startHover = new Date(year, month, date - day); endHover = new Date(year, month, date - day + 6); } else if (this.displayMode === Calendar.DisplayMode.WORK_WEEK) { startHover = new Date(year, month, date - day); endHover = new Date(year, month, date - day + 4); // don't allow selecting a weekend day if (date1 > endHover) { date1 = endHover; } } else if (this.displayMode === Calendar.DisplayMode.MONTH) { startHover = new Date(year, month, 1); endHover = new Date(year, month + 1, 0); } else if (this.displayMode === Planner.DisplayMode.YEAR) { startHover = new Date(year, month, 1); endHover = startHover; } else { startHover = new Date(year, month, date - day); endHover = startHover; } if (this.alwaysSelectFirstDay) { date1 = startHover; } // loop days and colorize based on hover start and hover end $('.year-day', this.$yearList).each(function() { $day2 = $(this); date2 = $day2.data('date'); if (date2 >= startHover && date2 <= endHover) { $day2.addClass('year-hover'); } else { $day2.removeClass('year-hover'); } if (dates.isSameDay(date1, date2)) { $day2.addClass('year-hover-day'); } }); } // remove all hover effects protected _onYearHoverOut(event: JQuery.MouseLeaveEvent) { $('.year-day.year-hover, .year-day.year-hover-day', this.$yearList).removeClass('year-hover year-hover-day'); } }