1 /* See license.txt for terms of usage */
  2 
  3 define([
  4     "firebug/lib/object",
  5     "firebug/chrome/infotip",
  6     "firebug/lib/domplate",
  7     "firebug/js/sourceLink",
  8     "firebug/lib/locale",
  9     "firebug/lib/dom",
 10     "firebug/lib/css",
 11     "firebug/lib/string",
 12     "firebug/lib/fonts"
 13 ],
 14 function(Obj, InfoTip, Domplate, SourceLink, Locale, Dom, Css, Str, Fonts) {
 15 
 16 with (Domplate) {
 17 
 18 // ********************************************************************************************* //
 19 // Constants
 20 
 21 const maxWidth = 100
 22 const maxHeight = 80;
 23 
 24 // ********************************************************************************************* //
 25 
 26 var CSSInfoTip = Obj.extend(InfoTip,
 27 {
 28     dispatchName: "cssInfoTip",
 29 
 30     tags: domplate(
 31     {
 32         infoTipTag: DIV({"class": "infoTip"}),
 33 
 34         colorTag:
 35             DIV({"class": "infoTipColorBox"},
 36                 DIV({style: "background: $rgbValue; width: 100px; height: 40px;"})
 37             ),
 38 
 39         imgTag:
 40             DIV({"class": "infoTipImageBox infoTipLoading"},
 41                 IMG({"class": "infoTipImage", src: "$urlValue", repeat: "$repeat",
 42                     onload: "$onLoadImage", onerror: "$onErrorImage"}),
 43                 IMG({"class": "infoTipBgImage", collapsed: true, src: "blank.gif"}),
 44                 DIV({"class": "infoTipCaption"})
 45             ),
 46 
 47         fontFamilyTag:
 48             DIV({"class": "infoTipFontFamilyBox"},
 49                 STYLE({"class": "infoTipFontFamilyStyle"}),
 50                 DIV({"class": "infoTipFontFamilySample"},
 51                     FOR("fontStyle", "$fontStyles",
 52                         DIV({"class": "infoTipFontFace", style: "$fontStyle"},
 53                             Locale.$STR("css.fontFamilyPreview"))
 54                     )
 55                 )
 56             ),
 57 
 58         onLoadImage: function(event)
 59         {
 60             var img = event.currentTarget;
 61             var bgImg = img.nextSibling;
 62             if (!bgImg)
 63                 return; // Sometimes gets called after element is dead
 64 
 65             var caption = bgImg.nextSibling;
 66             var innerBox = img.parentNode;
 67 
 68             var w = img.naturalWidth, h = img.naturalHeight;
 69             var repeat = img.getAttribute("repeat");
 70 
 71             if (repeat == "repeat-x" || (w == 1 && h > 1))
 72             {
 73                 Dom.collapse(img, true);
 74                 Dom.collapse(bgImg, false);
 75                 bgImg.style.background = "url(" + img.src + ") repeat-x";
 76                 bgImg.style.width = maxWidth + "px";
 77                 if (h > maxHeight)
 78                     bgImg.style.height = maxHeight + "px";
 79                 else
 80                     bgImg.style.height = h + "px";
 81             }
 82             else if (repeat == "repeat-y" || (h == 1 && w > 1))
 83             {
 84                 Dom.collapse(img, true);
 85                 Dom.collapse(bgImg, false);
 86                 bgImg.style.background = "url(" + img.src + ") repeat-y";
 87                 bgImg.style.height = maxHeight + "px";
 88                 if (w > maxWidth)
 89                     bgImg.style.width = maxWidth + "px";
 90                 else
 91                     bgImg.style.width = w + "px";
 92             }
 93             else if (repeat == "repeat" || (w == 1 && h == 1))
 94             {
 95                 Dom.collapse(img, true);
 96                 Dom.collapse(bgImg, false);
 97                 bgImg.style.background = "url(" + img.src + ") repeat";
 98                 bgImg.style.width = maxWidth + "px";
 99                 bgImg.style.height = maxHeight + "px";
100             }
101             else
102             {
103                 if (w > maxWidth || h > maxHeight)
104                 {
105                     if (w > h)
106                     {
107                         img.style.width = maxWidth + "px";
108                         img.style.height = Math.round((h / w) * maxWidth) + "px";
109                     }
110                     else
111                     {
112                         img.style.width = Math.round((w / h) * maxHeight) + "px";
113                         img.style.height = maxHeight + "px";
114                     }
115                 }
116             }
117 
118             caption.textContent = Locale.$STRF("Dimensions", [w, h]);
119 
120             Css.removeClass(innerBox, "infoTipLoading");
121         },
122 
123         onErrorImage: function(event)
124         {
125             var img = event.currentTarget;
126             var bgImg = img.nextSibling;
127             if (!bgImg)
128                 return;
129 
130             var caption = bgImg.nextSibling;
131 
132             // Display an error in the caption (instead of dimensions).
133             if (Str.hasPrefix(img.src, "moz-filedata"))
134                 caption.textContent = Locale.$STR("firebug.failedToPreviewObjectURL");
135             else
136                 caption.textContent = Locale.$STR("firebug.failedToPreviewImageURL");
137 
138             var innerBox = img.parentNode;
139             Css.removeClass(innerBox, "infoTipLoading");
140         }
141     }),
142 
143     populateFontFamilyInfoTip: function(infoTip, fontName)
144     {
145         var fontStyles = [
146            "font-size:12px;",
147            "font-weight:bold; font-size:12px;",
148            "font-style:italic; font-size:12px;",
149            "font-size:14px;",
150            "font-size:18px;"
151         ];
152         var fontObject = Fonts.getFontInfo(null, null,
153             fontName.replace(/^(["'])?(.*?)\1$/g, "$2"));
154 
155         if (FBTrace.DBG_INFOTIP)
156         {
157             FBTrace.sysout("infotip.populateFontFamilyInfoTip;", {fontName: fontName,
158                 fontObject: fontObject});
159         }
160 
161         var node = this.tags.fontFamilyTag.replace({fontStyles: fontStyles, fontName: fontName,
162             fontObject: fontObject}, infoTip);
163         var styleNode = node.getElementsByClassName("infoTipFontFamilyStyle").item(0);
164 
165         styleNode.textContent = getFontFaceCSS(fontObject ? fontObject : fontName);
166         return true;
167     },
168 
169     populateColorInfoTip: function(infoTip, color)
170     {
171         this.tags.colorTag.replace({rgbValue: color}, infoTip);
172         return true;
173     },
174 
175     populateImageInfoTip: function(infoTip, url, repeat)
176     {
177         if (!repeat)
178             repeat = "no-repeat";
179 
180         this.tags.imgTag.replace({urlValue: url, repeat: repeat}, infoTip);
181 
182         return true;
183     }
184 });
185 
186 //********************************************************************************************* //
187 //Local Helpers
188 
189 /**
190 * Returns the CSS for the infotip @font-face CSS
191 *
192 * @param fontObject: Font related information
193 * @return @font-face CSS
194 */
195 function getFontFaceCSS(font)
196 {
197     var fontFaceCSS = "";
198     var fontName = "";
199 
200     if (typeof font == "object")
201     {
202         if (font.rule)
203             fontFaceCSS = font.rule.cssText.replace(/url\(.*?\)/g, "url("+font.URI+")");
204         fontName = font.CSSFamilyName;
205     }
206     else
207     {
208         fontName = font;
209     }
210 
211     fontFaceCSS += " .infoTipFontFace {font-family: "+fontName+";}";
212 
213     return fontFaceCSS;
214 }
215 
216 // ********************************************************************************************* //
217 // Registration
218 
219 return CSSInfoTip;
220 
221 // ********************************************************************************************* //
222 }});
223