UNPKG

@eclipse-scout/core

Version:
209 lines (185 loc) 6.17 kB
/* * Copyright (c) 2010, 2023 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 {dates, Device, HtmlComponent, InitModelOf, ScrollbarInstallOptions, scrollbars, SomeRequired, TimePickerEventMap, TimePickerModel, TimePickerTouchPopup, Widget} from '../index'; import $ from 'jquery'; export class TimePicker extends Widget implements TimePickerModel { declare model: TimePickerModel; declare initModel: SomeRequired<this['model'], 'parent' | 'timeResolution'>; declare eventMap: TimePickerEventMap; declare self: TimePicker; preselectedTime: Date; selectedTime: Date; viewDate: Date; resolution: number; constructor() { super(); this.preselectedTime = null; this.selectedTime = null; this.resolution = null; } protected override _init(options: InitModelOf<this>) { super._init(options); this.resolution = options.timeResolution; } protected override _render() { this.$container = this.$parent .appendDiv('time-picker') .toggleClass('touch-only', Device.get().supportsOnlyTouch()); this.$parent.appendDiv('time-picker-separator'); this.htmlComp = HtmlComponent.install(this.$container, this.session); this._renderTimeSelection(); this._installScrollbars(); } protected _renderTimeSelection(): JQuery { let i, date = dates.trunc(new Date()), now = dates.ceil(new Date(), this.resolution), currentHours = 0, $hourRow, $time; let $box = this.$parent.makeDiv('day-table'); for (i = 0; i < 24; i++) { // reset minutes always every hour line starts with 00 date.setMinutes(0); currentHours = date.getHours(); $hourRow = $box.appendDiv('hour-row'); let $hour = $hourRow.appendDiv('cell hours') .data('time', new Date(date)) .on('click', this._onTimeClick.bind(this)); if (now.getHours() === date.getHours()) { $hour.addClass('now'); } $hour.appendSpan('text') .text(dates.format(date, this.session.locale, 'HH')); while (currentHours === date.getHours()) { $time = $hourRow.appendDiv('cell minutes') .data('time', new Date(date)) .on('click', this._onTimeClick.bind(this)); $time.appendSpan('text').text(dates.format(date, this.session.locale, 'mm')); if (dates.isSameTime(now, date)) { $time.addClass('now'); } date.setMinutes(date.getMinutes() + this.resolution); } } $box.appendTo(this.$container); return $box; } protected override _installScrollbars(options?: ScrollbarInstallOptions) { this._uninstallScrollbars(); super._installScrollbars({ axis: 'y' }); } protected _scrollTo($scrollTo: JQuery) { if (!$scrollTo) { return; } if (this.parent instanceof TimePickerTouchPopup) { // setTimeout seems to be necessary on ios setTimeout(() => { if (this.rendered) { scrollbars.scrollTo(this.$container, $scrollTo, 'center'); } }); } else { scrollbars.scrollTo(this.$container, $scrollTo, 'center'); } } preselectTime(time: Date) { if (time) { // Clear selection when a date is preselected this.setSelectedTime(null); } this.setPreselectedTime(time); } /** * @internal, use {@link preselectDate} to preselect a date */ setPreselectedTime(preselectedTime: Date) { this.setProperty('preselectedTime', preselectedTime); } protected _renderPreselectedTime() { let $scrollTo: JQuery; this.$container.find('.cell').each((i, elem) => { let $time = $(elem), time = $time.data('time'); $time.removeClass('preselected'); if (this.preselectedTime) { if ($time.hasClass('hours') && this.preselectedTime.getHours() === time.getHours()) { $time.addClass('preselected'); $scrollTo = $time; } else if ($time.hasClass('minutes') && dates.isSameTime(this.preselectedTime, time)) { $time.addClass('preselected'); $scrollTo = $time; } } }); this._scrollTo($scrollTo); } selectTime(time: Date) { if (time) { // Clear selection when a date is preselected this.setPreselectedTime(null); } this.setSelectedTime(time); } /** * @internal, use selectDate to select a date */ setSelectedTime(selectedTime: Date) { this.setProperty('selectedTime', selectedTime); } protected _renderSelectedTime() { let $scrollTo: JQuery; this.$container.find('.cell').each((i, elem) => { let $time = $(elem), time = $time.data('time'); $time.removeClass('selected'); if (this.selectedTime) { if ($time.hasClass('hours') && this.selectedTime.getHours() === time.getHours()) { $time.addClass('selected'); $scrollTo = $time; } else if ($time.hasClass('minutes') && dates.isSameTime(this.selectedTime, time)) { $time.addClass('selected'); $scrollTo = $time; } } }); this._scrollTo($scrollTo); } shiftSelectedTime(hourUnits: number, minuteUnits: number, secondUnits: number) { let time = this.preselectedTime; if (this.selectedTime) { time = dates.shiftTime(this.selectedTime, hourUnits, minuteUnits * this.resolution, secondUnits); } if (!time) { return; // do nothing when no date was found } this.selectTime(this._snapToTimeGrid(time)); } protected _snapToTimeGrid(time: Date): Date { if (!time) { return time; } let min = time.getMinutes(); min = (parseInt((min / this.resolution) + '') * this.resolution); time.setMinutes(min); return time; } protected _onTimeClick(event: JQuery.ClickEvent) { let $target = $(event.currentTarget); let time = new Date($target.data('time')); this.selectTime(time); this.trigger('timeSelect', { time: time }); } }