1 /* See license.txt for terms of usage */
  2 
  3 define([
  4     "firebug/lib/object",
  5     "firebug/firebug",
  6     "firebug/lib/domplate",
  7     "firebug/lib/locale",
  8     "firebug/lib/events",
  9     "firebug/lib/dom"
 10 ],
 11 function(Obj, Firebug, Domplate, Locale, Events, Dom) {
 12 
 13 // ********************************************************************************************* //
 14 // Constants
 15 
 16 const infoTipMargin = 10;
 17 
 18 // ********************************************************************************************* //
 19 
 20 with (Domplate) {
 21 Firebug.InfoTip = Obj.extend(Firebug.Module,
 22 {
 23     dispatchName: "infoTip",
 24     tags: domplate(
 25     {
 26         infoTipTag: DIV({"class": "infoTip"}),
 27     }),
 28 
 29     initializeBrowser: function(browser)
 30     {
 31         browser.onInfoTipMouseOut = Obj.bind(this.onMouseOut, this, browser);
 32         browser.onInfoTipMouseMove = Obj.bind(this.onMouseMove, this, browser);
 33 
 34         var doc = browser.contentDocument;
 35         if (!doc)
 36             return;
 37 
 38         doc.addEventListener("mouseover", browser.onInfoTipMouseMove, true);
 39         doc.addEventListener("mouseout", browser.onInfoTipMouseOut, true);
 40         doc.addEventListener("mousemove", browser.onInfoTipMouseMove, true);
 41 
 42         return browser.infoTip = this.tags.infoTipTag.append({}, Dom.getBody(doc));
 43     },
 44 
 45     uninitializeBrowser: function(browser)
 46     {
 47         if (browser.infoTip)
 48         {
 49             var doc = browser.contentDocument;
 50             doc.removeEventListener("mouseover", browser.onInfoTipMouseMove, true);
 51             doc.removeEventListener("mouseout", browser.onInfoTipMouseOut, true);
 52             doc.removeEventListener("mousemove", browser.onInfoTipMouseMove, true);
 53 
 54             browser.infoTip.parentNode.removeChild(browser.infoTip);
 55             delete browser.infoTip;
 56             delete browser.onInfoTipMouseMove;
 57         }
 58     },
 59 
 60     showInfoTip: function(infoTip, panel, target, x, y, rangeParent, rangeOffset)
 61     {
 62         if (!Firebug.showInfoTips)
 63             return;
 64 
 65         var scrollParent = Dom.getOverflowParent(target);
 66         var scrollX = x + (scrollParent ? scrollParent.scrollLeft : 0);
 67 
 68         var show = panel.showInfoTip(infoTip, target, scrollX, y, rangeParent, rangeOffset);
 69         if (!show && this.fbListeners)
 70         {
 71             show = Events.dispatch2(this.fbListeners, "showInfoTip", [infoTip, target, scrollX, y,
 72                 rangeParent, rangeOffset]);
 73         }
 74 
 75         if (show)
 76         {
 77             var htmlElt = infoTip.ownerDocument.documentElement;
 78             var panelWidth = htmlElt.clientWidth;
 79             var panelHeight = htmlElt.clientHeight;
 80 
 81             if (x+infoTip.offsetWidth+infoTipMargin > panelWidth)
 82             {
 83                 infoTip.style.left = Math.max(0, panelWidth -
 84                     (infoTip.offsetWidth + infoTipMargin)) + "px";
 85                 infoTip.style.right = "auto";
 86             }
 87             else
 88             {
 89                 infoTip.style.left = (x+infoTipMargin) + "px";
 90                 infoTip.style.right = "auto";
 91             }
 92 
 93             if (y+infoTip.offsetHeight+infoTipMargin > panelHeight)
 94             {
 95                 infoTip.style.top = Math.max(0, panelHeight -
 96                     (infoTip.offsetHeight+infoTipMargin)) + "px";
 97                 infoTip.style.bottom = "auto";
 98             }
 99             else
100             {
101                 infoTip.style.top = (y+infoTipMargin) + "px";
102                 infoTip.style.bottom = "auto";
103             }
104 
105             if (FBTrace.DBG_INFOTIP)
106                 FBTrace.sysout("infotip.showInfoTip; top: " + infoTip.style.top +
107                     ", left: " + infoTip.style.left + ", bottom: " + infoTip.style.bottom +
108                     ", right:" + infoTip.style.right + ", offsetHeight: " + infoTip.offsetHeight +
109                     ", offsetWidth: " + infoTip.offsetWidth +
110                     ", x: " + x + ", panelWidth: " + panelWidth +
111                     ", y: " + y + ", panelHeight: " + panelHeight);
112 
113             infoTip.setAttribute("active", "true");
114         }
115         else
116         {
117             this.hideInfoTip(infoTip);
118         }
119     },
120 
121     hideInfoTip: function(infoTip)
122     {
123         if (infoTip)
124             infoTip.removeAttribute("active");
125     },
126 
127     onMouseOut: function(event, browser)
128     {
129         if (!event.relatedTarget)
130             this.hideInfoTip(browser.infoTip);
131     },
132 
133     onMouseMove: function(event, browser)
134     {
135         // Ignore if the mouse is moving over the existing info tip.
136         if (Dom.getAncestorByClass(event.target, "infoTip"))
137             return;
138 
139         if (browser.currentPanel)
140         {
141             var x = event.clientX, y = event.clientY;
142             this.showInfoTip(browser.infoTip, browser.currentPanel, event.target, x, y,
143                 event.rangeParent, event.rangeOffset);
144         }
145         else
146         {
147             this.hideInfoTip(browser.infoTip);
148         }
149     },
150 
151     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
152     // extends Module
153 
154     disable: function()
155     {
156         // XXXjoe For each browser, call uninitializeBrowser
157     },
158 
159     showPanel: function(browser, panel)
160     {
161         if (panel)
162         {
163             var infoTip = panel.panelBrowser.infoTip;
164             if (!infoTip)
165                 infoTip = this.initializeBrowser(panel.panelBrowser);
166             this.hideInfoTip(infoTip);
167         }
168 
169     },
170 
171     showSidePanel: function(browser, panel)
172     {
173         this.showPanel(browser, panel);
174     }
175 })};
176 
177 // ********************************************************************************************* //
178 // Registration
179 
180 Firebug.registerModule(Firebug.InfoTip);
181 
182 return Firebug.InfoTip;
183 
184 // ********************************************************************************************* //
185 });
186