diff --git a/.eslintignore b/.eslintignore index 834b9b55f28b..1360e50bea26 100644 --- a/.eslintignore +++ b/.eslintignore @@ -350,6 +350,9 @@ toolkit/components/reader/JSDOMParser.js # Uses preprocessing toolkit/components/reader/Readerable.jsm +# Should be going away soon +toolkit/content/widgets/wizard.xml + # Uses preprocessing toolkit/mozapps/update/tests/data/xpcshellConstantsPP.js toolkit/modules/AppConstants.jsm diff --git a/testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/wizard.py b/testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/wizard.py index afacc8e95dec..cc1215078a0b 100644 --- a/testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/wizard.py +++ b/testing/marionette/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/wizard.py @@ -50,7 +50,7 @@ class Wizard(UIBaseLib): @property def _buttons(self): - return self.element.get_property('_wizardButtons') + return self.element.find_element(By.ANON_ATTRIBUTE, {'anonid': 'Buttons'}) @property def cancel_button(self): diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn index 565572a85102..7837239c4264 100644 --- a/toolkit/content/jar.mn +++ b/toolkit/content/jar.mn @@ -75,6 +75,7 @@ toolkit.jar: * content/global/bindings/textbox.xml (widgets/textbox.xml) content/global/bindings/timekeeper.js (widgets/timekeeper.js) content/global/bindings/timepicker.js (widgets/timepicker.js) + content/global/bindings/wizard.xml (widgets/wizard.xml) content/global/elements/autocomplete-popup.js (widgets/autocomplete-popup.js) content/global/elements/autocomplete-richlistitem.js (widgets/autocomplete-richlistitem.js) content/global/elements/browser-custom-element.js (widgets/browser-custom-element.js) diff --git a/toolkit/content/widgets/wizard.js b/toolkit/content/widgets/wizard.js index 4ba7841f6cce..bec7c7dfaa71 100644 --- a/toolkit/content/widgets/wizard.js +++ b/toolkit/content/widgets/wizard.js @@ -8,382 +8,14 @@ // a block to prevent accidentally leaking globals onto `window`. { const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm"); -const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); const kDTDs = [ "chrome://global/locale/wizard.dtd" ]; -class MozWizard extends MozXULElement { - constructor() { - super(); - - this._accessMethod = null; - this._currentPage = null; - this._canAdvance = true; - this._canRewind = false; - this._hasLoaded = false; - this._pageStack = []; - - this._bundle = - Services.strings.createBundle("chrome://global/locale/wizard.properties"); - - this.addEventListener("keypress", (event) => { - if (event.keyCode == KeyEvent.DOM_VK_RETURN) { - this._hitEnter(event); - } else if (event.keyCode == KeyEvent.DOM_VK_ESCAPE && !event.defaultPrevented) { - this.cancel(); - } - }, { mozSystemGroup: true }); - - this.attachShadow({ mode: "open" }).appendChild( - MozXULElement.parseXULToFragment(` - - - - - - - - `)); - this.initializeAttributeInheritance(); - - this._deck = this.shadowRoot.querySelector(".wizard-page-box"); - this._wizardButtons = this.shadowRoot.querySelector(".wizard-buttons"); - - this._wizardHeader = this.shadowRoot.querySelector(".wizard-header"); - this._wizardHeader.appendChild( - MozXULElement.parseXULToFragment(AppConstants.platform == "macosx" ? - ` - - - - - - - - - ` : - ` - - - - ` - ) - ); - } - - static get inheritedAttributes() { - return { - ".wizard-buttons": "pagestep,firstpage,lastpage", - }; - } - - connectedCallback() { - if (this.delayConnectedCallback()) { - return; - } - - this.pageCount = this.wizardPages.length; - - this._initPages(); - this.advance(); // start off on the first page - - window.addEventListener("close", (event) => { - if (document.documentElement.cancel()) { - event.preventDefault(); - } - }); - - // Give focus to the first focusable element in the wizard, do it after - // onload completes, see bug 103197. - window.addEventListener("load", () => window.setTimeout(() => { - document.documentElement._hasLoaded = true; - if (!document.commandDispatcher.focusedElement) { - document.commandDispatcher.advanceFocusIntoSubtree(this); - } - try { - let button = document.documentElement._wizardButtons.defaultButton; - if (button) { - window.notifyDefaultButtonLoaded(button); - } - } catch (e) {} - }, 0)); - } - - set title(val) { - return document.title = val; - } - - get title() { - return document.title; - } - - set canAdvance(val) { - this.getButton("next").disabled = !val; - return this._canAdvance = val; - } - - get canAdvance() { - return this._canAdvance; - } - - set canRewind(val) { - this.getButton("back").disabled = !val; - return this._canRewind = val; - } - - get canRewind() { - return this._canRewind; - } - - get pageStep() { - return this._pageStack.length; - } - - get wizardPages() { - const xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; - return this.getElementsByTagNameNS(xulns, "wizardpage"); - } - - set currentPage(val) { - if (!val) - return val; - - this._currentPage = val; - - // Setting this attribute allows wizard's clients to dynamically - // change the styles of each page based on purpose of the page. - this.setAttribute("currentpageid", val.pageid); - if (this.onFirstPage) { - this.canRewind = false; - this.setAttribute("firstpage", "true"); - if (AppConstants.platform == "linux") { - this.getButton("back").setAttribute("hidden", "true"); - } - } else { - this.canRewind = true; - this.setAttribute("firstpage", "false"); - if (AppConstants.platform == "linux") { - this.getButton("back").setAttribute("hidden", "false"); - } - } - - if (this.onLastPage) { - this.canAdvance = true; - this.setAttribute("lastpage", "true"); - } else { - this.setAttribute("lastpage", "false"); - } - - this._deck.setAttribute("selectedIndex", val.pageIndex); - this._advanceFocusToPage(val); - - this._adjustWizardHeader(); - this._wizardButtons.onPageChange(); - - this._fireEvent(val, "pageshow"); - - return val; - } - - get currentPage() { - return this._currentPage; - } - - set pageIndex(val) { - if (val < 0 || val >= this.pageCount) - return val; - - var page = this.wizardPages[val]; - this._pageStack[this._pageStack.length - 1] = page; - this.currentPage = page; - - return val; - } - - get pageIndex() { - return this._currentPage ? this._currentPage.pageIndex : -1; - } - - get onFirstPage() { - return this._pageStack.length == 1; - } - - get onLastPage() { - var cp = this.currentPage; - return cp && ((this._accessMethod == "sequential" && cp.pageIndex == this.pageCount - 1) || - (this._accessMethod == "random" && cp.next == "")); - } - - getButton(aDlgType) { - return this._wizardButtons.getButton(aDlgType); - } - - getPageById(aPageId) { - var els = this.getElementsByAttribute("pageid", aPageId); - return els.item(0); - } - - extra1() { - if (this.currentPage) - this._fireEvent(this.currentPage, "extra1"); - } - - extra2() { - if (this.currentPage) - this._fireEvent(this.currentPage, "extra2"); - } - - rewind() { - if (!this.canRewind) - return; - - if (this.currentPage && !this._fireEvent(this.currentPage, "pagehide")) - return; - - if (this.currentPage && !this._fireEvent(this.currentPage, "pagerewound")) - return; - - if (!this._fireEvent(this, "wizardback")) - return; - - this._pageStack.pop(); - this.currentPage = this._pageStack[this._pageStack.length - 1]; - this.setAttribute("pagestep", this._pageStack.length); - } - - advance(aPageId) { - if (!this.canAdvance) - return; - - if (this.currentPage && !this._fireEvent(this.currentPage, "pagehide")) - return; - - if (this.currentPage && !this._fireEvent(this.currentPage, "pageadvanced")) - return; - - if (this.onLastPage && !aPageId) { - if (this._fireEvent(this, "wizardfinish")) - window.setTimeout(function() { window.close(); }, 1); - } else { - if (!this._fireEvent(this, "wizardnext")) - return; - - let page; - if (aPageId) { - page = this.getPageById(aPageId); - } else if (this.currentPage) { - if (this._accessMethod == "random") { - page = this.getPageById(this.currentPage.next); - } else { - page = this.wizardPages[this.currentPage.pageIndex + 1]; - } - } else { - page = this.wizardPages[0]; - } - - if (page) { - this._pageStack.push(page); - this.setAttribute("pagestep", this._pageStack.length); - - this.currentPage = page; - } - } - } - - goTo(aPageId) { - var page = this.getPageById(aPageId); - if (page) { - this._pageStack[this._pageStack.length - 1] = page; - this.currentPage = page; - } - } - - cancel() { - if (!this._fireEvent(this, "wizardcancel")) - return true; - - window.close(); - window.setTimeout(function() { window.close(); }, 1); - return false; - } - - _advanceFocusToPage(aPage) { - if (!this._hasLoaded) - return; - - document.commandDispatcher.advanceFocusIntoSubtree(aPage); - - // if advanceFocusIntoSubtree tries to focus one of our - // dialog buttons, then remove it and put it on the root - var focused = document.commandDispatcher.focusedElement; - if (focused && focused.hasAttribute("dlgtype")) - this.focus(); - } - - _initPages() { - var meth = "sequential"; - var pages = this.wizardPages; - for (var i = 0; i < pages.length; ++i) { - var page = pages[i]; - page.pageIndex = i; - if (page.next != "") - meth = "random"; - } - this._accessMethod = meth; - } - - _adjustWizardHeader() { - var label = this.currentPage.getAttribute("label"); - if (!label && this.onFirstPage && this._bundle) { - if (AppConstants.platform == "macosx") { - label = this._bundle.GetStringFromName("default-first-title-mac"); - } else { - label = this._bundle.formatStringFromName("default-first-title", [this.title]); - } - } else if (!label && this.onLastPage && this._bundle) { - if (AppConstants.platform == "macosx") { - label = this._bundle.GetStringFromName("default-last-title-mac"); - } else { - label = this._bundle.formatStringFromName("default-last-title", [this.title]); - } - } - this._wizardHeader. - querySelector(".wizard-header-label").textContent = label; - let headerDescEl = - this._wizardHeader.querySelector(".wizard-header-description"); - if (headerDescEl) { - headerDescEl.textContent = - this.currentPage.getAttribute("description"); - } - } - - _hitEnter(evt) { - if (!evt.defaultPrevented) - this.advance(); - } - - _fireEvent(aTarget, aType) { - var event = document.createEvent("Events"); - event.initEvent(aType, true, true); - - // handle dom event handlers - return aTarget.dispatchEvent(event); - } -} - -customElements.define("wizard", MozWizard); - class MozWizardPage extends MozXULElement { constructor() { super(); this.pageIndex = -1; } - connectedCallback() { - this.setAttribute("slot", "wizardpage"); - } get pageid() { return this.getAttribute("pageid"); } diff --git a/toolkit/content/widgets/wizard.xml b/toolkit/content/widgets/wizard.xml new file mode 100644 index 000000000000..ad40e7445b6d --- /dev/null +++ b/toolkit/content/widgets/wizard.xml @@ -0,0 +1,428 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + null + null + null + + + + + + + + + + + + + + + + = this.pageCount) + return val; + + var page = this.wizardPages[val]; + this._pageStack[this._pageStack.length-1] = page; + this.currentPage = page; + + return val; + ]]> + + + + + + + + + + + + + + + + + + + + + + + + // see bug 63370 for details + this._bundle = Cc["@mozilla.org/intl/stringbundle;1"] + .getService(Ci.nsIStringBundleService) + .createBundle("chrome://global/locale/wizard.properties"); + } catch (e) { + // This fails in remote XUL, which has to provide titles for all pages + // see bug 142502 + } + + // get anonymous content references + this._wizardHeader = document.getAnonymousElementByAttribute(this, "anonid", "Header"); + + this._wizardHeader.appendChild( + MozXULElement.parseXULToFragment(/Mac/.test(navigator.platform) ? + ` + + + + + + + + + ` : + ` + + + + ` + ) + ); + + this._wizardButtons = document.getAnonymousElementByAttribute(this, "anonid", "Buttons"); + customElements.upgrade(this._wizardButtons); + + this._deck = document.getAnonymousElementByAttribute(this, "anonid", "Deck"); + + this._initPages(); + + window.addEventListener("close", (event) => { + if (document.documentElement.cancel()) { + event.preventDefault(); + } + }); + + // start off on the first page + this.pageCount = this.wizardPages.length; + this.advance(); + + // give focus to the first focusable element in the dialog + window.addEventListener("load", this._setInitialFocus); + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + if (!event.defaultPrevented) + this.cancel(); + + + + diff --git a/toolkit/content/xul.css b/toolkit/content/xul.css index 792458a34515..952bd23f75d0 100644 --- a/toolkit/content/xul.css +++ b/toolkit/content/xul.css @@ -592,6 +592,7 @@ page { wizard, wizard:root /* override :root from above */ { + -moz-binding: url("chrome://global/content/bindings/wizard.xml#wizard"); -moz-box-orient: vertical; width: 40em; height: 30em;