1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 export var DateTimePickerPanel = class {
7 this.element = element;
9 this.TIME_PICKER_WIDTH = "13em";
10 this.TIME_PICKER_HEIGHT = "22em";
11 this.DATE_PICKER_WIDTH = "24em";
12 this.DATE_PICKER_HEIGHT = "27em";
15 get dateTimePopupFrame() {
16 let frame = this.element.querySelector("#dateTimePopupFrame");
18 frame = this.element.ownerDocument.createXULElement("iframe");
19 frame.id = "dateTimePopupFrame";
20 this.element.appendChild(frame);
25 openPicker(type, rect, detail) {
26 if (type == "datetime-local") {
30 this.pickerState = {};
31 // TODO: Resize picker according to content zoom level
32 this.element.style.fontSize = "10px";
36 this.dateTimePopupFrame.addEventListener("load", this, true);
37 this.dateTimePopupFrame.setAttribute(
39 "chrome://global/content/timepicker.xhtml"
41 this.dateTimePopupFrame.style.width = this.TIME_PICKER_WIDTH;
42 this.dateTimePopupFrame.style.height = this.TIME_PICKER_HEIGHT;
47 this.dateTimePopupFrame.addEventListener("load", this, true);
48 this.dateTimePopupFrame.setAttribute(
50 "chrome://global/content/datepicker.xhtml"
52 this.dateTimePopupFrame.style.width = this.DATE_PICKER_WIDTH;
53 this.dateTimePopupFrame.style.height = this.DATE_PICKER_HEIGHT;
57 this.element.openPopupAtScreenRect(
70 this.element.dispatchEvent(new CustomEvent("DateTimePickerValueCleared"));
72 this.pickerState = {};
73 this.type = undefined;
74 this.dateTimePopupFrame.removeEventListener("load", this, true);
75 this.dateTimePopupFrame.contentDocument.removeEventListener(
79 this.dateTimePopupFrame.setAttribute("src", "");
80 this.element.hidePopup();
86 this.postMessageToPicker({
87 name: "PickerSetValue",
93 const { year, month, day } = data.value;
94 this.postMessageToPicker({
95 name: "PickerSetValue",
98 // Month value from input box starts from 1 instead of 0
99 month: month == undefined ? undefined : month - 1,
109 let locale = new Services.intl.Locale(
110 Services.locale.webExposedLocales[0],
116 // Workaround for bug 1418061, while we wait for resolution of
117 // http://bugs.icu-project.org/trac/ticket/13592: drop the PT region code,
118 // because it results in "abbreviated" day names that are too long;
119 // the region-less "pt" locale has shorter forms that are better here.
120 locale = locale.replace(/^pt-PT/i, "pt");
122 const dir = Services.locale.isAppLocaleRTL ? "rtl" : "ltr";
126 const { hour, minute } = detail.value;
127 const format = detail.format || "12";
129 this.postMessageToPicker({
144 const { year, month, day } = detail.value;
145 const { firstDayOfWeek, weekends } = this.getCalendarInfo(locale);
147 const monthDisplayNames = new Services.intl.DisplayNames(locale, {
152 const monthStrings = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].map(
153 month => monthDisplayNames.of(month)
156 const weekdayDisplayNames = new Services.intl.DisplayNames(locale, {
158 style: "abbreviated",
161 const weekdayStrings = [
162 // Weekdays starting Sunday (7) to Saturday (6).
164 ].map(weekday => weekdayDisplayNames.of(weekday));
166 this.postMessageToPicker({
170 // Month value from input box starts from 1 instead of 0
171 month: month == undefined ? undefined : month - 1,
182 stepBase: detail.stepBase,
191 * @param {Boolean} passAllValues: Pass spinner values regardless if they've been set/changed or not
193 setInputBoxValue(passAllValues) {
196 const { hour, minute, isHourSet, isMinuteSet, isDayPeriodSet } =
198 const isAnyValueSet = isHourSet || isMinuteSet || isDayPeriodSet;
199 if (passAllValues && isAnyValueSet) {
200 this.sendPickerValueChanged({ hour, minute });
202 this.sendPickerValueChanged({
203 hour: isHourSet || isDayPeriodSet ? hour : undefined,
204 minute: isMinuteSet ? minute : undefined,
210 this.sendPickerValueChanged(this.pickerState);
216 sendPickerValueChanged(value) {
219 this.element.dispatchEvent(
220 new CustomEvent("DateTimePickerValueChanged", {
223 minute: value.minute,
230 this.element.dispatchEvent(
231 new CustomEvent("DateTimePickerValueChanged", {
234 // Month value from input box starts from 1 instead of 0
235 month: value.month == undefined ? undefined : value.month + 1,
245 getCalendarInfo(locale) {
246 const calendarInfo = Services.intl.getCalendarInfo(locale);
248 // Day of week from calendarInfo starts from 1 as Monday to 7 as Sunday,
249 // so they need to be mapped to JavaScript convention with 0 as Sunday
251 function toDateWeekday(day) {
252 return day === 7 ? 0 : day;
255 let firstDayOfWeek = toDateWeekday(calendarInfo.firstDayOfWeek),
256 weekend = calendarInfo.weekend;
258 let weekends = weekend.map(toDateWeekday);
266 handleEvent(aEvent) {
267 switch (aEvent.type) {
269 this.initPicker(this.detail);
270 this.dateTimePopupFrame.contentWindow.addEventListener("message", this);
274 this.handleMessage(aEvent);
280 handleMessage(aEvent) {
282 !this.dateTimePopupFrame.contentDocument.nodePrincipal.isSystemPrincipal
287 switch (aEvent.data.name) {
288 case "PickerPopupChanged": {
289 this.pickerState = aEvent.data.detail;
290 this.setInputBoxValue();
294 this.closePicker(aEvent.data.detail);
300 postMessageToPicker(data) {
302 this.dateTimePopupFrame.contentDocument.nodePrincipal.isSystemPrincipal
304 this.dateTimePopupFrame.contentWindow.postMessage(data, "*");