Bug 1590573, create a unified approach for caching fragments in our Custom Elements r=emilio

Differential Revision: https://phabricator.services.mozilla.com/D58866

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emma Malysz 2020-04-08 16:17:50 +00:00
parent b90b5b3778
commit a7282ce447
25 changed files with 471 additions and 373 deletions

View File

@ -8,6 +8,34 @@
// a block to prevent accidentally leaking globals onto `window`.
{
class MozTabbrowserTab extends MozElements.MozTab {
static get markup() {
return `
<stack class="tab-stack" flex="1">
<vbox class="tab-background">
<hbox class="tab-line"/>
<spacer flex="1" class="tab-background-inner"/>
<hbox class="tab-bottom-line"/>
</vbox>
<hbox class="tab-loading-burst"/>
<hbox class="tab-content" align="center">
<hbox class="tab-throbber" layer="true"/>
<hbox class="tab-icon-pending"/>
<image class="tab-icon-image" validate="never" role="presentation"/>
<image class="tab-sharing-icon-overlay" role="presentation"/>
<image class="tab-icon-overlay" role="presentation"/>
<hbox class="tab-label-container"
onoverflow="this.setAttribute('textoverflow', 'true');"
onunderflow="this.removeAttribute('textoverflow');"
flex="1">
<label class="tab-text tab-label" role="presentation"/>
</hbox>
<image class="tab-icon-sound" role="presentation"/>
<image class="tab-close-button close-icon" role="presentation"/>
</hbox>
</stack>
`;
}
constructor() {
super();
@ -69,37 +97,6 @@
};
}
get fragment() {
if (!this.constructor.hasOwnProperty("_fragment")) {
this.constructor._fragment = MozXULElement.parseXULToFragment(`
<stack class="tab-stack" flex="1">
<vbox class="tab-background">
<hbox class="tab-line"/>
<spacer flex="1" class="tab-background-inner"/>
<hbox class="tab-bottom-line"/>
</vbox>
<hbox class="tab-loading-burst"/>
<hbox class="tab-content" align="center">
<hbox class="tab-throbber" layer="true"/>
<hbox class="tab-icon-pending"/>
<image class="tab-icon-image" validate="never" role="presentation"/>
<image class="tab-sharing-icon-overlay" role="presentation"/>
<image class="tab-icon-overlay" role="presentation"/>
<hbox class="tab-label-container"
onoverflow="this.setAttribute('textoverflow', 'true');"
onunderflow="this.removeAttribute('textoverflow');"
flex="1">
<label class="tab-text tab-label" role="presentation"/>
</hbox>
<image class="tab-icon-sound" role="presentation"/>
<image class="tab-close-button close-icon" role="presentation"/>
</hbox>
</stack>
`);
}
return document.importNode(this.constructor._fragment, true);
}
connectedCallback() {
this.initialize();
}
@ -110,7 +107,7 @@
}
this.textContent = "";
this.appendChild(this.fragment);
this.appendChild(this.constructor.fragment);
this.initializeAttributeInheritance();
this.setAttribute("context", "tabContextMenu");
this._initialized = true;

View File

@ -941,44 +941,45 @@ if (Services.prefs.getBoolPref("privacy.panicButton.enabled")) {
break;
}
},
get markup() {
return `
<vbox class="panel-subview-body">
<hbox id="PanelUI-panic-timeframe">
<image id="PanelUI-panic-timeframe-icon" alt=""/>
<vbox flex="1">
<description data-l10n-id="panic-main-timeframe-desc" id="PanelUI-panic-mainDesc"></description>
<radiogroup id="PanelUI-panic-timeSpan" aria-labelledby="PanelUI-panic-mainDesc" closemenu="none">
<radio id="PanelUI-panic-5min" data-l10n-id="panic-button-5min" selected="true"
value="5" class="subviewradio"/>
<radio id="PanelUI-panic-2hr" data-l10n-id="panic-button-2hr"
value="2" class="subviewradio"/>
<radio id="PanelUI-panic-day" data-l10n-id="panic-button-day"
value="6" class="subviewradio"/>
</radiogroup>
</vbox>
</hbox>
<vbox id="PanelUI-panic-explanations">
<label id="PanelUI-panic-actionlist-main-label" data-l10n-id="panic-button-action-desc"></label>
<label id="PanelUI-panic-actionlist-windows" class="PanelUI-panic-actionlist" data-l10n-id="panic-button-delete-tabs-and-windows"></label>
<label id="PanelUI-panic-actionlist-cookies" class="PanelUI-panic-actionlist" data-l10n-id="panic-button-delete-cookies"></label>
<label id="PanelUI-panic-actionlist-history" class="PanelUI-panic-actionlist" data-l10n-id="panic-button-delete-history"></label>
<label id="PanelUI-panic-actionlist-newwindow" class="PanelUI-panic-actionlist" data-l10n-id="panic-button-open-new-window"></label>
<label id="PanelUI-panic-warning" data-l10n-id="panic-button-undo-warning"></label>
</vbox>
<button id="PanelUI-panic-view-button"
data-l10n-id="panic-button-forget-button"/>
</vbox>
`;
},
onViewShowing(aEvent) {
let win = aEvent.target.ownerGlobal;
let doc = win.document;
let eventBlocker = null;
if (!doc.querySelector("#PanelUI-panic-timeframe")) {
win.MozXULElement.insertFTLIfNeeded("browser/panicButton.ftl");
let frag = win.MozXULElement.parseXULToFragment(`
<vbox class="panel-subview-body">
<hbox id="PanelUI-panic-timeframe">
<image id="PanelUI-panic-timeframe-icon" alt=""/>
<vbox flex="1">
<description data-l10n-id="panic-main-timeframe-desc" id="PanelUI-panic-mainDesc"></description>
<radiogroup id="PanelUI-panic-timeSpan" aria-labelledby="PanelUI-panic-mainDesc" closemenu="none">
<radio id="PanelUI-panic-5min" data-l10n-id="panic-button-5min" selected="true"
value="5" class="subviewradio"/>
<radio id="PanelUI-panic-2hr" data-l10n-id="panic-button-2hr"
value="2" class="subviewradio"/>
<radio id="PanelUI-panic-day" data-l10n-id="panic-button-day"
value="6" class="subviewradio"/>
</radiogroup>
</vbox>
</hbox>
<vbox id="PanelUI-panic-explanations">
<label id="PanelUI-panic-actionlist-main-label" data-l10n-id="panic-button-action-desc"></label>
<label id="PanelUI-panic-actionlist-windows" class="PanelUI-panic-actionlist" data-l10n-id="panic-button-delete-tabs-and-windows"></label>
<label id="PanelUI-panic-actionlist-cookies" class="PanelUI-panic-actionlist" data-l10n-id="panic-button-delete-cookies"></label>
<label id="PanelUI-panic-actionlist-history" class="PanelUI-panic-actionlist" data-l10n-id="panic-button-delete-history"></label>
<label id="PanelUI-panic-actionlist-newwindow" class="PanelUI-panic-actionlist" data-l10n-id="panic-button-open-new-window"></label>
<label id="PanelUI-panic-warning" data-l10n-id="panic-button-undo-warning"></label>
</vbox>
<button id="PanelUI-panic-view-button"
data-l10n-id="panic-button-forget-button"/>
</vbox>
`);
aEvent.target.appendChild(frag);
aEvent.target.appendChild(this.constructor.fragment);
eventBlocker = doc.l10n.translateElements([aEvent.target]);
}

View File

@ -502,6 +502,20 @@ DownloadsSubview.Button = class extends DownloadsViewUI.DownloadElementShell {
}
}
static get markup() {
return `
<image class="toolbarbutton-icon" validate="always"/>
<vbox class="toolbarbutton-text" flex="1">
<label crop="end"/>
<label class="status-text status-full" crop="end"/>
<label class="status-text status-open" crop="end"/>
<label class="status-text status-retry" crop="end"/>
<label class="status-text status-show" crop="end"/>
</vbox>
<toolbarbutton class="action-button"/>
`;
}
// DownloadElementShell
connect() {
let document = this.element.ownerDocument;
@ -510,17 +524,9 @@ DownloadsSubview.Button = class extends DownloadsViewUI.DownloadElementShell {
);
if (!downloadsSubviewItemFragment) {
let MozXULElement = document.defaultView.MozXULElement;
downloadsSubviewItemFragment = MozXULElement.parseXULToFragment(`
<image class="toolbarbutton-icon" validate="always"/>
<vbox class="toolbarbutton-text" flex="1">
<label crop="end"/>
<label class="status-text status-full" crop="end"/>
<label class="status-text status-open" crop="end"/>
<label class="status-text status-retry" crop="end"/>
<label class="status-text status-show" crop="end"/>
</vbox>
<toolbarbutton class="action-button"/>
`);
downloadsSubviewItemFragment = MozXULElement.parseXULToFragment(
this.markup
);
gDownloadsSubviewItemFragments.set(
document,
downloadsSubviewItemFragment

View File

@ -180,6 +180,28 @@ DownloadsViewUI.DownloadElementShell.prototype = {
return !!this._active;
},
get markup() {
return `
<hbox class="downloadMainArea" flex="1" align="center">
<stack>
<image class="downloadTypeIcon" validate="always"/>
<image class="downloadBlockedBadge" />
</stack>
<vbox class="downloadContainer" flex="1" pack="center">
<description class="downloadTarget" crop="center"/>
<description class="downloadDetails downloadDetailsNormal"
crop="end"/>
<description class="downloadDetails downloadDetailsHover"
crop="end"/>
<description class="downloadDetails downloadDetailsButtonHover"
crop="end"/>
</vbox>
</hbox>
<toolbarseparator />
<button class="downloadButton"/>
`;
},
connect() {
let document = this.element.ownerDocument;
let downloadListItemFragment = gDownloadListItemFragments.get(document);
@ -189,25 +211,7 @@ DownloadsViewUI.DownloadElementShell.prototype = {
// actions based on the check if originaltarget was not a button.
if (!downloadListItemFragment) {
let MozXULElement = document.defaultView.MozXULElement;
downloadListItemFragment = MozXULElement.parseXULToFragment(`
<hbox class="downloadMainArea" flex="1" align="center">
<stack>
<image class="downloadTypeIcon" validate="always"/>
<image class="downloadBlockedBadge" />
</stack>
<vbox class="downloadContainer" flex="1" pack="center">
<description class="downloadTarget" crop="center"/>
<description class="downloadDetails downloadDetailsNormal"
crop="end"/>
<description class="downloadDetails downloadDetailsHover"
crop="end"/>
<description class="downloadDetails downloadDetailsButtonHover"
crop="end"/>
</vbox>
</hbox>
<toolbarseparator />
<button class="downloadButton"/>
`);
downloadListItemFragment = MozXULElement.parseXULToFragment(this.markup);
gDownloadListItemFragments.set(document, downloadListItemFragment);
}
this.element.setAttribute("active", true);

View File

@ -3093,32 +3093,40 @@ function getLocalHandlerApp(aFile) {
return localHandlerApp;
}
// eslint-disable-next-line no-undef
let gHandlerListItemFragment = MozXULElement.parseXULToFragment(`
<richlistitem>
<hbox flex="1" equalsize="always">
<hbox class="typeContainer" flex="1" align="center">
<image class="typeIcon" width="16" height="16"
src="moz-icon://goat?size=16"/>
<label class="typeDescription" flex="1" crop="end"/>
</hbox>
<hbox class="actionContainer" flex="1" align="center">
<image class="actionIcon" width="16" height="16"/>
<label class="actionDescription" flex="1" crop="end"/>
</hbox>
<hbox class="actionsMenuContainer" flex="1">
<menulist class="actionsMenu" flex="1" crop="end" selectedIndex="1">
<menupopup/>
</menulist>
</hbox>
</hbox>
</richlistitem>
`);
/**
* This is associated to <richlistitem> elements in the handlers view.
*/
class HandlerListItem {
static get fragment() {
if (!this.hasOwnProperty("_fragment")) {
this._fragment = MozXULElement.parseXULToFragment(this.markup);
}
return document.importNode(this._fragment, true);
}
static get markup() {
return `
<richlistitem>
<hbox flex="1" equalsize="always">
<hbox class="typeContainer" flex="1" align="center">
<image class="typeIcon" width="16" height="16"
src="moz-icon://goat?size=16"/>
<label class="typeDescription" flex="1" crop="end"/>
</hbox>
<hbox class="actionContainer" flex="1" align="center">
<image class="actionIcon" width="16" height="16"/>
<label class="actionDescription" flex="1" crop="end"/>
</hbox>
<hbox class="actionsMenuContainer" flex="1">
<menulist class="actionsMenu" flex="1" crop="end" selectedIndex="1">
<menupopup/>
</menulist>
</hbox>
</hbox>
</richlistitem>
`;
}
static forNode(node) {
return gNodeToObjectMap.get(node);
}
@ -3139,7 +3147,7 @@ class HandlerListItem {
}
createNode(list) {
list.appendChild(document.importNode(gHandlerListItemFragment, true));
list.appendChild(this.constructor.fragment);
this.node = list.lastChild;
gNodeToObjectMap.set(this.node, this);
}

View File

@ -95,7 +95,7 @@
return this._oneOffButtons;
}
get _markup() {
static get markup() {
return `
<hbox class="search-panel-header search-panel-current-engine">
<image class="searchbar-engine-image"></image>

View File

@ -21,6 +21,25 @@
};
}
static get markup() {
return `
<stringbundle src="chrome://browser/locale/search.properties"></stringbundle>
<hbox class="searchbar-search-button" tooltiptext="&searchIcon.tooltip;">
<image class="searchbar-search-icon"></image>
<image class="searchbar-search-icon-overlay"></image>
</hbox>
<html:input class="searchbar-textbox" is="autocomplete-input" type="search" placeholder="&searchInput.placeholder;" autocompletepopup="PopupSearchAutoComplete" autocompletesearch="search-autocomplete" autocompletesearchparam="searchbar-history" maxrows="10" completeselectedindex="true" minresultsforpopup="0"/>
<menupopup class="textbox-contextmenu"></menupopup>
<hbox class="search-go-container">
<image class="search-go-button urlbar-icon" hidden="true" onclick="handleSearchCommand(event);" tooltiptext="&contentSearchSubmit.tooltip;"></image>
</hbox>
`;
}
static get entities() {
return ["chrome://browser/locale/browser.dtd"];
}
constructor() {
super();
@ -44,22 +63,6 @@
QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver]),
};
this.content = MozXULElement.parseXULToFragment(
`
<stringbundle src="chrome://browser/locale/search.properties"></stringbundle>
<hbox class="searchbar-search-button" tooltiptext="&searchIcon.tooltip;">
<image class="searchbar-search-icon"></image>
<image class="searchbar-search-icon-overlay"></image>
</hbox>
<html:input class="searchbar-textbox" is="autocomplete-input" type="search" placeholder="&searchInput.placeholder;" autocompletepopup="PopupSearchAutoComplete" autocompletesearch="search-autocomplete" autocompletesearchparam="searchbar-history" maxrows="10" completeselectedindex="true" minresultsforpopup="0"/>
<menupopup class="textbox-contextmenu"></menupopup>
<hbox class="search-go-container">
<image class="search-go-button urlbar-icon" hidden="true" onclick="handleSearchCommand(event);" tooltiptext="&contentSearchSubmit.tooltip;"></image>
</hbox>
`,
["chrome://browser/locale/browser.dtd"]
);
this._ignoreFocus = false;
this._engines = null;
}
@ -70,7 +73,7 @@
return;
}
this.appendChild(document.importNode(this.content, true));
this.appendChild(this.constructor.fragment);
this.initializeAttributeInheritance();
// Don't go further if in Customize mode.

View File

@ -5,10 +5,8 @@
"use strict";
class MozTranslationNotification extends MozElements.Notification {
connectedCallback() {
this.appendChild(
MozXULElement.parseXULToFragment(
`
static get markup() {
return `
<hbox anonid="details" align="center" flex="1">
<image class="translate-infobar-element messageImage"/>
<panel anonid="welcomePanel" class="translation-welcome-panel" type="arrow" align="start">
@ -82,13 +80,18 @@ class MozTranslationNotification extends MozElements.Notification {
class="messageCloseButton close-icon tabbable"
tooltiptext="&closeNotification.tooltip;"
oncommand="this.parentNode.closeCommand();"/>
`,
[
"chrome://global/locale/notification.dtd",
"chrome://browser/locale/translation.dtd",
]
)
);
`;
}
static get entities() {
return [
"chrome://global/locale/notification.dtd",
"chrome://browser/locale/translation.dtd",
];
}
connectedCallback() {
this.appendChild(this.constructor.fragment);
for (let [propertyName, selector] of [
["details", "[anonid=details]"],

View File

@ -81,15 +81,8 @@
}
MozElements.MozAutocompleteProfileListitem = class MozAutocompleteProfileListitem extends MozAutocompleteProfileListitemBase {
connectedCallback() {
if (this.delayConnectedCallback()) {
return;
}
this.textContent = "";
this.appendChild(
MozXULElement.parseXULToFragment(`
static get markup() {
return `
<div xmlns="http://www.w3.org/1999/xhtml" class="autofill-item-box">
<div class="profile-label-col profile-item-col">
<span class="profile-label-affix"></span>
@ -99,8 +92,17 @@
<span class="profile-comment"></span>
</div>
</div>
`)
);
`;
}
connectedCallback() {
if (this.delayConnectedCallback()) {
return;
}
this.textContent = "";
this.appendChild(this.constructor.fragment);
this._itemBox = this.querySelector(".autofill-item-box");
this._labelAffix = this.querySelector(".profile-label-affix");
@ -158,6 +160,15 @@
);
class MozAutocompleteProfileListitemFooter extends MozAutocompleteProfileListitemBase {
static get markup() {
return `
<div xmlns="http://www.w3.org/1999/xhtml" class="autofill-item-box autofill-footer">
<div class="autofill-footer-row autofill-warning"></div>
<div class="autofill-footer-row autofill-button"></div>
</div>
`;
}
constructor() {
super();
@ -180,14 +191,7 @@
}
this.textContent = "";
this.appendChild(
MozXULElement.parseXULToFragment(`
<div xmlns="http://www.w3.org/1999/xhtml" class="autofill-item-box autofill-footer">
<div class="autofill-footer-row autofill-warning"></div>
<div class="autofill-footer-row autofill-button"></div>
</div>
`)
);
this.appendChild(this.constructor.fragment);
this._itemBox = this.querySelector(".autofill-footer");
this._optionButton = this.querySelector(".autofill-button");
@ -312,16 +316,18 @@
);
class MozAutocompleteCreditcardInsecureField extends MozAutocompleteProfileListitemBase {
static get markup() {
return `
<div xmlns="http://www.w3.org/1999/xhtml" class="autofill-insecure-item"></div>
`;
}
connectedCallback() {
if (this.delayConnectedCallback()) {
return;
}
this.textContent = "";
this.appendChild(
MozXULElement.parseXULToFragment(`
<div xmlns="http://www.w3.org/1999/xhtml" class="autofill-insecure-item"></div>
`)
);
this.appendChild(this.constructor.fragment);
this._itemBox = this.querySelector(".autofill-insecure-item");
@ -353,6 +359,14 @@
);
class MozAutocompleteProfileListitemClearButton extends MozAutocompleteProfileListitemBase {
static get markup() {
return `
<div xmlns="http://www.w3.org/1999/xhtml" class="autofill-item-box autofill-footer">
<div class="autofill-footer-row autofill-button"></div>
</div>
`;
}
constructor() {
super();
@ -371,13 +385,7 @@
}
this.textContent = "";
this.appendChild(
MozXULElement.parseXULToFragment(`
<div xmlns="http://www.w3.org/1999/xhtml" class="autofill-item-box autofill-footer">
<div class="autofill-footer-row autofill-button"></div>
</div>
`)
);
this.appendChild(this.constructor.fragment);
this._itemBox = this.querySelector(".autofill-item-box");
this._clearBtn = this.querySelector(".autofill-button");

View File

@ -10,18 +10,8 @@
customElements.define(
"printpreview-toolbar",
class PrintPreviewToolbar extends MozXULElement {
constructor() {
super();
this.disconnectedCallback = this.disconnectedCallback.bind(this);
}
connectedCallback() {
window.addEventListener("unload", this.disconnectedCallback, {
once: true,
});
MozXULElement.insertFTLIfNeeded("toolkit/printing/printPreview.ftl");
this.appendChild(
MozXULElement.parseXULToFragment(`
static get markup() {
return `
<button id="print-preview-print" oncommand="this.parentNode.print();" data-l10n-id="printpreview-print"/>
<button id="print-preview-pageSetup" oncommand="this.parentNode.doPageSetup();" data-l10n-id="printpreview-page-setup"/>
<vbox align="center" pack="center">
@ -71,8 +61,19 @@ customElements.define(
<toolbarseparator class="toolbarseparator-primary"/>
<button id="print-preview-toolbar-close-button" oncommand="PrintUtils.exitPrintPreview();" data-l10n-id="printpreview-close"/>
<data id="print-preview-custom-scale-prompt-title" data-l10n-id="printpreview-custom-scale-prompt-title"/>
`)
);
`;
}
constructor() {
super();
this.disconnectedCallback = this.disconnectedCallback.bind(this);
}
connectedCallback() {
window.addEventListener("unload", this.disconnectedCallback, {
once: true,
});
MozXULElement.insertFTLIfNeeded("toolkit/printing/printPreview.ftl");
this.appendChild(this.constructor.fragment);
this.mPrintButton = document.getElementById("print-preview-print");

View File

@ -469,6 +469,48 @@
}
}
/**
* Used by custom elements for caching fragments. We now would be
* caching once per class while also supporting subclasses.
*
* If available, returns the cached fragment.
* Otherwise, creates it.
*
* Example:
*
* class ElementA extends MozXULElement {
* static get markup() {
* return `<hbox class="example"`;
* }
*
* static get entities() {
* // Optional field for parseXULToFragment
* return `["chrome://global/locale/notification.dtd"]`;
* }
*
* connectedCallback() {
* this.appendChild(this.constructor.fragment);
* }
* }
*
* @return {importedNode} The imported node that has not been
* inserted into document tree.
*/
static get fragment() {
if (!this.hasOwnProperty("_fragment")) {
let markup = this.markup;
if (markup) {
this._fragment = MozXULElement.parseXULToFragment(
markup,
this.entities
);
} else {
throw new Error("Markup is null");
}
}
return document.importNode(this._fragment, true);
}
/**
* Allows eager deterministic construction of XUL elements with XBL attached, by
* parsing an element tree and returning a DOM fragment to be inserted in the

View File

@ -25,7 +25,7 @@
this.setAttribute("consumeoutsideclicks", "never");
this.textContent = "";
this.appendChild(MozXULElement.parseXULToFragment(this._markup));
this.appendChild(this.constructor.fragment);
/**
* This is the default number of rows that we give the autocomplete
@ -108,7 +108,7 @@
return this._richlistbox;
}
get _markup() {
static get markup() {
return `
<richlistbox class="autocomplete-richlistbox" flex="1"/>
`;

View File

@ -62,7 +62,7 @@
}
this.textContent = "";
this.appendChild(MozXULElement.parseXULToFragment(this._markup));
this.appendChild(this.constructor.fragment);
this.initializeAttributeInheritance();
this._boundaryCutoff = null;
@ -83,7 +83,7 @@
};
}
get _markup() {
static get markup() {
return `
<image class="ac-type-icon"/>
<image class="ac-site-icon"/>
@ -553,7 +553,7 @@
};
}
get _markup() {
static get markup() {
return `
<image class="ac-type-icon"/>
<image class="ac-site-icon"/>
@ -624,7 +624,7 @@
}
this.textContent = "";
this.appendChild(MozXULElement.parseXULToFragment(this._markup));
this.appendChild(this.constructor.fragment);
this.initializeAttributeInheritance();
this._adjustAcItem();
}
@ -638,7 +638,7 @@
};
}
get _markup() {
static get markup() {
return `
<div xmlns="http://www.w3.org/1999/xhtml"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"

View File

@ -8,6 +8,16 @@
// leaking to window scope.
{
class MozCheckbox extends MozElements.BaseText {
static get markup() {
return `
<image class="checkbox-check"/>
<hbox class="checkbox-label-box" flex="1">
<image class="checkbox-icon"/>
<label class="checkbox-label" flex="1"/>
</hbox>
`;
}
constructor() {
super();
@ -41,23 +51,8 @@
return;
}
if (!MozCheckbox.contentFragment) {
let content = `
<image class="checkbox-check"/>
<hbox class="checkbox-label-box" flex="1">
<image class="checkbox-icon"/>
<label class="checkbox-label" flex="1"/>
</hbox>
`;
MozCheckbox.contentFragment = MozXULElement.parseXULToFragment(content);
}
this.textContent = "";
let fragment = this.ownerDocument.importNode(
MozCheckbox.contentFragment,
true
);
this.appendChild(fragment);
this.appendChild(this.constructor.fragment);
this.initializeAttributeInheritance();
}

View File

@ -38,28 +38,9 @@
]);
const TOPIC_MAC_APP_ACTIVATE = "mac_app_activate";
class MozFindbar extends XULElement {
constructor() {
super();
MozXULElement.insertFTLIfNeeded("toolkit/main-window/findbar.ftl");
this.destroy = this.destroy.bind(this);
// We have to guard against `this.close` being |null| due to an unknown
// issue, which is tracked in bug 957999.
this.addEventListener(
"keypress",
event => {
if (event.keyCode == event.DOM_VK_ESCAPE) {
if (this.close) {
this.close();
}
event.preventDefault();
}
},
true
);
this.content = MozXULElement.parseXULToFragment(`
class MozFindbar extends MozXULElement {
static get markup() {
return `
<hbox anonid="findbar-container" class="findbar-container" flex="1" align="center">
<hbox anonid="findbar-textbox-wrapper" align="stretch">
<html:input anonid="findbar-textbox" class="findbar-textbox findbar-find-fast" />
@ -86,7 +67,28 @@
</hbox>
<toolbarbutton anonid="find-closebutton" class="findbar-closebutton close-icon"
data-l10n-id="findbar-find-button-close" oncommand="close();" />
`);
`;
}
constructor() {
super();
MozXULElement.insertFTLIfNeeded("toolkit/main-window/findbar.ftl");
this.destroy = this.destroy.bind(this);
// We have to guard against `this.close` being |null| due to an unknown
// issue, which is tracked in bug 957999.
this.addEventListener(
"keypress",
event => {
if (event.keyCode == event.DOM_VK_ESCAPE) {
if (this.close) {
this.close();
}
event.preventDefault();
}
},
true
);
}
connectedCallback() {
@ -95,7 +97,7 @@
// findbar into a new window).
this.setAttribute("noanim", "true");
this.hidden = true;
this.appendChild(document.importNode(this.content, true));
this.appendChild(this.constructor.fragment);
/**
* Please keep in sync with toolkit/modules/FindBarContent.jsm

View File

@ -348,17 +348,8 @@
});
MozElements.Notification = class Notification extends MozXULElement {
constructor() {
super();
this.persistence = 0;
this.priority = 0;
this.timeout = 0;
}
connectedCallback() {
this.appendChild(
MozXULElement.parseXULToFragment(
`
static get markup() {
return `
<hbox class="messageDetails" align="center" flex="1"
oncommand="this.parentNode._doButtonCommand(event);">
<image class="messageImage"/>
@ -369,10 +360,22 @@
class="messageCloseButton close-icon tabbable"
tooltiptext="&closeNotification.tooltip;"
oncommand="this.parentNode.dismiss();"/>
`,
["chrome://global/locale/notification.dtd"]
)
);
`;
}
static get entities() {
return ["chrome://global/locale/notification.dtd"];
}
constructor() {
super();
this.persistence = 0;
this.priority = 0;
this.timeout = 0;
}
connectedCallback() {
this.appendChild(this.constructor.fragment);
for (let [propertyName, selector] of [
["messageDetails", ".messageDetails"],

View File

@ -64,14 +64,8 @@
this.hidden = false;
}
slotContents() {
if (this._hasSlotted) {
return;
}
this._hasSlotted = true;
this.appendChild(
MozXULElement.parseXULToFragment(
`
static get markup() {
return `
<hbox class="popup-notification-header-container"></hbox>
<hbox align="start" class="popup-notification-body-container">
<image class="popup-notification-icon"/>
@ -101,10 +95,19 @@
</button>
<button class="popup-notification-button popup-notification-primary-button" label="&defaultButton.label;" accesskey="&defaultButton.accesskey;"></button>
</hbox>
`,
["chrome://global/locale/notification.dtd"]
)
);
`;
}
static get entities() {
return ["chrome://global/locale/notification.dtd"];
}
slotContents() {
if (this._hasSlotted) {
return;
}
this._hasSlotted = true;
this.appendChild(this.constructor.fragment);
this.button = this.querySelector(".popup-notification-primary-button");
this.secondaryButton = this.querySelector(

View File

@ -466,21 +466,17 @@
customElements.define("radiogroup", MozRadiogroup);
let gRadioFrag = null;
function getRadioFragment() {
if (!gRadioFrag) {
gRadioFrag = MozXULElement.parseXULToFragment(`
<image class="radio-check"></image>
<hbox class="radio-label-box" align="center" flex="1">
<image class="radio-icon"></image>
<label class="radio-label" flex="1"></label>
</hbox>
`);
}
return document.importNode(gRadioFrag, true);
}
class MozRadio extends MozElements.BaseText {
static get markup() {
return `
<image class="radio-check"></image>
<hbox class="radio-label-box" align="center" flex="1">
<image class="radio-icon"></image>
<label class="radio-label" flex="1"></label>
</hbox>
`;
}
static get inheritedAttributes() {
return {
".radio-check": "disabled,selected",
@ -513,7 +509,7 @@
this.connectedOnce = true;
// If the caller didn't provide custom content then append the default:
if (!this.firstElementChild) {
this.appendChild(getRadioFragment());
this.appendChild(this.constructor.fragment);
this.initializeAttributeInheritance();
}
}

View File

@ -59,6 +59,17 @@
};
}
static get markup() {
// TODO: Bug 1534799 - Convert string to Fluent and use manual DOM construction
return `
<image class="textbox-search-clear" label="&searchTextBox.clear.label;"/>
`;
}
static get entities() {
return ["chrome://global/locale/textcontext.dtd"];
}
connectedCallback() {
if (this.delayConnectedCallback()) {
return;
@ -84,13 +95,7 @@
searchBtn.className = "textbox-search-icon";
searchBtn.addEventListener("click", e => this._iconClick(e));
// TODO: Bug 1534799 - Convert string to Fluent and use manual DOM construction
let clearBtn = MozXULElement.parseXULToFragment(
`
<image class="textbox-search-clear" label="&searchTextBox.clear.label;"/>
`,
["chrome://global/locale/textcontext.dtd"]
);
let clearBtn = this.constructor.fragment;
clearBtn = this._searchClearIcon = clearBtn.querySelector(
".textbox-search-clear"
);

View File

@ -272,6 +272,15 @@
customElements.define("tabpanels", MozTabpanels);
MozElements.MozTab = class MozTab extends MozElements.BaseText {
static get markup() {
return `
<hbox class="tab-middle box-inherit" flex="1">
<image class="tab-icon" role="presentation"></image>
<label class="tab-text" flex="1" role="presentation"></label>
</hbox>
`;
}
constructor() {
super();
@ -289,22 +298,10 @@
};
}
get fragment() {
if (!this._fragment) {
this._fragment = MozXULElement.parseXULToFragment(`
<hbox class="tab-middle box-inherit" flex="1">
<image class="tab-icon" role="presentation"></image>
<label class="tab-text" flex="1" role="presentation"></label>
</hbox>
`);
}
return this.ownerDocument.importNode(this._fragment, true);
}
connectedCallback() {
if (!this._initialized) {
this.textContent = "";
this.appendChild(this.fragment);
this.appendChild(this.constructor.fragment);
this.initializeAttributeInheritance();
this._initialized = true;
}

View File

@ -198,6 +198,19 @@
customElements.define("treechildren", MozTreeChildren);
class MozTreecolPicker extends MozElements.BaseControl {
static get entities() {
return ["chrome://global/locale/tree.dtd"];
}
static get markup() {
return `
<image class="tree-columnpicker-icon"></image>
<menupopup anonid="popup">
<menuseparator anonid="menuseparator"></menuseparator>
<menuitem anonid="menuitem" label="&restoreColumnOrder.label;"></menuitem>
</menupopup>
`;
}
constructor() {
super();
@ -235,18 +248,7 @@
}
this.textContent = "";
this.appendChild(
MozXULElement.parseXULToFragment(
`
<image class="tree-columnpicker-icon"></image>
<menupopup anonid="popup">
<menuseparator anonid="menuseparator"></menuseparator>
<menuitem anonid="menuitem" label="&restoreColumnOrder.label;"></menuitem>
</menupopup>
`,
["chrome://global/locale/tree.dtd"]
)
);
this.appendChild(this.constructor.fragment);
}
buildPopup(aPopup) {
@ -308,11 +310,11 @@
};
}
get content() {
return MozXULElement.parseXULToFragment(`
static get markup() {
return `
<label class="treecol-text" flex="1" crop="right"></label>
<image class="treecol-sortdirection"></image>
`);
`;
}
constructor() {
@ -373,7 +375,7 @@
}
this.textContent = "";
this.appendChild(this.content);
this.appendChild(this.constructor.fragment);
this.initializeAttributeInheritance();
if (this.hasAttribute("ordinal")) {
this.style.MozBoxOrdinalGroup = this.getAttribute("ordinal");
@ -559,6 +561,12 @@
};
}
static get markup() {
return `
<treecolpicker class="treecol-image" fixed="true"></treecolpicker>
`;
}
connectedCallback() {
if (this.delayConnectedCallback()) {
return;
@ -567,11 +575,7 @@
this.setAttribute("slot", "treecols");
if (!this.querySelector("treecolpicker")) {
this.appendChild(
MozXULElement.parseXULToFragment(`
<treecolpicker class="treecol-image" fixed="true"></treecolpicker>
`)
);
this.appendChild(this.constructor.fragment);
this.initializeAttributeInheritance();
}
@ -590,6 +594,28 @@
class MozTree extends MozElements.BaseControlMixin(
MozElements.MozElementMixin(XULTreeElement)
) {
static get markup() {
return `
<html:link rel="stylesheet" href="chrome://global/content/widgets.css" />
<html:slot name="treecols"></html:slot>
<stack class="tree-stack" flex="1">
<hbox class="tree-rows" flex="1">
<hbox flex="1" class="tree-bodybox">
<html:slot name="treechildren"></html:slot>
</hbox>
<scrollbar height="0" minwidth="0" minheight="0" orient="vertical"
class="hidevscroll-scrollbar scrollbar-topmost"
></scrollbar>
</hbox>
<html:input class="tree-input" type="text" hidden="true"/>
</stack>
<hbox class="hidehscroll-box">
<scrollbar orient="horizontal" flex="1" increment="16" class="scrollbar-topmost" ></scrollbar>
<scrollcorner class="hidevscroll-scrollcorner"></scrollcorner>
</hbox>
`;
}
constructor() {
super();
@ -599,26 +625,9 @@
this.NATURAL_ORDER = 1; // The original order, which is the DOM ordering
this.attachShadow({ mode: "open" });
let fragment = MozXULElement.parseXULToFragment(`
<html:link rel="stylesheet" href="chrome://global/content/widgets.css" />
<html:slot name="treecols"></html:slot>
<stack class="tree-stack" flex="1">
<hbox class="tree-rows" flex="1">
<hbox flex="1" class="tree-bodybox">
<html:slot name="treechildren"></html:slot>
</hbox>
<scrollbar height="0" minwidth="0" minheight="0" orient="vertical"
class="hidevscroll-scrollbar scrollbar-topmost"
></scrollbar>
</hbox>
<html:input class="tree-input" type="text" hidden="true"/>
</stack>
<hbox class="hidehscroll-box">
<scrollbar orient="horizontal" flex="1" increment="16" class="scrollbar-topmost" ></scrollbar>
<scrollcorner class="hidevscroll-scrollcorner"></scrollcorner>
</hbox>
`);
let handledElements = fragment.querySelectorAll("scrollbar,scrollcorner");
let handledElements = this.constructor.fragment.querySelectorAll(
"scrollbar,scrollcorner"
);
let stopAndPrevent = e => {
e.stopPropagation();
e.preventDefault();
@ -630,7 +639,7 @@
el.addEventListener("dblclick", stopProp);
el.addEventListener("command", stopProp);
}
this.shadowRoot.appendChild(fragment);
this.shadowRoot.appendChild(this.constructor.fragment);
}
static get inheritedAttributes() {

View File

@ -522,7 +522,7 @@
this._wizard = this.getRootNode().host;
this.textContent = "";
this.appendChild(MozXULElement.parseXULToFragment(this._markup));
this.appendChild(this.constructor.fragment);
MozXULElement.insertFTLIfNeeded("toolkit/global/wizard.ftl");
@ -556,7 +556,7 @@
: null;
}
get _markup() {
static get markup() {
if (AppConstants.platform == "macosx") {
return `
<vbox flex="1">

View File

@ -2170,20 +2170,31 @@ class FiveStarRating extends HTMLElement {
customElements.define("five-star-rating", FiveStarRating);
class ContentSelectDropdown extends HTMLElement {
static get markup() {
return `
<menulist popuponly="true" id="ContentSelectDropdown" hidden="true">
<menupopup rolluponmousewheel="true" activateontab="true"
position="after_start" level="parent"/>
</menulist>
`;
}
static get fragment() {
if (!this.constructor.hasOwnProperty("_fragment")) {
this.constructor._fragment = MozXULElement.parseXULToFragment(
this.constructor.markup
);
}
return document.importNode(this.constructor._fragment, true);
}
connectedCallback() {
if (this.children.length) {
return;
}
// This creates the menulist and menupopup elements needed for the inline
// browser to support <select> elements and context menus.
this.appendChild(
MozXULElement.parseXULToFragment(`
<menulist popuponly="true" id="ContentSelectDropdown" hidden="true">
<menupopup rolluponmousewheel="true" activateontab="true"
position="after_start" level="parent"/>
</menulist>
`)
);
this.appendChild(this.constructor.fragment);
}
}
customElements.define("content-select-dropdown", ContentSelectDropdown);

View File

@ -19,6 +19,17 @@
);
class AddonAbuseReportsXULFrame extends MozXULElement {
static get markup() {
return `
<browser id="abuse-report-xulframe-overlay-inner"
type="content"
disablehistory="true"
transparent="true"
flex="1">
</browser>
`;
}
constructor() {
super();
this.report = null;
@ -30,16 +41,7 @@
connectedCallback() {
this.textContent = "";
const content = MozXULElement.parseXULToFragment(`
<browser id="abuse-report-xulframe-overlay-inner"
type="content"
disablehistory="true"
transparent="true"
flex="1">
</browser>
`);
this.appendChild(content);
this.appendChild(this.constructor.fragment);
const browser = this.querySelector("browser");
this.promiseBrowserLoaded = new Promise(resolve => {

View File

@ -37,19 +37,21 @@ const { PrivateBrowsingUtils } = ChromeUtils.import(
);
class MozHandler extends window.MozElements.MozRichlistitem {
static get markup() {
return `
<vbox pack="center">
<image height="32" width="32"/>
</vbox>
<vbox flex="1">
<label class="name"/>
<label class="description"/>
</vbox>
`;
}
connectedCallback() {
this.textContent = "";
this.appendChild(
window.MozXULElement.parseXULToFragment(`
<vbox pack="center">
<image height="32" width="32"/>
</vbox>
<vbox flex="1">
<label class="name"/>
<label class="description"/>
</vbox>
`)
);
this.appendChild(this.constructor.fragment);
this.initializeAttributeInheritance();
}