/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is CaScadeS, a stylesheet editor for Composer. * * The Initial Developer of the Original Code is * Daniel Glazman. * Portions created by the Initial Developer are Copyright (C) 2002 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Original author: Daniel Glazman * Charley Manske , for local fonts access * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ var gTimerID; var textColor, backgroundColor, borderColor; var gLocalFonts = null; const kUrlString = "url("; // * if |value| is not empty, sets the CSS property |property| to |value| // in |elt| element's inline styles ; otherwise removes the property // param XULElement elt // param String property // param String value function AddStyleToElement(elt, property, value) { if (!elt || !elt.style) return; if (value == "") { elt.style.removeProperty(property); } else { try { elt.style.setProperty(property, value, elt.style.getPropertyPriority(property)); } catch (ex) { } } } // * Callback from font-family selection XUL elts // param String fontFamily function onFontFamilySelect(fontFamily) { if (!gDialog.selectedObject) return; var enableCustomInput = false; var enablePredefMenu = false; if (fontFamily == "") { // nothing to do here } else if (fontFamily == "-user-defined") { // user wants to select a font that is not pre-defined // so let's get that user defined name from the textarea enableCustomInput = true; fontFamily = gDialog.customFontFamilyInput.value; } else if (fontFamily == "-predefined"){ fontFamily = ""; enablePredefMenu = true; // user wants a predefined font family var valueElt = gDialog.predefFontFamilyMenulist.selectedItem; if (valueElt) { fontFamily = valueElt.value; } } else { // all other cases are user defined fonts enablePredefMenu = true; } EnableUI(gDialog.predefFontFamilyMenulist, enablePredefMenu); EnableUI(gDialog.customFontFamilyInput, enableCustomInput); AddStyleToElement(gDialog.brownFoxLabel, "font-family", fontFamily); AddStyleToElement(gDialog.selectedObject, "font-family", fontFamily); SetModifiedFlagOnStylesheet(); } // * Callback when the color textarea's value is changed // it sets the correspondinf property/value on the element elt // and sets the color of the corresponding UI button // param XULElement elt // param String property // param String id // param String ColorWellID function onColorZoneInput(elt, property, id, ColorWellID) { ChangeValueOnInput(elt, property, id); setColorWell(ColorWellID, elt.value); } // * Opens a color picker for the requested property and handles // the result // param String ColorWellID function GetColorAndUpdate(ColorWellID) { var colorObj = new Object; var colorWell = document.getElementById(ColorWellID); if (!colorWell) return; // Don't allow a blank color, i.e., using the "default" colorObj.NoDefault = true; switch( ColorWellID ) { case "textCW": colorObj.Type = "Text"; colorObj.TextColor = textColor; break; case "backgroundCW": colorObj.Type = "Page"; colorObj.PageColor = backgroundColor; break; case "bordertopCW": case "borderleftCW": case "borderrightCW": case "borderbottomCW": colorObj.Type = "Text"; colorObj.TextColor = borderColor; break; } window.openDialog("chrome://editor/content/EdColorPicker.xul", "_blank", "chrome,close,titlebar,modal", "", colorObj); // User canceled the dialog if (colorObj.Cancel) return; var color = ""; var property = ""; var textZone = null; switch( ColorWellID ) { case "textCW": color = textColor = colorObj.TextColor; property = "color"; AddStyleToElement(gDialog.brownFoxLabel, "color", color); textZone = gDialog.textColorInput; break; case "backgroundCW": color = backgroundColor = colorObj.BackgroundColor; property = "background-color"; textZone = gDialog.backgroundColorInput; break; case "bordertopCW": color = textColor = colorObj.TextColor; property = "border-top-color"; AddStyleToElement(gDialog.borderPreview, "border-top-color", color); textZone = gDialog.topBorderColorInput; break; case "borderleftCW": color = textColor = colorObj.TextColor; property = "border-left-color"; AddStyleToElement(gDialog.borderPreview, "border-left-color", color); textZone = gDialog.leftBorderColorInput; break; case "borderrightCW": color = textColor = colorObj.TextColor; property = "border-right-color"; AddStyleToElement(gDialog.borderPreview, "border-right-color", color); textZone = gDialog.rightBorderColorInput; break; case "borderbottomCW": color = textColor = colorObj.TextColor; property = "border-bottom-color"; AddStyleToElement(gDialog.borderPreview, "border-bottom-color", color); textZone = gDialog.bottomBorderColorInput; break; } setColorWell(ColorWellID, color); if (textZone != null) { textZone.value = color; if (ColorWellID == "bordertopCW") IfFourSidesSameStyle('border', 'color', color, 'allFourBordersSame', 'borderPreview', null); else if (ColorWellID == "backgroundCW") AddStyleToElement(gDialog.backgroundPreview, "background-color", color); } try { gDialog.selectedObject.style.setProperty(property, color, gDialog.selectedObject.style.getPropertyPriority(property)); } catch (ex) {} SetModifiedFlagOnStylesheet(); } // * Callback when a textarea's value is changed // it sets the corresponding property/value on the element elt // param XULElement elt // param String property // param String id function ChangeValueOnInput(elt, property, id) { if (!gDialog.selectedObject) return; var value = elt.value; if (id != null) { elt = document.getElementById(id); if (elt) { AddStyleToElement(elt, property, value); } } AddStyleToElement(gDialog.selectedObject, property, value); SetModifiedFlagOnStylesheet(); } // * Callback when a pulldown menu entry is selected // param String property // param String value // param String id function onPullDownChanged(property, value, id) { if (!gDialog.selectedObject) return; if (id != null) { var elt = document.getElementById(id); if (elt) { AddStyleToElement(elt, property, value); } } AddStyleToElement(gDialog.selectedObject, property, value); SetModifiedFlagOnStylesheet(); } // * Callback when the 'none' value is selected for the // 'text-decoration' property; it unchecks all other checkboxes // if the 'none' checkbox is checked function onNoneTextDecorationChange() { if (!gDialog.selectedObject) return; var textDecoration = ""; if (gDialog.noDecorationCheckbox.checked) { // uncheck other possible values for the property if 'none' is checked gDialog.textUnderlineCheckbox.checked = false; gDialog.textOverlineCheckbox.checked = false; gDialog.textLinethroughCheckbox.checked = false; gDialog.textBlinkCheckbox.checked = false; textDecoration = "none"; } AddStyleToElement(gDialog.selectedObject, "text-decoration", textDecoration); AddStyleToElement(gDialog.brownFoxLabel, "text-decoration", textDecoration); SetModifiedFlagOnStylesheet(); } // * Callback when one of the chekboxes but for 'none' for // 'text-decoration' property sees his state changed ; it // recomputes the value of the property appending the various // individual values function onTextDecorationChange() { if (!gDialog.selectedObject) return; var textDecoration = ""; if (gDialog.textUnderlineCheckbox.checked) textDecoration += "underline "; if (gDialog.textOverlineCheckbox.checked) textDecoration += "overline "; if (gDialog.textLinethroughCheckbox.checked) textDecoration += "line-through "; if (gDialog.textBlinkCheckbox.checked) textDecoration += "blink "; if (textDecoration != "") { gDialog.noDecorationCheckbox.checked = false; } AddStyleToElement(gDialog.selectedObject, "text-decoration", textDecoration); AddStyleToElement(gDialog.brownFoxLabel, "text-decoration", textDecoration); SetModifiedFlagOnStylesheet(); } // * This function sets a timer when the user changes an image URL // in a textarea. This leaves the user enough time to complete the // URL and avoids Gecko trying to load an incomplete URL function ChangeImageSrc() { if (gTimerID) clearTimeout(gTimerID); gTimerID = setTimeout("onBgImageUrlChanged()", 800); } // * This is the callback from ChangeImageSrc(). It loads an image and uses // the cache. function onBgImageUrlChanged() { var property = "background-image"; var id = "backgroundPreview"; if (!gDialog.selectedObject) return; var value = gDialog.backgroundImageInput.value; if (value != "" && value != "none") { try { // Remove the image URL from image cache so it loads fresh // (if we don't do this, loads after the first will always use image cache // and we won't see image edit changes or be able to get actual width and height) var IOService = GetIOService(); if (IOService) { // We must have an absolute URL to preview it or remove it from the cache value = MakeAbsoluteUrl(value); if (GetScheme(value)) { var uri = IOService.newURI(value, null, null); if (uri) { var imgCacheService = Components.classes["@mozilla.org/image/cache;1"].getService(); var imgCache = imgCacheService.QueryInterface(Components.interfaces.imgICache); // This returns error if image wasn't in the cache; ignore that imgCache.removeEntry(uri); } } } } catch(e) {} value = kUrlString + value + ")"; } if (id != null) { var xulElt = document.getElementById(id); if (xulElt) { AddStyleToElement(xulElt, property, value); } } AddStyleToElement(gDialog.selectedObject, property, value); SetModifiedFlagOnStylesheet(); if (property == "background-image") { enableBackgroundProps((value != "")); } } // * This function enable some of the background-* properties that // only make sense if there is a background image specified // param boolean enable function enableBackgroundProps(enable) { var idArray = [ "backgroundRepeatLabel", "backgroundRepeatMenulist", "backgroundAttachmentCheckbox", "backgroundPositionLabel", "xBackgroundPositionRadiogroup", "yBackgroundPositionRadiogroup" ]; var i, elt, lookAtNextSibling; for (i = 0; i < idArray.length; i++) { elt = document.getElementById(idArray[i]); lookAtNextSibling = false; if (elt.nodeName.toLowerCase() == "radiogroup") { elt = elt.firstChild; lookAtNextSibling = true; } while (elt) { EnableUI(elt, enable); if (lookAtNextSibling) { elt = elt.nextSibling; } else { elt = null; } } } } // * open a file picker dialog for the requested file filter and // returns the corresponding file URL into the element of ID id // param String filterType // param String id function chooseFile(filterType, id) { // Get a local image file, converted into URL format var fileName = GetLocalFileURL(filterType); var elt = document.getElementById(id); if (fileName) { // Always try to relativize local file URLs if (gHaveDocumentUrl) fileName = MakeRelativeUrl(fileName); elt.value = fileName; onBgImageUrlChanged(); } SetTextboxFocus(elt); } // * Callback when the user changes the value for background-attachment function onBackgroundAttachmentChange() { if (!gDialog.selectedObject) return; // the checkbox is checked if the background scrolls with the page var value = gDialog.backgroundAttachmentCheckbox.checked ? "" : "fixed"; AddStyleToElement(gDialog.selectedObject, "background-attachment", value); SetModifiedFlagOnStylesheet(); } // * Callback when one of the background positions (x or y) is changed function onBackGroundPositionSelect() { var xPosition = gDialog.xBackgroundPositionRadiogroup.selectedItem.value; var yPosition = gDialog.yBackgroundPositionRadiogroup.selectedItem.value; var value = xPosition + " " + yPosition; AddStyleToElement(gDialog.backgroundPreview, "background-position", value); AddStyleToElement(gDialog.selectedObject, "background-position", value); SetModifiedFlagOnStylesheet(); } // * Inits the values shown in the Text tab panel function InitTextTabPanel() { gDialog.selectedTab = TEXT_TAB; if (!gDialog.selectedObject || !gDialog.selectedObject.style) return; /* INIT FONT-FAMILY */ var fontFamily = getSpecifiedStyle("font-family"); AddStyleToElement(gDialog.brownFoxLabel, "font-family", fontFamily); var fontFamilyChoice = "noFontFamilyRadio"; var predefFontFamilyChoice = ""; var enableCustomInput = false; var enablePredefMenu = false; if (fontFamily == "arial,helvetica,sans-serif") { fontFamilyChoice = "predefFontFamilyRadio"; predefFontFamilyChoice = "sansSerifFontFamilyMenuitem"; enablePredefMenu = true; } else if (fontFamily == "times new roman,times,serif") { fontFamilyChoice = "predefFontFamilyRadio"; predefFontFamilyChoice = "serifFontFamilyMenuitem"; enablePredefMenu = true; } else if (fontFamily == "courier new,courier,monospace") { fontFamilyChoice = "predefFontFamilyRadio"; predefFontFamilyChoice = "monospaceFontFamilyMenuitem"; enablePredefMenu = true; } else if (fontFamily != "") { fontFamilyChoice = "customFontFamilyRadio"; gDialog.customFontFamilyInput.value = fontFamily; enableCustomInput = true; } /* selects the radio button */ var fontFamilyItem = document.getElementById(fontFamilyChoice); gDialog.fontFamilyRadiogroup.selectedItem = fontFamilyItem; /* enablers/disablers */ if (enablePredefMenu) { gDialog.predefFontFamilyMenulist.removeAttribute("disabled"); } else { gDialog.predefFontFamilyMenulist.setAttribute("disabled", "true"); } if (enableCustomInput) { gDialog.customFontFamilyInput.removeAttribute("disabled"); } else { gDialog.customFontFamilyInput.setAttribute("disabled", "true"); } if (predefFontFamilyChoice != "") { var predefFontFamilyMenuitem = document.getElementById(predefFontFamilyChoice); gDialog.predefFontFamilyMenulist.selectedItem = predefFontFamilyMenuitem; } /* INIT COLOR */ textColor = ConvertRGBColorIntoHEXColor(getSpecifiedStyle("color")); backgroundColor = ConvertRGBColorIntoHEXColor(getSpecifiedStyle("background-color")); gDialog.textColorInput.setAttribute("value", textColor); AddStyleToElement(gDialog.brownFoxLabel, "color", textColor); if (backgroundColor == "") backgroundColor = "white"; AddStyleToElement(gDialog.brownFoxLabel, "background-color", backgroundColor); setColorWell("textCW", textColor); /* INIT FONT-STYLE */ SelectsOneChoice("font-style", "fontStyleMenulist", "FontStyleMenu", gDialog.brownFoxLabel) /* INIT FONT-WEIGHT */ SelectsOneChoice("font-weight", "fontWeightMenulist", "FontWeightMenu", gDialog.brownFoxLabel) /* INIT TEXT-TRANSFORM */ SelectsOneChoice("text-transform", "textTransformMenulist", "TextTransformMenu", gDialog.brownFoxLabel) /* INIT TEXT-ALIGN */ SelectsOneChoice("text-align", "textAlignMenulist", "TextAlignMenu", gDialog.brownFoxLabel) /* INIT TEXT-DECORATION */ var textDecoration = getSpecifiedStyle("text-decoration"); AddStyleToElement(gDialog.brownFoxLabel, "text-decoration", textDecoration); SelectsCheckboxIfValueContains(textDecoration, "underline", "underlineTextDecorationCheckbox"); SelectsCheckboxIfValueContains(textDecoration, "overline", "overlineTextDecorationCheckbox"); SelectsCheckboxIfValueContains(textDecoration, "line-through", "linethroughTextDecorationCheckbox"); SelectsCheckboxIfValueContains(textDecoration, "blink", "blinkTextDecorationCheckbox"); SelectsCheckboxIfValueContains(textDecoration, "none", "noneTextDecorationCheckbox"); /* INIT FONT SIZE */ var fontSize = getSpecifiedStyle("font-size"); if (!fontSize || fontSize == "") gDialog.fontSizeInput.value = ""; else gDialog.fontSizeInput.value = fontSize; AddStyleToElement(gDialog.brownFoxLabel, "font-size", fontSize); /* INIT LINE-HEIGHT */ var lineHeight = getSpecifiedStyle("line-height"); if (!lineHeight || lineHeight == "") gDialog.lineHeightInput.value = ""; else gDialog.lineHeightInput.value = lineHeight; } // * Utility function to check if the four side values of a property // are equal so we an show a shorthand in the dialog // param String top // param String left // param String right // param String bottom // return boolean function AreAllFourValuesEqual(top, left, right, bottom) { return (top == left && top == right && top == bottom); } // * Retrieves the specified style for the property |prop| and // makes it become the value of the XUL element of ID |id| // param String id // param String prop function SetTextzoneValue(id, prop) { var elt = document.getElementById(id); if (elt) { var value = getSpecifiedStyle(prop); if (!value) elt.value = ""; else elt.value = value; } } // * Inits the values shown in the Aural tab panel function InitAuralTabPanel() { gDialog.selectedTab = AURAL_TAB; if (!gDialog.selectedObject || !gDialog.selectedObject.style) return; // observe the scrollbar and call onScrollbarAttrModified when an attribute is modified gDialog.volumeScrollbar.removeEventListener("DOMAttrModified", onVolumeScrollbarAttrModified, false); var volume = getSpecifiedStyle("volume"); if (volume == "silent") { gDialog.muteVolumeCheckbox.checked = true; gDialog.volumeScrollbar.setAttribute("disabled", "true"); } else { gDialog.muteVolumeCheckbox.checked = false; gDialog.volumeScrollbar.removeAttribute("disabled"); } // if no volume specified, display medium value if (!volume) volume = "50"; gDialog.volumeMenulist.value = volume; UpdateScrollbar(gDialog.volumeMenulist, 'volumeScrollbar'); gDialog.volumeScrollbar.addEventListener("DOMAttrModified", onVolumeScrollbarAttrModified, false); SelectsOneChoice("speak", "speakMenulist", "SpeakMenu", null); SelectsOneChoice("speech-rate", "speechRateMenulist", "SpeechRateMenu", null); } // * this is a callback of a listener set on the scrollbar for volume setting // param DOMMutationEvent aEvent function onVolumeScrollbarAttrModified(aEvent) { if (aEvent.attrName == "curpos") { var e = gDialog.volumeMenulist; if (e.value == "silent") return; var v = Math.floor(aEvent.newValue / 10); e.value = v; AddStyleToElement(gDialog.selectedObject, "volume", v); SetModifiedFlagOnStylesheet(); } } function onOpacityScrollbarAttrModified(aEvent) { if (aEvent.attrName == "curpos") { var v = aEvent.newValue / 1000; if (v == 1) gDialog.opacityLabel.setAttribute("value", "transparent"); else gDialog.opacityLabel.setAttribute("value", v); AddStyleToElement(gDialog.selectedObject, "opacity", v); SetModifiedFlagOnStylesheet(); } } // * when the user checks the "mute" checkbox, 'silent' should become // the new value of the 'volume' property. If the user unchecks it // the value should be computed from the volume scrollbar's position // param XULElement elt function MuteVolume(elt) { var v; if (elt.checked) { v = "silent"; gDialog.volumeScrollbar.setAttribute("disable", "true"); } else { v = Math.floor(gDialog.volumeScrollbar.getAttribute("curpos") / 10); gDialog.volumeScrollbar.removeAttribute("disable"); } gDialog.volumeMenulist.value = v; AddStyleToElement(gDialog.selectedObject, "volume", v); SetModifiedFlagOnStylesheet(); } // * updates the volume's scrollbar position using the value of the // 'volume' property stored in the value of the XUL element |elt|. // It also converts pre-defined volume names to the equivalent // numerical value (defined in CSS 2 spec) // param XULElement elt // param String id function UpdateScrollbar(elt, id) { var v = elt.value, x = 0; if (v == "silent") return; var e = document.getElementById(id); switch (v) { case "x-soft": x=0; break; case "soft": x=250; break; case "medium": x=500; break; case "loud": x=750; break; case "x-loud": x=1000; break; default: x = parseInt(v) * 10; // if we don't have a number, it must be a pre-defined keyword // and it can't be one because we checked that above if (isNaN(x)) x = 0; break; } // let's update the scrollbar's position e.setAttribute("curpos", x); } // * Inits the values shown in the Box model tab panel function InitBoxTabPanel() { gDialog.selectedTab = BOX_TAB; if (!gDialog.selectedObject || !gDialog.selectedObject.style) return; SelectsOneChoice("display", "displayMenulist", "DisplayMenuitem", null); SelectsOneChoice("visibility", "visibilityMenulist", "VisibilityMenuitem", null); SelectsOneChoice("float", "floatMenulist", "FloatMenuitem", null); SelectsOneChoice("clear", "clearMenulist", "ClearMenuitem", null); SelectsOneChoice("position", "positionMenulist", "PositionMenuitem", null); SelectsOneChoice("overflow", "overflowMenulist", "OverflowMenuitem", null); SetTextzoneValue("zindexInput", "z-index"); SetTextzoneValue("margintopEditableMenulist", "margin-top"); SetTextzoneValue("paddingtopEditableMenulist", "padding-top"); SetTextzoneValue("topEditableMenulist", "top"); SetTextzoneValue("marginleftEditableMenulist", "margin-left"); SetTextzoneValue("paddingleftEditableMenulist", "padding-left"); SetTextzoneValue("leftEditableMenulist", "left"); SetTextzoneValue("marginrightEditableMenulist", "margin-right"); SetTextzoneValue("paddingrightEditableMenulist", "padding-right"); SetTextzoneValue("rightEditableMenulist", "right"); SetTextzoneValue("marginbottomEditableMenulist", "margin-bottom"); SetTextzoneValue("paddingbottomEditableMenulist","padding-bottom"); SetTextzoneValue("bottomEditableMenulist", "bottom"); SetTextzoneValue("widthEditableMenulist", "width"); SetTextzoneValue("minwidthEditableMenulist", "min-width"); SetTextzoneValue("maxwidthEditableMenulist", "max-width"); SetTextzoneValue("heightEditableMenulist", "height"); SetTextzoneValue("minheightEditableMenulist", "min-height"); SetTextzoneValue("maxheightEditableMenulist", "max-height"); } // * Inits the values shown in the Border tab panel function InitBorderTabPanel() { gDialog.selectedTab = BORDER_TAB; if (!gDialog.selectedObject || !gDialog.selectedObject.style) return; /* INIT */ var style = [ getSpecifiedStyle("border-top-style"), getSpecifiedStyle("border-left-style"), getSpecifiedStyle("border-right-style"), getSpecifiedStyle("border-bottom-style") ]; var width = [ getSpecifiedStyle("border-top-width"), getSpecifiedStyle("border-left-width"), getSpecifiedStyle("border-right-width"), getSpecifiedStyle("border-bottom-width") ]; var color = [ ConvertRGBColorIntoHEXColor(getSpecifiedStyle("border-top-color")), ConvertRGBColorIntoHEXColor(getSpecifiedStyle("border-left-color")), ConvertRGBColorIntoHEXColor(getSpecifiedStyle("border-right-color")), ConvertRGBColorIntoHEXColor(getSpecifiedStyle("border-bottom-color")) ]; var sameFourSides = false; // let's see if we have same style/color/width for all four borders if (AreAllFourValuesEqual(style[0], style[1], style[2], style[3]) && AreAllFourValuesEqual(width[0], width[1], width[2], width[3]) && AreAllFourValuesEqual(getHexColorFromColorName(color[0]), getHexColorFromColorName(color[1]), getHexColorFromColorName(color[2]), getHexColorFromColorName(color[3]))) { sameFourSides = true; } var sideArray = [ "top", "left", "right", "bottom" ]; for (var i=0; i 1) cssText += "\n\n"; } var child = ownerNode.lastChild; while (child) { tmp = child.previousSibling; ownerNode.removeChild(child); child = tmp; } var textNode = document.createTextNode(cssText + "\n"); ownerNode.appendChild(textNode); } // * This recreates the textual content of an external stylesheet // param DOMCSSStyleSheet sheet // param String href function SerializeExternalSheet(sheet, href) { const classes = Components.classes; const interfaces = Components.interfaces; const nsILocalFile = interfaces.nsILocalFile; const nsIFileOutputStream = interfaces.nsIFileOutputStream; const FILEOUT_CTRID = '@mozilla.org/network/file-output-stream;1'; var fileHandler = GetFileProtocolHandler(); var localFile; if (href) localFile = fileHandler.getFileFromURLSpec(href).QueryInterface(nsILocalFile); else localFile = fileHandler.getFileFromURLSpec(sheet.href).QueryInterface(nsILocalFile); var fileOuputStream = classes[FILEOUT_CTRID].createInstance(nsIFileOutputStream); try { fileOuputStream.init(localFile, -1, -1, 0); var cssText = "/* Generated by CaScadeS, a stylesheet editor for Mozilla Composer */\n\n"; var l = sheet.cssRules.length, tmp; var re = /;\s*/; var cssTextSplitted, ruleIndex, singleDeclIndex; for (ruleIndex = 0; ruleIndex< l; ruleIndex++) { tmp = sheet.cssRules.item(ruleIndex).cssText; cssTextSplitted = tmp.split(re); cssText += " "; for (singleDeclIndex=0; singleDeclIndex 1) cssText += "\n\n"; } var textNode = document.createTextNode(cssText + "\n"); fileOuputStream.write(cssText, cssText.length); fileOuputStream.close(); } catch (ex) {} } // * if the checkbox of ID |checkboxID| is checked, copies the value |value|, // supposed to be the one for the top side, to the other three sides, makes // the XUL Element |elt| have that value. |propertyBase| and |propertySuffix| // are used to create side properties like in border-*-style. // The property and value are also added to the styles of the element of ID // |previewID| if it not null. // param String propertyBase // param String propertySuffix // param String value // param String checkboxID // param String previewID // param XULElement elt function IfFourSidesSameStyle(propertyBase, propertySuffix, value, checkboxID, previewID, elt) { // value is the value of the '*-top' property var checkbox = document.getElementById(checkboxID); if (!checkbox || !checkbox.checked) return; if (!value) { if (elt) { value = elt.value; } } var xulElt = document.getElementById(previewID); var sideArray = [ "left", "right", "bottom" ]; for (var i=0; i // param XULElement menuPopup function initLocalFontFaceMenu(menuPopup) { if (!menuPopup) return; var menu = menuPopup.parentNode; if (!gLocalFonts) { // Build list of all local fonts once per editor try { var enumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"].createInstance(); if( enumerator ) enumerator = enumerator.QueryInterface(Components.interfaces.nsIFontEnumerator); var localFontCount = { value: 0 } var localFontsString = enumerator.EnumerateAllFonts(localFontCount); if (localFontsString) gLocalFonts = localFontsString.toString().split(","); if (gLocalFonts) { // faces.sort(); Array is already sorted for( var i = 0; i < gLocalFonts.length; i++ ) { if( gLocalFonts[i] != "" ) { var itemNode = document.createElement("menuitem"); itemNode.setAttribute("label", gLocalFonts[i]); //itemNode.value = gLocalFonts[i]; itemNode.setAttribute("value", gLocalFonts[i]); menuPopup.appendChild(itemNode); } } } } catch(e) { } } //SetElementEnabledById("localFontFaceMenu", gLocalFonts != 0); } // * Handles a command in a menulist // param XULElement elt // param String property // param String id function DoMenulistCommand(elt, property, id) { var choice = elt.selectedItem; var value = choice.value; onPullDownChanged(property, value, id); if (property == "border-top-style") { // this one is a special case : we need to check if the checkbox // "all sides have same style" is checked ; if it's checked, make // the other 3 sides acquire the style assigned to the top border IfFourSidesSameStyle('border', 'style', value, 'allFourBordersSame', id, null); } }