зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1512489 - Convert datetime-popup binding to a JSM r=Felipe
Differential Revision: https://phabricator.services.mozilla.com/D13944 --HG-- rename : toolkit/content/widgets/datetimepopup.xml => toolkit/modules/DateTimePickerPanel.jsm extra : moz-landing-system : lando
This commit is contained in:
Родитель
12e4f91411
Коммит
9292b73037
|
@ -739,10 +739,6 @@ html|input.urlbar-input {
|
|||
transition: none;
|
||||
}
|
||||
|
||||
#DateTimePickerPanel[active="true"] {
|
||||
-moz-binding: url("chrome://global/content/bindings/datetimepopup.xml#datetime-popup");
|
||||
}
|
||||
|
||||
#urlbar[pageproxystate=invalid] > #page-action-buttons > .urlbar-page-action,
|
||||
#identity-box.chromeUI ~ #page-action-buttons > .urlbar-page-action:not(#star-button-box),
|
||||
.urlbar-history-dropmarker[usertyping],
|
||||
|
|
|
@ -68,7 +68,6 @@ toolkit.jar:
|
|||
content/global/bindings/checkbox.xml (widgets/checkbox.xml)
|
||||
content/global/bindings/datekeeper.js (widgets/datekeeper.js)
|
||||
content/global/bindings/datepicker.js (widgets/datepicker.js)
|
||||
content/global/bindings/datetimepopup.xml (widgets/datetimepopup.xml)
|
||||
content/global/bindings/datetimebox.xml (widgets/datetimebox.xml)
|
||||
content/global/bindings/datetimebox.css (widgets/datetimebox.css)
|
||||
* content/global/bindings/dialog.xml (widgets/dialog.xml)
|
||||
|
|
|
@ -142,14 +142,7 @@ class DateTimeTestHelper {
|
|||
async openPicker(pageUrl) {
|
||||
this.tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
|
||||
await BrowserTestUtils.synthesizeMouseAtCenter("input", {}, gBrowser.selectedBrowser);
|
||||
// If dateTimePopupFrame doesn't exist yet, wait for the binding to be
|
||||
// attached.
|
||||
// FIXME: This has a race condition and we may miss the following events.
|
||||
// (bug 1423498)
|
||||
if (!this.panel.dateTimePopupFrame) {
|
||||
await BrowserTestUtils.waitForEvent(this.panel, "DateTimePickerBindingReady");
|
||||
}
|
||||
this.frame = this.panel.dateTimePopupFrame;
|
||||
this.frame = this.panel.querySelector("#dateTimePopupFrame");
|
||||
await this.waitForPickerReady();
|
||||
}
|
||||
|
||||
|
@ -207,7 +200,6 @@ class DateTimeTestHelper {
|
|||
this.panel.addEventListener("popuphidden", resolve, {once: true});
|
||||
});
|
||||
this.panel.hidePopup();
|
||||
this.panel.closePicker();
|
||||
await pickerClosePromise;
|
||||
}
|
||||
BrowserTestUtils.removeTab(this.tab);
|
||||
|
|
|
@ -1,337 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- 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/. -->
|
||||
|
||||
<bindings id="dateTimePopupBindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
<binding id="datetime-popup"
|
||||
extends="chrome://global/content/bindings/popup.xml#arrowpanel">
|
||||
<implementation>
|
||||
<property name="dateTimePopupFrame">
|
||||
<getter>
|
||||
let frame = this.querySelector("#dateTimePopupFrame");
|
||||
if (!frame) {
|
||||
frame = this.ownerDocument.createXULElement("iframe");
|
||||
frame.id = "dateTimePopupFrame";
|
||||
this.appendChild(frame);
|
||||
}
|
||||
return frame;
|
||||
</getter>
|
||||
</property>
|
||||
<field name="TIME_PICKER_WIDTH" readonly="true">"12em"</field>
|
||||
<field name="TIME_PICKER_HEIGHT" readonly="true">"21em"</field>
|
||||
<field name="DATE_PICKER_WIDTH" readonly="true">"23.1em"</field>
|
||||
<field name="DATE_PICKER_HEIGHT" readonly="true">"20.7em"</field>
|
||||
<constructor><![CDATA[
|
||||
this.mozIntl = Cc["@mozilla.org/mozintl;1"]
|
||||
.getService(Ci.mozIMozIntl);
|
||||
// Notify DateTimePickerParent.jsm that binding is ready.
|
||||
this.dispatchEvent(new CustomEvent("DateTimePickerBindingReady"));
|
||||
]]></constructor>
|
||||
<method name="openPicker">
|
||||
<parameter name="type"/>
|
||||
<parameter name="anchor"/>
|
||||
<parameter name="detail"/>
|
||||
<body><![CDATA[
|
||||
this.type = type;
|
||||
this.pickerState = {};
|
||||
// TODO: Resize picker according to content zoom level
|
||||
this.style.fontSize = "10px";
|
||||
switch (type) {
|
||||
case "time": {
|
||||
this.detail = detail;
|
||||
this.dateTimePopupFrame.addEventListener("load", this, true);
|
||||
this.dateTimePopupFrame.setAttribute("src", "chrome://global/content/timepicker.xhtml");
|
||||
this.dateTimePopupFrame.style.width = this.TIME_PICKER_WIDTH;
|
||||
this.dateTimePopupFrame.style.height = this.TIME_PICKER_HEIGHT;
|
||||
break;
|
||||
}
|
||||
case "date": {
|
||||
this.detail = detail;
|
||||
this.dateTimePopupFrame.addEventListener("load", this, true);
|
||||
this.dateTimePopupFrame.setAttribute("src", "chrome://global/content/datepicker.xhtml");
|
||||
this.dateTimePopupFrame.style.width = this.DATE_PICKER_WIDTH;
|
||||
this.dateTimePopupFrame.style.height = this.DATE_PICKER_HEIGHT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.hidden = false;
|
||||
this.openPopup(anchor, "after_start", 0, 0);
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="closePicker">
|
||||
<body><![CDATA[
|
||||
this.setInputBoxValue(true);
|
||||
this.pickerState = {};
|
||||
this.type = undefined;
|
||||
this.dateTimePopupFrame.removeEventListener("load", this, true);
|
||||
this.dateTimePopupFrame.contentDocument.removeEventListener("message", this);
|
||||
this.dateTimePopupFrame.setAttribute("src", "");
|
||||
this.hidden = true;
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="setPopupValue">
|
||||
<parameter name="data"/>
|
||||
<body><![CDATA[
|
||||
switch (this.type) {
|
||||
case "time": {
|
||||
this.postMessageToPicker({
|
||||
name: "PickerSetValue",
|
||||
detail: data.value,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "date": {
|
||||
const { year, month, day } = data.value;
|
||||
this.postMessageToPicker({
|
||||
name: "PickerSetValue",
|
||||
detail: {
|
||||
year,
|
||||
// Month value from input box starts from 1 instead of 0
|
||||
month: month == undefined ? undefined : month - 1,
|
||||
day,
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="initPicker">
|
||||
<parameter name="detail"/>
|
||||
<body><![CDATA[
|
||||
// TODO: When bug 1376616 lands, replace this.setGregorian with
|
||||
// mozIntl.Locale for setting calendar to Gregorian
|
||||
const locale = this.setGregorian(Services.locale.appLocaleAsBCP47);
|
||||
const dir = this.mozIntl.getLocaleInfo(locale).direction;
|
||||
|
||||
switch (this.type) {
|
||||
case "time": {
|
||||
const { hour, minute } = detail.value;
|
||||
const format = detail.format || "12";
|
||||
|
||||
this.postMessageToPicker({
|
||||
name: "PickerInit",
|
||||
detail: {
|
||||
hour,
|
||||
minute,
|
||||
format,
|
||||
locale,
|
||||
min: detail.min,
|
||||
max: detail.max,
|
||||
step: detail.step,
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "date": {
|
||||
const { year, month, day } = detail.value;
|
||||
const { firstDayOfWeek, weekends } =
|
||||
this.getCalendarInfo(locale);
|
||||
const monthStrings = this.getDisplayNames(
|
||||
locale, [
|
||||
"dates/gregorian/months/january",
|
||||
"dates/gregorian/months/february",
|
||||
"dates/gregorian/months/march",
|
||||
"dates/gregorian/months/april",
|
||||
"dates/gregorian/months/may",
|
||||
"dates/gregorian/months/june",
|
||||
"dates/gregorian/months/july",
|
||||
"dates/gregorian/months/august",
|
||||
"dates/gregorian/months/september",
|
||||
"dates/gregorian/months/october",
|
||||
"dates/gregorian/months/november",
|
||||
"dates/gregorian/months/december",
|
||||
], "short");
|
||||
const weekdayStrings = this.getDisplayNames(
|
||||
locale, [
|
||||
"dates/gregorian/weekdays/sunday",
|
||||
"dates/gregorian/weekdays/monday",
|
||||
"dates/gregorian/weekdays/tuesday",
|
||||
"dates/gregorian/weekdays/wednesday",
|
||||
"dates/gregorian/weekdays/thursday",
|
||||
"dates/gregorian/weekdays/friday",
|
||||
"dates/gregorian/weekdays/saturday",
|
||||
], "short");
|
||||
|
||||
this.postMessageToPicker({
|
||||
name: "PickerInit",
|
||||
detail: {
|
||||
year,
|
||||
// Month value from input box starts from 1 instead of 0
|
||||
month: month == undefined ? undefined : month - 1,
|
||||
day,
|
||||
firstDayOfWeek,
|
||||
weekends,
|
||||
monthStrings,
|
||||
weekdayStrings,
|
||||
locale,
|
||||
dir,
|
||||
min: detail.min,
|
||||
max: detail.max,
|
||||
step: detail.step,
|
||||
stepBase: detail.stepBase,
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="setInputBoxValue">
|
||||
<parameter name="passAllValues"/>
|
||||
<body><![CDATA[
|
||||
/**
|
||||
* @param {Boolean} passAllValues: Pass spinner values regardless if they've been set/changed or not
|
||||
*/
|
||||
switch (this.type) {
|
||||
case "time": {
|
||||
const { hour, minute, isHourSet, isMinuteSet, isDayPeriodSet } = this.pickerState;
|
||||
const isAnyValueSet = isHourSet || isMinuteSet || isDayPeriodSet;
|
||||
if (passAllValues && isAnyValueSet) {
|
||||
this.sendPickerValueChanged({ hour, minute });
|
||||
} else {
|
||||
this.sendPickerValueChanged({
|
||||
hour: isHourSet || isDayPeriodSet ? hour : undefined,
|
||||
minute: isMinuteSet ? minute : undefined,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "date": {
|
||||
this.sendPickerValueChanged(this.pickerState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="sendPickerValueChanged">
|
||||
<parameter name="value"/>
|
||||
<body><![CDATA[
|
||||
switch (this.type) {
|
||||
case "time": {
|
||||
this.dispatchEvent(new CustomEvent("DateTimePickerValueChanged", {
|
||||
detail: {
|
||||
hour: value.hour,
|
||||
minute: value.minute,
|
||||
},
|
||||
}));
|
||||
break;
|
||||
}
|
||||
case "date": {
|
||||
this.dispatchEvent(new CustomEvent("DateTimePickerValueChanged", {
|
||||
detail: {
|
||||
year: value.year,
|
||||
// Month value from input box starts from 1 instead of 0
|
||||
month: value.month == undefined ? undefined : value.month + 1,
|
||||
day: value.day,
|
||||
},
|
||||
}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="getCalendarInfo">
|
||||
<parameter name="locale"/>
|
||||
<body><![CDATA[
|
||||
const calendarInfo = this.mozIntl.getCalendarInfo(locale);
|
||||
|
||||
// Day of week from calendarInfo starts from 1 as Sunday to 7 as Saturday,
|
||||
// so they need to be mapped to JavaScript convention with 0 as Sunday
|
||||
// and 6 as Saturday
|
||||
let firstDayOfWeek = calendarInfo.firstDayOfWeek - 1,
|
||||
weekendStart = calendarInfo.weekendStart - 1,
|
||||
weekendEnd = calendarInfo.weekendEnd - 1;
|
||||
|
||||
let weekends = [];
|
||||
|
||||
// Make sure weekendEnd is greater than weekendStart
|
||||
if (weekendEnd < weekendStart) {
|
||||
weekendEnd += 7;
|
||||
}
|
||||
|
||||
// We get the weekends by incrementing weekendStart up to weekendEnd.
|
||||
// If the start and end is the same day, then weekends only has one day.
|
||||
for (let day = weekendStart; day <= weekendEnd; day++) {
|
||||
weekends.push(day % 7);
|
||||
}
|
||||
|
||||
return {
|
||||
firstDayOfWeek,
|
||||
weekends,
|
||||
};
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="getDisplayNames">
|
||||
<parameter name="locale"/>
|
||||
<parameter name="keys"/>
|
||||
<parameter name="style"/>
|
||||
<body><![CDATA[
|
||||
const displayNames = this.mozIntl.getDisplayNames(locale, {keys, style});
|
||||
return keys.map(key => displayNames.values[key]);
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="setGregorian">
|
||||
<parameter name="locale"/>
|
||||
<body><![CDATA[
|
||||
if (locale.match(/u-ca-/)) {
|
||||
return locale.replace(/u-ca-[^-]+/, "u-ca-gregory");
|
||||
}
|
||||
return locale + "-u-ca-gregory";
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="handleEvent">
|
||||
<parameter name="aEvent"/>
|
||||
<body><![CDATA[
|
||||
switch (aEvent.type) {
|
||||
case "load": {
|
||||
this.initPicker(this.detail);
|
||||
this.dateTimePopupFrame.contentWindow.addEventListener("message", this);
|
||||
break;
|
||||
}
|
||||
case "message": {
|
||||
this.handleMessage(aEvent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="handleMessage">
|
||||
<parameter name="aEvent"/>
|
||||
<body><![CDATA[
|
||||
if (!this.dateTimePopupFrame.contentDocument.nodePrincipal.isSystemPrincipal) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aEvent.data.name) {
|
||||
case "PickerPopupChanged": {
|
||||
this.pickerState = aEvent.data.detail;
|
||||
this.setInputBoxValue();
|
||||
break;
|
||||
}
|
||||
case "ClosePopup": {
|
||||
this.hidePopup();
|
||||
this.closePicker();
|
||||
break;
|
||||
}
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
<method name="postMessageToPicker">
|
||||
<parameter name="data"/>
|
||||
<body><![CDATA[
|
||||
if (this.dateTimePopupFrame.contentDocument.nodePrincipal.isSystemPrincipal) {
|
||||
this.dateTimePopupFrame.contentWindow.postMessage(data, "*");
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
</implementation>
|
||||
</binding>
|
||||
</bindings>
|
|
@ -0,0 +1,317 @@
|
|||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = [
|
||||
"DateTimePickerPanel",
|
||||
];
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var DateTimePickerPanel = class {
|
||||
constructor(element) {
|
||||
this.element = element;
|
||||
|
||||
this.TIME_PICKER_WIDTH = "12em";
|
||||
this.TIME_PICKER_HEIGHT = "21em";
|
||||
this.DATE_PICKER_WIDTH = "23.1em";
|
||||
this.DATE_PICKER_HEIGHT = "20.7em";
|
||||
}
|
||||
|
||||
get dateTimePopupFrame() {
|
||||
let frame = this.element.querySelector("#dateTimePopupFrame");
|
||||
if (!frame) {
|
||||
frame = this.element.ownerDocument.createXULElement("iframe");
|
||||
frame.id = "dateTimePopupFrame";
|
||||
this.element.appendChild(frame);
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
|
||||
openPicker(type, anchor, detail) {
|
||||
this.type = type;
|
||||
this.pickerState = {};
|
||||
// TODO: Resize picker according to content zoom level
|
||||
this.element.style.fontSize = "10px";
|
||||
switch (type) {
|
||||
case "time":
|
||||
{
|
||||
this.detail = detail;
|
||||
this.dateTimePopupFrame.addEventListener("load", this, true);
|
||||
this.dateTimePopupFrame.setAttribute("src", "chrome://global/content/timepicker.xhtml");
|
||||
this.dateTimePopupFrame.style.width = this.TIME_PICKER_WIDTH;
|
||||
this.dateTimePopupFrame.style.height = this.TIME_PICKER_HEIGHT;
|
||||
break;
|
||||
}
|
||||
case "date":
|
||||
{
|
||||
this.detail = detail;
|
||||
this.dateTimePopupFrame.addEventListener("load", this, true);
|
||||
this.dateTimePopupFrame.setAttribute("src", "chrome://global/content/datepicker.xhtml");
|
||||
this.dateTimePopupFrame.style.width = this.DATE_PICKER_WIDTH;
|
||||
this.dateTimePopupFrame.style.height = this.DATE_PICKER_HEIGHT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.element.hidden = false;
|
||||
this.element.openPopup(anchor, "after_start", 0, 0);
|
||||
}
|
||||
|
||||
closePicker() {
|
||||
this.setInputBoxValue(true);
|
||||
this.pickerState = {};
|
||||
this.type = undefined;
|
||||
this.dateTimePopupFrame.removeEventListener("load", this, true);
|
||||
this.dateTimePopupFrame.contentDocument.removeEventListener("message", this);
|
||||
this.dateTimePopupFrame.setAttribute("src", "");
|
||||
this.element.hidden = true;
|
||||
}
|
||||
|
||||
setPopupValue(data) {
|
||||
switch (this.type) {
|
||||
case "time":
|
||||
{
|
||||
this.postMessageToPicker({
|
||||
name: "PickerSetValue",
|
||||
detail: data.value,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "date":
|
||||
{
|
||||
const { year, month, day } = data.value;
|
||||
this.postMessageToPicker({
|
||||
name: "PickerSetValue",
|
||||
detail: {
|
||||
year,
|
||||
// Month value from input box starts from 1 instead of 0
|
||||
month: month == undefined ? undefined : month - 1,
|
||||
day,
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initPicker(detail) {
|
||||
// TODO: When bug 1376616 lands, replace this.setGregorian with
|
||||
// mozIntl.Locale for setting calendar to Gregorian
|
||||
const locale = this.setGregorian(Services.locale.appLocaleAsBCP47);
|
||||
const dir = Services.intl.getLocaleInfo(locale).direction;
|
||||
|
||||
switch (this.type) {
|
||||
case "time":
|
||||
{
|
||||
const { hour, minute } = detail.value;
|
||||
const format = detail.format || "12";
|
||||
|
||||
this.postMessageToPicker({
|
||||
name: "PickerInit",
|
||||
detail: {
|
||||
hour,
|
||||
minute,
|
||||
format,
|
||||
locale,
|
||||
min: detail.min,
|
||||
max: detail.max,
|
||||
step: detail.step,
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
case "date":
|
||||
{
|
||||
const { year, month, day } = detail.value;
|
||||
const { firstDayOfWeek, weekends } =
|
||||
this.getCalendarInfo(locale);
|
||||
const monthStrings = this.getDisplayNames(
|
||||
locale, [
|
||||
"dates/gregorian/months/january",
|
||||
"dates/gregorian/months/february",
|
||||
"dates/gregorian/months/march",
|
||||
"dates/gregorian/months/april",
|
||||
"dates/gregorian/months/may",
|
||||
"dates/gregorian/months/june",
|
||||
"dates/gregorian/months/july",
|
||||
"dates/gregorian/months/august",
|
||||
"dates/gregorian/months/september",
|
||||
"dates/gregorian/months/october",
|
||||
"dates/gregorian/months/november",
|
||||
"dates/gregorian/months/december",
|
||||
], "short");
|
||||
const weekdayStrings = this.getDisplayNames(
|
||||
locale, [
|
||||
"dates/gregorian/weekdays/sunday",
|
||||
"dates/gregorian/weekdays/monday",
|
||||
"dates/gregorian/weekdays/tuesday",
|
||||
"dates/gregorian/weekdays/wednesday",
|
||||
"dates/gregorian/weekdays/thursday",
|
||||
"dates/gregorian/weekdays/friday",
|
||||
"dates/gregorian/weekdays/saturday",
|
||||
], "short");
|
||||
|
||||
this.postMessageToPicker({
|
||||
name: "PickerInit",
|
||||
detail: {
|
||||
year,
|
||||
// Month value from input box starts from 1 instead of 0
|
||||
month: month == undefined ? undefined : month - 1,
|
||||
day,
|
||||
firstDayOfWeek,
|
||||
weekends,
|
||||
monthStrings,
|
||||
weekdayStrings,
|
||||
locale,
|
||||
dir,
|
||||
min: detail.min,
|
||||
max: detail.max,
|
||||
step: detail.step,
|
||||
stepBase: detail.stepBase,
|
||||
},
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Boolean} passAllValues: Pass spinner values regardless if they've been set/changed or not
|
||||
*/
|
||||
setInputBoxValue(passAllValues) {
|
||||
switch (this.type) {
|
||||
case "time":
|
||||
{
|
||||
const { hour, minute, isHourSet, isMinuteSet, isDayPeriodSet } = this.pickerState;
|
||||
const isAnyValueSet = isHourSet || isMinuteSet || isDayPeriodSet;
|
||||
if (passAllValues && isAnyValueSet) {
|
||||
this.sendPickerValueChanged({ hour, minute });
|
||||
} else {
|
||||
this.sendPickerValueChanged({
|
||||
hour: isHourSet || isDayPeriodSet ? hour : undefined,
|
||||
minute: isMinuteSet ? minute : undefined,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "date":
|
||||
{
|
||||
this.sendPickerValueChanged(this.pickerState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sendPickerValueChanged(value) {
|
||||
switch (this.type) {
|
||||
case "time":
|
||||
{
|
||||
this.element.dispatchEvent(new CustomEvent("DateTimePickerValueChanged", {
|
||||
detail: {
|
||||
hour: value.hour,
|
||||
minute: value.minute,
|
||||
},
|
||||
}));
|
||||
break;
|
||||
}
|
||||
case "date":
|
||||
{
|
||||
this.element.dispatchEvent(new CustomEvent("DateTimePickerValueChanged", {
|
||||
detail: {
|
||||
year: value.year,
|
||||
// Month value from input box starts from 1 instead of 0
|
||||
month: value.month == undefined ? undefined : value.month + 1,
|
||||
day: value.day,
|
||||
},
|
||||
}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getCalendarInfo(locale) {
|
||||
const calendarInfo = Services.intl.getCalendarInfo(locale);
|
||||
|
||||
// Day of week from calendarInfo starts from 1 as Sunday to 7 as Saturday,
|
||||
// so they need to be mapped to JavaScript convention with 0 as Sunday
|
||||
// and 6 as Saturday
|
||||
let firstDayOfWeek = calendarInfo.firstDayOfWeek - 1,
|
||||
weekendStart = calendarInfo.weekendStart - 1,
|
||||
weekendEnd = calendarInfo.weekendEnd - 1;
|
||||
|
||||
let weekends = [];
|
||||
|
||||
// Make sure weekendEnd is greater than weekendStart
|
||||
if (weekendEnd < weekendStart) {
|
||||
weekendEnd += 7;
|
||||
}
|
||||
|
||||
// We get the weekends by incrementing weekendStart up to weekendEnd.
|
||||
// If the start and end is the same day, then weekends only has one day.
|
||||
for (let day = weekendStart; day <= weekendEnd; day++) {
|
||||
weekends.push(day % 7);
|
||||
}
|
||||
|
||||
return {
|
||||
firstDayOfWeek,
|
||||
weekends,
|
||||
};
|
||||
}
|
||||
|
||||
getDisplayNames(locale, keys, style) {
|
||||
const displayNames = Services.intl.getDisplayNames(locale, { keys, style });
|
||||
return keys.map(key => displayNames.values[key]);
|
||||
}
|
||||
|
||||
setGregorian(locale) {
|
||||
if (locale.match(/u-ca-/)) {
|
||||
return locale.replace(/u-ca-[^-]+/, "u-ca-gregory");
|
||||
}
|
||||
return locale + "-u-ca-gregory";
|
||||
}
|
||||
|
||||
handleEvent(aEvent) {
|
||||
switch (aEvent.type) {
|
||||
case "load":
|
||||
{
|
||||
this.initPicker(this.detail);
|
||||
this.dateTimePopupFrame.contentWindow.addEventListener("message", this);
|
||||
break;
|
||||
}
|
||||
case "message":
|
||||
{
|
||||
this.handleMessage(aEvent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleMessage(aEvent) {
|
||||
if (!this.dateTimePopupFrame.contentDocument.nodePrincipal.isSystemPrincipal) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aEvent.data.name) {
|
||||
case "PickerPopupChanged":
|
||||
{
|
||||
this.pickerState = aEvent.data.detail;
|
||||
this.setInputBoxValue();
|
||||
break;
|
||||
}
|
||||
case "ClosePopup":
|
||||
{
|
||||
this.element.hidePopup();
|
||||
this.closePicker();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
postMessageToPicker(data) {
|
||||
if (this.dateTimePopupFrame.contentDocument.nodePrincipal.isSystemPrincipal) {
|
||||
this.dateTimePopupFrame.contentWindow.postMessage(data, "*");
|
||||
}
|
||||
}
|
||||
};
|
|
@ -16,6 +16,7 @@ var EXPORTED_SYMBOLS = [
|
|||
];
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.defineModuleGetter(this, "DateTimePickerPanel", "resource://gre/modules/DateTimePickerPanel.jsm");
|
||||
|
||||
/*
|
||||
* DateTimePickerParent receives message from content side (input box) and
|
||||
|
@ -105,7 +106,7 @@ var DateTimePickerParent = {
|
|||
},
|
||||
|
||||
// Get picker from browser and show it anchored to the input box.
|
||||
async showPicker(aBrowser, aData) {
|
||||
showPicker(aBrowser, aData) {
|
||||
let rect = aData.rect;
|
||||
let type = aData.type;
|
||||
let detail = aData.detail;
|
||||
|
@ -129,22 +130,11 @@ var DateTimePickerParent = {
|
|||
}
|
||||
|
||||
this.weakBrowser = Cu.getWeakReference(aBrowser);
|
||||
this.picker = aBrowser.dateTimePicker;
|
||||
if (!this.picker) {
|
||||
if (!aBrowser.dateTimePicker) {
|
||||
debug("aBrowser.dateTimePicker not found, exiting now.");
|
||||
return;
|
||||
}
|
||||
// The datetimepopup binding is only attached when it is needed.
|
||||
// Check if openPicker method is present to determine if binding has
|
||||
// been attached. If not, attach the binding first before calling it.
|
||||
if (!this.picker.openPicker) {
|
||||
let bindingPromise = new Promise(resolve => {
|
||||
this.picker.addEventListener("DateTimePickerBindingReady",
|
||||
resolve, {once: true});
|
||||
});
|
||||
this.picker.setAttribute("active", true);
|
||||
await bindingPromise;
|
||||
}
|
||||
this.picker = new DateTimePickerPanel(aBrowser.dateTimePicker);
|
||||
// The arrow panel needs an anchor to work. The popupAnchor (this._anchor)
|
||||
// is a transparent div that the arrow can point to.
|
||||
this.picker.openPicker(type, this._anchor, detail);
|
||||
|
@ -165,8 +155,8 @@ var DateTimePickerParent = {
|
|||
if (!this.picker) {
|
||||
return;
|
||||
}
|
||||
this.picker.addEventListener("popuphidden", this);
|
||||
this.picker.addEventListener("DateTimePickerValueChanged", this);
|
||||
this.picker.element.addEventListener("popuphidden", this);
|
||||
this.picker.element.addEventListener("DateTimePickerValueChanged", this);
|
||||
},
|
||||
|
||||
// Stop listening to picker's event.
|
||||
|
@ -174,7 +164,7 @@ var DateTimePickerParent = {
|
|||
if (!this.picker) {
|
||||
return;
|
||||
}
|
||||
this.picker.removeEventListener("popuphidden", this);
|
||||
this.picker.removeEventListener("DateTimePickerValueChanged", this);
|
||||
this.picker.element.removeEventListener("popuphidden", this);
|
||||
this.picker.element.removeEventListener("DateTimePickerValueChanged", this);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -194,6 +194,7 @@ EXTRA_JS_MODULES += [
|
|||
'Console.jsm',
|
||||
'CreditCard.jsm',
|
||||
'css-selector.js',
|
||||
'DateTimePickerPanel.jsm',
|
||||
'DateTimePickerParent.jsm',
|
||||
'DeferredTask.jsm',
|
||||
'Deprecated.jsm',
|
||||
|
|
Загрузка…
Ссылка в новой задаче