mirror of
https://github.com/ManchildProductions/UXP-Fixed.git
synced 2026-05-27 16:38:36 +00:00
1cb62d2845
Issue #162
323 lines
12 KiB
XML
323 lines
12 KiB
XML
<?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">
|
|
<resources>
|
|
<stylesheet src="chrome://global/skin/datetimepopup.css"/>
|
|
</resources>
|
|
<implementation>
|
|
<field name="dateTimePopupFrame">
|
|
this.querySelector("#dateTimePopupFrame");
|
|
</field>
|
|
<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.l10n = {};
|
|
const mozIntl = Components.classes["@mozilla.org/mozintl;1"]
|
|
.getService(Components.interfaces.mozIMozIntl);
|
|
mozIntl.addGetCalendarInfo(this.l10n);
|
|
mozIntl.addGetDisplayNames(this.l10n);
|
|
// Notify DateTimePickerHelper.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, false);
|
|
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[
|
|
const locale = Components.classes["@mozilla.org/chrome/chrome-registry;1"].getService(Ci.nsIXULChromeRegistry).getSelectedLocale("global");
|
|
|
|
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,
|
|
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.l10n.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.l10n.getDisplayNames(locale, {keys, style});
|
|
return keys.map(key => displayNames.values[key]);
|
|
]]></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, false);
|
|
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>
|