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

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

mercurial