gecko/toolkit/components/prompts/content/tabprompts.xml
2012-05-21 12:12:37 +01:00

332 lines
14 KiB
XML

<?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 % commonDialogDTD SYSTEM "chrome://global/locale/commonDialog.dtd">
<!ENTITY % dialogOverlayDTD SYSTEM "chrome://global/locale/dialogOverlay.dtd">
%commonDialogDTD;
%dialogOverlayDTD;
]>
<bindings id="tabPrompts"
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="tabmodalprompt">
<resources>
<stylesheet src="chrome://global/content/tabprompts.css"/>
<stylesheet src="chrome://global/skin/tabprompts.css"/>
</resources>
<xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
role="dialog"
aria-describedby="info.body">
<!-- This is based on the guts of commonDialog.xul -->
<spacer flex="1"/>
<hbox pack="center">
<vbox anonid="mainContainer" class="mainContainer">
<grid class="topContainer" flex="1">
<columns>
<column/>
<column flex="1"/>
</columns>
<rows>
<vbox anonid="infoContainer" align="center" pack="center" flex="1">
<description anonid="info.title" class="info.title" hidden="true" />
<description anonid="info.body" class="info.body"/>
</vbox>
<row anonid="loginContainer" hidden="true" align="center">
<label anonid="loginLabel" value="&editfield0.label;" control="loginTextbox"/>
<textbox anonid="loginTextbox"/>
</row>
<row anonid="password1Container" hidden="true" align="center">
<label anonid="password1Label" value="&editfield1.label;" control="password1Textbox"/>
<textbox anonid="password1Textbox" type="password"/>
</row>
<row anonid="checkboxContainer" hidden="true">
<spacer/>
<checkbox anonid="checkbox"/>
</row>
</rows>
</grid>
<xbl:children/>
<hbox class="buttonContainer">
#ifdef XP_UNIX
<button anonid="button3" hidden="true"/>
<button anonid="button2" hidden="true"/>
<spacer anonid="buttonSpacer" flex="1"/>
<button anonid="button1" label="&cancelButton.label;"/>
<button anonid="button0" label="&okButton.label;"/>
#else
<button anonid="button3" hidden="true"/>
<spacer anonid="buttonSpacer" flex="1"/>
<button anonid="button0" label="&okButton.label;"/>
<button anonid="button2" hidden="true"/>
<button anonid="button1" label="&cancelButton.label;"/>
#endif
</hbox>
</vbox>
</hbox>
<spacer flex="2"/>
</xbl:content>
<implementation implements="nsIDOMEventListener">
<constructor>
<![CDATA[
let self = this;
function getElement(anonid) {
return document.getAnonymousElementByAttribute(self, "anonid", anonid);
}
this.ui = {
prompt : this,
loginContainer : getElement("loginContainer"),
loginTextbox : getElement("loginTextbox"),
loginLabel : getElement("loginLabel"),
password1Container : getElement("password1Container"),
password1Textbox : getElement("password1Textbox"),
password1Label : getElement("password1Label"),
infoBody : getElement("info.body"),
infoTitle : getElement("info.title"),
infoIcon : null,
checkbox : getElement("checkbox"),
checkboxContainer : getElement("checkboxContainer"),
button3 : getElement("button3"),
button2 : getElement("button2"),
button1 : getElement("button1"),
button0 : getElement("button0"),
// focusTarget (for BUTTON_DELAY_ENABLE) not yet supported
};
this.ui.button0.addEventListener("command", this.onButtonClick.bind(this, 0), false);
this.ui.button1.addEventListener("command", this.onButtonClick.bind(this, 1), false);
this.ui.button2.addEventListener("command", this.onButtonClick.bind(this, 2), false);
this.ui.button3.addEventListener("command", this.onButtonClick.bind(this, 3), false);
// Anonymous wrapper used here because |Dialog| doesn't exist until init() is called!
this.ui.checkbox.addEventListener("command", function() { self.Dialog.onCheckbox(); } , false);
this.isLive = false;
]]>
</constructor>
<destructor>
<![CDATA[
if (this.isLive) {
this.Dialog.abortPrompt();
this.shutdownPrompt();
}
]]>
</destructor>
<field name="ui"/>
<field name="args"/>
<field name="linkedTab"/>
<field name="onCloseCallback"/>
<field name="Dialog"/>
<field name="isLive"/>
<field name="availWidth"/>
<field name="availHeight"/>
<field name="minWidth"/>
<field name="minHeight"/>
<method name="init">
<parameter name="args"/>
<parameter name="linkedTab"/>
<parameter name="onCloseCallback"/>
<body>
<![CDATA[
this.args = args;
this.linkedTab = linkedTab;
this.onCloseCallback = onCloseCallback;
if (args.enableDelay)
throw "BUTTON_DELAY_ENABLE not yet supported for tab-modal prompts";
// We need to remove the prompt when the tab or browser window is closed or
// the page navigates, else we never unwind the event loop and that's sad times.
// Remember to cleanup in shutdownPrompt()!
this.isLive = true;
window.addEventListener("resize", this, false);
window.addEventListener("unload", this, false);
linkedTab.addEventListener("TabClose", this, false);
this.args.domWindow.addEventListener("pagehide", this, false);
let tmp = {};
Components.utils.import("resource://gre/modules/CommonDialog.jsm", tmp);
this.Dialog = new tmp.CommonDialog(args, this.ui);
this.Dialog.onLoad(null);
// Display the tabprompt title that shows the prompt origin when
// the prompt origin is not the same as that of the top window.
let topPrincipal = this.args.domWindow.top.document.nodePrincipal;
let promptPrincipal = this.args.domWindow.document.nodePrincipal;
if (!topPrincipal.equals(promptPrincipal))
this.ui.infoTitle.removeAttribute("hidden");
// TODO: should unhide buttonSpacer on Windows when there are 4 buttons.
// Better yet, just drop support for 4-button dialogs. (bug 609510)
this.onResize();
]]>
</body>
</method>
<method name="shutdownPrompt">
<body>
<![CDATA[
// remove our event listeners
try {
window.removeEventListener("resize", this, false);
window.removeEventListener("unload", this, false);
this.linkedTab.removeEventListener("TabClose", this, false);
this.args.domWindow.removeEventListener("pagehide", this, false);
} catch(e) { }
this.isLive = false;
// invoke callback
this.onCloseCallback();
]]>
</body>
</method>
<method name="handleEvent">
<parameter name="aEvent"/>
<body>
<![CDATA[
switch (aEvent.type) {
case "resize":
this.onResize();
break;
case "unload":
case "TabClose":
case "pagehide":
this.Dialog.abortPrompt();
this.shutdownPrompt();
break;
}
]]>
</body>
</method>
<method name="onResize">
<body>
<![CDATA[
let availWidth = this.clientWidth;
let availHeight = this.clientHeight;
if (availWidth == this.availWidth && availHeight == this.availHeight)
return;
this.availWidth = availWidth;
this.availHeight = availHeight;
let self = this;
function getElement(anonid) {
return document.getAnonymousElementByAttribute(self, "anonid", anonid);
}
let main = getElement("mainContainer");
let info = getElement("infoContainer");
let body = this.ui.infoBody;
// cap prompt dimensions at 60% width and 60% height of content area
if (!this.minWidth)
this.minWidth = parseInt(window.getComputedStyle(main).minWidth);
if (!this.minHeight)
this.minHeight = parseInt(window.getComputedStyle(main).minHeight);
let maxWidth = Math.max(Math.floor(availWidth * 0.6), this.minWidth) +
info.clientWidth - main.clientWidth;
let maxHeight = Math.max(Math.floor(availHeight * 0.6), this.minHeight) +
info.clientHeight - main.clientHeight;
body.style.maxWidth = maxWidth + "px";
info.style.overflow = info.style.width = info.style.height = "";
// when prompt text is too long, use scrollbars
if (info.clientWidth > maxWidth) {
info.style.overflow = "auto";
info.style.width = maxWidth + "px";
}
if (info.clientHeight > maxHeight) {
info.style.overflow = "auto";
info.style.height = maxHeight + "px";
}
]]>
</body>
</method>
<method name="onButtonClick">
<parameter name="buttonNum"/>
<body>
<![CDATA[
this.Dialog["onButton" + buttonNum]();
this.shutdownPrompt();
]]>
</body>
</method>
<method name="onKeyAction">
<parameter name="action"/>
<parameter name="event"/>
<body>
<![CDATA[
if (event.defaultPrevented)
return;
event.stopPropagation();
if (action == "default") {
let bnum = this.args.defaultButtonNum || 0;
let button = this.ui["button" + bnum];
this.onButtonClick(bnum);
} else { // action == "cancel"
this.onButtonClick(1); // Cancel button
}
]]>
</body>
</method>
</implementation>
<handlers>
<!-- Based on dialog.xml handlers -->
<handler event="keypress" keycode="VK_ENTER"
group="system" action="this.onKeyAction('default', event);"/>
<handler event="keypress" keycode="VK_RETURN"
group="system" action="this.onKeyAction('default', event);"/>
<handler event="keypress" keycode="VK_ESCAPE"
group="system" action="this.onKeyAction('cancel', event);"/>
#ifdef XP_MACOSX
<handler event="keypress" key="." modifiers="meta"
group="system" action="this.onKeyAction('cancel', event);"/>
#endif
<handler event="focus" phase="capturing">
let bnum = this.args.defaultButtonNum || 0;
let defaultButton = this.ui["button" + bnum];
#ifdef XP_MACOSX
// On OS X, the default button always stays marked as such (until
// the entire prompt blurs).
defaultButton.setAttribute("default", true);
#else
// On other platforms, the default button is only marked as such
// when no other button has focus. XUL buttons on not-OSX will
// react to pressing enter as a command, so you can't trigger the
// default without tabbing to it or something that isn't a button.
let focusedDefault = (event.originalTarget == defaultButton);
let someButtonFocused = event.originalTarget instanceof Ci.nsIDOMXULButtonElement;
defaultButton.setAttribute("default", focusedDefault || !someButtonFocused);
#endif
</handler>
<handler event="blur">
// If focus shifted to somewhere else in the browser, don't make
// the default button look active.
let bnum = this.args.defaultButtonNum || 0;
let button = this.ui["button" + bnum];
button.setAttribute("default", false);
</handler>
</handlers>
</binding>
</bindings>