From 26a239839919ea2d5d32c0f6e01b57bfa5f79792 Mon Sep 17 00:00:00 2001 From: Abe Jellinek Date: Wed, 20 Jul 2022 11:12:52 -0400 Subject: [PATCH] fx-compat: Restore guidance panels as CE Fixes #2711. --- .../content/zotero/bindings/guidancepanel.xml | 242 ------------------ .../content/zotero/elements/guidancePanel.js | 202 +++++++++++++++ chrome/content/zotero/elements/itemBox.js | 12 +- .../zotero/integration/quickFormat.xul | 4 +- chrome/skin/default/zotero/zotero.css | 5 - scss/_guidancePanel.scss | 1 + .../components/_guidancePanel.scss | 22 +- scss/guidancePanel-mac.scss | 1 + scss/guidancePanel-unix.scss | 1 + scss/guidancePanel-win.scss | 1 + 10 files changed, 227 insertions(+), 264 deletions(-) delete mode 100644 chrome/content/zotero/bindings/guidancepanel.xml create mode 100644 chrome/content/zotero/elements/guidancePanel.js create mode 100644 scss/_guidancePanel.scss rename chrome/skin/default/zotero/bindings/guidancepanel.css => scss/components/_guidancePanel.scss (75%) create mode 100644 scss/guidancePanel-mac.scss create mode 100644 scss/guidancePanel-unix.scss create mode 100644 scss/guidancePanel-win.scss diff --git a/chrome/content/zotero/bindings/guidancepanel.xml b/chrome/content/zotero/bindings/guidancepanel.xml deleted file mode 100644 index 82e9bbdf55..0000000000 --- a/chrome/content/zotero/bindings/guidancepanel.xml +++ /dev/null @@ -1,242 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/chrome/content/zotero/elements/guidancePanel.js b/chrome/content/zotero/elements/guidancePanel.js new file mode 100644 index 0000000000..de4876a19d --- /dev/null +++ b/chrome/content/zotero/elements/guidancePanel.js @@ -0,0 +1,202 @@ +/* + ***** BEGIN LICENSE BLOCK ***** + + Copyright © 2022 Corporation for Digital Scholarship + Vienna, Virginia, USA + https://www.zotero.org + + This file is part of Zotero. + + Zotero is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Zotero is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with Zotero. If not, see . + + ***** END LICENSE BLOCK ***** +*/ + +"use strict"; + +{ + Services.scriptloader.loadSubScript("chrome://zotero/content/elements/base.js", this); + + class GuidancePanel extends XULElementBase { + content = MozXULElement.parseXULToFragment(` + + + + + + + + + + + + + + + + `); + + stylesheets = ['chrome://global/skin/', 'chrome://zotero-platform/content/guidancePanel.css']; + + get panel() { + return this.shadowRoot.querySelector('panel'); + } + + init() { + this.panel.addEventListener('popupshown', () => { + Zotero.guidanceBeingShown = true; + }); + + this.panel.addEventListener('popuphidden', () => { + Zotero.guidanceBeingShown = false; + }); + + if (this.getAttribute("noautohide") == 'true' + && !this.hasAttribute('forward')) { + let listener = () => { + this.panel.removeEventListener("click", listener); + this.panel.hidePopup(); + }; + this.panel.addEventListener("click", listener); + } + } + + /** + * @param {Object} [options] + * @param {String} [options.text] Text to use in place of firstRunGuidance. + * @param {DOMElement} [options.forEl] Anchor node + * @param {Boolean} [options.force] Show even if already shown + */ + show(options) { + Components.utils.import("resource://gre/modules/Services.jsm"); + if (!Zotero.Prefs.get("firstRunGuidance")) return; + + options = options || {}; + let text = options.text; + let useLastText = options.useLastText || false; + let forEl = options.forEl || document.getElementById(this.getAttribute("for")); + let force = options.force || false; + + if (!forEl) return; + // Don't show two panels at once + if (Zotero.guidanceBeingShown) { + return; + } + + var about = this.getAttribute("about"); + var pref = false; + if (about) { + pref = "firstRunGuidanceShown." + about; + let shown = false; + try { + shown = Zotero.Prefs.get(pref); + } + catch (e) {} + if (shown && !force) { + return; + } + } + + var x = this.getAttribute("x"), + y = this.getAttribute("y"), + position = this.getAttribute("position"); + + if (!useLastText) { + if (!text) { + text = Zotero.getString("firstRunGuidance." + about); + } + text = text.split("\n"); + var descriptionNode = this.id('panel-description'); + + while (descriptionNode.hasChildNodes()) { + descriptionNode.removeChild(descriptionNode.firstChild); + } + + while (text.length) { + var textLine = text.shift(); + descriptionNode.appendChild(document.createTextNode(textLine)); + if (text.length) descriptionNode.appendChild(document.createElement("br")); + } + } + + this._initNavButton('back', options.back); + this._initNavButton('forward', options.forward); + + var f = () => { + if (this.hasAttribute("foregroundonly") && Services.ww.activeWindow != window) return; + + this.panel.openPopup(forEl, position || "after_start", + x ? parseInt(x, 10) : 0, y ? parseInt(y, 10) : 0); + if (pref) { + Zotero.Prefs.set(pref, true); + } + }; + + if (this.hasAttribute("delay") && !force) { + window.setTimeout(f, this.getAttribute("delay")); + } + else { + f(); + } + } + + hide() { + this.panel.hidePopup(); + } + + _initNavButton(dir, nextID) { + if (!nextID) { + nextID = this.getAttribute(dir); + } + if (!nextID) { + return; + } + var nextElem = document.getElementById(nextID); + var button = this.id(dir + '-button'); + button.hidden = false; + var target; + // If there's a forward action and no back action, the whole panel triggers + // the forward in noautohide mode + if (dir == 'forward' && !this.hasAttribute('back') + && this.getAttribute('noautohide') == 'true') { + target = this.panel; + } + else { + target = button; + } + var listener = (event) => { + target.removeEventListener("click", listener); + this.hide(); + var data = { + force: true + }; + // Point the next panel back to this one + data[dir == 'back' ? 'forward' : 'back'] = this.getAttribute('id'); + // When going backwards, don't regenerate text + if (dir == 'back') { + data.useLastText = true; + } + nextElem.show(data); + event.stopPropagation(); + }; + target.addEventListener("click", listener); + } + + id(id) { + return this.shadowRoot.getElementById(id); + } + } + + customElements.define("guidance-panel", GuidancePanel); +} diff --git a/chrome/content/zotero/elements/itemBox.js b/chrome/content/zotero/elements/itemBox.js index c42b641667..83fc0b9306 100644 --- a/chrome/content/zotero/elements/itemBox.js +++ b/chrome/content/zotero/elements/itemBox.js @@ -29,6 +29,7 @@ var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm"); Services.scriptloader.loadSubScript("chrome://zotero/content/elements/shadowAutocompleteInput.js", this); + Services.scriptloader.loadSubScript("chrome://zotero/content/elements/guidancePanel.js", this); class ItemBox extends XULElement { constructor() { @@ -76,7 +77,7 @@ - +