mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-23 10:54:33 +00:00
Backed out 7 changesets (bug 1519577) for mochitest failures. CLOSED TREE
Backed out changeset 5192370c4f79 (bug 1519577) Backed out changeset 2999bbc0422b (bug 1519577) Backed out changeset bcedf1e9b09c (bug 1519577) Backed out changeset 293af339be51 (bug 1519577) Backed out changeset 9f311461ad1e (bug 1519577) Backed out changeset cf4e91d423b4 (bug 1519577) Backed out changeset 4f53ad1e3674 (bug 1519577)
This commit is contained in:
parent
bdf1d2a559
commit
ce81aa750c
@ -239,9 +239,6 @@ var BrowserPageActions = {
|
||||
"subviewbutton-iconic",
|
||||
"pageAction-panel-button"
|
||||
);
|
||||
if (action.isBadged) {
|
||||
buttonNode.setAttribute("badged", "true");
|
||||
}
|
||||
buttonNode.setAttribute("actionid", action.id);
|
||||
buttonNode.addEventListener("command", event => {
|
||||
this.doCommandForAction(action, event, buttonNode);
|
||||
@ -1129,6 +1126,7 @@ BrowserPageActions.addSearchEngine = {
|
||||
this._updateTitleAndIcon();
|
||||
this.action.setWantsSubview(this.engines.length > 1, window);
|
||||
let button = BrowserPageActions.panelButtonNodeForActionID(this.action.id);
|
||||
button.classList.add("badged-button");
|
||||
button.setAttribute("image", this.engines[0].icon);
|
||||
button.setAttribute("uri", this.engines[0].uri);
|
||||
button.setAttribute("crop", "center");
|
||||
@ -1141,7 +1139,7 @@ BrowserPageActions.addSearchEngine = {
|
||||
}
|
||||
for (let engine of this.engines) {
|
||||
let button = document.createXULElement("toolbarbutton");
|
||||
button.classList.add("subviewbutton", "subviewbutton-iconic", "badged-button");
|
||||
button.classList.add("subviewbutton", "subviewbutton-iconic");
|
||||
button.setAttribute("label", engine.title);
|
||||
button.setAttribute("image", engine.icon);
|
||||
button.setAttribute("uri", engine.uri);
|
||||
|
@ -1136,7 +1136,8 @@ var LibraryUI = {
|
||||
|
||||
let animatableBox = document.getElementById("library-animatable-box");
|
||||
let navBar = document.getElementById("nav-bar");
|
||||
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(libraryButton.icon);
|
||||
let libraryIcon = document.getAnonymousElementByAttribute(libraryButton, "class", "toolbarbutton-icon");
|
||||
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(libraryIcon);
|
||||
let libraryBounds = window.windowUtils.getBoundsWithoutFlushing(libraryButton);
|
||||
|
||||
animatableBox.style.setProperty("--library-button-height", libraryBounds.height + "px");
|
||||
@ -1196,7 +1197,8 @@ var LibraryUI = {
|
||||
}
|
||||
|
||||
let animatableBox = document.getElementById("library-animatable-box");
|
||||
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(libraryButton.icon);
|
||||
let libraryIcon = document.getAnonymousElementByAttribute(libraryButton, "class", "toolbarbutton-icon");
|
||||
let iconBounds = window.windowUtils.getBoundsWithoutFlushing(libraryIcon);
|
||||
|
||||
// Resizing the window will only have the ability to change the X offset of the
|
||||
// library button.
|
||||
|
@ -568,7 +568,7 @@ function UpdateBackForwardCommands(aWebNavigation) {
|
||||
|
||||
/**
|
||||
* Click-and-Hold implementation for the Back and Forward buttons
|
||||
* XXXmano: should this live in toolbarbutton.js?
|
||||
* XXXmano: should this live in toolbarbutton.xml?
|
||||
*/
|
||||
function SetClickAndHoldHandlers() {
|
||||
// Bug 414797: Clone the back/forward buttons' context menu into both buttons.
|
||||
@ -579,13 +579,13 @@ function SetClickAndHoldHandlers() {
|
||||
|
||||
let backButton = document.getElementById("back-button");
|
||||
backButton.setAttribute("type", "menu");
|
||||
backButton.prepend(popup);
|
||||
backButton.appendChild(popup);
|
||||
gClickAndHoldListenersOnElement.add(backButton);
|
||||
|
||||
let forwardButton = document.getElementById("forward-button");
|
||||
popup = popup.cloneNode(true);
|
||||
forwardButton.setAttribute("type", "menu");
|
||||
forwardButton.prepend(popup);
|
||||
forwardButton.appendChild(popup);
|
||||
gClickAndHoldListenersOnElement.add(forwardButton);
|
||||
}
|
||||
|
||||
@ -600,7 +600,7 @@ const gClickAndHoldListenersOnElement = {
|
||||
return;
|
||||
|
||||
// Prevent the menupopup from opening immediately
|
||||
aEvent.currentTarget.menupopup.hidden = true;
|
||||
aEvent.currentTarget.firstElementChild.hidden = true;
|
||||
|
||||
aEvent.currentTarget.addEventListener("mouseout", this);
|
||||
aEvent.currentTarget.addEventListener("mouseup", this);
|
||||
@ -8423,7 +8423,8 @@ var PanicButtonNotifier = {
|
||||
popup.addEventListener("popuphidden", removeListeners);
|
||||
|
||||
let widget = CustomizableUI.getWidget("panic-button").forWindow(window);
|
||||
let anchor = widget.anchor.icon;
|
||||
let anchor = widget.anchor;
|
||||
anchor = document.getAnonymousElementByAttribute(anchor, "class", "toolbarbutton-icon");
|
||||
popup.openPopup(anchor, popup.getAttribute("position"));
|
||||
} catch (ex) {
|
||||
Cu.reportError(ex);
|
||||
|
@ -745,8 +745,7 @@
|
||||
removable="true"/>
|
||||
|
||||
<toolbarbutton id="alltabs-button"
|
||||
class="toolbarbutton-1 chromeclass-toolbar-additional tabs-alltabs-button"
|
||||
badged="true"
|
||||
class="toolbarbutton-1 chromeclass-toolbar-additional tabs-alltabs-button badged-button"
|
||||
oncommand="gTabsPanel.showAllTabsPanel();"
|
||||
label="&listAllTabs.label;"
|
||||
tooltiptext="&listAllTabs.label;"
|
||||
@ -1022,8 +1021,7 @@
|
||||
during the customization of the toolbar, in the palette, and before
|
||||
the Downloads Indicator overlay is loaded. -->
|
||||
<toolbarbutton id="downloads-button"
|
||||
class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
badged="true"
|
||||
class="toolbarbutton-1 chromeclass-toolbar-additional badged-button"
|
||||
key="key_openDownloads"
|
||||
onmousedown="DownloadsIndicatorView.onCommand(event);"
|
||||
onkeypress="DownloadsIndicatorView.onCommand(event);"
|
||||
@ -1059,8 +1057,7 @@
|
||||
tooltiptext="&libraryButton.tooltip;"
|
||||
label="&places.library.title;"/>
|
||||
|
||||
<toolbarbutton id="fxa-toolbar-menu-button" class="toolbarbutton-1 chromeclass-toolbar-additional subviewbutton-nav"
|
||||
badged="true"
|
||||
<toolbarbutton id="fxa-toolbar-menu-button" class="toolbarbutton-1 badged-button chromeclass-toolbar-additional subviewbutton-nav"
|
||||
onmousedown="gSync.toggleAccountPanel('PanelUI-fxa', event)"
|
||||
onkeypress="gSync.toggleAccountPanel('PanelUI-fxa', event)"
|
||||
consumeanchor="fxa-toolbar-menu-button"
|
||||
@ -1087,8 +1084,7 @@
|
||||
<toolbaritem id="PanelUI-button"
|
||||
removable="false">
|
||||
<toolbarbutton id="PanelUI-menu-button"
|
||||
class="toolbarbutton-1"
|
||||
badged="true"
|
||||
class="toolbarbutton-1 badged-button"
|
||||
consumeanchor="PanelUI-button"
|
||||
label="&brandShortName;"
|
||||
tooltiptext="&appmenu.tooltip;"/>
|
||||
@ -1207,6 +1203,7 @@
|
||||
type="menu"
|
||||
label="&bookmarksMenuButton2.label;"
|
||||
tooltip="dynamic-shortcut-tooltip"
|
||||
anchor="dropmarker"
|
||||
ondragenter="PlacesMenuDNDHandler.onDragEnter(event);"
|
||||
ondragover="PlacesMenuDNDHandler.onDragOver(event);"
|
||||
ondragleave="PlacesMenuDNDHandler.onDragLeave(event);"
|
||||
|
@ -210,9 +210,6 @@
|
||||
containersEnabled = false;
|
||||
}
|
||||
|
||||
// There are separate "new tab" buttons for when the tab strip
|
||||
// is overflowed and when it is not. Attach the long click
|
||||
// popup to both of them.
|
||||
const newTab = document.getElementById("new-tab-button");
|
||||
const newTab2 = document.getAnonymousElementByAttribute(this, "anonid", "tabs-newtab-button");
|
||||
|
||||
@ -222,8 +219,8 @@
|
||||
|
||||
gClickAndHoldListenersOnElement.remove(parent);
|
||||
parent.removeAttribute("type");
|
||||
if (parent.menupopup) {
|
||||
parent.menupopup.remove();
|
||||
if (parent.firstElementChild) {
|
||||
parent.firstElementChild.remove();
|
||||
}
|
||||
|
||||
if (containersEnabled) {
|
||||
@ -243,7 +240,7 @@
|
||||
showDefaultTab: Services.prefs.getIntPref("privacy.userContext.longPressBehavior") == 1,
|
||||
});
|
||||
});
|
||||
parent.prepend(popup);
|
||||
parent.appendChild(popup);
|
||||
|
||||
// longPressBehavior == 2 means that the menu is shown after X
|
||||
// millisecs. Otherwise, with 1, the menu is open immediatelly.
|
||||
|
@ -167,7 +167,8 @@ async function test_playing_icon_on_hidden_tab(tab) {
|
||||
];
|
||||
let tabContainer = tab.parentNode;
|
||||
let alltabsButton = document.getElementById("alltabs-button");
|
||||
let alltabsBadge = alltabsButton.badgeLabel;
|
||||
let alltabsBadge = document.getAnonymousElementByAttribute(
|
||||
alltabsButton, "class", "toolbarbutton-badge");
|
||||
|
||||
function assertIconShowing() {
|
||||
is(getComputedStyle(alltabsBadge).backgroundImage,
|
||||
|
@ -4438,7 +4438,7 @@ OverflowableToolbar.prototype = {
|
||||
let mainView = doc.getElementById(mainViewId);
|
||||
let contextMenu = doc.getElementById(mainView.getAttribute("context"));
|
||||
gELS.addSystemEventListener(contextMenu, "command", this, true);
|
||||
let anchor = this._chevron.icon;
|
||||
let anchor = doc.getAnonymousElementByAttribute(this._chevron, "class", "toolbarbutton-icon");
|
||||
// Ensure we update the gEditUIVisible flag when opening the popup, in
|
||||
// case the edit controls are in it.
|
||||
this._panel.addEventListener("popupshowing", () => doc.defaultView.updateEditUIVisibility(), {once: true});
|
||||
|
@ -1348,11 +1348,6 @@ var PanelView = class extends AssociatedToNode {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore content inside a <toolbarbutton>
|
||||
if (element.tagName != "toolbarbutton" && element.closest("toolbarbutton")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Take the label for toolbarbuttons; it only exists on those elements.
|
||||
element = element.multilineLabel || element;
|
||||
|
||||
|
@ -866,7 +866,11 @@ const PanelUI = {
|
||||
_getBadgeStatus(notification) { return notification.id; },
|
||||
|
||||
_getPanelAnchor(candidate) {
|
||||
let iconAnchor = candidate.badgeStack || candidate.icon;
|
||||
let iconAnchor =
|
||||
document.getAnonymousElementByAttribute(candidate, "class",
|
||||
"toolbarbutton-badge-stack") ||
|
||||
document.getAnonymousElementByAttribute(candidate, "class",
|
||||
"toolbarbutton-icon");
|
||||
return iconAnchor || candidate;
|
||||
},
|
||||
|
||||
|
@ -30,7 +30,7 @@ const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
const kForceOverflowWidthPx = 300;
|
||||
|
||||
function createDummyXULButton(id, label, win = window) {
|
||||
let btn = win.document.createElementNS(kNSXUL, "toolbarbutton");
|
||||
let btn = document.createElementNS(kNSXUL, "toolbarbutton");
|
||||
btn.id = id;
|
||||
btn.setAttribute("label", label || id);
|
||||
btn.className = "toolbarbutton-1 chromeclass-toolbar-additional";
|
||||
@ -445,7 +445,8 @@ function checkContextMenu(aContextMenu, aExpectedEntries, aWindow = window) {
|
||||
|
||||
function waitForOverflowButtonShown(win = window) {
|
||||
let ov = win.document.getElementById("nav-bar-overflow-button");
|
||||
return waitForElementShown(ov.icon);
|
||||
let icon = win.document.getAnonymousElementByAttribute(ov, "class", "toolbarbutton-icon");
|
||||
return waitForElementShown(icon);
|
||||
}
|
||||
function waitForElementShown(element) {
|
||||
let win = element.ownerGlobal;
|
||||
|
@ -613,10 +613,11 @@ const DownloadsIndicatorView = {
|
||||
let widgetGroup = CustomizableUI.getWidget("downloads-button");
|
||||
if (widgetGroup.areaType == CustomizableUI.TYPE_MENU_PANEL) {
|
||||
let overflowIcon = widgetGroup.forWindow(window).anchor;
|
||||
return overflowIcon.icon;
|
||||
return document.getAnonymousElementByAttribute(overflowIcon, "class", "toolbarbutton-icon");
|
||||
}
|
||||
|
||||
return this.indicator.badgeStack;
|
||||
return document.getAnonymousElementByAttribute(this.indicator, "class",
|
||||
"toolbarbutton-badge-stack");
|
||||
},
|
||||
|
||||
get _progressIcon() {
|
||||
|
@ -47,7 +47,8 @@ add_task(async function test_overflow_anchor() {
|
||||
EventUtils.sendMouseEvent({ type: "mousedown", button: 0 }, button.node);
|
||||
await promise;
|
||||
|
||||
let downloadsAnchor = button.node.badgeStack;
|
||||
let downloadsAnchor = document.getAnonymousElementByAttribute(button.node, "class",
|
||||
"toolbarbutton-badge-stack");
|
||||
is(panel.anchorNode, downloadsAnchor);
|
||||
|
||||
DownloadsPanel.hidePanel();
|
||||
|
@ -275,7 +275,8 @@ class ExtensionControlledPopup {
|
||||
// Anchor to a toolbar browserAction if found, otherwise use the menu button.
|
||||
anchorButton = action || doc.getElementById("PanelUI-menu-button");
|
||||
}
|
||||
let anchor = anchorButton.icon;
|
||||
let anchor = doc.getAnonymousElementByAttribute(
|
||||
anchorButton, "class", "toolbarbutton-icon");
|
||||
panel.hidden = false;
|
||||
popupnotification.show();
|
||||
panel.openPopup(anchor);
|
||||
|
@ -165,8 +165,8 @@ this.browserAction = class extends ExtensionAPI {
|
||||
},
|
||||
|
||||
onCreated: node => {
|
||||
node.classList.add("badged-button");
|
||||
node.classList.add("webextension-browser-action");
|
||||
node.setAttribute("badged", "true");
|
||||
node.setAttribute("constrain-size", "true");
|
||||
node.setAttribute("data-extensionid", this.extension.id);
|
||||
|
||||
|
@ -129,7 +129,8 @@ async function runTests(options) {
|
||||
is(button.getAttribute("disabled") == "true", !details.enabled, "disabled state is correct");
|
||||
|
||||
if (details.badge) {
|
||||
let badge = button.badgeLabel;
|
||||
let badge = button.ownerDocument.getAnonymousElementByAttribute(
|
||||
button, "class", "toolbarbutton-badge");
|
||||
let style = window.getComputedStyle(badge);
|
||||
let expected = {
|
||||
backgroundColor: serializeColor(details.badgeBackgroundColor),
|
||||
@ -425,7 +426,7 @@ add_task(async function testBadgeColorPersistence() {
|
||||
|
||||
function getBadgeForWindow(win) {
|
||||
const widget = getBrowserActionWidget(extension).forWindow(win).node;
|
||||
return widget.badgeLabel;
|
||||
return document.getAnonymousElementByAttribute(widget, "class", "toolbarbutton-badge");
|
||||
}
|
||||
|
||||
let badge = getBadgeForWindow(window);
|
||||
|
@ -247,7 +247,7 @@ add_task(async function browseraction_contextmenu_manage_extension() {
|
||||
|
||||
info("Wait until the overflow menu is ready");
|
||||
let overflowButton = win.document.getElementById("nav-bar-overflow-button");
|
||||
let icon = overflowButton.icon;
|
||||
let icon = win.document.getAnonymousElementByAttribute(overflowButton, "class", "toolbarbutton-icon");
|
||||
await waitForElementShown(icon);
|
||||
|
||||
if (!customizing) {
|
||||
@ -326,7 +326,7 @@ async function runTestContextMenu({
|
||||
|
||||
info("Wait until the overflow menu is ready");
|
||||
let overflowButton = win.document.getElementById("nav-bar-overflow-button");
|
||||
let icon = overflowButton.icon;
|
||||
let icon = win.document.getAnonymousElementByAttribute(overflowButton, "class", "toolbarbutton-icon");
|
||||
await waitForElementShown(icon);
|
||||
|
||||
if (!customizing) {
|
||||
|
@ -1519,7 +1519,7 @@ PlacesToolbar.prototype = {
|
||||
|
||||
// If the menu is open, close it.
|
||||
if (draggedElt.open) {
|
||||
draggedElt.menupopup.hidePopup();
|
||||
draggedElt.lastElementChild.hidePopup();
|
||||
draggedElt.open = false;
|
||||
}
|
||||
}
|
||||
|
@ -289,7 +289,7 @@ function getNodeForToolbarItem(itemGuid, validator) {
|
||||
// Don't search in queries, they could contain our item in a
|
||||
// different position. Search only folders
|
||||
if (PlacesUtils.nodeIsFolder(child._placesNode)) {
|
||||
var popup = child.menupopup;
|
||||
var popup = child.lastElementChild;
|
||||
popup.openPopup();
|
||||
var foundNode = findNode(popup);
|
||||
popup.hidePopup();
|
||||
|
@ -37,7 +37,7 @@ add_task(async function test() {
|
||||
Assert.equal(menuButton.type, "menu", "A menu button");
|
||||
|
||||
// Mouse over the menu button to open it.
|
||||
let buttonPopup = menuButton.menupopup;
|
||||
let buttonPopup = menuButton.firstElementChild;
|
||||
promise = promiseEvent(buttonPopup, "popupshown");
|
||||
EventUtils.synthesizeMouse(menuButton, 5, 5, { type: "mousemove" });
|
||||
await promise;
|
||||
|
@ -87,7 +87,9 @@ var UITour = {
|
||||
|
||||
// Otherwise use the sync setup icon.
|
||||
let statusButton = aDocument.getElementById("appMenu-fxa-label");
|
||||
return statusButton.icon;
|
||||
return aDocument.getAnonymousElementByAttribute(statusButton,
|
||||
"class",
|
||||
"toolbarbutton-icon");
|
||||
},
|
||||
// This is a fake widgetName starting with the "appMenu-" prefix so we know
|
||||
// to automatically open the appMenu when annotating this target.
|
||||
|
@ -455,9 +455,6 @@ var PageActions = {
|
||||
* some reason. You can also pass an object that maps pixel sizes to
|
||||
* URLs, like { 16: url16, 32: url32 }. The best size for the user's
|
||||
* screen will be used.
|
||||
* @param isBadged (bool, optional)
|
||||
* If true, the toolbarbutton for this action will get the
|
||||
* "badged-button" class.
|
||||
* @param onBeforePlacedInWindow (function, optional)
|
||||
* Called before the action is placed in the window:
|
||||
* onBeforePlacedInWindow(window)
|
||||
@ -540,7 +537,6 @@ function Action(options) {
|
||||
disabled: false,
|
||||
extensionID: false,
|
||||
iconURL: false,
|
||||
isBadged: false,
|
||||
labelForHistogram: false,
|
||||
onBeforePlacedInWindow: false,
|
||||
onCommand: false,
|
||||
@ -820,10 +816,6 @@ Action.prototype = {
|
||||
return this._wantsIframe || false;
|
||||
},
|
||||
|
||||
get isBadged() {
|
||||
return this._isBadged || false;
|
||||
},
|
||||
|
||||
get labelForHistogram() {
|
||||
// The histogram label value has a length limit of 20 and restricted to a
|
||||
// pattern. See MAX_LABEL_LENGTH and CPP_IDENTIFIER_PATTERN in
|
||||
@ -1192,7 +1184,6 @@ var gBuiltInActions = [
|
||||
id: "addSearchEngine",
|
||||
// The title is set in browser-pageActions.js.
|
||||
title: "",
|
||||
isBadged: true,
|
||||
_transient: true,
|
||||
onShowingInPanel(buttonNode) {
|
||||
browserPageActions(buttonNode).addSearchEngine.onShowingInPanel();
|
||||
|
@ -12,14 +12,14 @@ const TEST_URL = URL_ROOT + "doc_markup_anonymous_xul.xul";
|
||||
add_task(async function() {
|
||||
const {inspector} = await openInspectorForURL(TEST_URL);
|
||||
|
||||
const boundNode = await getNodeFront("#xbl-host", inspector);
|
||||
const children = await inspector.walker.children(boundNode);
|
||||
const toolbarbutton = await getNodeFront("toolbarbutton", inspector);
|
||||
const children = await inspector.walker.children(toolbarbutton);
|
||||
|
||||
is(boundNode.numChildren, 2, "Correct number of children");
|
||||
is(children.nodes.length, 2, "Children returned from walker");
|
||||
is(toolbarbutton.numChildren, 4, "Correct number of children");
|
||||
is(children.nodes.length, 4, "Children returned from walker");
|
||||
|
||||
is(boundNode.isAnonymous, false, "Node with XBL binding is not anonymous");
|
||||
await isEditingMenuEnabled(boundNode, inspector);
|
||||
is(toolbarbutton.isAnonymous, false, "Toolbarbutton is not anonymous");
|
||||
await isEditingMenuEnabled(toolbarbutton, inspector);
|
||||
|
||||
for (const node of children.nodes) {
|
||||
ok(node.isAnonymous, "Child is anonymous");
|
||||
|
@ -3,15 +3,6 @@
|
||||
<xul:window xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Test anonymous xul nodes.">
|
||||
<xbl:bindings xmlns:xbl="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gaktekeeper/there.is.only.xul">
|
||||
<xbl:binding id="test">
|
||||
<xbl:content>
|
||||
<xul:box anonid="xbl-anon1">Anonymous</xul:box>
|
||||
<xul:box anonid="xbl-anon2">Anonymous</xul:box>
|
||||
</xbl:content>
|
||||
</xbl:binding>
|
||||
</xbl:bindings>
|
||||
<box id="xbl-host" style="-moz-binding: url(#test)"/>
|
||||
<xul:toolbarbutton id="test"></xul:toolbarbutton>
|
||||
</xul:window>
|
||||
|
||||
|
@ -4,7 +4,6 @@ support-files =
|
||||
blockNoPlugins.xml
|
||||
blockPluginHard.xml
|
||||
bug418986-1.js
|
||||
clonedoc/**
|
||||
cpows_child.js
|
||||
cpows_parent.xul
|
||||
file_bug549682.xul
|
||||
|
@ -1 +0,0 @@
|
||||
content clonedoc content/
|
@ -1,4 +0,0 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<something>
|
||||
<somethinglese/>
|
||||
</something>
|
@ -17,20 +17,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=467123
|
||||
|
||||
<!-- test code goes here -->
|
||||
<script type="application/javascript"><![CDATA[
|
||||
/** Test for Bug 467123 **/
|
||||
let url = Cc["@mozilla.org/network/io-service;1"]
|
||||
.getService(Ci.nsIIOService)
|
||||
.newURI(document.location.href);
|
||||
let file = Cc["@mozilla.org/chrome/chrome-registry;1"]
|
||||
.getService(Ci.nsIChromeRegistry)
|
||||
.convertChromeURL(url)
|
||||
.QueryInterface(Ci.nsIFileURL)
|
||||
.file.parent;
|
||||
file.append("clonedoc");
|
||||
Components.manager.addBootstrappedManifestLocation(file);
|
||||
|
||||
/** Test for Bug 467123 **/
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", "chrome://clonedoc/content/doc.xml", false);
|
||||
xhr.open("GET", "chrome://global/content/bindings/button.xml", false);
|
||||
xhr.send();
|
||||
ok(xhr.responseXML, "We should have response document!");
|
||||
var e = null;
|
||||
|
@ -625,6 +625,25 @@ nsresult nsMenuFrame::AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIContent* nsMenuFrame::GetAnchor() {
|
||||
mozilla::dom::Element* anchor = nullptr;
|
||||
|
||||
nsAutoString id;
|
||||
mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::anchor, id);
|
||||
if (!id.IsEmpty()) {
|
||||
Document* doc = mContent->OwnerDoc();
|
||||
|
||||
anchor =
|
||||
doc->GetAnonymousElementByAttribute(mContent, nsGkAtoms::anonid, id);
|
||||
if (!anchor) {
|
||||
anchor = doc->GetElementById(id);
|
||||
}
|
||||
}
|
||||
|
||||
// Always return the menu's content if the anchor wasn't set or wasn't found.
|
||||
return anchor && anchor->GetPrimaryFrame() ? anchor : GetContent();
|
||||
}
|
||||
|
||||
void nsMenuFrame::OpenMenu(bool aSelectFirstItem) {
|
||||
if (!mContent) return;
|
||||
|
||||
@ -674,7 +693,8 @@ nsMenuFrame::DoXULLayout(nsBoxLayoutState& aState) {
|
||||
nsMenuPopupFrame* popupFrame = GetPopup();
|
||||
if (popupFrame) {
|
||||
bool sizeToPopup = IsSizedToPopup(mContent, false);
|
||||
popupFrame->LayoutPopup(aState, this, sizeToPopup);
|
||||
popupFrame->LayoutPopup(aState, this, GetAnchor()->GetPrimaryFrame(),
|
||||
sizeToPopup);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -123,6 +123,12 @@ class nsMenuFrame final : public nsBoxFrame, public nsIReflowCallback {
|
||||
|
||||
virtual nsIScrollableFrame* GetScrollTargetFrame() override;
|
||||
|
||||
// Retrieve the element that the menu should be anchored to. By default this
|
||||
// is the menu itself. However, the anchor attribute may refer to the value of
|
||||
// an anonid within the menu's binding, or, if not found, the id of an element
|
||||
// in the document.
|
||||
nsIContent* GetAnchor();
|
||||
|
||||
/**
|
||||
* NOTE: OpenMenu will open the menu asynchronously.
|
||||
*/
|
||||
|
@ -461,7 +461,8 @@ void nsMenuPopupFrame::UpdateWidgetProperties() {
|
||||
}
|
||||
|
||||
void nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState,
|
||||
nsIFrame* aParentMenu, bool aSizedToPopup) {
|
||||
nsIFrame* aParentMenu, nsIFrame* aAnchor,
|
||||
bool aSizedToPopup) {
|
||||
if (IsLeaf()) {
|
||||
return;
|
||||
}
|
||||
@ -516,7 +517,7 @@ void nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState,
|
||||
|
||||
bool needCallback = false;
|
||||
if (shouldPosition) {
|
||||
SetPopupPosition(aParentMenu, false, aSizedToPopup,
|
||||
SetPopupPosition(aAnchor, false, aSizedToPopup,
|
||||
mPopupState == ePopupPositioning);
|
||||
needCallback = true;
|
||||
}
|
||||
@ -543,7 +544,7 @@ void nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState,
|
||||
}
|
||||
|
||||
if (rePosition) {
|
||||
SetPopupPosition(aParentMenu, false, aSizedToPopup, false);
|
||||
SetPopupPosition(aAnchor, false, aSizedToPopup, false);
|
||||
}
|
||||
|
||||
nsPresContext* pc = PresContext();
|
||||
@ -603,7 +604,7 @@ void nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState,
|
||||
|
||||
if (needCallback && !mReflowCallbackData.mPosted) {
|
||||
pc->PresShell()->PostReflowCallback(this);
|
||||
mReflowCallbackData.MarkPosted(aParentMenu, aSizedToPopup, openChanged);
|
||||
mReflowCallbackData.MarkPosted(aAnchor, aSizedToPopup, openChanged);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,7 +257,7 @@ class nsMenuPopupFrame final : public nsBoxFrame,
|
||||
// layout, position and display the popup as needed
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
void LayoutPopup(nsBoxLayoutState& aState, nsIFrame* aParentMenu,
|
||||
bool aSizedToPopup);
|
||||
nsIFrame* aAnchor, bool aSizedToPopup);
|
||||
|
||||
nsView* GetRootViewForPopup(nsIFrame* aStartFrame);
|
||||
|
||||
|
@ -109,7 +109,7 @@ nsPopupSetFrame::DoXULLayout(nsBoxLayoutState& aState) {
|
||||
// lay out all of our currently open popups.
|
||||
for (nsFrameList::Enumerator e(mPopupList); !e.AtEnd(); e.Next()) {
|
||||
nsMenuPopupFrame* popupChild = static_cast<nsMenuPopupFrame*>(e.get());
|
||||
popupChild->LayoutPopup(aState, nullptr, false);
|
||||
popupChild->LayoutPopup(aState, nullptr, nullptr, false);
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -682,7 +682,7 @@ void nsXULPopupManager::ShowMenu(nsIContent* aMenu, bool aSelectFirstItem,
|
||||
|
||||
// there is no trigger event for menus
|
||||
InitTriggerEvent(nullptr, nullptr, nullptr);
|
||||
popupFrame->InitializePopup(aMenu, nullptr, position, 0, 0,
|
||||
popupFrame->InitializePopup(menuFrame->GetAnchor(), nullptr, position, 0, 0,
|
||||
MenuPopupAnchorType_Node, true);
|
||||
|
||||
if (aAsynchronous) {
|
||||
|
@ -32,7 +32,7 @@ add_task(async function test_button_background_properties() {
|
||||
await extension.startup();
|
||||
|
||||
let toolbarButton = document.querySelector("#home-button");
|
||||
let toolbarButtonIcon = toolbarButton.icon;
|
||||
let toolbarButtonIcon = document.getAnonymousElementByAttribute(toolbarButton, "class", "toolbarbutton-icon");
|
||||
let toolbarButtonIconCS = window.getComputedStyle(toolbarButtonIcon);
|
||||
|
||||
InspectorUtils.addPseudoClassLock(toolbarButton, ":hover");
|
||||
|
@ -659,7 +659,6 @@ if (!isDummyDocument) {
|
||||
"chrome://global/content/elements/textbox.js",
|
||||
"chrome://global/content/elements/tabbox.js",
|
||||
"chrome://global/content/elements/text.js",
|
||||
"chrome://global/content/elements/toolbarbutton.js",
|
||||
"chrome://global/content/elements/tree.js",
|
||||
"chrome://global/content/elements/wizard.js",
|
||||
]) {
|
||||
|
@ -62,6 +62,7 @@ toolkit.jar:
|
||||
#endif
|
||||
content/global/widgets.css
|
||||
content/global/bindings/autocomplete.xml (widgets/autocomplete.xml)
|
||||
content/global/bindings/button.xml (widgets/button.xml)
|
||||
content/global/bindings/calendar.js (widgets/calendar.js)
|
||||
content/global/bindings/datekeeper.js (widgets/datekeeper.js)
|
||||
content/global/bindings/datepicker.js (widgets/datepicker.js)
|
||||
@ -76,6 +77,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/toolbarbutton.xml (widgets/toolbarbutton.xml)
|
||||
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)
|
||||
@ -101,7 +103,6 @@ toolkit.jar:
|
||||
content/global/elements/tabbox.js (widgets/tabbox.js)
|
||||
content/global/elements/text.js (widgets/text.js)
|
||||
content/global/elements/textbox.js (widgets/textbox.js)
|
||||
content/global/elements/toolbarbutton.js (widgets/toolbarbutton.js)
|
||||
content/global/elements/videocontrols.js (widgets/videocontrols.js)
|
||||
content/global/elements/tree.js (widgets/tree.js)
|
||||
content/global/elements/wizard.js (widgets/wizard.js)
|
||||
|
@ -127,6 +127,7 @@ support-files = window_maximized_persist.xul
|
||||
[test_navigate_persist.html]
|
||||
support-files = window_navigate_persist.html
|
||||
[test_menu.xul]
|
||||
[test_menu_anchored.xul]
|
||||
[test_menu_withcapture.xul]
|
||||
[test_menu_hide.xul]
|
||||
[test_menuchecks.xul]
|
||||
|
@ -9,14 +9,22 @@
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<toolbarbutton type="menu" id="toolbarmenu" height="200">
|
||||
<xbl:bindings xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
<xbl:binding id="menu" extends="chrome://global/content/bindings/button.xml#button-base">
|
||||
<xbl:content>
|
||||
<xbl:children includes="menupopup"/>
|
||||
<xul:stack>
|
||||
<xul:button width="100" left="0" top="0" height="30" allowevents="true"
|
||||
onclick="eventReceived('clickbutton1'); return false;"/>
|
||||
<xul:button width="100" left="70" top="0" height="30"
|
||||
onclick="eventReceived('clickbutton2'); return false;"/>
|
||||
</xul:stack>
|
||||
</xbl:content>
|
||||
</xbl:binding>
|
||||
</xbl:bindings>
|
||||
|
||||
<toolbarbutton type="menu" id="toolbarmenu" height="200" style="-moz-binding: url(#menu);">
|
||||
<menupopup id="menupopup" onpopupshowing="eventReceived('popupshowing'); return false;"/>
|
||||
<stack>
|
||||
<button width="100" left="0" top="0" height="30" allowevents="true"
|
||||
onclick="eventReceived('clickbutton1'); return false;"/>
|
||||
<button width="100" left="70" top="0" height="30"
|
||||
onclick="eventReceived('clickbutton2'); return false;"/>
|
||||
</stack>
|
||||
</toolbarbutton>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
|
77
toolkit/content/tests/chrome/test_menu_anchored.xul
Normal file
77
toolkit/content/tests/chrome/test_menu_anchored.xul
Normal file
@ -0,0 +1,77 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
|
||||
<!--
|
||||
Test for menus with the anchor attribute set
|
||||
-->
|
||||
<window title="Anchored Menus Test"
|
||||
align="start"
|
||||
onload="setTimeout(runTest, 0, 'tb1');"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="xul_selectcontrol.js"/>
|
||||
|
||||
<hbox>
|
||||
|
||||
<toolbarbutton id="tb1" type="menu" label="Open" anchor="dropmarker">
|
||||
<menupopup id="popup1"
|
||||
onpopupshown="checkPopup(this, document.getAnonymousElementByAttribute(this.parentNode, 'anonid', 'dropmarker'))"
|
||||
onpopuphidden="runTest('tb2')">
|
||||
<menuitem label="Item"/>
|
||||
</menupopup>
|
||||
</toolbarbutton>
|
||||
|
||||
<toolbarbutton id="tb2" type="menu" label="Open" anchor="someanchor">
|
||||
<menupopup id="popup2" onpopupshown="checkPopup(this, $('someanchor'))" onpopuphidden="runTest('tb3')">
|
||||
<menuitem label="Item"/>
|
||||
</menupopup>
|
||||
</toolbarbutton>
|
||||
|
||||
<toolbarbutton id="tb3" type="menu" label="Open" anchor="noexist">
|
||||
<menupopup id="popup3" onpopupshown="checkPopup(this, this.parentNode)" onpopuphidden="SimpleTest.finish()">
|
||||
<menuitem label="Item"/>
|
||||
</menupopup>
|
||||
</toolbarbutton>
|
||||
|
||||
</hbox>
|
||||
|
||||
<hbox pack="end" width="180">
|
||||
<button id="someanchor" label="Anchor"/>
|
||||
</hbox>
|
||||
|
||||
<!-- test results are displayed in the html:body -->
|
||||
<body xmlns="http://www.w3.org/1999/xhtml" style="height: 300px; overflow: auto;"/>
|
||||
|
||||
<script type="application/javascript"><![CDATA[
|
||||
|
||||
function runTest(menuid)
|
||||
{
|
||||
let menu = $(menuid);
|
||||
let dropmarker = document.getAnonymousElementByAttribute(menu, "anonid", "dropmarker");
|
||||
|
||||
synthesizeMouseAtCenter(dropmarker, { });
|
||||
}
|
||||
|
||||
function isWithinHalfPixel(a, b)
|
||||
{
|
||||
return Math.abs(a - b) <= 0.5;
|
||||
}
|
||||
|
||||
function checkPopup(popup, anchor)
|
||||
{
|
||||
let popupRect = popup.getBoundingClientRect();
|
||||
let anchorRect = anchor.getBoundingClientRect();
|
||||
|
||||
ok(isWithinHalfPixel(popupRect.left, anchorRect.left), popup.id + " left");
|
||||
ok(isWithinHalfPixel(popupRect.top, anchorRect.bottom), popup.id + " top");
|
||||
|
||||
popup.hidePopup();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
]]>
|
||||
</script>
|
||||
|
||||
</window>
|
@ -214,8 +214,6 @@
|
||||
|
||||
MozXULElement.implementCustomInterface(MozButtonBase, [Ci.nsIDOMXULButtonElement]);
|
||||
|
||||
MozElements.ButtonBase = MozButtonBase;
|
||||
|
||||
class MozButton extends MozButtonBase {
|
||||
static get inheritedAttributes() {
|
||||
return {
|
||||
|
192
toolkit/content/widgets/button.xml
Normal file
192
toolkit/content/widgets/button.xml
Normal file
@ -0,0 +1,192 @@
|
||||
<?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="buttonBindings"
|
||||
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="button-base" extends="chrome://global/content/bindings/general.xml#basetext">
|
||||
<implementation implements="nsIDOMXULButtonElement">
|
||||
<property name="type"
|
||||
onget="return this.getAttribute('type');"
|
||||
onset="this.setAttribute('type', val); return val;"/>
|
||||
|
||||
<property name="dlgType"
|
||||
onget="return this.getAttribute('dlgtype');"
|
||||
onset="this.setAttribute('dlgtype', val); return val;"/>
|
||||
|
||||
<property name="group"
|
||||
onget="return this.getAttribute('group');"
|
||||
onset="this.setAttribute('group', val); return val;"/>
|
||||
|
||||
<property name="open" onget="return this.hasAttribute('open');">
|
||||
<setter><![CDATA[
|
||||
if (this.hasMenu()) {
|
||||
this.openMenu(val);
|
||||
} else if (val) {
|
||||
// Fall back to just setting the attribute
|
||||
this.setAttribute("open", "true");
|
||||
} else {
|
||||
this.removeAttribute("open");
|
||||
}
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<property name="checked" onget="return this.hasAttribute('checked');">
|
||||
<setter><![CDATA[
|
||||
if (this.type == "radio" && val) {
|
||||
var sibs = this.parentNode.getElementsByAttribute("group", this.group);
|
||||
for (var i = 0; i < sibs.length; ++i)
|
||||
sibs[i].removeAttribute("checked");
|
||||
}
|
||||
|
||||
if (val)
|
||||
this.setAttribute("checked", "true");
|
||||
else
|
||||
this.removeAttribute("checked");
|
||||
|
||||
return val;
|
||||
]]></setter>
|
||||
</property>
|
||||
|
||||
<method name ="filterButtons">
|
||||
<parameter name="node"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
// if the node isn't visible, don't descend into it.
|
||||
var cs = node.ownerGlobal.getComputedStyle(node);
|
||||
if (cs.visibility != "visible" || cs.display == "none") {
|
||||
return NodeFilter.FILTER_REJECT;
|
||||
}
|
||||
// but it may be a popup element, in which case we look at "state"...
|
||||
if (cs.display == "-moz-popup" && node.state != "open") {
|
||||
return NodeFilter.FILTER_REJECT;
|
||||
}
|
||||
// OK - the node seems visible, so it is a candidate.
|
||||
if (node.localName == "button" && node.accessKey && !node.disabled)
|
||||
return NodeFilter.FILTER_ACCEPT;
|
||||
return NodeFilter.FILTER_SKIP;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="fireAccessKeyButton">
|
||||
<parameter name="aSubtree"/>
|
||||
<parameter name="aAccessKeyLower"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var iterator = aSubtree.ownerDocument.createTreeWalker(aSubtree,
|
||||
NodeFilter.SHOW_ELEMENT,
|
||||
this.filterButtons);
|
||||
while (iterator.nextNode()) {
|
||||
var test = iterator.currentNode;
|
||||
if (test.accessKey.toLowerCase() == aAccessKeyLower &&
|
||||
!test.disabled && !test.collapsed && !test.hidden) {
|
||||
test.focus();
|
||||
test.click();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_handleClick">
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!this.disabled) {
|
||||
if (this.type == "checkbox") {
|
||||
this.checked = !this.checked;
|
||||
} else if (this.type == "radio") {
|
||||
this.checked = true;
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<!-- While it would seem we could do this by handling oncommand, we can't
|
||||
because any external oncommand handlers might get called before ours,
|
||||
and then they would see the incorrect value of checked. Additionally
|
||||
a command attribute would redirect the command events anyway.-->
|
||||
<handler event="click" button="0" action="this._handleClick();"/>
|
||||
<handler event="keypress" key=" ">
|
||||
<![CDATA[
|
||||
this._handleClick();
|
||||
// Prevent page from scrolling on the space key.
|
||||
event.preventDefault();
|
||||
]]>
|
||||
</handler>
|
||||
|
||||
<handler event="keypress">
|
||||
<![CDATA[
|
||||
if (this.hasMenu()) {
|
||||
if (this.open)
|
||||
return;
|
||||
} else {
|
||||
if (event.keyCode == KeyEvent.DOM_VK_UP ||
|
||||
(event.keyCode == KeyEvent.DOM_VK_LEFT &&
|
||||
document.defaultView.getComputedStyle(this.parentNode)
|
||||
.direction == "ltr") ||
|
||||
(event.keyCode == KeyEvent.DOM_VK_RIGHT &&
|
||||
document.defaultView.getComputedStyle(this.parentNode)
|
||||
.direction == "rtl")) {
|
||||
event.preventDefault();
|
||||
window.document.commandDispatcher.rewindFocus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.keyCode == KeyEvent.DOM_VK_DOWN ||
|
||||
(event.keyCode == KeyEvent.DOM_VK_RIGHT &&
|
||||
document.defaultView.getComputedStyle(this.parentNode)
|
||||
.direction == "ltr") ||
|
||||
(event.keyCode == KeyEvent.DOM_VK_LEFT &&
|
||||
document.defaultView.getComputedStyle(this.parentNode)
|
||||
.direction == "rtl")) {
|
||||
event.preventDefault();
|
||||
window.document.commandDispatcher.advanceFocus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (event.keyCode || event.charCode <= 32 || event.altKey ||
|
||||
event.ctrlKey || event.metaKey)
|
||||
return; // No printable char pressed, not a potential accesskey
|
||||
|
||||
// Possible accesskey pressed
|
||||
var charPressedLower = String.fromCharCode(event.charCode).toLowerCase();
|
||||
|
||||
// If the accesskey of the current button is pressed, just activate it
|
||||
if (this.accessKey.toLowerCase() == charPressedLower) {
|
||||
this.click();
|
||||
return;
|
||||
}
|
||||
|
||||
// Search for accesskey in the list of buttons for this doc and each subdoc
|
||||
// Get the buttons for the main document and all sub-frames
|
||||
for (var frameCount = -1; frameCount < window.top.frames.length; frameCount++) {
|
||||
var doc = (frameCount == -1) ? window.top.document :
|
||||
window.top.frames[frameCount].document;
|
||||
if (this.fireAccessKeyButton(doc.documentElement, charPressedLower))
|
||||
return;
|
||||
}
|
||||
|
||||
// Test anonymous buttons
|
||||
var dlg = window.top.document;
|
||||
var buttonBox = dlg.getAnonymousElementByAttribute(dlg.documentElement,
|
||||
"anonid", "buttons");
|
||||
if (buttonBox)
|
||||
this.fireAccessKeyButton(buttonBox, charPressedLower);
|
||||
]]>
|
||||
</handler>
|
||||
</handlers>
|
||||
</binding>
|
||||
</bindings>
|
@ -1,153 +0,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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
// This is loaded into all XUL windows. Wrap in a block to prevent
|
||||
// leaking to window scope.
|
||||
{
|
||||
const KEEP_CHILDREN = new Set(["observes", "template", "menupopup", "panel", "tooltip"]);
|
||||
|
||||
window.addEventListener("popupshowing", (e) => {
|
||||
if (e.originalTarget.ownerDocument != document) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.originalTarget.setAttribute("hasbeenopened", "true");
|
||||
for (let el of e.originalTarget.querySelectorAll("toolbarbutton")) {
|
||||
el.render();
|
||||
}
|
||||
}, {capture: true});
|
||||
|
||||
class MozToolbarbutton extends MozElements.ButtonBase {
|
||||
static get inheritedAttributes() {
|
||||
return {
|
||||
".toolbarbutton-icon": "validate,src=image,label,type,consumeanchor,triggeringprincipal=iconloadingprincipal",
|
||||
".toolbarbutton-text": "value=label,accesskey,crop,dragover-top,wrap",
|
||||
".toolbarbutton-multiline-text": "text=label,accesskey,wrap",
|
||||
".toolbarbutton-menu-dropmarker": "disabled,label",
|
||||
|
||||
".toolbarbutton-badge": "value=badge,style=badgeStyle",
|
||||
};
|
||||
}
|
||||
|
||||
static get fragment() {
|
||||
let frag = document.importNode(MozXULElement.parseXULToFragment(`
|
||||
<image class="toolbarbutton-icon"></image>
|
||||
<label class="toolbarbutton-text" crop="right" flex="1"></label>
|
||||
<label class="toolbarbutton-multiline-text" flex="1"></label>
|
||||
<dropmarker type="menu" class="toolbarbutton-menu-dropmarker"></dropmarker>`), true);
|
||||
Object.defineProperty(this, "fragment", {value: frag});
|
||||
return frag;
|
||||
}
|
||||
|
||||
static get badgedFragment() {
|
||||
let frag = document.importNode(MozXULElement.parseXULToFragment(`
|
||||
<stack class="toolbarbutton-badge-stack">
|
||||
<image class="toolbarbutton-icon"/>
|
||||
<label class="toolbarbutton-badge" top="0" end="0" crop="none"/>
|
||||
</stack>
|
||||
<label class="toolbarbutton-text" crop="right" flex="1"/>
|
||||
<label class="toolbarbutton-multiline-text" flex="1"/>
|
||||
<dropmarker anonid="dropmarker" type="menu"
|
||||
class="toolbarbutton-menu-dropmarker"/>`), true);
|
||||
Object.defineProperty(this, "badgedFragment", {value: frag});
|
||||
return frag;
|
||||
}
|
||||
|
||||
get _hasRendered() {
|
||||
return (this.querySelector(":scope > .toolbarbutton-text") != null);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
if (this.delayConnectedCallback()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Defer creating DOM elements for content inside popups.
|
||||
// These will be added in the popupshown handler above.
|
||||
let panel = this.closest("panel");
|
||||
if (panel && !panel.hasAttribute("hasbeenopened")) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this._hasRendered) {
|
||||
return;
|
||||
}
|
||||
|
||||
let badged = (this.getAttribute("badged") == "true");
|
||||
|
||||
if (badged) {
|
||||
let moveChildren = [];
|
||||
for (let child of this.children) {
|
||||
if (!KEEP_CHILDREN.has(child.tagName)) {
|
||||
moveChildren.push(child);
|
||||
}
|
||||
}
|
||||
|
||||
this.appendChild(this.constructor.badgedFragment.cloneNode(true));
|
||||
|
||||
if (moveChildren.length > 0) {
|
||||
let {badgeStack, icon} = this;
|
||||
for (let child of moveChildren) {
|
||||
badgeStack.insertBefore(child, icon);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let moveChildren = [];
|
||||
for (let child of this.children) {
|
||||
if (!KEEP_CHILDREN.has(child.tagName) && child.tagName != "box") {
|
||||
// XBL toolbarbutton doesn't insert any anonymous content
|
||||
// if it has a child of any other type
|
||||
return;
|
||||
}
|
||||
|
||||
if (child.tagName == "box") {
|
||||
moveChildren.push(child);
|
||||
}
|
||||
}
|
||||
|
||||
this.appendChild(this.constructor.fragment.cloneNode(true));
|
||||
|
||||
// XBL toolbarbutton explicitly places any <box> children
|
||||
// right before the menu marker.
|
||||
for (let child of moveChildren) {
|
||||
this.insertBefore(child, this.lastChild);
|
||||
}
|
||||
}
|
||||
|
||||
this.initializeAttributeInheritance();
|
||||
}
|
||||
|
||||
get icon() {
|
||||
return this.querySelector(".toolbarbutton-icon");
|
||||
}
|
||||
|
||||
get badgeLabel() {
|
||||
return this.querySelector(".toolbarbutton-badge");
|
||||
}
|
||||
|
||||
get badgeStack() {
|
||||
return this.querySelector(".toolbarbutton-badge-stack");
|
||||
}
|
||||
|
||||
get multilineLabel() {
|
||||
return this.querySelector(".toolbarbutton-multiline-text");
|
||||
}
|
||||
|
||||
get dropmarker() {
|
||||
return this.querySelector(".toolbarbutton-menu-dropmarker");
|
||||
}
|
||||
|
||||
get menupopup() {
|
||||
return this.querySelector("menupopup");
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("toolbarbutton", MozToolbarbutton);
|
||||
}
|
48
toolkit/content/widgets/toolbarbutton.xml
Normal file
48
toolkit/content/widgets/toolbarbutton.xml
Normal file
@ -0,0 +1,48 @@
|
||||
<?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="toolbarbuttonBindings"
|
||||
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="toolbarbutton"
|
||||
extends="chrome://global/content/bindings/button.xml#button-base">
|
||||
<implementation>
|
||||
<property name="multilineLabel"
|
||||
onget="return document.getAnonymousElementByAttribute(this, 'class', 'toolbarbutton-multiline-text');" />
|
||||
</implementation>
|
||||
<content>
|
||||
<children includes="observes|template|menupopup|panel|tooltip"/>
|
||||
<xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label,type,consumeanchor,triggeringprincipal=iconloadingprincipal"/>
|
||||
<xul:label class="toolbarbutton-text" crop="right" flex="1"
|
||||
xbl:inherits="value=label,accesskey,crop,dragover-top,wrap"/>
|
||||
<xul:label class="toolbarbutton-multiline-text" flex="1"
|
||||
xbl:inherits="xbl:text=label,accesskey,wrap"/>
|
||||
<children includes="box"/>
|
||||
<xul:dropmarker anonid="dropmarker" type="menu"
|
||||
class="toolbarbutton-menu-dropmarker" xbl:inherits="disabled,label"/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="toolbarbutton-badged"
|
||||
extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton">
|
||||
<content>
|
||||
<children includes="observes|template|menupopup|panel|tooltip"/>
|
||||
<xul:stack class="toolbarbutton-badge-stack">
|
||||
<children/>
|
||||
<xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label,consumeanchor"/>
|
||||
<xul:label class="toolbarbutton-badge" xbl:inherits="value=badge,style=badgeStyle" top="0" end="0" crop="none"/>
|
||||
</xul:stack>
|
||||
<xul:label class="toolbarbutton-text" crop="right" flex="1"
|
||||
xbl:inherits="value=label,accesskey,crop,wrap"/>
|
||||
<xul:label class="toolbarbutton-multiline-text" flex="1"
|
||||
xbl:inherits="xbl:text=label,accesskey,wrap"/>
|
||||
<xul:dropmarker anonid="dropmarker" type="menu"
|
||||
class="toolbarbutton-menu-dropmarker" xbl:inherits="disabled,label"/>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
@ -107,6 +107,15 @@ label html|span.accesskey {
|
||||
|
||||
/********** toolbarbutton **********/
|
||||
|
||||
toolbarbutton {
|
||||
-moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton");
|
||||
}
|
||||
|
||||
toolbarbutton.badged-button > toolbarbutton,
|
||||
toolbarbutton.badged-button {
|
||||
-moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-badged");
|
||||
}
|
||||
|
||||
.toolbarbutton-badge:not([value]),
|
||||
.toolbarbutton-badge[value=""] {
|
||||
display: none;
|
||||
|
Loading…
x
Reference in New Issue
Block a user