blob: 84828a16fd5710f9df0443154e114f6489fed1d8 [file] [log] [blame]
'use strict';
// Copyright (C) 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Picker used by <input type='datetime-local' />
*/
function initializeDateTimeLocalPicker(config) {
const dateTimeLocalPicker = new DateTimeLocalPicker(config);
global.picker = dateTimeLocalPicker;
main.append(dateTimeLocalPicker);
main.style.border = '1px solid transparent';
main.style.height = dateTimeLocalPicker.height + 'px';
main.style.width = dateTimeLocalPicker.width + 'px';
resizeWindow(dateTimeLocalPicker.width + 2, dateTimeLocalPicker.height + 2);
}
/**
* DateTimeLocalPicker: Custom element providing a datetime-local picker implementation.
* DateTimeLocalPicker contains 2 parts:
* - date picker
* - time picker
*/
class DateTimeLocalPicker extends HTMLElement {
constructor(config) {
super();
this.className = DateTimeLocalPicker.ClassName;
this.datePicker_ = new CalendarPicker(config.mode, config);
this.timePicker_ = new TimePicker(config);
this.append(this.datePicker_.element, this.timePicker_);
this.hadValidValueWhenOpened_ =
(config.currentValue !== '') && (this.datePicker_.selection() != null);
this.initialSelectedValue_ = this.selectedValue;
this.initialFocusedFieldIndex_ = config.focusedFieldIndex || 0;
this.addEventListener('keydown', this.onKeyDown_);
this.addEventListener('click', this.onClick_);
window.addEventListener('resize', this.onWindowResize_, {once: true});
};
onKeyDown_ = (event) => {
switch (event.key) {
case 'Enter':
// Submit the popup for an Enter keypress except when the user is
// hitting Enter to activate the month switcher button, Today button,
// or previous/next month arrows.
if (!event.target.matches(
'.calendar-navigation-button, .month-popup-button, .year-list-view')) {
window.pagePopupController.setValueAndClosePopup(
0, this.selectedValue);
} else if (event.target.matches(
'.calendar-navigation-button, .year-list-view')) {
// Navigating with the previous/next arrows may change selection,
// so push this change to the in-page control but don't
// close the popup.
window.pagePopupController.setValue(this.selectedValue);
}
break;
case 'Escape':
if (this.selectedValue === this.initialSelectedValue_) {
window.pagePopupController.closePopup();
} else {
this.datePicker_.resetToInitialValue();
this.timePicker_.resetToInitialValue();
window.pagePopupController.setValue(
this.hadValidValueWhenOpened_ ? this.initialSelectedValue_ : '');
}
break;
case 'ArrowUp':
case 'ArrowDown':
case 'ArrowLeft':
case 'ArrowRight':
case 'PageUp':
case 'PageDown':
if (event.target.matches('.calendar-table-view, .time-column') &&
this.hasSelectedDate) {
window.pagePopupController.setValue(this.selectedValue);
}
// Stop the native scrolling behavior; the Time picker needs to manage
// its own scroll position.
event.preventDefault();
break;
case 'Home':
case 'End':
window.pagePopupController.setValue(this.selectedValue);
event.stopPropagation();
// Prevent an attempt to scroll to the end of
// of an infinitely looping time picker column.
event.preventDefault();
break;
}
};
onClick_ = (event) => {
if (event.target.matches(
'.day-cell, .time-cell, .today-button-refresh, .calendar-navigation-button, .year-list-view, .calendar-navigation-button, .navigation-button-icon-refresh, .month-button') &&
this.hasSelectedDate) {
window.pagePopupController.setValue(this.selectedValue);
}
};
onWindowResize_ = (event) => {
// Check if we should focus on time field by subtracting 3 (month, day, and
// year) from index
let timeFocusFieldIndex = this.initialFocusedFieldIndex_ - 3;
if (timeFocusFieldIndex < 0 ||
!this.timePicker_.focusOnFieldIndex(timeFocusFieldIndex)) {
// Default to focus on date
this.datePicker_.calendarTableView.element.focus();
}
};
// This will be false if neither the initial value of the
// control nor today's date are within a valid date range defined
// by the 'step', 'min', and 'max' attributes of the control.
get hasSelectedDate() {
return (this.datePicker_.selection() != null);
}
get selectedValue() {
return this.hasSelectedDate ? (this.datePicker_.getSelectedValue() + 'T' +
this.timePicker_.selectedValue) :
'';
}
get height() {
return DateTimeLocalPicker.Height;
}
get width() {
return this.datePicker_.width() + this.timePicker_.width;
}
get datePicker() {
return this.datePicker_;
}
get timePicker() {
return this.timePicker_;
}
}
DateTimeLocalPicker.ClassName = 'datetimelocal-picker';
DateTimeLocalPicker.Height = 280;
window.customElements.define('datetimelocal-picker', DateTimeLocalPicker);