summaryrefslogtreecommitdiffstats
path: root/toolkit/actors/DateTimePickerParent.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/actors/DateTimePickerParent.sys.mjs')
-rw-r--r--toolkit/actors/DateTimePickerParent.sys.mjs157
1 files changed, 157 insertions, 0 deletions
diff --git a/toolkit/actors/DateTimePickerParent.sys.mjs b/toolkit/actors/DateTimePickerParent.sys.mjs
new file mode 100644
index 0000000000..ba78a39ffb
--- /dev/null
+++ b/toolkit/actors/DateTimePickerParent.sys.mjs
@@ -0,0 +1,157 @@
+/* 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/. */
+
+const DEBUG = false;
+function debug(aStr) {
+ if (DEBUG) {
+ dump("-*- DateTimePickerParent: " + aStr + "\n");
+ }
+}
+
+const lazy = {};
+ChromeUtils.defineESModuleGetters(lazy, {
+ DateTimePickerPanel: "resource://gre/modules/DateTimePickerPanel.sys.mjs",
+});
+
+/*
+ * DateTimePickerParent receives message from content side (input box) and
+ * is reposible for opening, closing and updating the picker. Similarly,
+ * DateTimePickerParent listens for picker's events and notifies the content
+ * side (input box) about them.
+ */
+export class DateTimePickerParent extends JSWindowActorParent {
+ receiveMessage(aMessage) {
+ debug("receiveMessage: " + aMessage.name);
+ switch (aMessage.name) {
+ case "FormDateTime:OpenPicker": {
+ this.showPicker(aMessage.data);
+ break;
+ }
+ case "FormDateTime:ClosePicker": {
+ if (!this._picker) {
+ return;
+ }
+ this.close();
+ break;
+ }
+ case "FormDateTime:UpdatePicker": {
+ if (!this._picker) {
+ return;
+ }
+ this._picker.setPopupValue(aMessage.data);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ handleEvent(aEvent) {
+ debug("handleEvent: " + aEvent.type);
+ switch (aEvent.type) {
+ case "DateTimePickerValueCleared": {
+ this.sendAsyncMessage("FormDateTime:PickerValueChanged", null);
+ break;
+ }
+ case "DateTimePickerValueChanged": {
+ this.sendAsyncMessage("FormDateTime:PickerValueChanged", aEvent.detail);
+ break;
+ }
+ case "popuphidden": {
+ this.sendAsyncMessage("FormDateTime:PickerClosed", {});
+ this.close();
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ // Get picker from browser and show it anchored to the input box.
+ showPicker(aData) {
+ let rect = aData.rect;
+ let type = aData.type;
+ let detail = aData.detail;
+
+ debug("Opening picker with details: " + JSON.stringify(detail));
+ let topBC = this.browsingContext.top;
+ let window = topBC.topChromeWindow;
+ if (Services.focus.activeWindow != window) {
+ debug("Not in the active window");
+ return;
+ }
+
+ {
+ let browser = topBC.embedderElement;
+ if (
+ browser &&
+ browser.ownerGlobal.gBrowser &&
+ browser.ownerGlobal.gBrowser.selectedBrowser != browser
+ ) {
+ debug("In background tab");
+ return;
+ }
+ }
+
+ let doc = window.document;
+ let panel = doc.getElementById("DateTimePickerPanel");
+ if (!panel) {
+ panel = doc.createXULElement("panel");
+ panel.id = "DateTimePickerPanel";
+ panel.setAttribute("type", "arrow");
+ panel.setAttribute("orient", "vertical");
+ panel.setAttribute("ignorekeys", "true");
+ panel.setAttribute("noautofocus", "true");
+ // This ensures that clicks on the anchored input box are never consumed.
+ panel.setAttribute("consumeoutsideclicks", "never");
+ panel.setAttribute("level", "parent");
+ panel.setAttribute("tabspecific", "true");
+ let container =
+ doc.getElementById("mainPopupSet") ||
+ doc.querySelector("popupset") ||
+ doc.documentElement.appendChild(doc.createXULElement("popupset"));
+ container.appendChild(panel);
+ }
+ this._oldFocus = doc.activeElement;
+ this._picker = new lazy.DateTimePickerPanel(panel);
+ this._picker.openPicker(type, rect, detail);
+ this.addPickerListeners();
+ }
+
+ // Close the picker and do some cleanup.
+ close() {
+ this._picker.closePicker();
+ // Restore focus to where it was before the picker opened.
+ this._oldFocus?.focus();
+ this._oldFocus = null;
+ this.removePickerListeners();
+ this._picker = null;
+ }
+
+ // Listen to picker's event.
+ addPickerListeners() {
+ if (!this._picker) {
+ return;
+ }
+ this._picker.element.addEventListener("popuphidden", this);
+ this._picker.element.addEventListener("DateTimePickerValueChanged", this);
+ this._picker.element.addEventListener("DateTimePickerValueCleared", this);
+ }
+
+ // Stop listening to picker's event.
+ removePickerListeners() {
+ if (!this._picker) {
+ return;
+ }
+ this._picker.element.removeEventListener("popuphidden", this);
+ this._picker.element.removeEventListener(
+ "DateTimePickerValueChanged",
+ this
+ );
+ this._picker.element.removeEventListener(
+ "DateTimePickerValueCleared",
+ this
+ );
+ }
+}