toolkit/components/prompts/content/tabprompts.xml

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 <?xml version="1.0"?>
michael@0 2 <!-- This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 - License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
michael@0 5
michael@0 6 <!DOCTYPE bindings [
michael@0 7 <!ENTITY % commonDialogDTD SYSTEM "chrome://global/locale/commonDialog.dtd">
michael@0 8 <!ENTITY % dialogOverlayDTD SYSTEM "chrome://global/locale/dialogOverlay.dtd">
michael@0 9 %commonDialogDTD;
michael@0 10 %dialogOverlayDTD;
michael@0 11 ]>
michael@0 12
michael@0 13 <bindings id="tabPrompts"
michael@0 14 xmlns="http://www.mozilla.org/xbl"
michael@0 15 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
michael@0 16 xmlns:xbl="http://www.mozilla.org/xbl">
michael@0 17
michael@0 18 <binding id="tabmodalprompt">
michael@0 19
michael@0 20 <resources>
michael@0 21 <stylesheet src="chrome://global/content/tabprompts.css"/>
michael@0 22 <stylesheet src="chrome://global/skin/tabprompts.css"/>
michael@0 23 </resources>
michael@0 24
michael@0 25 <xbl:content xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
michael@0 26 role="dialog"
michael@0 27 aria-describedby="info.body">
michael@0 28
michael@0 29 <!-- This is based on the guts of commonDialog.xul -->
michael@0 30 <spacer flex="1"/>
michael@0 31 <hbox pack="center">
michael@0 32 <vbox anonid="mainContainer" class="mainContainer">
michael@0 33 <grid class="topContainer" flex="1">
michael@0 34 <columns>
michael@0 35 <column/>
michael@0 36 <column flex="1"/>
michael@0 37 </columns>
michael@0 38
michael@0 39 <rows>
michael@0 40 <vbox anonid="infoContainer" align="center" pack="center" flex="1">
michael@0 41 <description anonid="info.title" class="info.title" hidden="true" />
michael@0 42 <description anonid="info.body" class="info.body"/>
michael@0 43 </vbox>
michael@0 44
michael@0 45 <row anonid="loginContainer" hidden="true" align="center">
michael@0 46 <label anonid="loginLabel" value="&editfield0.label;" control="loginTextbox"/>
michael@0 47 <textbox anonid="loginTextbox"/>
michael@0 48 </row>
michael@0 49
michael@0 50 <row anonid="password1Container" hidden="true" align="center">
michael@0 51 <label anonid="password1Label" value="&editfield1.label;" control="password1Textbox"/>
michael@0 52 <textbox anonid="password1Textbox" type="password"/>
michael@0 53 </row>
michael@0 54
michael@0 55 <row anonid="checkboxContainer" hidden="true">
michael@0 56 <spacer/>
michael@0 57 <checkbox anonid="checkbox"/>
michael@0 58 </row>
michael@0 59 </rows>
michael@0 60 </grid>
michael@0 61 <xbl:children/>
michael@0 62 <hbox class="buttonContainer">
michael@0 63 #ifdef XP_UNIX
michael@0 64 <button anonid="button3" hidden="true"/>
michael@0 65 <button anonid="button2" hidden="true"/>
michael@0 66 <spacer anonid="buttonSpacer" flex="1"/>
michael@0 67 <button anonid="button1" label="&cancelButton.label;"/>
michael@0 68 <button anonid="button0" label="&okButton.label;"/>
michael@0 69 #else
michael@0 70 <button anonid="button3" hidden="true"/>
michael@0 71 <spacer anonid="buttonSpacer" flex="1"/>
michael@0 72 <button anonid="button0" label="&okButton.label;"/>
michael@0 73 <button anonid="button2" hidden="true"/>
michael@0 74 <button anonid="button1" label="&cancelButton.label;"/>
michael@0 75 #endif
michael@0 76 </hbox>
michael@0 77 </vbox>
michael@0 78 </hbox>
michael@0 79 <spacer flex="2"/>
michael@0 80 </xbl:content>
michael@0 81
michael@0 82 <implementation implements="nsIDOMEventListener">
michael@0 83 <constructor>
michael@0 84 <![CDATA[
michael@0 85 let self = this;
michael@0 86 function getElement(anonid) {
michael@0 87 return document.getAnonymousElementByAttribute(self, "anonid", anonid);
michael@0 88 }
michael@0 89
michael@0 90 this.ui = {
michael@0 91 prompt : this,
michael@0 92 loginContainer : getElement("loginContainer"),
michael@0 93 loginTextbox : getElement("loginTextbox"),
michael@0 94 loginLabel : getElement("loginLabel"),
michael@0 95 password1Container : getElement("password1Container"),
michael@0 96 password1Textbox : getElement("password1Textbox"),
michael@0 97 password1Label : getElement("password1Label"),
michael@0 98 infoBody : getElement("info.body"),
michael@0 99 infoTitle : getElement("info.title"),
michael@0 100 infoIcon : null,
michael@0 101 checkbox : getElement("checkbox"),
michael@0 102 checkboxContainer : getElement("checkboxContainer"),
michael@0 103 button3 : getElement("button3"),
michael@0 104 button2 : getElement("button2"),
michael@0 105 button1 : getElement("button1"),
michael@0 106 button0 : getElement("button0"),
michael@0 107 // focusTarget (for BUTTON_DELAY_ENABLE) not yet supported
michael@0 108 };
michael@0 109
michael@0 110 this.ui.button0.addEventListener("command", this.onButtonClick.bind(this, 0), false);
michael@0 111 this.ui.button1.addEventListener("command", this.onButtonClick.bind(this, 1), false);
michael@0 112 this.ui.button2.addEventListener("command", this.onButtonClick.bind(this, 2), false);
michael@0 113 this.ui.button3.addEventListener("command", this.onButtonClick.bind(this, 3), false);
michael@0 114 // Anonymous wrapper used here because |Dialog| doesn't exist until init() is called!
michael@0 115 this.ui.checkbox.addEventListener("command", function() { self.Dialog.onCheckbox(); } , false);
michael@0 116 this.isLive = false;
michael@0 117 ]]>
michael@0 118 </constructor>
michael@0 119 <destructor>
michael@0 120 <![CDATA[
michael@0 121 if (this.isLive) {
michael@0 122 this.abortPrompt();
michael@0 123 }
michael@0 124 ]]>
michael@0 125 </destructor>
michael@0 126
michael@0 127 <field name="ui"/>
michael@0 128 <field name="args"/>
michael@0 129 <field name="linkedTab"/>
michael@0 130 <field name="onCloseCallback"/>
michael@0 131 <field name="Dialog"/>
michael@0 132 <field name="isLive"/>
michael@0 133 <field name="availWidth"/>
michael@0 134 <field name="availHeight"/>
michael@0 135 <field name="minWidth"/>
michael@0 136 <field name="minHeight"/>
michael@0 137
michael@0 138 <method name="init">
michael@0 139 <parameter name="args"/>
michael@0 140 <parameter name="linkedTab"/>
michael@0 141 <parameter name="onCloseCallback"/>
michael@0 142 <body>
michael@0 143 <![CDATA[
michael@0 144 this.args = args;
michael@0 145 this.linkedTab = linkedTab;
michael@0 146 this.onCloseCallback = onCloseCallback;
michael@0 147
michael@0 148 if (args.enableDelay)
michael@0 149 throw "BUTTON_DELAY_ENABLE not yet supported for tab-modal prompts";
michael@0 150
michael@0 151 // We need to remove the prompt when the tab or browser window is closed or
michael@0 152 // the page navigates, else we never unwind the event loop and that's sad times.
michael@0 153 // Remember to cleanup in shutdownPrompt()!
michael@0 154 this.isLive = true;
michael@0 155 window.addEventListener("resize", this, false);
michael@0 156 window.addEventListener("unload", this, false);
michael@0 157 linkedTab.addEventListener("TabClose", this, false);
michael@0 158 // Note:
michael@0 159 // nsPrompter.js or in e10s mode browser-parent.js call abortPrompt,
michael@0 160 // when the domWindow, for which the prompt was created, generates
michael@0 161 // a "pagehide" event.
michael@0 162
michael@0 163 let tmp = {};
michael@0 164 Components.utils.import("resource://gre/modules/CommonDialog.jsm", tmp);
michael@0 165 this.Dialog = new tmp.CommonDialog(args, this.ui);
michael@0 166 this.Dialog.onLoad(null);
michael@0 167
michael@0 168 // Display the tabprompt title that shows the prompt origin when
michael@0 169 // the prompt origin is not the same as that of the top window.
michael@0 170 if (!args.showAlertOrigin)
michael@0 171 this.ui.infoTitle.removeAttribute("hidden");
michael@0 172
michael@0 173 // TODO: should unhide buttonSpacer on Windows when there are 4 buttons.
michael@0 174 // Better yet, just drop support for 4-button dialogs. (bug 609510)
michael@0 175
michael@0 176 this.onResize();
michael@0 177 ]]>
michael@0 178 </body>
michael@0 179 </method>
michael@0 180
michael@0 181 <method name="shutdownPrompt">
michael@0 182 <body>
michael@0 183 <![CDATA[
michael@0 184 // remove our event listeners
michael@0 185 try {
michael@0 186 window.removeEventListener("resize", this, false);
michael@0 187 window.removeEventListener("unload", this, false);
michael@0 188 this.linkedTab.removeEventListener("TabClose", this, false);
michael@0 189 } catch(e) { }
michael@0 190 this.isLive = false;
michael@0 191 // invoke callback
michael@0 192 this.onCloseCallback();
michael@0 193 ]]>
michael@0 194 </body>
michael@0 195 </method>
michael@0 196
michael@0 197 <method name="abortPrompt">
michael@0 198 <body>
michael@0 199 <![CDATA[
michael@0 200 // Called from other code when the page changes.
michael@0 201 this.Dialog.abortPrompt();
michael@0 202 this.shutdownPrompt();
michael@0 203 ]]>
michael@0 204 </body>
michael@0 205 </method>
michael@0 206
michael@0 207 <method name="handleEvent">
michael@0 208 <parameter name="aEvent"/>
michael@0 209 <body>
michael@0 210 <![CDATA[
michael@0 211 switch (aEvent.type) {
michael@0 212 case "resize":
michael@0 213 this.onResize();
michael@0 214 break;
michael@0 215 case "unload":
michael@0 216 case "TabClose":
michael@0 217 this.abortPrompt();
michael@0 218 break;
michael@0 219 }
michael@0 220 ]]>
michael@0 221 </body>
michael@0 222 </method>
michael@0 223
michael@0 224 <method name="onResize">
michael@0 225 <body>
michael@0 226 <![CDATA[
michael@0 227 let availWidth = this.clientWidth;
michael@0 228 let availHeight = this.clientHeight;
michael@0 229 if (availWidth == this.availWidth && availHeight == this.availHeight)
michael@0 230 return;
michael@0 231 this.availWidth = availWidth;
michael@0 232 this.availHeight = availHeight;
michael@0 233
michael@0 234 let self = this;
michael@0 235 function getElement(anonid) {
michael@0 236 return document.getAnonymousElementByAttribute(self, "anonid", anonid);
michael@0 237 }
michael@0 238 let main = getElement("mainContainer");
michael@0 239 let info = getElement("infoContainer");
michael@0 240 let body = this.ui.infoBody;
michael@0 241
michael@0 242 // cap prompt dimensions at 60% width and 60% height of content area
michael@0 243 if (!this.minWidth)
michael@0 244 this.minWidth = parseInt(window.getComputedStyle(main).minWidth);
michael@0 245 if (!this.minHeight)
michael@0 246 this.minHeight = parseInt(window.getComputedStyle(main).minHeight);
michael@0 247 let maxWidth = Math.max(Math.floor(availWidth * 0.6), this.minWidth) +
michael@0 248 info.clientWidth - main.clientWidth;
michael@0 249 let maxHeight = Math.max(Math.floor(availHeight * 0.6), this.minHeight) +
michael@0 250 info.clientHeight - main.clientHeight;
michael@0 251 body.style.maxWidth = maxWidth + "px";
michael@0 252 info.style.overflow = info.style.width = info.style.height = "";
michael@0 253
michael@0 254 // when prompt text is too long, use scrollbars
michael@0 255 if (info.clientWidth > maxWidth) {
michael@0 256 info.style.overflow = "auto";
michael@0 257 info.style.width = maxWidth + "px";
michael@0 258 }
michael@0 259 if (info.clientHeight > maxHeight) {
michael@0 260 info.style.overflow = "auto";
michael@0 261 info.style.height = maxHeight + "px";
michael@0 262 }
michael@0 263 ]]>
michael@0 264 </body>
michael@0 265 </method>
michael@0 266
michael@0 267 <method name="onButtonClick">
michael@0 268 <parameter name="buttonNum"/>
michael@0 269 <body>
michael@0 270 <![CDATA[
michael@0 271 this.Dialog["onButton" + buttonNum]();
michael@0 272 this.shutdownPrompt();
michael@0 273 ]]>
michael@0 274 </body>
michael@0 275 </method>
michael@0 276
michael@0 277 <method name="onKeyAction">
michael@0 278 <parameter name="action"/>
michael@0 279 <parameter name="event"/>
michael@0 280 <body>
michael@0 281 <![CDATA[
michael@0 282 if (event.defaultPrevented)
michael@0 283 return;
michael@0 284
michael@0 285 event.stopPropagation();
michael@0 286 if (action == "default") {
michael@0 287 let bnum = this.args.defaultButtonNum || 0;
michael@0 288 let button = this.ui["button" + bnum];
michael@0 289 this.onButtonClick(bnum);
michael@0 290 } else { // action == "cancel"
michael@0 291 this.onButtonClick(1); // Cancel button
michael@0 292 }
michael@0 293 ]]>
michael@0 294 </body>
michael@0 295 </method>
michael@0 296 </implementation>
michael@0 297
michael@0 298 <handlers>
michael@0 299 <!-- Based on dialog.xml handlers -->
michael@0 300 <handler event="keypress" keycode="VK_RETURN"
michael@0 301 group="system" action="this.onKeyAction('default', event);"/>
michael@0 302 <handler event="keypress" keycode="VK_ESCAPE"
michael@0 303 group="system" action="this.onKeyAction('cancel', event);"/>
michael@0 304 #ifdef XP_MACOSX
michael@0 305 <handler event="keypress" key="." modifiers="meta"
michael@0 306 group="system" action="this.onKeyAction('cancel', event);"/>
michael@0 307 #endif
michael@0 308 <handler event="focus" phase="capturing">
michael@0 309 let bnum = this.args.defaultButtonNum || 0;
michael@0 310 let defaultButton = this.ui["button" + bnum];
michael@0 311
michael@0 312 #ifdef XP_MACOSX
michael@0 313 // On OS X, the default button always stays marked as such (until
michael@0 314 // the entire prompt blurs).
michael@0 315 defaultButton.setAttribute("default", true);
michael@0 316 #else
michael@0 317 // On other platforms, the default button is only marked as such
michael@0 318 // when no other button has focus. XUL buttons on not-OSX will
michael@0 319 // react to pressing enter as a command, so you can't trigger the
michael@0 320 // default without tabbing to it or something that isn't a button.
michael@0 321 let focusedDefault = (event.originalTarget == defaultButton);
michael@0 322 let someButtonFocused = event.originalTarget instanceof Ci.nsIDOMXULButtonElement;
michael@0 323 defaultButton.setAttribute("default", focusedDefault || !someButtonFocused);
michael@0 324 #endif
michael@0 325 </handler>
michael@0 326 <handler event="blur">
michael@0 327 // If focus shifted to somewhere else in the browser, don't make
michael@0 328 // the default button look active.
michael@0 329 let bnum = this.args.defaultButtonNum || 0;
michael@0 330 let button = this.ui["button" + bnum];
michael@0 331 button.setAttribute("default", false);
michael@0 332 </handler>
michael@0 333 </handlers>
michael@0 334
michael@0 335 </binding>
michael@0 336 </bindings>

mercurial