toolkit/content/widgets/popup.xml

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. -->
     7 <bindings id="popupBindings"
     8    xmlns="http://www.mozilla.org/xbl"
     9    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    10    xmlns:xbl="http://www.mozilla.org/xbl">
    12   <binding id="popup-base">
    13     <resources>
    14       <stylesheet src="chrome://global/skin/popup.css"/>
    15     </resources>
    17     <implementation implements="nsIDOMXULPopupElement">
    18       <property name="label" onget="return this.getAttribute('label');"
    19                              onset="this.setAttribute('label', val); return val;"/>
    20       <property name="position" onget="return this.getAttribute('position');"
    21                                 onset="this.setAttribute('position', val); return val;"/>
    22       <property name="popupBoxObject">
    23         <getter>
    24           return this.boxObject.QueryInterface(Components.interfaces.nsIPopupBoxObject);
    25         </getter>
    26       </property>
    28       <property name="state" readonly="true"
    29                 onget="return this.popupBoxObject.popupState"/>
    31       <property name="triggerNode" readonly="true"
    32                 onget="return this.popupBoxObject.triggerNode"/>
    34       <property name="anchorNode" readonly="true"
    35                 onget="return this.popupBoxObject.anchorNode"/>
    37       <method name="openPopup">
    38         <parameter name="aAnchorElement"/>
    39         <parameter name="aPosition"/>
    40         <parameter name="aX"/>
    41         <parameter name="aY"/>
    42         <parameter name="aIsContextMenu"/>
    43         <parameter name="aAttributesOverride"/>
    44         <parameter name="aTriggerEvent"/>
    45         <body>
    46         <![CDATA[
    47           try {
    48             var popupBox = this.popupBoxObject;
    49             if (popupBox)
    50               popupBox.openPopup(aAnchorElement, aPosition, aX, aY,
    51                                  aIsContextMenu, aAttributesOverride, aTriggerEvent);
    52           } catch(e) {}
    53         ]]>
    54         </body>
    55       </method>
    57       <method name="openPopupAtScreen">
    58         <parameter name="aX"/>
    59         <parameter name="aY"/>
    60         <parameter name="aIsContextMenu"/>
    61         <parameter name="aTriggerEvent"/>
    62         <body>
    63         <![CDATA[
    64           try {
    65             var popupBox = this.popupBoxObject;
    66             if (popupBox)
    67               popupBox.openPopupAtScreen(aX, aY, aIsContextMenu, aTriggerEvent);
    68           } catch(e) {}
    69         ]]>
    70         </body>
    71       </method>
    73       <method name="showPopup">
    74         <parameter name="element"/>
    75         <parameter name="xpos"/>
    76         <parameter name="ypos"/>
    77         <parameter name="popuptype"/>
    78         <parameter name="anchoralignment"/>
    79         <parameter name="popupalignment"/>
    80         <body>
    81         <![CDATA[
    82           var popupBox = null;
    83           var menuBox = null;
    84           try {
    85             popupBox = this.popupBoxObject;
    86           } catch(e) {}
    87           try {
    88             menuBox = this.parentNode.boxObject;
    89           } catch(e) {}
    90           if (menuBox instanceof Components.interfaces.nsIMenuBoxObject)
    91             menuBox.openMenu(true);
    92           else if (popupBox)
    93             popupBox.showPopup(element, this, xpos, ypos, popuptype, anchoralignment, popupalignment);
    94         ]]>
    95         </body>
    96       </method>
    98       <method name="hidePopup">
    99         <body>
   100         <![CDATA[
   101           var popupBox = null;
   102           var menuBox = null;
   103           try {
   104             popupBox = this.boxObject.QueryInterface(Components.interfaces.nsIPopupBoxObject);
   105           } catch(e) {}
   106           try {
   107             menuBox = this.parentNode.boxObject;
   108           } catch(e) {}
   109           if (menuBox instanceof Components.interfaces.nsIMenuBoxObject)
   110             menuBox.openMenu(false);
   111           else if (popupBox)
   112             popupBox.hidePopup();
   113         ]]>
   114         </body>
   115       </method>
   117       <property name="autoPosition">
   118         <getter>
   119         <![CDATA[
   120           return this.popupBoxObject.autoPosition;
   121         ]]>
   122         </getter>
   123         <setter>
   124         <![CDATA[
   125           return this.popupBoxObject.autoPosition = val;
   126         ]]>
   127         </setter>
   128       </property>
   130       <property name="alignmentPosition" readonly="true">
   131         <getter>
   132         <![CDATA[
   133           return this.popupBoxObject.alignmentPosition;
   134         ]]>
   135         </getter>
   136       </property>
   138       <property name="alignmentOffset" readonly="true">
   139         <getter>
   140         <![CDATA[
   141           return this.popupBoxObject.alignmentOffset;
   142         ]]>
   143         </getter>
   144       </property>
   146       <method name="enableKeyboardNavigator">
   147         <parameter name="aEnableKeyboardNavigator"/>
   148         <body>
   149         <![CDATA[
   150           this.popupBoxObject.enableKeyboardNavigator(aEnableKeyboardNavigator);
   151         ]]>
   152         </body>
   153       </method>
   155       <method name="enableRollup">
   156         <parameter name="aEnableRollup"/>
   157         <body>
   158         <![CDATA[
   159           this.popupBoxObject.enableRollup(aEnableRollup);
   160         ]]>
   161         </body>
   162       </method>
   164       <method name="sizeTo">
   165         <parameter name="aWidth"/>
   166         <parameter name="aHeight"/>
   167         <body>
   168         <![CDATA[
   169           this.popupBoxObject.sizeTo(aWidth, aHeight);
   170         ]]>
   171         </body>
   172       </method>
   174       <method name="moveTo">
   175         <parameter name="aLeft"/>
   176         <parameter name="aTop"/>
   177         <body>
   178         <![CDATA[
   179           this.popupBoxObject.moveTo(aLeft, aTop);
   180         ]]>
   181         </body>
   182       </method>
   184       <method name="moveToAnchor">
   185         <parameter name="aAnchorElement"/>
   186         <parameter name="aPosition"/>
   187         <parameter name="aX"/>
   188         <parameter name="aY"/>
   189         <parameter name="aAttributesOverride"/>
   190         <body>
   191         <![CDATA[
   192           this.popupBoxObject.moveToAnchor(aAnchorElement, aPosition, aX, aY, aAttributesOverride);
   193         ]]>
   194         </body>
   195       </method>
   197       <method name="getOuterScreenRect">
   198         <body>
   199         <![CDATA[
   200           return this.popupBoxObject.getOuterScreenRect();
   201         ]]>
   202         </body>
   203       </method>
   204     </implementation>     
   206   </binding>
   208   <binding id="popup" role="xul:menupopup"
   209            extends="chrome://global/content/bindings/popup.xml#popup-base">
   211     <content>
   212       <xul:arrowscrollbox class="popup-internal-box" flex="1" orient="vertical"
   213                           smoothscroll="false">
   214         <children/>
   215       </xul:arrowscrollbox>
   216     </content>
   218     <handlers>
   219       <handler event="popupshowing" phase="target">
   220         <![CDATA[
   221           var array = [];
   222           var width = 0;
   223           for (var menuitem = this.firstChild; menuitem; menuitem = menuitem.nextSibling) {
   224             if (menuitem.localName == "menuitem" && menuitem.hasAttribute("acceltext")) {
   225               var accel = document.getAnonymousElementByAttribute(menuitem, "anonid", "accel");
   226               if (accel && accel.boxObject) {
   227                 array.push(accel);
   228                 if (accel.boxObject.width > width)
   229                   width = accel.boxObject.width;
   230               }
   231             }
   232           }
   233           for (var i = 0; i < array.length; i++)
   234             array[i].width = width;
   235         ]]>
   236       </handler>
   237     </handlers>
   238   </binding>
   240   <binding id="panel" role="xul:panel"
   241            extends="chrome://global/content/bindings/popup.xml#popup-base">
   242     <implementation implements="nsIDOMXULPopupElement">
   243       <field name="_prevFocus">0</field>
   244       <field name="_dragBindingAlive">true</field>
   245       <constructor>
   246       <![CDATA[
   247         if (this.getAttribute("backdrag") == "true" && !this._draggableStarted) {
   248           this._draggableStarted = true;
   249           try {
   250             let tmp = {};
   251             Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
   252             let draghandle = new tmp.WindowDraggingElement(this);
   253             draghandle.mouseDownCheck = function () this._dragBindingAlive;
   254           } catch (e) {}
   255         }
   256       ]]>
   257       </constructor>
   258     </implementation>
   260     <handlers>
   261       <handler event="popupshowing"><![CDATA[
   262         // Capture the previous focus before has a chance to get set inside the panel
   263         try {
   264           this._prevFocus = document.commandDispatcher.focusedElement;
   265           if (!this._prevFocus)  // Content window has focus
   266             this._prevFocus = document.commandDispatcher.focusedWindow;
   267         } catch (ex) {
   268           this._prevFocus = document.activeElement;
   269         }
   270       ]]></handler>
   271       <handler event="popupshown"><![CDATA[
   272         // Fire event for accessibility APIs
   273         var alertEvent = document.createEvent("Events");
   274         alertEvent.initEvent("AlertActive", true, true);
   275         this.dispatchEvent(alertEvent);
   276        ]]></handler>
   277       <handler event="popuphiding"><![CDATA[
   278         try {
   279           this._currentFocus = document.commandDispatcher.focusedElement;
   280         } catch (e) {
   281           this._currentFocus = document.activeElement;
   282         }
   283       ]]></handler>
   284       <handler event="popuphidden"><![CDATA[
   285         var currentFocus = this._currentFocus;
   286         var prevFocus = this._prevFocus;
   287         this._currentFocus = null;
   288         this._prevFocus = null;
   289         if (prevFocus && currentFocus && this.getAttribute("norestorefocus") != "true") {
   290           // Try to restore focus
   291           try {
   292             if (document.commandDispatcher.focusedWindow != window)
   293               return; // Focus has already been set to a window outside of this panel
   294           } catch(ex) {}
   295           while (currentFocus) {
   296             if (currentFocus == this) {
   297               // Focus was set on an element inside this panel,
   298               // so we need to move it back to where it was previously
   299               try {
   300                 let fm = Components.classes["@mozilla.org/focus-manager;1"]
   301                                    .getService(Components.interfaces.nsIFocusManager);
   302                 fm.setFocus(prevFocus, fm.FLAG_NOSCROLL);
   303               } catch(e) {
   304                 prevFocus.focus();
   305               }
   306               return;
   307             }
   308             currentFocus = currentFocus.parentNode;
   309           }
   310         }
   311       ]]></handler>
   312     </handlers>
   313   </binding>
   315   <binding id="arrowpanel" extends="chrome://global/content/bindings/popup.xml#panel">
   316     <content flip="both" side="top" position="bottomcenter topleft" consumeoutsideclicks="false">
   317       <xul:vbox anonid="container" class="panel-arrowcontainer" flex="1"
   318                xbl:inherits="side,panelopen">
   319         <xul:box anonid="arrowbox" class="panel-arrowbox">
   320           <xul:image anonid="arrow" class="panel-arrow" xbl:inherits="side"/>
   321         </xul:box>
   322         <xul:box class="panel-arrowcontent" xbl:inherits="side,align,dir,orient,pack" flex="1">
   323           <children/>
   324           <xul:box class="panel-inner-arrowcontentfooter" xbl:inherits="footertype" hidden="true"/>
   325         </xul:box>
   326       </xul:vbox>
   327     </content>
   328     <implementation>
   329       <field name="_fadeTimer">null</field>
   330       <method name="sizeTo">
   331         <parameter name="aWidth"/>
   332         <parameter name="aHeight"/>
   333         <body>
   334         <![CDATA[
   335           this.popupBoxObject.sizeTo(aWidth, aHeight);
   336           if (this.state == "open")
   337             this.adjustArrowPosition();
   338         ]]>
   339         </body>
   340       </method>
   341       <method name="moveTo">
   342         <parameter name="aLeft"/>
   343         <parameter name="aTop"/>
   344         <body>
   345         <![CDATA[
   346           this.popupBoxObject.moveTo(aLeft, aTop);
   347           if (this.state == "open")
   348             this.adjustArrowPosition();
   349         ]]>
   350         </body>
   351       </method>
   352       <method name="moveToAnchor">
   353         <parameter name="aAnchorElement"/>
   354         <parameter name="aPosition"/>
   355         <parameter name="aX"/>
   356         <parameter name="aY"/>
   357         <parameter name="aAttributesOverride"/>
   358         <body>
   359         <![CDATA[
   360           this.popupBoxObject.moveToAnchor(aAnchorElement, aPosition, aX, aY, aAttributesOverride);
   361           if (this.state == "open")
   362             this.adjustArrowPosition();
   363         ]]>
   364         </body>
   365       </method>
   366       <method name="adjustArrowPosition">
   367         <body>
   368         <![CDATA[
   369         var arrow = document.getAnonymousElementByAttribute(this, "anonid", "arrow");
   371         var anchor = this.anchorNode;
   372         if (!anchor) {
   373           arrow.hidden = true;
   374           return;
   375         }
   377         var container = document.getAnonymousElementByAttribute(this, "anonid", "container");
   378         var arrowbox = document.getAnonymousElementByAttribute(this, "anonid", "arrowbox");
   380         var position = this.alignmentPosition;
   381         var offset = this.alignmentOffset;
   383         // if this panel has a "sliding" arrow, we may have previously set margins...
   384         arrowbox.style.removeProperty("transform");
   385         if (position.indexOf("start_") == 0 || position.indexOf("end_") == 0) {
   386           container.orient = "horizontal";
   387           arrowbox.orient = "vertical";
   388           if (position.indexOf("_after") > 0) {
   389             arrowbox.pack = "end";
   390           } else {
   391             arrowbox.pack = "start";
   392           }
   393           arrowbox.style.transform = "translate(0, " + -offset + "px)";
   395           // The assigned side stays the same regardless of direction.
   396           var isRTL = (window.getComputedStyle(this).direction == "rtl");
   398           if (position.indexOf("start_") == 0) {
   399             container.dir = "reverse";
   400             this.setAttribute("side", isRTL ? "left" : "right");
   401           }
   402           else {
   403             container.dir = "";
   404             this.setAttribute("side", isRTL ? "right" : "left");
   405           }
   406         }
   407         else if (position.indexOf("before_") == 0 || position.indexOf("after_") == 0) {
   408           container.orient = "";
   409           arrowbox.orient = "";
   410           if (position.indexOf("_end") > 0) {
   411             arrowbox.pack = "end";
   412           } else {
   413             arrowbox.pack = "start";
   414           }
   415           arrowbox.style.transform = "translate(" + -offset + "px, 0)";
   417           if (position.indexOf("before_") == 0) {
   418             container.dir = "reverse";
   419             this.setAttribute("side", "bottom");
   420           }
   421           else {
   422             container.dir = "";
   423             this.setAttribute("side", "top");
   424           }
   425         }
   427         arrow.hidden = false;
   428         ]]>
   429         </body>
   430       </method>
   431     </implementation>
   432     <handlers>
   433       <handler event="popupshowing" phase="target">
   434       <![CDATA[
   435         this.adjustArrowPosition();
   437         // set fading
   438         var fade = this.getAttribute("fade");
   439         var fadeDelay = (fade == "fast") ? 1 : fade == "slow" ? 4000 : 0;
   440         if (fadeDelay) {
   441           this._fadeTimer = setTimeout(function (self) {
   442             self.style.opacity = 0.2;
   443           }, fadeDelay, this);
   444         }
   445       ]]>
   446       </handler>
   447       <handler event="popuphiding" phase="target">
   448         clearTimeout(this._fadeTimer);
   449         this.style.removeProperty("opacity");
   450       </handler>
   451       <handler event="transitionend" phase="target">
   452       <![CDATA[
   453         if (event.propertyName == "opacity" &&
   454             event.originalTarget == this) {
   455           this.hidePopup();
   456           this.style.removeProperty("opacity");
   457         }
   458         ]]>
   459       </handler>
   460       <handler event="popupshown" phase="target">
   461         this.setAttribute("panelopen", "true");
   462       </handler>
   463       <handler event="popuphidden" phase="target">
   464         this.removeAttribute("panelopen");
   465       </handler>
   466     </handlers>
   467   </binding>
   469   <binding id="tooltip" role="xul:tooltip"
   470            extends="chrome://global/content/bindings/popup.xml#popup-base">
   471     <content>
   472       <children>
   473         <xul:label class="tooltip-label" xbl:inherits="xbl:text=label" flex="1"/>
   474       </children>
   475     </content>
   477     <implementation>
   478       <field name="_mouseOutCount">0</field>
   479       <field name="_isMouseOver">false</field>
   481       <property name="label"
   482                 onget="return this.getAttribute('label');"
   483                 onset="this.setAttribute('label', val); return val;"/>
   485       <property name="page" onset="if (val) this.setAttribute('page', 'true');
   486                                    else this.removeAttribute('page');
   487                                    return val;"
   488                             onget="return this.getAttribute('page') == 'true';"/>
   490       <!-- Given the supplied element within a page, set the tooltip's text to the text
   491            for that element. Returns true if text was assigned, and false if the no text
   492            is set, which normally would be used to cancel tooltip display.
   494            Note that DefaultTooltipTextProvider::GetNodeText() from nsDocShellTreeOwner.cpp
   495            also performs the same function, but for embedded clients that don't use a XUL/JS
   496            layer. These two should be kept synchronized.
   497         --> 
   498       <method name="fillInPageTooltip">
   499         <parameter name="tipElement"/>
   500         <body>
   501         <![CDATA[
   502           // Don't show the tooltip if the tooltip node is a document or disconnected.
   503           if (!tipElement || !tipElement.ownerDocument ||
   504               (tipElement.ownerDocument.compareDocumentPosition(tipElement) & document.DOCUMENT_POSITION_DISCONNECTED)) {
   505             return false;
   506           }
   508           var defView = tipElement.ownerDocument.defaultView;
   509           // XXX Work around bug 350679:
   510           // "Tooltips can be fired in documents with no view".
   511           if (!defView)
   512             return false;
   514           const XLinkNS = "http://www.w3.org/1999/xlink";
   515           const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
   517           var titleText = null;
   518           var XLinkTitleText = null;
   519           var SVGTitleText = null;
   520           var XULtooltiptextText = null;
   521           var lookingForSVGTitle = true;
   522           var direction = tipElement.ownerDocument.dir;
   524           // If the element is invalid per HTML5 Forms specifications and has no title,
   525           // show the constraint validation error message.
   526           if ((tipElement instanceof HTMLInputElement ||
   527                tipElement instanceof HTMLTextAreaElement ||
   528                tipElement instanceof HTMLSelectElement ||
   529                tipElement instanceof HTMLButtonElement) &&
   530               !tipElement.hasAttribute('title') &&
   531               (!tipElement.form || !tipElement.form.noValidate)) {
   532             // If the element is barred from constraint validation or valid,
   533             // the validation message will be the empty string.
   534             titleText = tipElement.validationMessage || null;
   535           }
   537           // If the element is an <input type='file'> without a title, we should show
   538           // the current file selection.
   539           if (!titleText &&
   540               tipElement instanceof HTMLInputElement &&
   541               tipElement.type == 'file' &&
   542               !tipElement.hasAttribute('title')) {
   543             let files = tipElement.files;
   545             try {
   546               var bundle = Components.classes['@mozilla.org/intl/stringbundle;1']
   547                                      .getService(Components.interfaces.nsIStringBundleService)
   548                                      .createBundle("chrome://global/locale/layout/HtmlForm.properties");
   549               if (files.length == 0) {
   550                 if (tipElement.multiple) {
   551                   titleText = bundle.GetStringFromName("NoFilesSelected");
   552                 } else {
   553                   titleText = bundle.GetStringFromName("NoFileSelected");
   554                 }
   555               } else {
   556                 titleText = files[0].name;
   557                 // For UX and performance (jank) reasons we cap the number of
   558                 // files that we list in the tooltip to 20 plus a "and xxx more"
   559                 // line, or to 21 if exactly 21 files were picked.
   560                 const TRUNCATED_FILE_COUNT = 20;
   561                 let count = Math.min(files.length, TRUNCATED_FILE_COUNT);
   562                 for (let i = 1; i < count; ++i) {
   563                   titleText += "\n" + files[i].name;
   564                 }
   565                 if (files.length == TRUNCATED_FILE_COUNT + 1) {
   566                   titleText += "\n" + files[TRUNCATED_FILE_COUNT].name;
   567                 } else if (files.length > TRUNCATED_FILE_COUNT + 1) {
   568                   let xmoreStr = bundle.GetStringFromName("AndNMoreFiles");
   569                   let xmoreNum = files.length - TRUNCATED_FILE_COUNT;
   570                   let tmp = {};
   571                   Components.utils.import("resource://gre/modules/PluralForm.jsm", tmp);
   572                   let andXMoreStr = tmp.PluralForm.get(xmoreNum, xmoreStr).replace("#1", xmoreNum);
   573                   titleText += "\n" + andXMoreStr;
   574                 }
   575               }
   576             } catch(e) {}
   577           }
   579           // Check texts against null so that title="" can be used to undefine a
   580           // title on a child element.
   581           while (tipElement &&
   582                  (titleText == null) && (XLinkTitleText == null) &&
   583                  (SVGTitleText == null) && (XULtooltiptextText == null)) {
   585             if (tipElement.nodeType == Node.ELEMENT_NODE) {
   586               if (tipElement.namespaceURI == XULNS)
   587                 XULtooltiptextText = tipElement.getAttribute("tooltiptext");
   588               else
   589                 titleText = tipElement.getAttribute("title");
   591               if ((tipElement instanceof HTMLAnchorElement ||
   592                    tipElement instanceof HTMLAreaElement ||
   593                    tipElement instanceof HTMLLinkElement ||
   594                    tipElement instanceof SVGAElement) && tipElement.href) {
   595                 XLinkTitleText = tipElement.getAttributeNS(XLinkNS, "title");
   596               }
   597               if (lookingForSVGTitle &&
   598                   (!(tipElement instanceof SVGElement) ||
   599                    tipElement.parentNode.nodeType == Node.DOCUMENT_NODE)) {
   600                 lookingForSVGTitle = false;
   601               }
   602               if (lookingForSVGTitle) {
   603                 for (let childNode of tipElement.childNodes) {
   604                   if (childNode instanceof SVGTitleElement) {
   605                     SVGTitleText = childNode.textContent;
   606                     break;
   607                   }
   608                 }
   609               }
   611               direction = defView.getComputedStyle(tipElement, "")
   612                                  .getPropertyValue("direction");
   613             }
   615             tipElement = tipElement.parentNode;
   616           }
   618           this.style.direction = direction;
   620           return [titleText, XLinkTitleText, SVGTitleText, XULtooltiptextText].some(function (t) {
   621             if (t && /\S/.test(t)) {
   622               // Make CRLF and CR render one line break each.
   623               this.label = t.replace(/\r\n?/g, '\n');
   624               return true;
   625             }
   627             return false;
   628           }, this);
   630           return false;
   631         ]]>
   632         </body>
   633       </method>
   634     </implementation>
   636     <handlers>
   637       <handler event="mouseover"><![CDATA[
   638         var rel = event.relatedTarget;
   639         //dump("ENTERING " + (rel ? rel.localName : "null") + "\n");
   640         if (!rel)
   641           return;
   643         // find out if the node we entered from is one of our anonymous children
   644         while (rel) {
   645           if (rel == this)
   646             break;
   647           rel = rel.parentNode;
   648         }
   650         // if the exited node is not a descendant of ours, we are entering for the first time
   651         if (rel != this)
   652           this._isMouseOver = true;
   653       ]]></handler>
   655       <handler event="mouseout"><![CDATA[
   656         var rel = event.relatedTarget;
   657         //dump("LEAVING " + (rel ? rel.localName : "null") + "\n");
   659         // relatedTarget is null when the titletip is first shown: a mouseout event fires
   660         // because the mouse is exiting the main window and entering the titletip "window".
   661         // relatedTarget is also null when the mouse exits the main window completely,
   662         // so count how many times relatedTarget was null after titletip is first shown 
   663         // and hide popup the 2nd time
   664         if (!rel) {
   665           ++this._mouseOutCount;
   666           if (this._mouseOutCount > 1)
   667             this.hidePopup();
   668           return;
   669         }
   671         // find out if the node we are entering is one of our anonymous children
   672         while (rel) {
   673           if (rel == this)
   674             break;
   675           rel = rel.parentNode;
   676         }
   678         // if the entered node is not a descendant of ours, hide the tooltip
   679         if (rel != this && this._isMouseOver) {
   680           this.hidePopup();
   681         }        
   682       ]]></handler>
   684       <handler event="popupshowing"><![CDATA[
   685         if (this.page && !this.fillInPageTooltip(this.triggerNode)) {
   686           event.preventDefault();
   687         }
   688       ]]></handler>
   690       <handler event="popuphiding"><![CDATA[
   691         this._isMouseOver = false;
   692         this._mouseOutCount = 0;
   693       ]]></handler>
   694     </handlers>
   695   </binding>
   697   <binding id="popup-scrollbars" extends="chrome://global/content/bindings/popup.xml#popup">
   698     <content>
   699       <xul:hbox class="popup-internal-box" flex="1" orient="vertical" style="overflow: auto;">
   700         <children/>
   701       </xul:hbox>
   702     </content>
   703   </binding>
   705 </bindings>

mercurial