зеркало из https://github.com/mozilla/gecko-dev.git
337 строки
14 KiB
XML
337 строки
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.abortPrompt();
|
|
}
|
|
]]>
|
|
</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);
|
|
// Note:
|
|
// nsPrompter.js or in e10s mode browser-parent.js call abortPrompt,
|
|
// when the domWindow, for which the prompt was created, generates
|
|
// a "pagehide" event.
|
|
|
|
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.
|
|
if (!args.showAlertOrigin)
|
|
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);
|
|
} catch(e) { }
|
|
this.isLive = false;
|
|
// invoke callback
|
|
this.onCloseCallback();
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="abortPrompt">
|
|
<body>
|
|
<![CDATA[
|
|
// Called from other code when the page changes.
|
|
this.Dialog.abortPrompt();
|
|
this.shutdownPrompt();
|
|
]]>
|
|
</body>
|
|
</method>
|
|
|
|
<method name="handleEvent">
|
|
<parameter name="aEvent"/>
|
|
<body>
|
|
<![CDATA[
|
|
switch (aEvent.type) {
|
|
case "resize":
|
|
this.onResize();
|
|
break;
|
|
case "unload":
|
|
case "TabClose":
|
|
this.abortPrompt();
|
|
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_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>
|