Bug 1417042 - Remove the "panelview" binding. r=Gijs
MozReview-Commit-ID: 26uQb3pteQd
--- a/browser/base/content/browser-pageActions.js
+++ b/browser/base/content/browser-pageActions.js
@@ -946,17 +946,17 @@ BrowserPageActions.emailLink = {
// send to device
BrowserPageActions.sendToDevice = {
onPlacedInPanel(buttonNode) {
let action = PageActions.actionForID("sendToDevice");
BrowserPageActions.takeActionTitleFromPanel(action);
},
onSubviewPlaced(panelViewNode) {
- let bodyNode = panelViewNode.firstChild;
+ let bodyNode = panelViewNode.querySelector(".panel-subview-body");
for (let node of bodyNode.childNodes) {
BrowserPageActions.takeNodeAttributeFromPanel(node, "title");
BrowserPageActions.takeNodeAttributeFromPanel(node, "shortcut");
}
},
onLocationChange() {
let action = PageActions.actionForID("sendToDevice");
@@ -965,17 +965,17 @@ BrowserPageActions.sendToDevice = {
action.setDisabled(!gSync.isSendableURI(url), window);
},
onShowingSubview(panelViewNode) {
let browser = gBrowser.selectedBrowser;
let url = browser.currentURI.spec;
let title = browser.contentTitle;
- let bodyNode = panelViewNode.firstChild;
+ let bodyNode = panelViewNode.querySelector(".panel-subview-body");
let panelNode = panelViewNode.closest("panel");
// This is on top because it also clears the device list between state
// changes.
gSync.populateSendTabToDevicesMenu(bodyNode, url, title, (clientId, name, clientType, lastModified) => {
if (!name) {
return document.createElement("toolbarseparator");
}
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -68,31 +68,29 @@ toolbar[customizable="true"] {
}
panelmultiview {
-moz-box-align: start;
-moz-binding: url("chrome://browser/content/customizableui/panelUI.xml#panelmultiview");
}
panelview {
- -moz-binding: url("chrome://browser/content/customizableui/panelUI.xml#panelview");
-moz-box-orient: vertical;
}
-panel[hidden] panelmultiview,
-panel[hidden] panelview {
+panel[hidden] panelmultiview {
-moz-binding: none;
}
panelview:not([current]):not([in-transition]) {
visibility: collapse;
}
-panelview[mainview] > .panel-header,
-panelview:not([title]) > .panel-header {
+/* Hide the header when a subview is reused as a main view. */
+panelview[mainview] > .panel-header {
display: none;
}
tabbrowser {
-moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser");
}
#tabbrowser-tabs {
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -363,19 +363,59 @@ this.PanelMultiView = class {
}
_placeSubView(viewNode) {
this._viewStack.appendChild(viewNode);
if (!this.panelViews.includes(viewNode))
this.panelViews.push(viewNode);
}
- goBack(target) {
+ _setHeader(viewNode, titleText) {
+ // If the header already exists, update or remove it as requested.
+ let header = viewNode.firstChild;
+ if (header && header.classList.contains("panel-header")) {
+ if (titleText) {
+ header.querySelector("label").setAttribute("value", titleText);
+ } else {
+ header.remove();
+ }
+ return;
+ }
+
+ // The header doesn't exist, only create it if needed.
+ if (!titleText) {
+ return;
+ }
+
+ header = this.document.createElement("box");
+ header.classList.add("panel-header");
+
+ let backButton = this.document.createElement("toolbarbutton");
+ backButton.className =
+ "subviewbutton subviewbutton-iconic subviewbutton-back";
+ backButton.setAttribute("closemenu", "none");
+ backButton.setAttribute("tabindex", "0");
+ backButton.setAttribute("tooltip",
+ this.node.getAttribute("data-subviewbutton-tooltip"));
+ backButton.addEventListener("command", () => {
+ // The panelmultiview element may change if the view is reused.
+ viewNode.panelMultiView.goBack();
+ backButton.blur();
+ });
+
+ let label = this.document.createElement("label");
+ label.setAttribute("value", titleText);
+
+ header.append(backButton, label);
+ viewNode.prepend(header);
+ }
+
+ goBack() {
let [current, previous] = this.panelViews.back();
- return this.showSubView(current, target, previous);
+ return this.showSubView(current, null, previous);
}
/**
* Checks whether it is possible to navigate backwards currently. Returns
* false if this is the panelmultiview's mainview, true otherwise.
*
* @param {panelview} view View to check, defaults to the currently active view.
* @return {Boolean}
@@ -449,16 +489,20 @@ this.PanelMultiView = class {
this._placeSubView(viewNode);
} else {
throw new Error(`Subview ${aViewId} doesn't exist!`);
}
} else if (viewNode.parentNode == this._panelViewCache) {
this._placeSubView(viewNode);
}
+ viewNode.panelMultiView = this.node;
+ this._setHeader(viewNode, viewNode.getAttribute("title") ||
+ (aAnchor && aAnchor.getAttribute("label")));
+
let reverse = !!aPreviousView;
let previousViewNode = aPreviousView || this._currentSubView;
// If the panelview to show is the same as the previous one, the 'ViewShowing'
// event has already been dispatched. Don't do it twice.
let showingSameView = viewNode == previousViewNode;
let playTransition = (!!previousViewNode && !showingSameView && this._panel.state == "open");
let isMainView = viewNode.id == this._mainViewId;
@@ -483,20 +527,17 @@ this.PanelMultiView = class {
// Because the 'mainview' attribute may be out-of-sync, due to view node
// reparenting in combination with ephemeral PanelMultiView instances,
// this is the best place to correct it (just before showing).
if (isMainView)
viewNode.setAttribute("mainview", true);
else
viewNode.removeAttribute("mainview");
- // Make sure that new panels always have a title set.
if (aAnchor) {
- if (!viewNode.hasAttribute("title"))
- viewNode.setAttribute("title", aAnchor.getAttribute("label"));
viewNode.classList.add("PanelUI-subView");
}
if (!isMainView && this._mainViewWidth)
viewNode.style.maxWidth = viewNode.style.minWidth = this._mainViewWidth + "px";
if (!showingSameView || !viewNode.hasAttribute("current")) {
// Emit the ViewShowing event so that the widget definition has a chance
// to lazily populate the subview with things or perhaps even cancel this
@@ -594,18 +635,18 @@ this.PanelMultiView = class {
// reopening a subview, because its contents may have changed.
viewRect = viewNode.__lastKnownBoundingRect;
viewNode.setAttribute("in-transition", true);
} else if (viewNode.customRectGetter) {
// Can't use Object.assign directly with a DOM Rect object because its properties
// aren't enumerable.
let {height, width} = previousRect;
viewRect = Object.assign({height, width}, viewNode.customRectGetter());
- let {header} = viewNode;
- if (header) {
+ let header = viewNode.firstChild;
+ if (header && header.classList.contains("panel-header")) {
viewRect.height += this._dwu.getBoundsWithoutFlushing(header).height;
}
viewNode.setAttribute("in-transition", true);
} else {
let oldSibling = viewNode.nextSibling || null;
this._offscreenViewStack.style.minHeight =
this._viewContainer.style.height;
this._offscreenViewStack.appendChild(viewNode);
@@ -1018,17 +1059,17 @@ this.PanelMultiView = class {
}
case "ArrowLeft":
case "ArrowRight": {
stop();
let dir = this._dir;
if ((dir == "ltr" && keyCode == "ArrowLeft") ||
(dir == "rtl" && keyCode == "ArrowRight")) {
if (this._canGoBack(view))
- this.goBack(view.backButton);
+ this.goBack();
break;
}
// If the current button is _not_ one that points to a subview, pressing
// the arrow key shouldn't do anything.
if (!navMap.selected || !navMap.selected.get() ||
!navMap.selected.get().classList.contains("subviewbutton-nav")) {
break;
}
@@ -1084,18 +1125,16 @@ this.PanelMultiView = class {
* Retrieve the button elements from a view node that can be used for navigation
* using the keyboard; enabled buttons and the back button, if visible.
*
* @param {nsIDOMNode} view
* @return {Array}
*/
_getNavigableElements(view) {
let buttons = Array.from(view.querySelectorAll(".subviewbutton:not([disabled])"));
- if (this._canGoBack(view))
- buttons.unshift(view.backButton);
let dwu = this._dwu;
return buttons.filter(button => {
let bounds = dwu.getBoundsWithoutFlushing(button);
return bounds.width > 0 && bounds.height > 0;
});
}
/**
--- a/browser/components/customizableui/content/panelUI.xml
+++ b/browser/components/customizableui/content/panelUI.xml
@@ -12,17 +12,17 @@
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="panelmultiview">
<resources>
<stylesheet src="chrome://browser/content/customizableui/panelUI.css"/>
</resources>
- <content>
+ <content data-subviewbutton-tooltip="&backCmd.label;">
<xul:box anonid="viewContainer" class="panel-viewcontainer" xbl:inherits="panelopen,transitioning">
<xul:box anonid="viewStack" xbl:inherits="transitioning" class="panel-viewstack">
<children includes="panelview"/>
</xul:box>
</xul:box>
<xul:box class="panel-viewcontainer offscreen">
<xul:box anonid="offscreenViewStack" class="panel-viewstack"/>
</xul:box>
@@ -33,41 +33,9 @@
this.instance = new PanelMultiView(this);
]]></constructor>
<destructor><![CDATA[
this.instance.destructor();
]]></destructor>
</implementation>
</binding>
-
- <binding id="panelview">
- <content>
- <xul:box class="panel-header" anonid="header">
- <xul:toolbarbutton anonid="back"
- class="subviewbutton subviewbutton-iconic subviewbutton-back"
- closemenu="none"
- tabindex="0"
- tooltip="&backCmd.label;"
- oncommand="document.getBindingParent(this).panelMultiView.goBack(); this.blur()"/>
- <xul:label xbl:inherits="value=title"/>
- </xul:box>
- <children/>
- </content>
- <implementation>
- <property name="header"
- readonly="true"
- onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'header');"/>
- <property name="backButton"
- readonly="true"
- onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'back');"/>
- <property name="panelMultiView" readonly="true">
- <getter><![CDATA[
- if (!this.parentNode.localName.endsWith("panelmultiview")) {
- return document.getBindingParent(this.parentNode);
- }
-
- return this.parentNode;
- ]]></getter>
- </property>
- </implementation>
- </binding>
</bindings>
--- a/browser/components/customizableui/test/browser_987640_charEncoding.js
+++ b/browser/components/customizableui/test/browser_987640_charEncoding.js
@@ -24,17 +24,17 @@ add_task(async function() {
charEncodingButton.click();
await subviewShownPromise;
let checkedButtons = characterEncodingView.querySelectorAll("toolbarbutton[checked='true']");
let initialEncoding = checkedButtons[0];
is(initialEncoding.getAttribute("label"), "Western", "The western encoding is initially selected");
// change the encoding
- let encodings = characterEncodingView.querySelectorAll("toolbarbutton");
+ let encodings = characterEncodingView.querySelectorAll("toolbarbutton:not(.subviewbutton-back)");
let newEncoding = encodings[0].hasAttribute("checked") ? encodings[1] : encodings[0];
let browserStopPromise = BrowserTestUtils.browserStopped(gBrowser, TEST_PAGE);
newEncoding.click();
await browserStopPromise;
is(gBrowser.selectedBrowser.characterSet, "UTF-8", "The encoding should be changed to UTF-8");
ok(!gBrowser.selectedBrowser.mayEnableCharacterEncodingMenu, "The encoding menu should be disabled");
// check that the new encodng is applied
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -1482,28 +1482,28 @@ menuitem[checked="true"].subviewbutton >
font-size: 13px;
font-weight: 500;
margin: 0;
/* Add the size of the back button to center properly. */
margin-inline-end: 32px;
text-align: center;
}
-.PanelUI-subView .panel-header > .subviewbutton-back {
+.panel-header > .subviewbutton-back {
-moz-context-properties: fill;
fill: var(--arrowpanel-color);
list-style-image: url(chrome://browser/skin/arrow-left.svg);
padding: 8px;
}
-.panel-header > .subviewbutton-back:-moz-locale-dir(rtl) {
+.subviewbutton-back:-moz-locale-dir(rtl) {
transform: scaleX(-1);
}
-.panel-header > .subviewbutton-back > .toolbarbutton-text {
+.subviewbutton-back > .toolbarbutton-text {
/* !important to override .cui-widget-panel toolbarbutton:not([wrap]) > .toolbarbutton-text
* selector further down. */
display: none !important;
}
#panelMenu_pocket {
display: none;
}