@eclipse-scout/core
Version:
Eclipse Scout runtime
209 lines (185 loc) • 6.17 kB
text/typescript
/*
* 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
});
}
}