mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-26 04:09:50 +00:00
Bug 1544916 - migrate dialog binding to Custom Element r=bgrins,whimboo
Differential Revision: https://phabricator.services.mozilla.com/D30289 --HG-- rename : toolkit/content/widgets/dialog.xml => toolkit/content/widgets/dialog.js extra : moz-landing-system : lando
This commit is contained in:
parent
58da2cbd6a
commit
61cc7103cf
@ -17,14 +17,13 @@ dialog {
|
||||
-moz-box-flex: 1;
|
||||
}
|
||||
|
||||
.contentPane,
|
||||
dialog > .dialog-content-box {
|
||||
/* This allows the focus ring to display fully when scrolling is enabled. */
|
||||
.contentPane {
|
||||
/* This allows the focus ring to display fully when scrolling is enabled.
|
||||
Note: dialog.js CE have a matching style for dialog-content-box */
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.contentPane.doScroll,
|
||||
dialog.doScroll > .dialog-content-box {
|
||||
.contentPane.doScroll {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
|
@ -28,10 +28,22 @@
|
||||
</xul:box>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="buttonbox">
|
||||
<content>
|
||||
<xul:box anonid="buttons">
|
||||
<xul:button dlgtype="cancel" class="dialog-button"/>
|
||||
<xul:button dlgtype="accept" class="dialog-button"/>
|
||||
</xul:box>
|
||||
<xul:vbox></xul:vbox>
|
||||
<xul:vbox></xul:vbox>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
||||
|
||||
<hbox id="testAnonymousContentBox"/>
|
||||
<hbox id="container" style="-moz-binding: url('#testBindings');"/>
|
||||
<hbox id="container2" style="-moz-binding: url('#iframebox');"/>
|
||||
<hbox id="container3" style="-moz-binding: url('#buttonbox');"/>
|
||||
|
||||
</dialog>
|
||||
|
@ -51,35 +51,26 @@ class TestAnonymousNodes(WindowManagerMixin, MarionetteTestCase):
|
||||
not_existent = (By.ANON_ATTRIBUTE, {"anonid": "notexistent"},)
|
||||
|
||||
# By using the window document element
|
||||
start_node = self.marionette.find_element(By.CSS_SELECTOR, ":root")
|
||||
start_node = self.marionette.find_element(By.ID, "container3")
|
||||
button = start_node.find_element(*accept_button)
|
||||
self.assertEquals(HTMLElement, type(button))
|
||||
with self.assertRaises(NoSuchElementException):
|
||||
start_node.find_element(*not_existent)
|
||||
|
||||
# By using the default start node
|
||||
self.assertEquals(button, self.marionette.find_element(*accept_button))
|
||||
with self.assertRaises(NoSuchElementException):
|
||||
self.marionette.find_element(*not_existent)
|
||||
|
||||
def test_find_anonymous_elements_by_attribute(self):
|
||||
dialog_buttons = (By.ANON_ATTRIBUTE, {"anonid": "buttons"},)
|
||||
not_existent = (By.ANON_ATTRIBUTE, {"anonid": "notexistent"},)
|
||||
|
||||
# By using the window document element
|
||||
start_node = self.marionette.find_element(By.CSS_SELECTOR, ":root")
|
||||
start_node = self.marionette.find_element(By.ID, "container3")
|
||||
buttons = start_node.find_elements(*dialog_buttons)
|
||||
self.assertEquals(1, len(buttons))
|
||||
self.assertEquals(HTMLElement, type(buttons[0]))
|
||||
self.assertListEqual([], start_node.find_elements(*not_existent))
|
||||
|
||||
# By using the default start node
|
||||
self.assertListEqual(buttons, self.marionette.find_elements(*dialog_buttons))
|
||||
self.assertListEqual([], self.marionette.find_elements(*not_existent))
|
||||
|
||||
def test_find_anonymous_children(self):
|
||||
self.assertEquals(HTMLElement, type(self.marionette.find_element(By.ANON, None)))
|
||||
self.assertEquals(3, len(self.marionette.find_elements(By.ANON, None)))
|
||||
start_node = self.marionette.find_element(By.ID, "container3")
|
||||
self.assertEquals(HTMLElement, type(start_node.find_element(By.ANON, None)))
|
||||
self.assertEquals(3, len(start_node.find_elements(By.ANON, None)))
|
||||
|
||||
frame = self.marionette.find_element(By.ID, "framebox")
|
||||
with self.assertRaises(NoSuchElementException):
|
||||
|
@ -645,6 +645,7 @@ customElements.setElementCreationCallback("browser", () => {
|
||||
const isDummyDocument = document.documentURI == "chrome://extensions/content/dummy.xul";
|
||||
if (!isDummyDocument) {
|
||||
for (let script of [
|
||||
"chrome://global/content/elements/dialog.js",
|
||||
"chrome://global/content/elements/general.js",
|
||||
"chrome://global/content/elements/button.js",
|
||||
"chrome://global/content/elements/checkbox.js",
|
||||
|
@ -66,7 +66,6 @@ toolkit.jar:
|
||||
content/global/bindings/datekeeper.js (widgets/datekeeper.js)
|
||||
content/global/bindings/datepicker.js (widgets/datepicker.js)
|
||||
content/global/bindings/datetimebox.css (widgets/datetimebox.css)
|
||||
* content/global/bindings/dialog.xml (widgets/dialog.xml)
|
||||
content/global/bindings/general.xml (widgets/general.xml)
|
||||
content/global/bindings/popup.xml (widgets/popup.xml)
|
||||
content/global/bindings/richlistbox.xml (widgets/richlistbox.xml)
|
||||
@ -83,6 +82,7 @@ toolkit.jar:
|
||||
content/global/elements/button.js (widgets/button.js)
|
||||
content/global/elements/checkbox.js (widgets/checkbox.js)
|
||||
content/global/elements/datetimebox.js (widgets/datetimebox.js)
|
||||
content/global/elements/dialog.js (widgets/dialog.js)
|
||||
content/global/elements/findbar.js (widgets/findbar.js)
|
||||
content/global/elements/editor.js (widgets/editor.js)
|
||||
content/global/elements/general.js (widgets/general.js)
|
||||
|
@ -62,9 +62,18 @@ function runTest()
|
||||
|
||||
function checkDialogFocus(event)
|
||||
{
|
||||
info("checkDialogFocus()");
|
||||
info(`checkDialogFocus()`);
|
||||
let match = false;
|
||||
let activeElement = win.document.activeElement;
|
||||
|
||||
if (activeElement == win.document.documentElement) {
|
||||
let shadowActiveElement =
|
||||
win.document.documentElement.shadowRoot.activeElement;
|
||||
if (shadowActiveElement) {
|
||||
activeElement = shadowActiveElement;
|
||||
}
|
||||
}
|
||||
// if full keyboard access is not on, just skip the tests
|
||||
var match = false;
|
||||
if (fullKeyboardAccess) {
|
||||
if (!(event.target instanceof Element)) {
|
||||
info("target not an Element");
|
||||
@ -72,44 +81,51 @@ function runTest()
|
||||
}
|
||||
|
||||
if (expectedFocus == "textbox-yes")
|
||||
match = (win.document.activeElement == win.document.getElementById(expectedFocus).inputField);
|
||||
match = (activeElement == win.document.getElementById(expectedFocus).inputField);
|
||||
else if (expectedFocus[0] == "_")
|
||||
match = (win.document.activeElement.dlgType == expectedFocus.substring(1));
|
||||
match = (activeElement.dlgType == expectedFocus.substring(1));
|
||||
else
|
||||
match = (win.document.activeElement.id == expectedFocus);
|
||||
match = (activeElement.id == expectedFocus);
|
||||
info("match = " + match);
|
||||
if (!match)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
match = (win.document.activeElement == win.document.documentElement);
|
||||
match = (activeElement == win.document.documentElement);
|
||||
info("match = " + match);
|
||||
}
|
||||
|
||||
win.removeEventListener("focus", checkDialogFocusEvent, true);
|
||||
win.document.documentElement.shadowRoot.removeEventListener(
|
||||
"focus", checkDialogFocusEvent, true);
|
||||
ok(match, "focus step " + step);
|
||||
|
||||
win.close();
|
||||
SimpleTest.waitForFocus(runTest, window);
|
||||
}
|
||||
|
||||
function checkDialogFocusRoot(event) {
|
||||
if (event.target == win) {
|
||||
is(win.document.activeElement, win.document.documentElement, "No other focus but root");
|
||||
win.close();
|
||||
SimpleTest.waitForFocus(runTest, window);
|
||||
}
|
||||
}
|
||||
|
||||
let finalCheckInitiated = false;
|
||||
function checkDialogFocusEvent(event) {
|
||||
// Delay to have time for focus/blur to occur.
|
||||
if (expectedFocus == "root") {
|
||||
setTimeout(checkDialogFocusRoot, 0, event);
|
||||
if (!finalCheckInitiated) {
|
||||
setTimeout(() => {
|
||||
is(win.document.activeElement, win.document.documentElement,
|
||||
"No other focus but root");
|
||||
win.close();
|
||||
SimpleTest.waitForFocus(runTest, window);
|
||||
}, 0);
|
||||
finalCheckInitiated = true;
|
||||
}
|
||||
} else {
|
||||
checkDialogFocus(event);
|
||||
}
|
||||
}
|
||||
win.addEventListener("focus", checkDialogFocusEvent, true);
|
||||
win.addEventListener("load", () => {
|
||||
win.document.documentElement.shadowRoot.addEventListener(
|
||||
"focus", checkDialogFocusEvent, true);
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(startTest, window);
|
||||
|
@ -85,12 +85,11 @@
|
||||
return;
|
||||
}
|
||||
|
||||
// Test anonymous buttons
|
||||
var dlg = window.top.document;
|
||||
var buttonBox = dlg.getAnonymousElementByAttribute(dlg.documentElement,
|
||||
"anonid", "buttons");
|
||||
if (buttonBox)
|
||||
// Test dialog buttons
|
||||
let buttonBox = window.top.document.documentElement.buttonBox;
|
||||
if (buttonBox) {
|
||||
this.fireAccessKeyButton(buttonBox, charPressedLower);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
453
toolkit/content/widgets/dialog.js
Normal file
453
toolkit/content/widgets/dialog.js
Normal file
@ -0,0 +1,453 @@
|
||||
/* 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 {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
||||
|
||||
class MozDialog extends MozXULElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.addEventListener("keypress", (event) => {
|
||||
if (event.keyCode == KeyEvent.DOM_VK_RETURN) {
|
||||
this._hitEnter(event);
|
||||
}
|
||||
}, { mozSystemGroup: true });
|
||||
|
||||
this.addEventListener("keypress", (event) => {
|
||||
if (event.keyCode == KeyEvent.DOM_VK_ESCAPE && !event.defaultPrevented) {
|
||||
this.cancelDialog();
|
||||
}
|
||||
}, { mozSystemGroup: true });
|
||||
|
||||
if (AppConstants.platform == "macosx") {
|
||||
this.addEventListener("keypress", (event) => {
|
||||
if (event.key == "." && event.metaKey) {
|
||||
this.cancelDialog();
|
||||
}
|
||||
}, true);
|
||||
} else {
|
||||
this.addEventListener("focus", (event) => {
|
||||
let btn = this.getButton(this.defaultButton);
|
||||
if (btn) {
|
||||
btn.setAttribute("default",
|
||||
event.originalTarget == btn ||
|
||||
!(event.originalTarget.localName == "button" ||
|
||||
event.originalTarget.localName == "toolbarbutton"));
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
|
||||
// listen for when window is closed via native close buttons
|
||||
window.addEventListener("close", (event) => {
|
||||
if (!document.documentElement.cancelDialog()) {
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
// for things that we need to initialize after onload fires
|
||||
window.addEventListener("load", (event) => this.postLoadInit(event));
|
||||
|
||||
this.attachShadow({mode: "open"});
|
||||
}
|
||||
|
||||
static get inheritedAttributes() {
|
||||
return {
|
||||
".dialog-button-box": "pack=buttonpack,align=buttonalign,dir=buttondir,orient=buttonorient",
|
||||
"[dlgtype='accept']": "disabled=buttondisabledaccept",
|
||||
};
|
||||
}
|
||||
|
||||
get _markup() {
|
||||
let buttons = AppConstants.platform == "linux" ? `
|
||||
<hbox class="dialog-button-box">
|
||||
<button dlgtype="disclosure" class="dialog-button" hidden="true"/>
|
||||
<button dlgtype="help" class="dialog-button" hidden="true"/>
|
||||
<button dlgtype="extra2" class="dialog-button" hidden="true"/>
|
||||
<button dlgtype="extra1" class="dialog-button" hidden="true"/>
|
||||
<spacer class="spacer" flex="1"/>
|
||||
<button dlgtype="cancel" class="dialog-button"/>
|
||||
<button dlgtype="accept" class="dialog-button"/>
|
||||
</hbox>` : `
|
||||
<hbox class="dialog-button-box" pack="end">
|
||||
<button dlgtype="extra2" class="dialog-button" hidden="true"/>
|
||||
<spacer class="spacer" flex="1" hidden="true"/>
|
||||
<button dlgtype="accept" class="dialog-button"/>
|
||||
<button dlgtype="extra1" class="dialog-button" hidden="true"/>
|
||||
<button dlgtype="cancel" class="dialog-button"/>
|
||||
<button dlgtype="help" class="dialog-button" hidden="true"/>
|
||||
<button dlgtype="disclosure" class="dialog-button" hidden="true"/>
|
||||
</hbox>`;
|
||||
|
||||
let key = AppConstants.platform == "macosx" ?
|
||||
`<key phase="capturing"
|
||||
oncommand="document.documentElement.openHelp(event)"
|
||||
key="&openHelpMac.commandkey;" modifiers="accel"/>` :
|
||||
`<key phase="capturing"
|
||||
oncommand="document.documentElement.openHelp(event)"
|
||||
keycode="&openHelp.commandkey;"/>`;
|
||||
|
||||
return `
|
||||
<html:link rel="stylesheet" href="chrome://global/content/widgets.css" />
|
||||
<html:style>
|
||||
:host([nobuttonspacer]) .spacer {
|
||||
display: none;
|
||||
}
|
||||
:host([subdialog]) > .dialog-content-box {
|
||||
/* This allows the focus ring to display fully when scrolling is enabled.
|
||||
See matching style in dialog.inc.css.
|
||||
*/
|
||||
padding: 4px;
|
||||
}
|
||||
:host(.doScroll) > .dialog-content-box {
|
||||
overflow-y: auto;
|
||||
}
|
||||
</html:style>
|
||||
<vbox class="box-inherit dialog-content-box" flex="1">
|
||||
<html:slot></html:slot>
|
||||
</vbox>
|
||||
${buttons}
|
||||
<keyset>${key}</keyset>`;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
if (this.delayConnectedCallback()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.shadowRoot.textContent = "";
|
||||
this.shadowRoot.appendChild(MozXULElement.parseXULToFragment(
|
||||
this._markup, ["chrome://global/locale/globalKeys.dtd"]));
|
||||
this.initializeAttributeInheritance();
|
||||
|
||||
/**
|
||||
* Gets populated by elements that are passed to document.l10n.setAttributes
|
||||
* to localize the dialog buttons. Needed to properly size the dialog after
|
||||
* the asynchronous translation.
|
||||
*/
|
||||
this._l10nButtons = [];
|
||||
|
||||
this._configureButtons(this.buttons);
|
||||
|
||||
window.moveToAlertPosition = this.moveToAlertPosition;
|
||||
window.centerWindowOnScreen = this.centerWindowOnScreen;
|
||||
}
|
||||
|
||||
set buttons(val) {
|
||||
this._configureButtons(val);
|
||||
return val;
|
||||
}
|
||||
|
||||
get buttons() {
|
||||
return this.getAttribute("buttons");
|
||||
}
|
||||
|
||||
set defaultButton(val) {
|
||||
this._setDefaultButton(val);
|
||||
return val;
|
||||
}
|
||||
|
||||
get defaultButton() {
|
||||
if (this.hasAttribute("defaultButton"))
|
||||
return this.getAttribute("defaultButton");
|
||||
return "accept"; // default to the accept button
|
||||
}
|
||||
|
||||
get _strBundle() {
|
||||
if (!this.__stringBundle) {
|
||||
this.__stringBundle = Services.strings.createBundle(
|
||||
"chrome://global/locale/dialog.properties");
|
||||
}
|
||||
return this.__stringBundle;
|
||||
}
|
||||
|
||||
acceptDialog() {
|
||||
return this._doButtonCommand("accept");
|
||||
}
|
||||
|
||||
cancelDialog() {
|
||||
return this._doButtonCommand("cancel");
|
||||
}
|
||||
|
||||
getButton(aDlgType) {
|
||||
return this._buttons[aDlgType];
|
||||
}
|
||||
|
||||
get buttonBox() {
|
||||
return this.shadowRoot.querySelector(".dialog-button-box");
|
||||
}
|
||||
|
||||
moveToAlertPosition() {
|
||||
// hack. we need this so the window has something like its final size
|
||||
if (window.outerWidth == 1) {
|
||||
dump("Trying to position a sizeless window; caller should have called sizeToContent() or sizeTo(). See bug 75649.\n");
|
||||
sizeToContent();
|
||||
}
|
||||
|
||||
if (opener) {
|
||||
var xOffset = (opener.outerWidth - window.outerWidth) / 2;
|
||||
var yOffset = opener.outerHeight / 5;
|
||||
|
||||
var newX = opener.screenX + xOffset;
|
||||
var newY = opener.screenY + yOffset;
|
||||
} else {
|
||||
newX = (screen.availWidth - window.outerWidth) / 2;
|
||||
newY = (screen.availHeight - window.outerHeight) / 2;
|
||||
}
|
||||
|
||||
// ensure the window is fully onscreen (if smaller than the screen)
|
||||
if (newX < screen.availLeft)
|
||||
newX = screen.availLeft + 20;
|
||||
if ((newX + window.outerWidth) > (screen.availLeft + screen.availWidth))
|
||||
newX = (screen.availLeft + screen.availWidth) - window.outerWidth - 20;
|
||||
|
||||
if (newY < screen.availTop)
|
||||
newY = screen.availTop + 20;
|
||||
if ((newY + window.outerHeight) > (screen.availTop + screen.availHeight))
|
||||
newY = (screen.availTop + screen.availHeight) - window.outerHeight - 60;
|
||||
|
||||
window.moveTo(newX, newY);
|
||||
}
|
||||
|
||||
centerWindowOnScreen() {
|
||||
var xOffset = screen.availWidth / 2 - window.outerWidth / 2;
|
||||
var yOffset = screen.availHeight / 2 - window.outerHeight / 2;
|
||||
|
||||
xOffset = xOffset > 0 ? xOffset : 0;
|
||||
yOffset = yOffset > 0 ? yOffset : 0;
|
||||
window.moveTo(xOffset, yOffset);
|
||||
}
|
||||
|
||||
postLoadInit(aEvent) {
|
||||
function focusInit() {
|
||||
const dialog = document.documentElement;
|
||||
const defaultButton = dialog.getButton(dialog.defaultButton);
|
||||
|
||||
// give focus to the first focusable element in the dialog
|
||||
let focusedElt = document.commandDispatcher.focusedElement;
|
||||
if (!focusedElt) {
|
||||
document.commandDispatcher.advanceFocusIntoSubtree(dialog);
|
||||
|
||||
focusedElt = document.commandDispatcher.focusedElement;
|
||||
if (focusedElt) {
|
||||
var initialFocusedElt = focusedElt;
|
||||
while (focusedElt.localName == "tab" ||
|
||||
focusedElt.getAttribute("noinitialfocus") == "true") {
|
||||
document.commandDispatcher.advanceFocusIntoSubtree(focusedElt);
|
||||
focusedElt = document.commandDispatcher.focusedElement;
|
||||
if (focusedElt)
|
||||
if (focusedElt == initialFocusedElt) {
|
||||
if (focusedElt.getAttribute("noinitialfocus") == "true") {
|
||||
focusedElt.blur();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (initialFocusedElt.localName == "tab") {
|
||||
if (focusedElt.hasAttribute("dlgtype")) {
|
||||
// We don't want to focus on anonymous OK, Cancel, etc. buttons,
|
||||
// so return focus to the tab itself
|
||||
initialFocusedElt.focus();
|
||||
}
|
||||
} else if (!/Mac/.test(navigator.platform) &&
|
||||
focusedElt.hasAttribute("dlgtype") &&
|
||||
focusedElt != defaultButton) {
|
||||
defaultButton.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (defaultButton)
|
||||
window.notifyDefaultButtonLoaded(defaultButton);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// Give focus after onload completes, see bug 103197.
|
||||
setTimeout(focusInit, 0);
|
||||
|
||||
if (this._l10nButtons.length) {
|
||||
document.l10n.translateElements(this._l10nButtons).then(() => {
|
||||
window.sizeToContent();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
openHelp(event) {
|
||||
var helpButton = document.documentElement.getButton("help");
|
||||
if (helpButton.disabled || helpButton.hidden)
|
||||
return;
|
||||
this._fireButtonEvent("help");
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
_configureButtons(aButtons) {
|
||||
// by default, get all the anonymous button elements
|
||||
var buttons = {};
|
||||
this._buttons = buttons;
|
||||
|
||||
for (let type of ["accept", "cancel", "extra1", "extra2", "help", "disclosure"]) {
|
||||
buttons[type] = this.shadowRoot.querySelector(`[dlgtype="${type}"]`);
|
||||
}
|
||||
|
||||
// look for any overriding explicit button elements
|
||||
var exBtns = this.getElementsByAttribute("dlgtype", "*");
|
||||
var dlgtype;
|
||||
for (let i = 0; i < exBtns.length; ++i) {
|
||||
dlgtype = exBtns[i].getAttribute("dlgtype");
|
||||
buttons[dlgtype].hidden = true; // hide the anonymous button
|
||||
buttons[dlgtype] = exBtns[i];
|
||||
}
|
||||
|
||||
// add the label and oncommand handler to each button
|
||||
for (dlgtype in buttons) {
|
||||
var button = buttons[dlgtype];
|
||||
button.addEventListener("command", this._handleButtonCommand, true);
|
||||
|
||||
// don't override custom labels with pre-defined labels on explicit buttons
|
||||
if (!button.hasAttribute("label")) {
|
||||
// dialog attributes override the default labels in dialog.properties
|
||||
if (this.hasAttribute("buttonlabel" + dlgtype)) {
|
||||
button.setAttribute("label", this.getAttribute("buttonlabel" + dlgtype));
|
||||
if (this.hasAttribute("buttonaccesskey" + dlgtype))
|
||||
button.setAttribute("accesskey", this.getAttribute("buttonaccesskey" + dlgtype));
|
||||
} else if (this.hasAttribute("buttonid" + dlgtype)) {
|
||||
document.l10n.setAttributes(button, this.getAttribute("buttonid" + dlgtype));
|
||||
this._l10nButtons.push(button);
|
||||
} else if (dlgtype != "extra1" && dlgtype != "extra2") {
|
||||
button.setAttribute("label", this._strBundle.GetStringFromName("button-" + dlgtype));
|
||||
var accessKey = this._strBundle.GetStringFromName("accesskey-" + dlgtype);
|
||||
if (accessKey)
|
||||
button.setAttribute("accesskey", accessKey);
|
||||
}
|
||||
}
|
||||
// allow specifying alternate icons in the dialog header
|
||||
if (!button.hasAttribute("icon")) {
|
||||
// if there's an icon specified, use that
|
||||
if (this.hasAttribute("buttonicon" + dlgtype))
|
||||
button.setAttribute("icon", this.getAttribute("buttonicon" + dlgtype));
|
||||
// otherwise set defaults
|
||||
else
|
||||
switch (dlgtype) {
|
||||
case "accept":
|
||||
button.setAttribute("icon", "accept");
|
||||
break;
|
||||
case "cancel":
|
||||
button.setAttribute("icon", "cancel");
|
||||
break;
|
||||
case "disclosure":
|
||||
button.setAttribute("icon", "properties");
|
||||
break;
|
||||
case "help":
|
||||
button.setAttribute("icon", "help");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that hitting enter triggers the default button command
|
||||
this.defaultButton = this.defaultButton;
|
||||
|
||||
// if there is a special button configuration, use it
|
||||
if (aButtons) {
|
||||
// expect a comma delimited list of dlgtype values
|
||||
var list = aButtons.split(",");
|
||||
|
||||
// mark shown dlgtypes as true
|
||||
var shown = {
|
||||
accept: false,
|
||||
cancel: false,
|
||||
help: false,
|
||||
disclosure: false,
|
||||
extra1: false,
|
||||
extra2: false,
|
||||
};
|
||||
for (let i = 0; i < list.length; ++i) {
|
||||
shown[list[i].replace(/ /g, "")] = true;
|
||||
}
|
||||
|
||||
// hide/show the buttons we want
|
||||
for (dlgtype in buttons) {
|
||||
buttons[dlgtype].hidden = !shown[dlgtype];
|
||||
}
|
||||
|
||||
// show the spacer on Windows only when the extra2 button is present
|
||||
if (/Win/.test(navigator.platform)) {
|
||||
let spacer = this.shadowRoot.querySelector(".spacer");
|
||||
spacer.removeAttribute("hidden");
|
||||
spacer.setAttribute("flex", shown.extra2 ? "1" : "0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_setDefaultButton(aNewDefault) {
|
||||
// remove the default attribute from the previous default button, if any
|
||||
var oldDefaultButton = this.getButton(this.defaultButton);
|
||||
if (oldDefaultButton)
|
||||
oldDefaultButton.removeAttribute("default");
|
||||
|
||||
var newDefaultButton = this.getButton(aNewDefault);
|
||||
if (newDefaultButton) {
|
||||
this.setAttribute("defaultButton", aNewDefault);
|
||||
newDefaultButton.setAttribute("default", "true");
|
||||
} else {
|
||||
this.setAttribute("defaultButton", "none");
|
||||
if (aNewDefault != "none")
|
||||
dump("invalid new default button: " + aNewDefault + ", assuming: none\n");
|
||||
}
|
||||
}
|
||||
|
||||
_handleButtonCommand(aEvent) {
|
||||
return document.documentElement._doButtonCommand(
|
||||
aEvent.target.getAttribute("dlgtype"));
|
||||
}
|
||||
|
||||
_doButtonCommand(aDlgType) {
|
||||
var button = this.getButton(aDlgType);
|
||||
if (!button.disabled) {
|
||||
var noCancel = this._fireButtonEvent(aDlgType);
|
||||
if (noCancel) {
|
||||
if (aDlgType == "accept" || aDlgType == "cancel") {
|
||||
var closingEvent = new CustomEvent("dialogclosing", {
|
||||
bubbles: true,
|
||||
detail: { button: aDlgType },
|
||||
});
|
||||
this.dispatchEvent(closingEvent);
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
return noCancel;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
_fireButtonEvent(aDlgType) {
|
||||
var event = document.createEvent("Events");
|
||||
event.initEvent("dialog" + aDlgType, true, true);
|
||||
|
||||
// handle dom event handlers
|
||||
return this.dispatchEvent(event);
|
||||
}
|
||||
|
||||
_hitEnter(evt) {
|
||||
if (evt.defaultPrevented)
|
||||
return;
|
||||
|
||||
var btn = this.getButton(this.defaultButton);
|
||||
if (btn)
|
||||
this._doButtonCommand(this.defaultButton);
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define("dialog", MozDialog);
|
||||
}
|
@ -1,490 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<!DOCTYPE bindings [
|
||||
<!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd">
|
||||
%globalKeysDTD;
|
||||
]>
|
||||
|
||||
<bindings id="dialogBindings"
|
||||
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="dialog">
|
||||
<content>
|
||||
<xul:vbox class="box-inherit dialog-content-box" flex="1">
|
||||
<children/>
|
||||
</xul:vbox>
|
||||
|
||||
<xul:hbox class="dialog-button-box" anonid="buttons"
|
||||
xbl:inherits="pack=buttonpack,align=buttonalign,dir=buttondir,orient=buttonorient"
|
||||
#ifdef XP_UNIX
|
||||
>
|
||||
<xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
|
||||
<xul:button dlgtype="help" class="dialog-button" hidden="true"/>
|
||||
<xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
|
||||
<xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
|
||||
<xul:spacer anonid="spacer" flex="1"/>
|
||||
<xul:button dlgtype="cancel" class="dialog-button"/>
|
||||
<xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
|
||||
#else
|
||||
pack="end">
|
||||
<xul:button dlgtype="extra2" class="dialog-button" hidden="true"/>
|
||||
<xul:spacer anonid="spacer" flex="1" hidden="true"/>
|
||||
<xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/>
|
||||
<xul:button dlgtype="extra1" class="dialog-button" hidden="true"/>
|
||||
<xul:button dlgtype="cancel" class="dialog-button"/>
|
||||
<xul:button dlgtype="help" class="dialog-button" hidden="true"/>
|
||||
<xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/>
|
||||
#endif
|
||||
</xul:hbox>
|
||||
|
||||
<xul:keyset>
|
||||
<xul:key phase="capturing" oncommand="document.documentElement.openHelp(event)"
|
||||
#ifdef XP_MACOSX
|
||||
key="&openHelpMac.commandkey;" modifiers="accel"/>
|
||||
#else
|
||||
keycode="&openHelp.commandkey;"/>
|
||||
#endif
|
||||
</xul:keyset>
|
||||
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<field name="_mStrBundle">null</field>
|
||||
<field name="_closeHandler">(function(event) {
|
||||
if (!document.documentElement.cancelDialog())
|
||||
event.preventDefault();
|
||||
})</field>
|
||||
|
||||
<!-- Gets populated by elements that are passed to document.l10n.setAttributes
|
||||
to localize the dialog buttons. Needed to properly size the dialog after
|
||||
the asynchronous translation. -->
|
||||
<field name="_l10nButtons">[]</field>
|
||||
|
||||
<property name="buttons"
|
||||
onget="return this.getAttribute('buttons');"
|
||||
onset="this._configureButtons(val); return val;"/>
|
||||
|
||||
<property name="defaultButton">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
if (this.hasAttribute("defaultButton"))
|
||||
return this.getAttribute("defaultButton");
|
||||
return "accept"; // default to the accept button
|
||||
]]>
|
||||
</getter>
|
||||
<setter>
|
||||
<![CDATA[
|
||||
this._setDefaultButton(val);
|
||||
return val;
|
||||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
<method name="acceptDialog">
|
||||
<body>
|
||||
<![CDATA[
|
||||
return this._doButtonCommand("accept");
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="cancelDialog">
|
||||
<body>
|
||||
<![CDATA[
|
||||
return this._doButtonCommand("cancel");
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="getButton">
|
||||
<parameter name="aDlgType"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
return this._buttons[aDlgType];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="moveToAlertPosition">
|
||||
<body>
|
||||
<![CDATA[
|
||||
// hack. we need this so the window has something like its final size
|
||||
if (window.outerWidth == 1) {
|
||||
dump("Trying to position a sizeless window; caller should have called sizeToContent() or sizeTo(). See bug 75649.\n");
|
||||
sizeToContent();
|
||||
}
|
||||
|
||||
if (opener) {
|
||||
var xOffset = (opener.outerWidth - window.outerWidth) / 2;
|
||||
var yOffset = opener.outerHeight / 5;
|
||||
|
||||
var newX = opener.screenX + xOffset;
|
||||
var newY = opener.screenY + yOffset;
|
||||
} else {
|
||||
newX = (screen.availWidth - window.outerWidth) / 2;
|
||||
newY = (screen.availHeight - window.outerHeight) / 2;
|
||||
}
|
||||
|
||||
// ensure the window is fully onscreen (if smaller than the screen)
|
||||
if (newX < screen.availLeft)
|
||||
newX = screen.availLeft + 20;
|
||||
if ((newX + window.outerWidth) > (screen.availLeft + screen.availWidth))
|
||||
newX = (screen.availLeft + screen.availWidth) - window.outerWidth - 20;
|
||||
|
||||
if (newY < screen.availTop)
|
||||
newY = screen.availTop + 20;
|
||||
if ((newY + window.outerHeight) > (screen.availTop + screen.availHeight))
|
||||
newY = (screen.availTop + screen.availHeight) - window.outerHeight - 60;
|
||||
|
||||
window.moveTo( newX, newY );
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="centerWindowOnScreen">
|
||||
<body>
|
||||
<![CDATA[
|
||||
var xOffset = screen.availWidth / 2 - window.outerWidth / 2;
|
||||
var yOffset = screen.availHeight / 2 - window.outerHeight / 2;
|
||||
|
||||
xOffset = xOffset > 0 ? xOffset : 0;
|
||||
yOffset = yOffset > 0 ? yOffset : 0;
|
||||
window.moveTo(xOffset, yOffset);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
this._configureButtons(this.buttons);
|
||||
|
||||
// listen for when window is closed via native close buttons
|
||||
window.addEventListener("close", this);
|
||||
|
||||
// for things that we need to initialize after onload fires
|
||||
window.addEventListener("load", this);
|
||||
|
||||
window.moveToAlertPosition = this.moveToAlertPosition;
|
||||
window.centerWindowOnScreen = this.centerWindowOnScreen;
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
<method name="handleEvent">
|
||||
<parameter name="aEvent"/>
|
||||
<body><![CDATA[
|
||||
switch (aEvent.type) {
|
||||
case "close": {
|
||||
this._closeHandler(aEvent);
|
||||
break;
|
||||
}
|
||||
case "load": {
|
||||
this.postLoadInit(aEvent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="postLoadInit">
|
||||
<parameter name="aEvent"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
function focusInit() {
|
||||
const dialog = document.documentElement;
|
||||
const defaultButton = dialog.getButton(dialog.defaultButton);
|
||||
// give focus to the first focusable element in the dialog
|
||||
if (!document.commandDispatcher.focusedElement) {
|
||||
document.commandDispatcher.advanceFocusIntoSubtree(dialog);
|
||||
|
||||
var focusedElt = document.commandDispatcher.focusedElement;
|
||||
if (focusedElt) {
|
||||
var initialFocusedElt = focusedElt;
|
||||
while (focusedElt.localName == "tab" ||
|
||||
focusedElt.getAttribute("noinitialfocus") == "true") {
|
||||
document.commandDispatcher.advanceFocusIntoSubtree(focusedElt);
|
||||
focusedElt = document.commandDispatcher.focusedElement;
|
||||
if (focusedElt == initialFocusedElt) {
|
||||
if (focusedElt.getAttribute("noinitialfocus") == "true") {
|
||||
focusedElt.blur();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (initialFocusedElt.localName == "tab") {
|
||||
if (focusedElt.hasAttribute("dlgtype")) {
|
||||
// We don't want to focus on anonymous OK, Cancel, etc. buttons,
|
||||
// so return focus to the tab itself
|
||||
initialFocusedElt.focus();
|
||||
}
|
||||
} else if (!/Mac/.test(navigator.platform) &&
|
||||
focusedElt.hasAttribute("dlgtype") && focusedElt != defaultButton) {
|
||||
defaultButton.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if (defaultButton)
|
||||
window.notifyDefaultButtonLoaded(defaultButton);
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
// Give focus after onload completes, see bug 103197.
|
||||
setTimeout(focusInit, 0);
|
||||
|
||||
if (this._l10nButtons.length) {
|
||||
document.l10n.translateElements(this._l10nButtons).then(() => {
|
||||
window.sizeToContent();
|
||||
});
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="openHelp">
|
||||
<parameter name="event"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var helpButton = document.documentElement.getButton("help");
|
||||
if (helpButton.disabled || helpButton.hidden)
|
||||
return;
|
||||
this._fireButtonEvent("help");
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<property name="mStrBundle">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
if (!this._mStrBundle) {
|
||||
// need to create string bundle manually instead of using <xul:stringbundle/>
|
||||
// see bug 63370 for details
|
||||
this._mStrBundle = Cc["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Ci.nsIStringBundleService)
|
||||
.createBundle("chrome://global/locale/dialog.properties");
|
||||
}
|
||||
return this._mStrBundle;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<method name="_configureButtons">
|
||||
<parameter name="aButtons"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
// by default, get all the anonymous button elements
|
||||
var buttons = {};
|
||||
this._buttons = buttons;
|
||||
buttons.accept = document.getAnonymousElementByAttribute(this, "dlgtype", "accept");
|
||||
buttons.cancel = document.getAnonymousElementByAttribute(this, "dlgtype", "cancel");
|
||||
buttons.extra1 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra1");
|
||||
buttons.extra2 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra2");
|
||||
buttons.help = document.getAnonymousElementByAttribute(this, "dlgtype", "help");
|
||||
buttons.disclosure = document.getAnonymousElementByAttribute(this, "dlgtype", "disclosure");
|
||||
|
||||
for (let button in buttons) {
|
||||
customElements.upgrade(buttons[button]);
|
||||
}
|
||||
|
||||
// look for any overriding explicit button elements
|
||||
var exBtns = this.getElementsByAttribute("dlgtype", "*");
|
||||
var dlgtype;
|
||||
var i;
|
||||
for (i = 0; i < exBtns.length; ++i) {
|
||||
dlgtype = exBtns[i].getAttribute("dlgtype");
|
||||
buttons[dlgtype].hidden = true; // hide the anonymous button
|
||||
buttons[dlgtype] = exBtns[i];
|
||||
}
|
||||
|
||||
// add the label and oncommand handler to each button
|
||||
for (dlgtype in buttons) {
|
||||
var button = buttons[dlgtype];
|
||||
button.addEventListener("command", this._handleButtonCommand, true);
|
||||
|
||||
// don't override custom labels with pre-defined labels on explicit buttons
|
||||
if (!button.hasAttribute("label")) {
|
||||
// dialog attributes override the default labels in dialog.properties
|
||||
if (this.hasAttribute("buttonlabel" + dlgtype)) {
|
||||
button.setAttribute("label", this.getAttribute("buttonlabel" + dlgtype));
|
||||
if (this.hasAttribute("buttonaccesskey" + dlgtype))
|
||||
button.setAttribute("accesskey", this.getAttribute("buttonaccesskey" + dlgtype));
|
||||
} else if (this.hasAttribute("buttonid" + dlgtype)) {
|
||||
document.l10n.setAttributes(button, this.getAttribute("buttonid" + dlgtype));
|
||||
this._l10nButtons.push(button);
|
||||
} else if (dlgtype != "extra1" && dlgtype != "extra2") {
|
||||
button.setAttribute("label", this.mStrBundle.GetStringFromName("button-" + dlgtype));
|
||||
var accessKey = this.mStrBundle.GetStringFromName("accesskey-" + dlgtype);
|
||||
if (accessKey)
|
||||
button.setAttribute("accesskey", accessKey);
|
||||
}
|
||||
}
|
||||
// allow specifying alternate icons in the dialog header
|
||||
if (!button.hasAttribute("icon")) {
|
||||
// if there's an icon specified, use that
|
||||
if (this.hasAttribute("buttonicon" + dlgtype))
|
||||
button.setAttribute("icon", this.getAttribute("buttonicon" + dlgtype));
|
||||
// otherwise set defaults
|
||||
else
|
||||
switch (dlgtype) {
|
||||
case "accept":
|
||||
button.setAttribute("icon", "accept");
|
||||
break;
|
||||
case "cancel":
|
||||
button.setAttribute("icon", "cancel");
|
||||
break;
|
||||
case "disclosure":
|
||||
button.setAttribute("icon", "properties");
|
||||
break;
|
||||
case "help":
|
||||
button.setAttribute("icon", "help");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that hitting enter triggers the default button command
|
||||
this.defaultButton = this.defaultButton;
|
||||
|
||||
// if there is a special button configuration, use it
|
||||
if (aButtons) {
|
||||
// expect a comma delimited list of dlgtype values
|
||||
var list = aButtons.split(",");
|
||||
|
||||
// mark shown dlgtypes as true
|
||||
var shown = { accept: false, cancel: false, help: false,
|
||||
disclosure: false, extra1: false, extra2: false };
|
||||
for (i = 0; i < list.length; ++i)
|
||||
shown[list[i].replace(/ /g, "")] = true;
|
||||
|
||||
// hide/show the buttons we want
|
||||
for (dlgtype in buttons)
|
||||
buttons[dlgtype].hidden = !shown[dlgtype];
|
||||
|
||||
// show the spacer on Windows only when the extra2 button is present
|
||||
if (/Win/.test(navigator.platform)) {
|
||||
var spacer = document.getAnonymousElementByAttribute(this, "anonid", "spacer");
|
||||
spacer.removeAttribute("hidden");
|
||||
spacer.setAttribute("flex", shown.extra2 ? "1" : "0");
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_setDefaultButton">
|
||||
<parameter name="aNewDefault"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
// remove the default attribute from the previous default button, if any
|
||||
var oldDefaultButton = this.getButton(this.defaultButton);
|
||||
if (oldDefaultButton)
|
||||
oldDefaultButton.removeAttribute("default");
|
||||
|
||||
var newDefaultButton = this.getButton(aNewDefault);
|
||||
if (newDefaultButton) {
|
||||
this.setAttribute("defaultButton", aNewDefault);
|
||||
newDefaultButton.setAttribute("default", "true");
|
||||
} else {
|
||||
this.setAttribute("defaultButton", "none");
|
||||
if (aNewDefault != "none")
|
||||
dump("invalid new default button: " + aNewDefault + ", assuming: none\n");
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_handleButtonCommand">
|
||||
<parameter name="aEvent"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
return document.documentElement._doButtonCommand(
|
||||
aEvent.target.getAttribute("dlgtype"));
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_doButtonCommand">
|
||||
<parameter name="aDlgType"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var button = this.getButton(aDlgType);
|
||||
if (!button.disabled) {
|
||||
var noCancel = this._fireButtonEvent(aDlgType);
|
||||
if (noCancel) {
|
||||
if (aDlgType == "accept" || aDlgType == "cancel") {
|
||||
var closingEvent = new CustomEvent("dialogclosing", {
|
||||
bubbles: true,
|
||||
detail: { button: aDlgType },
|
||||
});
|
||||
this.dispatchEvent(closingEvent);
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
return noCancel;
|
||||
}
|
||||
return true;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_fireButtonEvent">
|
||||
<parameter name="aDlgType"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
var event = document.createEvent("Events");
|
||||
event.initEvent("dialog" + aDlgType, true, true);
|
||||
|
||||
// handle dom event handlers
|
||||
return this.dispatchEvent(event);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="_hitEnter">
|
||||
<parameter name="evt"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (evt.defaultPrevented)
|
||||
return;
|
||||
|
||||
var btn = this.getButton(this.defaultButton);
|
||||
if (btn)
|
||||
this._doButtonCommand(this.defaultButton);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
<handler event="keypress" keycode="VK_RETURN"
|
||||
group="system" action="this._hitEnter(event);"/>
|
||||
<handler event="keypress" keycode="VK_ESCAPE" group="system">
|
||||
if (!event.defaultPrevented)
|
||||
this.cancelDialog();
|
||||
</handler>
|
||||
#ifdef XP_MACOSX
|
||||
<handler event="keypress" key="." modifiers="meta" phase="capturing" action="this.cancelDialog();"/>
|
||||
#else
|
||||
<handler event="focus" phase="capturing">
|
||||
var btn = this.getButton(this.defaultButton);
|
||||
if (btn)
|
||||
btn.setAttribute("default", event.originalTarget == btn ||
|
||||
!(event.originalTarget.localName == "button" ||
|
||||
event.originalTarget.localName == "toolbarbutton"));
|
||||
</handler>
|
||||
#endif
|
||||
</handlers>
|
||||
|
||||
</binding>
|
||||
|
||||
</bindings>
|
@ -573,7 +573,6 @@ stringbundleset {
|
||||
|
||||
dialog,
|
||||
dialog:root /* override :root from above */ {
|
||||
-moz-binding: url("chrome://global/content/bindings/dialog.xml#dialog");
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,8 @@
|
||||
#else
|
||||
buttonlabelaccept="&window.quit-nonwin;"
|
||||
#endif
|
||||
buttons="accept,extra1" buttonpack="end">
|
||||
buttons="accept,extra1" buttonpack="end"
|
||||
nobuttonspacer="true">
|
||||
|
||||
<script src="profileDowngrade.js"/>
|
||||
<script src="chrome://global/content/customElements.js"/>
|
||||
|
@ -2,10 +2,6 @@
|
||||
* 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/. */
|
||||
|
||||
spacer[anonid="spacer"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#info {
|
||||
list-style-image: url("chrome://mozapps/skin/profile/information.svg");
|
||||
width: 32px;
|
||||
|
Loading…
x
Reference in New Issue
Block a user