forked from mirrors/gecko-dev
		
	Bug 1495621 - convert wizard binding to Custom Element r=bgrins
Differential Revision: https://phabricator.services.mozilla.com/D26334 --HG-- extra : moz-landing-system : lando
This commit is contained in:
		
							parent
							
								
									4ed00f362c
								
							
						
					
					
						commit
						595da48d95
					
				
					 6 changed files with 369 additions and 434 deletions
				
			
		|  | @ -350,9 +350,6 @@ toolkit/components/reader/JSDOMParser.js | ||||||
| # Uses preprocessing | # Uses preprocessing | ||||||
| toolkit/components/reader/Readerable.jsm | toolkit/components/reader/Readerable.jsm | ||||||
| 
 | 
 | ||||||
| # Should be going away soon |  | ||||||
| toolkit/content/widgets/wizard.xml |  | ||||||
| 
 |  | ||||||
| # Uses preprocessing | # Uses preprocessing | ||||||
| toolkit/mozapps/update/tests/data/xpcshellConstantsPP.js | toolkit/mozapps/update/tests/data/xpcshellConstantsPP.js | ||||||
| toolkit/modules/AppConstants.jsm | toolkit/modules/AppConstants.jsm | ||||||
|  |  | ||||||
|  | @ -50,7 +50,7 @@ class Wizard(UIBaseLib): | ||||||
| 
 | 
 | ||||||
|     @property |     @property | ||||||
|     def _buttons(self): |     def _buttons(self): | ||||||
|         return self.element.find_element(By.ANON_ATTRIBUTE, {'anonid': 'Buttons'}) |         return self.element.get_property('_wizardButtons') | ||||||
| 
 | 
 | ||||||
|     @property |     @property | ||||||
|     def cancel_button(self): |     def cancel_button(self): | ||||||
|  |  | ||||||
|  | @ -75,7 +75,6 @@ toolkit.jar: | ||||||
| *  content/global/bindings/textbox.xml         (widgets/textbox.xml) | *  content/global/bindings/textbox.xml         (widgets/textbox.xml) | ||||||
|    content/global/bindings/timekeeper.js       (widgets/timekeeper.js) |    content/global/bindings/timekeeper.js       (widgets/timekeeper.js) | ||||||
|    content/global/bindings/timepicker.js       (widgets/timepicker.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-popup.js              (widgets/autocomplete-popup.js) | ||||||
|    content/global/elements/autocomplete-richlistitem.js       (widgets/autocomplete-richlistitem.js) |    content/global/elements/autocomplete-richlistitem.js       (widgets/autocomplete-richlistitem.js) | ||||||
|    content/global/elements/browser-custom-element.js          (widgets/browser-custom-element.js) |    content/global/elements/browser-custom-element.js          (widgets/browser-custom-element.js) | ||||||
|  |  | ||||||
|  | @ -8,14 +8,382 @@ | ||||||
| // a block to prevent accidentally leaking globals onto `window`.
 | // a block to prevent accidentally leaking globals onto `window`.
 | ||||||
| { | { | ||||||
| const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm"); | 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" ]; | 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(` | ||||||
|  |         <html:link rel="stylesheet" href="chrome://global/content/widgets.css" /> | ||||||
|  |         <hbox class="wizard-header"></hbox> | ||||||
|  |         <deck class="wizard-page-box" flex="1"> | ||||||
|  |           <slot xmlns="http://www.w3.org/1999/xhtml" name="wizardpage"></slot> | ||||||
|  |         </deck> | ||||||
|  |         <slot xmlns="http://www.w3.org/1999/xhtml"></slot> | ||||||
|  |         <wizard-buttons class="wizard-buttons"></wizard-buttons> | ||||||
|  |     `));
 | ||||||
|  |     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" ? | ||||||
|  |         `<stack class="wizard-header-stack" flex="1">
 | ||||||
|  |            <vbox class="wizard-header-box-1"> | ||||||
|  |              <vbox class="wizard-header-box-text"> | ||||||
|  |                <label class="wizard-header-label"/> | ||||||
|  |              </vbox> | ||||||
|  |            </vbox> | ||||||
|  |            <hbox class="wizard-header-box-icon"> | ||||||
|  |              <spacer flex="1"/> | ||||||
|  |              <image class="wizard-header-icon"/> | ||||||
|  |            </hbox> | ||||||
|  |          </stack>` : | ||||||
|  |         `<hbox class="wizard-header-box-1" flex="1">
 | ||||||
|  |            <vbox class="wizard-header-box-text" flex="1"> | ||||||
|  |              <label class="wizard-header-label"/> | ||||||
|  |              <label class="wizard-header-description"/> | ||||||
|  |            </vbox> | ||||||
|  |            <image class="wizard-header-icon"/> | ||||||
|  |          </hbox>` | ||||||
|  |       ) | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   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 { | class MozWizardPage extends MozXULElement { | ||||||
|   constructor() { |   constructor() { | ||||||
|     super(); |     super(); | ||||||
|     this.pageIndex = -1; |     this.pageIndex = -1; | ||||||
|   } |   } | ||||||
|  |   connectedCallback() { | ||||||
|  |     this.setAttribute("slot", "wizardpage"); | ||||||
|  |   } | ||||||
|   get pageid() { |   get pageid() { | ||||||
|     return this.getAttribute("pageid"); |     return this.getAttribute("pageid"); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -1,428 +0,0 @@ | ||||||
| <?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="wizardBindings" |  | ||||||
|    xmlns="http://www.mozilla.org/xbl" |  | ||||||
|    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" |  | ||||||
|    xmlns:xbl="http://www.mozilla.org/xbl"> |  | ||||||
| 
 |  | ||||||
|   <binding id="wizard"> |  | ||||||
|     <content> |  | ||||||
|       <xul:hbox class="wizard-header" anonid="Header"/> |  | ||||||
| 
 |  | ||||||
|       <xul:deck class="wizard-page-box" flex="1" anonid="Deck"> |  | ||||||
|         <children includes="wizardpage"/> |  | ||||||
|       </xul:deck> |  | ||||||
|       <children/> |  | ||||||
| 
 |  | ||||||
|       <xul:wizard-buttons class="wizard-buttons" anonid="Buttons" xbl:inherits="pagestep,firstpage,lastpage"/> |  | ||||||
|     </content> |  | ||||||
| 
 |  | ||||||
|     <implementation> |  | ||||||
|       <property name="title" onget="return document.title;" |  | ||||||
|                              onset="return document.title = val;"/> |  | ||||||
| 
 |  | ||||||
|       <property name="canAdvance" onget="return this._canAdvance;" |  | ||||||
|                                   onset="this.getButton('next').disabled = !val; return this._canAdvance = val;"/> |  | ||||||
|       <property name="canRewind" onget="return this._canRewind;" |  | ||||||
|                                  onset="this.getButton('back').disabled = !val; return this._canRewind = val;"/> |  | ||||||
| 
 |  | ||||||
|       <property name="pageStep" readonly="true" onget="return this._pageStack.length"/> |  | ||||||
| 
 |  | ||||||
|       <field name="pageCount">0</field> |  | ||||||
| 
 |  | ||||||
|       <field name="_accessMethod">null</field> |  | ||||||
|       <field name="_pageStack">null</field> |  | ||||||
|       <field name="_currentPage">null</field> |  | ||||||
| 
 |  | ||||||
|       <property name="wizardPages"> |  | ||||||
|         <getter> |  | ||||||
|         <![CDATA[ |  | ||||||
|           var xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; |  | ||||||
|           return this.getElementsByTagNameNS(xulns, "wizardpage"); |  | ||||||
|         ]]> |  | ||||||
|         </getter> |  | ||||||
|       </property> |  | ||||||
| 
 |  | ||||||
|       <property name="currentPage" onget="return this._currentPage"> |  | ||||||
|         <setter> |  | ||||||
|         <![CDATA[ |  | ||||||
|           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 (/Linux/.test(navigator.platform)) { |  | ||||||
|               this.getButton("back").setAttribute("hidden", "true"); |  | ||||||
|             } |  | ||||||
|           } else { |  | ||||||
|             this.canRewind = true; |  | ||||||
|             this.setAttribute("firstpage", "false"); |  | ||||||
|             if (/Linux/.test(navigator.platform)) { |  | ||||||
|               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; |  | ||||||
|         ]]> |  | ||||||
|         </setter> |  | ||||||
|       </property> |  | ||||||
| 
 |  | ||||||
|       <property name="pageIndex" |  | ||||||
|                 onget="return this._currentPage ? this._currentPage.pageIndex : -1;"> |  | ||||||
|         <setter> |  | ||||||
|         <![CDATA[ |  | ||||||
|           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; |  | ||||||
|         ]]> |  | ||||||
|         </setter> |  | ||||||
|       </property> |  | ||||||
| 
 |  | ||||||
|       <property name="onFirstPage" readonly="true" |  | ||||||
|                 onget="return this._pageStack.length == 1;"/> |  | ||||||
| 
 |  | ||||||
|       <property name="onLastPage" readonly="true"> |  | ||||||
|         <getter><![CDATA[ |  | ||||||
|           var cp = this.currentPage; |  | ||||||
|           return cp && ((this._accessMethod == "sequential" && cp.pageIndex == this.pageCount-1) || |  | ||||||
|                        (this._accessMethod == "random" && cp.next == "")); |  | ||||||
|          ]]></getter> |  | ||||||
|       </property> |  | ||||||
| 
 |  | ||||||
|       <method name="getButton"> |  | ||||||
|         <parameter name="aDlgType"/> |  | ||||||
|         <body> |  | ||||||
|         <![CDATA[ |  | ||||||
|           return this._wizardButtons.getButton(aDlgType); |  | ||||||
|         ]]> |  | ||||||
|         </body> |  | ||||||
|       </method> |  | ||||||
| 
 |  | ||||||
|       <field name="_canAdvance"/> |  | ||||||
|       <field name="_canRewind"/> |  | ||||||
|       <field name="_wizardHeader"/> |  | ||||||
|       <field name="_wizardButtons"/> |  | ||||||
|       <field name="_deck"/> |  | ||||||
| 
 |  | ||||||
|       <constructor><![CDATA[ |  | ||||||
|         this._canAdvance = true; |  | ||||||
|         this._canRewind = false; |  | ||||||
|         this._hasLoaded = false; |  | ||||||
| 
 |  | ||||||
|         this._pageStack = []; |  | ||||||
| 
 |  | ||||||
|         try { |  | ||||||
|           // need to create string bundle manually instead of using <xul:stringbundle/> |  | ||||||
|           // 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) ? |  | ||||||
|             `<stack class="wizard-header-stack" flex="1"> |  | ||||||
|               <vbox class="wizard-header-box-1"> |  | ||||||
|                 <vbox class="wizard-header-box-text"> |  | ||||||
|                   <label class="wizard-header-label"/> |  | ||||||
|                 </vbox> |  | ||||||
|               </vbox> |  | ||||||
|               <hbox class="wizard-header-box-icon"> |  | ||||||
|                 <spacer flex="1"/> |  | ||||||
|                 <image class="wizard-header-icon"/> |  | ||||||
|               </hbox> |  | ||||||
|             </stack>` : |  | ||||||
|             `<hbox class="wizard-header-box-1" flex="1"> |  | ||||||
|               <vbox class="wizard-header-box-text" flex="1"> |  | ||||||
|                 <label class="wizard-header-label"/> |  | ||||||
|                 <label class="wizard-header-description"/> |  | ||||||
|               </vbox> |  | ||||||
|               <image class="wizard-header-icon"/> |  | ||||||
|             </hbox>` |  | ||||||
|           ) |  | ||||||
|         ); |  | ||||||
| 
 |  | ||||||
|         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); |  | ||||||
|       ]]></constructor> |  | ||||||
| 
 |  | ||||||
|       <method name="getPageById"> |  | ||||||
|         <parameter name="aPageId"/> |  | ||||||
|         <body><![CDATA[ |  | ||||||
|           var els = this.getElementsByAttribute("pageid", aPageId); |  | ||||||
|           return els.item(0); |  | ||||||
|         ]]></body> |  | ||||||
|       </method> |  | ||||||
| 
 |  | ||||||
|       <method name="extra1"> |  | ||||||
|         <body><![CDATA[ |  | ||||||
|           if (this.currentPage) |  | ||||||
|             this._fireEvent(this.currentPage, "extra1"); |  | ||||||
|         ]]></body> |  | ||||||
|       </method> |  | ||||||
| 
 |  | ||||||
|       <method name="extra2"> |  | ||||||
|         <body><![CDATA[ |  | ||||||
|           if (this.currentPage) |  | ||||||
|             this._fireEvent(this.currentPage, "extra2"); |  | ||||||
|         ]]></body> |  | ||||||
|       </method> |  | ||||||
| 
 |  | ||||||
|       <method name="rewind"> |  | ||||||
|         <body><![CDATA[ |  | ||||||
|           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); |  | ||||||
|         ]]></body> |  | ||||||
|       </method> |  | ||||||
| 
 |  | ||||||
|       <method name="advance"> |  | ||||||
|         <parameter name="aPageId"/> |  | ||||||
|         <body><![CDATA[ |  | ||||||
|           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; |  | ||||||
| 
 |  | ||||||
|             var 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; |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         ]]></body> |  | ||||||
|       </method> |  | ||||||
| 
 |  | ||||||
|       <method name="goTo"> |  | ||||||
|         <parameter name="aPageId"/> |  | ||||||
|         <body><![CDATA[ |  | ||||||
|           var page = this.getPageById(aPageId); |  | ||||||
|           if (page) { |  | ||||||
|             this._pageStack[this._pageStack.length-1] = page; |  | ||||||
|             this.currentPage = page; |  | ||||||
|           } |  | ||||||
|         ]]></body> |  | ||||||
|       </method> |  | ||||||
| 
 |  | ||||||
|       <method name="cancel"> |  | ||||||
|         <body><![CDATA[ |  | ||||||
|           if (!this._fireEvent(this, "wizardcancel")) |  | ||||||
|             return true; |  | ||||||
| 
 |  | ||||||
|           window.close(); |  | ||||||
|           window.setTimeout(function() {window.close();}, 1); |  | ||||||
|           return false; |  | ||||||
|         ]]></body> |  | ||||||
|       </method> |  | ||||||
| 
 |  | ||||||
|       <method name="_setInitialFocus"> |  | ||||||
|         <parameter name="aEvent"/> |  | ||||||
|         <body> |  | ||||||
|         <![CDATA[ |  | ||||||
|           document.documentElement._hasLoaded = true; |  | ||||||
|           var focusInit = |  | ||||||
|             function() { |  | ||||||
|               // give focus to the first focusable element in the dialog |  | ||||||
|               if (!document.commandDispatcher.focusedElement) |  | ||||||
|                 document.commandDispatcher.advanceFocusIntoSubtree(document.documentElement); |  | ||||||
| 
 |  | ||||||
|               try { |  | ||||||
|                 var button = |  | ||||||
|                       document.documentElement._wizardButtons.defaultButton; |  | ||||||
|                 if (button) |  | ||||||
|                   window.notifyDefaultButtonLoaded(button); |  | ||||||
|               } catch (e) { } |  | ||||||
|             }; |  | ||||||
| 
 |  | ||||||
|           // Give focus after onload completes, see bug 103197. |  | ||||||
|           setTimeout(focusInit, 0); |  | ||||||
|         ]]> |  | ||||||
|         </body> |  | ||||||
|       </method> |  | ||||||
| 
 |  | ||||||
|       <method name="_advanceFocusToPage"> |  | ||||||
|         <parameter name="aPage"/> |  | ||||||
|         <body> |  | ||||||
|         <![CDATA[ |  | ||||||
|           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(); |  | ||||||
|         ]]> |  | ||||||
|         </body> |  | ||||||
|       </method> |  | ||||||
| 
 |  | ||||||
|       <method name="_initPages"> |  | ||||||
|         <body><![CDATA[ |  | ||||||
|           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; |  | ||||||
|         ]]></body> |  | ||||||
|       </method> |  | ||||||
| 
 |  | ||||||
|       <method name="_adjustWizardHeader"> |  | ||||||
|         <body><![CDATA[ |  | ||||||
|           var label = this.currentPage.getAttribute("label"); |  | ||||||
|           if (!label && this.onFirstPage && this._bundle) { |  | ||||||
|             if (/Mac/.test(navigator.platform)) { |  | ||||||
|               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 (/Mac/.test(navigator.platform)) { |  | ||||||
|               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"); |  | ||||||
|           } |  | ||||||
|         ]]></body> |  | ||||||
|       </method> |  | ||||||
| 
 |  | ||||||
|       <method name="_hitEnter"> |  | ||||||
|         <parameter name="evt"/> |  | ||||||
|         <body> |  | ||||||
|         <![CDATA[ |  | ||||||
|           if (!evt.defaultPrevented) |  | ||||||
|             this.advance(); |  | ||||||
|         ]]> |  | ||||||
|         </body> |  | ||||||
|       </method> |  | ||||||
| 
 |  | ||||||
|       <method name="_fireEvent"> |  | ||||||
|         <parameter name="aTarget"/> |  | ||||||
|         <parameter name="aType"/> |  | ||||||
|         <body> |  | ||||||
|         <![CDATA[ |  | ||||||
|           var event = document.createEvent("Events"); |  | ||||||
|           event.initEvent(aType, true, true); |  | ||||||
| 
 |  | ||||||
|           // handle dom event handlers |  | ||||||
|           return aTarget.dispatchEvent(event); |  | ||||||
|         ]]> |  | ||||||
|         </body> |  | ||||||
|       </method> |  | ||||||
| 
 |  | ||||||
|     </implementation> |  | ||||||
| 
 |  | ||||||
|     <handlers> |  | ||||||
|       <handler event="keypress" keycode="VK_RETURN" |  | ||||||
|                group="system" action="this._hitEnter(event)"/> |  | ||||||
|       <handler event="keypress" keycode="VK_ESCAPE" group="system"> |  | ||||||
|         if (!event.defaultPrevented) |  | ||||||
|           this.cancel(); |  | ||||||
|       </handler> |  | ||||||
|     </handlers> |  | ||||||
|   </binding> |  | ||||||
| </bindings> |  | ||||||
|  | @ -592,7 +592,6 @@ page { | ||||||
| 
 | 
 | ||||||
| wizard, | wizard, | ||||||
| wizard:root /* override :root from above */ { | wizard:root /* override :root from above */ { | ||||||
|   -moz-binding: url("chrome://global/content/bindings/wizard.xml#wizard"); |  | ||||||
|   -moz-box-orient: vertical; |   -moz-box-orient: vertical; | ||||||
|   width: 40em; |   width: 40em; | ||||||
|   height: 30em; |   height: 30em; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Alexander Surkov
						Alexander Surkov