diff options
Diffstat (limited to '')
-rw-r--r-- | toolkit/actors/DateTimePickerParent.sys.mjs | 157 |
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 + ); + } +} |