- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 90 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 98 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
- : 99 %
Source code
Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import { InputPickerPanelCommon } from "./InputPickerPanelCommon.sys.mjs";
/** @import {OpenPickerInfo} from "./InputPickerPanelCommon.sys.mjs" */
const TIME_PICKER_WIDTH = "13em";
const TIME_PICKER_HEIGHT = "22em";
const DATE_PICKER_WIDTH = "24em";
const DATE_PICKER_HEIGHT = "27em";
const DATETIME_PICKER_WIDTH = "40em";
const DATETIME_PICKER_HEIGHT = "27em";
export class DateTimePickerPanel extends InputPickerPanelCommon {
constructor(element) {
super(element, "chrome://global/content/datetimepicker.xhtml");
}
/**
* Picker window initialization function called when opening the picker
*
* @param {string} type The input element type
* @returns {OpenPickerInfo}
*/
openPickerImpl(type) {
if (
type == "datetime-local" &&
!Services.prefs.getBoolPref("dom.forms.datetime.timepicker")
) {
type = "date";
}
switch (type) {
case "time": {
return {
type,
width: TIME_PICKER_WIDTH,
height: TIME_PICKER_HEIGHT,
};
}
case "date": {
return {
type,
width: DATE_PICKER_WIDTH,
height: DATE_PICKER_HEIGHT,
};
}
case "datetime-local": {
return {
type,
width: DATETIME_PICKER_WIDTH,
height: DATETIME_PICKER_HEIGHT,
};
}
}
throw new Error(`Unexpected type ${type}`);
}
/**
* Popup frame initialization function called when the picker window is loaded
*
* @param {string} type The picker type
* @param {object} detail The argument from the child actor's openPickerImpl
* @returns An argument object to pass to the popup frame
*/
initPickerImpl(type, detail) {
let locale = new Services.intl.Locale(
Services.locale.webExposedLocales[0],
{
calendar: "gregory",
}
).toString();
// Workaround for bug 1418061, while we wait for resolution of
// http://bugs.icu-project.org/trac/ticket/13592: drop the PT region code,
// because it results in "abbreviated" day names that are too long;
// the region-less "pt" locale has shorter forms that are better here.
locale = locale.replace(/^pt-PT/i, "pt");
const dir = Services.locale.isAppLocaleRTL ? "rtl" : "ltr";
const { year, month, day, hour, minute } = detail.value;
const flattenDetail = {
type,
year,
// Month value from input box starts from 1 instead of 0
month: month == undefined ? undefined : month - 1,
day,
hour,
minute,
locale,
dir,
format: detail.format || "12",
min: detail.min,
max: detail.max,
step: detail.step,
stepBase: detail.stepBase,
};
if (type !== "time") {
const { firstDayOfWeek, weekends } = this.getCalendarInfo(locale);
const monthDisplayNames = new Services.intl.DisplayNames(locale, {
type: "month",
style: "short",
calendar: "gregory",
});
const monthStrings = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].map(
monthNumber => monthDisplayNames.of(monthNumber)
);
const weekdayDisplayNames = new Services.intl.DisplayNames(locale, {
type: "weekday",
style: "abbreviated",
calendar: "gregory",
});
const weekdayStrings = [
// Weekdays starting Sunday (7) to Saturday (6).
7, 1, 2, 3, 4, 5, 6,
].map(weekday => weekdayDisplayNames.of(weekday));
Object.assign(flattenDetail, {
firstDayOfWeek,
weekends,
monthStrings,
weekdayStrings,
});
}
return flattenDetail;
}
/**
* Input element state updater function called when the picker value is changed
*
* @param {string} type
* @param {object} pickerState
*/
sendPickerValueChangedImpl(type, pickerState) {
let { year, month, day, hour, minute } = pickerState;
if (month !== undefined) {
// Month value from input box starts from 1 instead of 0
month += 1;
}
switch (type) {
case "time": {
return { hour, minute };
}
case "date": {
return { year, month, day };
}
case "datetime-local": {
return { year, month, day, hour, minute };
}
}
throw new Error(`Unexpected type ${type}`);
}
getCalendarInfo(locale) {
const calendarInfo = Services.intl.getCalendarInfo(locale);
// Day of week from calendarInfo starts from 1 as Monday to 7 as Sunday,
// so they need to be mapped to JavaScript convention with 0 as Sunday
// and 6 as Saturday
function toDateWeekday(day) {
return day === 7 ? 0 : day;
}
let firstDayOfWeek = toDateWeekday(calendarInfo.firstDayOfWeek),
weekend = calendarInfo.weekend;
let weekends = weekend.map(toDateWeekday);
return {
firstDayOfWeek,
weekends,
};
}
}