1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/prompts/content/tabprompts.xml Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,336 @@ 1.4 +<?xml version="1.0"?> 1.5 +<!-- This Source Code Form is subject to the terms of the Mozilla Public 1.6 + - License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> 1.8 + 1.9 +<!DOCTYPE bindings [ 1.10 +<!ENTITY % commonDialogDTD SYSTEM "chrome://global/locale/commonDialog.dtd"> 1.11 +<!ENTITY % dialogOverlayDTD SYSTEM "chrome://global/locale/dialogOverlay.dtd"> 1.12 +%commonDialogDTD; 1.13 +%dialogOverlayDTD; 1.14 +]> 1.15 + 1.16 +<bindings id="tabPrompts" 1.17 + xmlns="http://www.mozilla.org/xbl" 1.18 + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 1.19 + xmlns:xbl="http://www.mozilla.org/xbl"> 1.20 + 1.21 + <binding id="tabmodalprompt"> 1.22 + 1.23 + <resources> 1.24 + <stylesheet src="chrome://global/content/tabprompts.css"/> 1.25 + <stylesheet src="chrome://global/skin/tabprompts.css"/> 1.26 + </resources> 1.27 + 1.28 + <xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 1.29 + role="dialog" 1.30 + aria-describedby="info.body"> 1.31 + 1.32 + <!-- This is based on the guts of commonDialog.xul --> 1.33 + <spacer flex="1"/> 1.34 + <hbox pack="center"> 1.35 + <vbox anonid="mainContainer" class="mainContainer"> 1.36 + <grid class="topContainer" flex="1"> 1.37 + <columns> 1.38 + <column/> 1.39 + <column flex="1"/> 1.40 + </columns> 1.41 + 1.42 + <rows> 1.43 + <vbox anonid="infoContainer" align="center" pack="center" flex="1"> 1.44 + <description anonid="info.title" class="info.title" hidden="true" /> 1.45 + <description anonid="info.body" class="info.body"/> 1.46 + </vbox> 1.47 + 1.48 + <row anonid="loginContainer" hidden="true" align="center"> 1.49 + <label anonid="loginLabel" value="&editfield0.label;" control="loginTextbox"/> 1.50 + <textbox anonid="loginTextbox"/> 1.51 + </row> 1.52 + 1.53 + <row anonid="password1Container" hidden="true" align="center"> 1.54 + <label anonid="password1Label" value="&editfield1.label;" control="password1Textbox"/> 1.55 + <textbox anonid="password1Textbox" type="password"/> 1.56 + </row> 1.57 + 1.58 + <row anonid="checkboxContainer" hidden="true"> 1.59 + <spacer/> 1.60 + <checkbox anonid="checkbox"/> 1.61 + </row> 1.62 + </rows> 1.63 + </grid> 1.64 + <xbl:children/> 1.65 + <hbox class="buttonContainer"> 1.66 +#ifdef XP_UNIX 1.67 + <button anonid="button3" hidden="true"/> 1.68 + <button anonid="button2" hidden="true"/> 1.69 + <spacer anonid="buttonSpacer" flex="1"/> 1.70 + <button anonid="button1" label="&cancelButton.label;"/> 1.71 + <button anonid="button0" label="&okButton.label;"/> 1.72 +#else 1.73 + <button anonid="button3" hidden="true"/> 1.74 + <spacer anonid="buttonSpacer" flex="1"/> 1.75 + <button anonid="button0" label="&okButton.label;"/> 1.76 + <button anonid="button2" hidden="true"/> 1.77 + <button anonid="button1" label="&cancelButton.label;"/> 1.78 +#endif 1.79 + </hbox> 1.80 + </vbox> 1.81 + </hbox> 1.82 + <spacer flex="2"/> 1.83 + </xbl:content> 1.84 + 1.85 + <implementation implements="nsIDOMEventListener"> 1.86 + <constructor> 1.87 + <![CDATA[ 1.88 + let self = this; 1.89 + function getElement(anonid) { 1.90 + return document.getAnonymousElementByAttribute(self, "anonid", anonid); 1.91 + } 1.92 + 1.93 + this.ui = { 1.94 + prompt : this, 1.95 + loginContainer : getElement("loginContainer"), 1.96 + loginTextbox : getElement("loginTextbox"), 1.97 + loginLabel : getElement("loginLabel"), 1.98 + password1Container : getElement("password1Container"), 1.99 + password1Textbox : getElement("password1Textbox"), 1.100 + password1Label : getElement("password1Label"), 1.101 + infoBody : getElement("info.body"), 1.102 + infoTitle : getElement("info.title"), 1.103 + infoIcon : null, 1.104 + checkbox : getElement("checkbox"), 1.105 + checkboxContainer : getElement("checkboxContainer"), 1.106 + button3 : getElement("button3"), 1.107 + button2 : getElement("button2"), 1.108 + button1 : getElement("button1"), 1.109 + button0 : getElement("button0"), 1.110 + // focusTarget (for BUTTON_DELAY_ENABLE) not yet supported 1.111 + }; 1.112 + 1.113 + this.ui.button0.addEventListener("command", this.onButtonClick.bind(this, 0), false); 1.114 + this.ui.button1.addEventListener("command", this.onButtonClick.bind(this, 1), false); 1.115 + this.ui.button2.addEventListener("command", this.onButtonClick.bind(this, 2), false); 1.116 + this.ui.button3.addEventListener("command", this.onButtonClick.bind(this, 3), false); 1.117 + // Anonymous wrapper used here because |Dialog| doesn't exist until init() is called! 1.118 + this.ui.checkbox.addEventListener("command", function() { self.Dialog.onCheckbox(); } , false); 1.119 + this.isLive = false; 1.120 + ]]> 1.121 + </constructor> 1.122 + <destructor> 1.123 + <![CDATA[ 1.124 + if (this.isLive) { 1.125 + this.abortPrompt(); 1.126 + } 1.127 + ]]> 1.128 + </destructor> 1.129 + 1.130 + <field name="ui"/> 1.131 + <field name="args"/> 1.132 + <field name="linkedTab"/> 1.133 + <field name="onCloseCallback"/> 1.134 + <field name="Dialog"/> 1.135 + <field name="isLive"/> 1.136 + <field name="availWidth"/> 1.137 + <field name="availHeight"/> 1.138 + <field name="minWidth"/> 1.139 + <field name="minHeight"/> 1.140 + 1.141 + <method name="init"> 1.142 + <parameter name="args"/> 1.143 + <parameter name="linkedTab"/> 1.144 + <parameter name="onCloseCallback"/> 1.145 + <body> 1.146 + <![CDATA[ 1.147 + this.args = args; 1.148 + this.linkedTab = linkedTab; 1.149 + this.onCloseCallback = onCloseCallback; 1.150 + 1.151 + if (args.enableDelay) 1.152 + throw "BUTTON_DELAY_ENABLE not yet supported for tab-modal prompts"; 1.153 + 1.154 + // We need to remove the prompt when the tab or browser window is closed or 1.155 + // the page navigates, else we never unwind the event loop and that's sad times. 1.156 + // Remember to cleanup in shutdownPrompt()! 1.157 + this.isLive = true; 1.158 + window.addEventListener("resize", this, false); 1.159 + window.addEventListener("unload", this, false); 1.160 + linkedTab.addEventListener("TabClose", this, false); 1.161 + // Note: 1.162 + // nsPrompter.js or in e10s mode browser-parent.js call abortPrompt, 1.163 + // when the domWindow, for which the prompt was created, generates 1.164 + // a "pagehide" event. 1.165 + 1.166 + let tmp = {}; 1.167 + Components.utils.import("resource://gre/modules/CommonDialog.jsm", tmp); 1.168 + this.Dialog = new tmp.CommonDialog(args, this.ui); 1.169 + this.Dialog.onLoad(null); 1.170 + 1.171 + // Display the tabprompt title that shows the prompt origin when 1.172 + // the prompt origin is not the same as that of the top window. 1.173 + if (!args.showAlertOrigin) 1.174 + this.ui.infoTitle.removeAttribute("hidden"); 1.175 + 1.176 + // TODO: should unhide buttonSpacer on Windows when there are 4 buttons. 1.177 + // Better yet, just drop support for 4-button dialogs. (bug 609510) 1.178 + 1.179 + this.onResize(); 1.180 + ]]> 1.181 + </body> 1.182 + </method> 1.183 + 1.184 + <method name="shutdownPrompt"> 1.185 + <body> 1.186 + <![CDATA[ 1.187 + // remove our event listeners 1.188 + try { 1.189 + window.removeEventListener("resize", this, false); 1.190 + window.removeEventListener("unload", this, false); 1.191 + this.linkedTab.removeEventListener("TabClose", this, false); 1.192 + } catch(e) { } 1.193 + this.isLive = false; 1.194 + // invoke callback 1.195 + this.onCloseCallback(); 1.196 + ]]> 1.197 + </body> 1.198 + </method> 1.199 + 1.200 + <method name="abortPrompt"> 1.201 + <body> 1.202 + <![CDATA[ 1.203 + // Called from other code when the page changes. 1.204 + this.Dialog.abortPrompt(); 1.205 + this.shutdownPrompt(); 1.206 + ]]> 1.207 + </body> 1.208 + </method> 1.209 + 1.210 + <method name="handleEvent"> 1.211 + <parameter name="aEvent"/> 1.212 + <body> 1.213 + <![CDATA[ 1.214 + switch (aEvent.type) { 1.215 + case "resize": 1.216 + this.onResize(); 1.217 + break; 1.218 + case "unload": 1.219 + case "TabClose": 1.220 + this.abortPrompt(); 1.221 + break; 1.222 + } 1.223 + ]]> 1.224 + </body> 1.225 + </method> 1.226 + 1.227 + <method name="onResize"> 1.228 + <body> 1.229 + <![CDATA[ 1.230 + let availWidth = this.clientWidth; 1.231 + let availHeight = this.clientHeight; 1.232 + if (availWidth == this.availWidth && availHeight == this.availHeight) 1.233 + return; 1.234 + this.availWidth = availWidth; 1.235 + this.availHeight = availHeight; 1.236 + 1.237 + let self = this; 1.238 + function getElement(anonid) { 1.239 + return document.getAnonymousElementByAttribute(self, "anonid", anonid); 1.240 + } 1.241 + let main = getElement("mainContainer"); 1.242 + let info = getElement("infoContainer"); 1.243 + let body = this.ui.infoBody; 1.244 + 1.245 + // cap prompt dimensions at 60% width and 60% height of content area 1.246 + if (!this.minWidth) 1.247 + this.minWidth = parseInt(window.getComputedStyle(main).minWidth); 1.248 + if (!this.minHeight) 1.249 + this.minHeight = parseInt(window.getComputedStyle(main).minHeight); 1.250 + let maxWidth = Math.max(Math.floor(availWidth * 0.6), this.minWidth) + 1.251 + info.clientWidth - main.clientWidth; 1.252 + let maxHeight = Math.max(Math.floor(availHeight * 0.6), this.minHeight) + 1.253 + info.clientHeight - main.clientHeight; 1.254 + body.style.maxWidth = maxWidth + "px"; 1.255 + info.style.overflow = info.style.width = info.style.height = ""; 1.256 + 1.257 + // when prompt text is too long, use scrollbars 1.258 + if (info.clientWidth > maxWidth) { 1.259 + info.style.overflow = "auto"; 1.260 + info.style.width = maxWidth + "px"; 1.261 + } 1.262 + if (info.clientHeight > maxHeight) { 1.263 + info.style.overflow = "auto"; 1.264 + info.style.height = maxHeight + "px"; 1.265 + } 1.266 + ]]> 1.267 + </body> 1.268 + </method> 1.269 + 1.270 + <method name="onButtonClick"> 1.271 + <parameter name="buttonNum"/> 1.272 + <body> 1.273 + <![CDATA[ 1.274 + this.Dialog["onButton" + buttonNum](); 1.275 + this.shutdownPrompt(); 1.276 + ]]> 1.277 + </body> 1.278 + </method> 1.279 + 1.280 + <method name="onKeyAction"> 1.281 + <parameter name="action"/> 1.282 + <parameter name="event"/> 1.283 + <body> 1.284 + <![CDATA[ 1.285 + if (event.defaultPrevented) 1.286 + return; 1.287 + 1.288 + event.stopPropagation(); 1.289 + if (action == "default") { 1.290 + let bnum = this.args.defaultButtonNum || 0; 1.291 + let button = this.ui["button" + bnum]; 1.292 + this.onButtonClick(bnum); 1.293 + } else { // action == "cancel" 1.294 + this.onButtonClick(1); // Cancel button 1.295 + } 1.296 + ]]> 1.297 + </body> 1.298 + </method> 1.299 + </implementation> 1.300 + 1.301 + <handlers> 1.302 + <!-- Based on dialog.xml handlers --> 1.303 + <handler event="keypress" keycode="VK_RETURN" 1.304 + group="system" action="this.onKeyAction('default', event);"/> 1.305 + <handler event="keypress" keycode="VK_ESCAPE" 1.306 + group="system" action="this.onKeyAction('cancel', event);"/> 1.307 +#ifdef XP_MACOSX 1.308 + <handler event="keypress" key="." modifiers="meta" 1.309 + group="system" action="this.onKeyAction('cancel', event);"/> 1.310 +#endif 1.311 + <handler event="focus" phase="capturing"> 1.312 + let bnum = this.args.defaultButtonNum || 0; 1.313 + let defaultButton = this.ui["button" + bnum]; 1.314 + 1.315 +#ifdef XP_MACOSX 1.316 + // On OS X, the default button always stays marked as such (until 1.317 + // the entire prompt blurs). 1.318 + defaultButton.setAttribute("default", true); 1.319 +#else 1.320 + // On other platforms, the default button is only marked as such 1.321 + // when no other button has focus. XUL buttons on not-OSX will 1.322 + // react to pressing enter as a command, so you can't trigger the 1.323 + // default without tabbing to it or something that isn't a button. 1.324 + let focusedDefault = (event.originalTarget == defaultButton); 1.325 + let someButtonFocused = event.originalTarget instanceof Ci.nsIDOMXULButtonElement; 1.326 + defaultButton.setAttribute("default", focusedDefault || !someButtonFocused); 1.327 +#endif 1.328 + </handler> 1.329 + <handler event="blur"> 1.330 + // If focus shifted to somewhere else in the browser, don't make 1.331 + // the default button look active. 1.332 + let bnum = this.args.defaultButtonNum || 0; 1.333 + let button = this.ui["button" + bnum]; 1.334 + button.setAttribute("default", false); 1.335 + </handler> 1.336 + </handlers> 1.337 + 1.338 + </binding> 1.339 +</bindings>