1 /* See license.txt for terms of usage */ 2 3 FBL.ns(function() { with (FBL) { 4 5 // ************************************************************************************************ 6 // Constants 7 8 const maxWidth = 100, maxHeight = 80; 9 const infoTipMargin = 10; 10 const infoTipWindowPadding = 25; 11 12 // ************************************************************************************************ 13 14 Firebug.InfoTip = extend(Firebug.Module, 15 { 16 dispatchName: "infoTip", 17 tags: domplate( 18 { 19 infoTipTag: DIV({"class": "infoTip"}), 20 21 colorTag: 22 DIV({style: "background: $rgbValue; width: 100px; height: 40px"}, " "), 23 24 imgTag: 25 DIV({"class": "infoTipImageBox infoTipLoading"}, 26 IMG({"class": "infoTipImage", src: "$urlValue", repeat: "$repeat", 27 onload: "$onLoadImage"}), 28 IMG({"class": "infoTipBgImage", collapsed: true, src: "blank.gif"}), 29 DIV({"class": "infoTipCaption"}) 30 ), 31 32 onLoadImage: function(event) 33 { 34 var img = event.currentTarget; 35 var bgImg = img.nextSibling; 36 if (!bgImg) 37 return; // Sometimes gets called after element is dead 38 39 var caption = bgImg.nextSibling; 40 var innerBox = img.parentNode; 41 42 var w = img.naturalWidth, h = img.naturalHeight; 43 var repeat = img.getAttribute("repeat"); 44 45 if (repeat == "repeat-x" || (w == 1 && h > 1)) 46 { 47 collapse(img, true); 48 collapse(bgImg, false); 49 bgImg.style.background = "url(" + img.src + ") repeat-x"; 50 bgImg.style.width = maxWidth + "px"; 51 if (h > maxHeight) 52 bgImg.style.height = maxHeight + "px"; 53 else 54 bgImg.style.height = h + "px"; 55 } 56 else if (repeat == "repeat-y" || (h == 1 && w > 1)) 57 { 58 collapse(img, true); 59 collapse(bgImg, false); 60 bgImg.style.background = "url(" + img.src + ") repeat-y"; 61 bgImg.style.height = maxHeight + "px"; 62 if (w > maxWidth) 63 bgImg.style.width = maxWidth + "px"; 64 else 65 bgImg.style.width = w + "px"; 66 } 67 else if (repeat == "repeat" || (w == 1 && h == 1)) 68 { 69 collapse(img, true); 70 collapse(bgImg, false); 71 bgImg.style.background = "url(" + img.src + ") repeat"; 72 bgImg.style.width = maxWidth + "px"; 73 bgImg.style.height = maxHeight + "px"; 74 } 75 else 76 { 77 if (w > maxWidth || h > maxHeight) 78 { 79 if (w > h) 80 { 81 img.style.width = maxWidth + "px"; 82 img.style.height = Math.round((h / w) * maxWidth) + "px"; 83 } 84 else 85 { 86 img.style.width = Math.round((w / h) * maxHeight) + "px"; 87 img.style.height = maxHeight + "px"; 88 } 89 } 90 } 91 92 caption.innerHTML = $STRF("Dimensions", [w, h]); 93 94 removeClass(innerBox, "infoTipLoading"); 95 } 96 }), 97 98 initializeBrowser: function(browser) 99 { 100 browser.onInfoTipMouseOut = bind(this.onMouseOut, this, browser); 101 browser.onInfoTipMouseMove = bind(this.onMouseMove, this, browser); 102 103 var doc = browser.contentDocument; 104 if (!doc) 105 return; 106 107 doc.addEventListener("mouseover", browser.onInfoTipMouseMove, true); 108 doc.addEventListener("mouseout", browser.onInfoTipMouseOut, true); 109 doc.addEventListener("mousemove", browser.onInfoTipMouseMove, true); 110 111 return browser.infoTip = this.tags.infoTipTag.append({}, getBody(doc)); 112 }, 113 114 uninitializeBrowser: function(browser) 115 { 116 if (browser.infoTip) 117 { 118 var doc = browser.contentDocument; 119 doc.removeEventListener("mouseover", browser.onInfoTipMouseMove, true); 120 doc.removeEventListener("mouseout", browser.onInfoTipMouseOut, true); 121 doc.removeEventListener("mousemove", browser.onInfoTipMouseMove, true); 122 123 browser.infoTip.parentNode.removeChild(browser.infoTip); 124 delete browser.infoTip; 125 delete browser.onInfoTipMouseMove; 126 } 127 }, 128 129 showInfoTip: function(infoTip, panel, target, x, y, rangeParent, rangeOffset) 130 { 131 if (!Firebug.showInfoTips) 132 return; 133 134 var scrollParent = getOverflowParent(target); 135 var scrollX = x + (scrollParent ? scrollParent.scrollLeft : 0); 136 137 if (panel.showInfoTip(infoTip, target, scrollX, y, rangeParent, rangeOffset)) 138 { 139 var htmlElt = infoTip.ownerDocument.documentElement; 140 var panelWidth = htmlElt.clientWidth; 141 var panelHeight = htmlElt.clientHeight; 142 143 if (x+infoTip.offsetWidth+infoTipMargin > panelWidth) 144 { 145 infoTip.style.left = Math.max(0, panelWidth-(infoTip.offsetWidth+infoTipMargin)) + "px"; 146 infoTip.style.right = "auto"; 147 } 148 else 149 { 150 infoTip.style.left = (x+infoTipMargin) + "px"; 151 infoTip.style.right = "auto"; 152 } 153 154 if (y+infoTip.offsetHeight+infoTipMargin > panelHeight) 155 { 156 infoTip.style.top = Math.max(0, panelHeight-(infoTip.offsetHeight+infoTipMargin)) + "px"; 157 infoTip.style.bottom = "auto"; 158 } 159 else 160 { 161 infoTip.style.top = (y+infoTipMargin) + "px"; 162 infoTip.style.bottom = "auto"; 163 } 164 165 if (FBTrace.DBG_INFOTIP) 166 FBTrace.sysout("infotip.showInfoTip; top: " + infoTip.style.top + 167 ", left: " + infoTip.style.left + ", bottom: " + infoTip.style.bottom + 168 ", right:" + infoTip.style.right + ", offsetHeight: " + infoTip.offsetHeight + 169 ", offsetWidth: " + infoTip.offsetWidth + 170 ", x: " + x + ", panelWidth: " + panelWidth + 171 ", y: " + y + ", panelHeight: " + panelHeight); 172 173 infoTip.setAttribute("active", "true"); 174 } 175 else 176 this.hideInfoTip(infoTip); 177 }, 178 179 hideInfoTip: function(infoTip) 180 { 181 if (infoTip) 182 infoTip.removeAttribute("active"); 183 }, 184 185 onMouseOut: function(event, browser) 186 { 187 if (!event.relatedTarget) 188 this.hideInfoTip(browser.infoTip); 189 }, 190 191 onMouseMove: function(event, browser) 192 { 193 // Ignore if the mouse is moving over the existing info tip. 194 if (getAncestorByClass(event.target, "infoTip")) 195 return; 196 197 if (browser.currentPanel) 198 { 199 var x = event.clientX, y = event.clientY; 200 this.showInfoTip(browser.infoTip, browser.currentPanel, event.target, x, y, event.rangeParent, event.rangeOffset); 201 } 202 else 203 this.hideInfoTip(browser.infoTip); 204 }, 205 206 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 207 208 populateColorInfoTip: function(infoTip, color) 209 { 210 this.tags.colorTag.replace({rgbValue: color}, infoTip); 211 return true; 212 }, 213 214 populateImageInfoTip: function(infoTip, url, repeat) 215 { 216 if (!repeat) 217 repeat = "no-repeat"; 218 219 this.tags.imgTag.replace({urlValue: url, repeat: repeat}, infoTip); 220 221 return true; 222 }, 223 224 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 225 // extends Module 226 227 disable: function() 228 { 229 // XXXjoe For each browser, call uninitializeBrowser 230 }, 231 232 showPanel: function(browser, panel) 233 { 234 if (panel) 235 { 236 var infoTip = panel.panelBrowser.infoTip; 237 if (!infoTip) 238 infoTip = this.initializeBrowser(panel.panelBrowser); 239 this.hideInfoTip(infoTip); 240 } 241 242 }, 243 244 showSidePanel: function(browser, panel) 245 { 246 this.showPanel(browser, panel); 247 } 248 }); 249 250 // ************************************************************************************************ 251 252 Firebug.registerModule(Firebug.InfoTip); 253 254 // ************************************************************************************************ 255 256 }}); 257