summaryrefslogtreecommitdiffstats
path: root/toolkit/content/widgets/dialog.xml
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/content/widgets/dialog.xml')
-rw-r--r--toolkit/content/widgets/dialog.xml448
1 files changed, 448 insertions, 0 deletions
diff --git a/toolkit/content/widgets/dialog.xml b/toolkit/content/widgets/dialog.xml
new file mode 100644
index 000000000..d83570ac0
--- /dev/null
+++ b/toolkit/content/widgets/dialog.xml
@@ -0,0 +1,448 @@
+<?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="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" extends="chrome://global/content/bindings/general.xml#root-element">
+ <resources>
+ <stylesheet src="chrome://global/skin/dialog.css"/>
+ </resources>
+ <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>
+ </content>
+
+ <implementation>
+ <field name="_mStrBundle">null</field>
+ <field name="_closeHandler">(function(event) {
+ if (!document.documentElement.cancelDialog())
+ event.preventDefault();
+ })</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._closeHandler, false);
+
+ // for things that we need to initialize after onload fires
+ window.addEventListener("load", this.postLoadInit, false);
+
+ window.moveToAlertPosition = this.moveToAlertPosition;
+ window.centerWindowOnScreen = this.centerWindowOnScreen;
+ ]]>
+ </constructor>
+
+ <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)
+ 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);
+ ]]>
+ </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 = Components.classes["@mozilla.org/intl/stringbundle;1"]
+ .getService(Components.interfaces.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");
+
+ // 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 (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
+ var noCancel = this.dispatchEvent(event);
+
+ // handle any xml attribute event handlers
+ var handler = this.getAttribute("ondialog"+aDlgType);
+ if (handler != "") {
+ var fn = new Function("event", handler);
+ var returned = fn(event);
+ if (returned == false)
+ noCancel = false;
+ }
+
+ return noCancel;
+ ]]>
+ </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 instanceof Components.interfaces.nsIDOMXULButtonElement));
+ </handler>
+#endif
+ </handlers>
+
+ </binding>
+
+ <binding id="dialogheader">
+ <resources>
+ <stylesheet src="chrome://global/skin/dialog.css"/>
+ </resources>
+ <content>
+ <xul:label class="dialogheader-title" xbl:inherits="value=title,crop" crop="right" flex="1"/>
+ <xul:label class="dialogheader-description" xbl:inherits="value=description"/>
+ </content>
+ </binding>
+
+</bindings>