Bug 1874684 - Part 4: Prefer const references instead of copying Instant values....
[gecko.git] / devtools / client / styleeditor / StyleEditorUtil.sys.mjs
blob11dae675d9ab4ad2b11d2e56d79585eed963e620
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 /* All top-level definitions here are exports.  */
6 /* eslint no-unused-vars: [2, {"vars": "local"}] */
8 const PROPERTIES_URL = "chrome://devtools/locale/styleeditor.properties";
10 import { loader } from "resource://devtools/shared/loader/Loader.sys.mjs";
12 const gStringBundle = Services.strings.createBundle(PROPERTIES_URL);
14 const lazy = {};
16 loader.lazyRequireGetter(
17   lazy,
18   "Menu",
19   "resource://devtools/client/framework/menu.js"
21 loader.lazyRequireGetter(
22   lazy,
23   "MenuItem",
24   "resource://devtools/client/framework/menu-item.js"
27 const PREF_AT_RULES_SIDEBAR = "devtools.styleeditor.showAtRulesSidebar";
28 const PREF_ORIG_SOURCES = "devtools.source-map.client-service.enabled";
30 /**
31  * Returns a localized string with the given key name from the string bundle.
32  *
33  * @param name
34  * @param ...rest
35  *        Optional arguments to format in the string.
36  * @return string
37  */
38 export function getString(name) {
39   try {
40     if (arguments.length == 1) {
41       return gStringBundle.GetStringFromName(name);
42     }
43     const rest = Array.prototype.slice.call(arguments, 1);
44     return gStringBundle.formatStringFromName(name, rest);
45   } catch (ex) {
46     console.error(ex);
47     throw new Error(
48       "L10N error. '" + name + "' is missing from " + PROPERTIES_URL
49     );
50   }
53 /**
54  * Retrieve or set the text content of an element.
55  *
56  * @param DOMElement root
57  *        The element to use for querySelector.
58  * @param string selector
59  *        Selector string for the element to get/set the text content.
60  * @param string textContent
61  *        Optional text to set.
62  * @return string
63  *         Text content of matching element or null if there were no element
64  *         matching selector.
65  */
66 export function text(root, selector, textContent) {
67   const element = root.querySelector(selector);
68   if (!element) {
69     return null;
70   }
72   if (textContent === undefined) {
73     return element.textContent;
74   }
75   element.textContent = textContent;
76   return textContent;
79 /**
80  * Show file picker and return the file user selected.
81  *
82  * @param mixed file
83  *        Optional nsIFile or string representing the filename to auto-select.
84  * @param boolean toSave
85  *        If true, the user is selecting a filename to save.
86  * @param nsIWindow parentWindow
87  *        Optional parent window. If null the parent window of the file picker
88  *        will be the window of the attached input element.
89  * @param callback
90  *        The callback method, which will be called passing in the selected
91  *        file or null if the user did not pick one.
92  * @param AString suggestedFilename
93  *        The suggested filename when toSave is true.
94  */
95 export function showFilePicker(
96   path,
97   toSave,
98   parentWindow,
99   callback,
100   suggestedFilename
101 ) {
102   if (typeof path == "string") {
103     try {
104       if (Services.io.extractScheme(path) == "file") {
105         const uri = Services.io.newURI(path);
106         const file = uri.QueryInterface(Ci.nsIFileURL).file;
107         callback(file);
108         return;
109       }
110     } catch (ex) {
111       callback(null);
112       return;
113     }
114     try {
115       const file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
116       file.initWithPath(path);
117       callback(file);
118       return;
119     } catch (ex) {
120       callback(null);
121       return;
122     }
123   }
124   if (path) {
125     // "path" is an nsIFile
126     callback(path);
127     return;
128   }
130   const fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
131   const mode = toSave ? fp.modeSave : fp.modeOpen;
132   const key = toSave ? "saveStyleSheet" : "importStyleSheet";
133   const fpCallback = function (result) {
134     if (result == Ci.nsIFilePicker.returnCancel) {
135       callback(null);
136     } else {
137       callback(fp.file);
138     }
139   };
141   if (toSave && suggestedFilename) {
142     fp.defaultString = suggestedFilename;
143   }
145   fp.init(parentWindow.browsingContext, getString(key + ".title"), mode);
146   fp.appendFilter(getString(key + ".filter"), "*.css");
147   fp.appendFilters(fp.filterAll);
148   fp.open(fpCallback);
152  * Returns a Popup Menu for the Options ("gear") Button
153  * @param {function} toggleOrigSources
154  *        To toggle the original source pref
155  * @param {function} toggleAtRulesSidebar
156  *        To toggle the pref to show at-rules side bar
157  * @return {object} popupMenu
158  *         A Menu object holding the MenuItems
159  */
160 export function optionsPopupMenu(toggleOrigSources, toggleAtRulesSidebar) {
161   const popupMenu = new lazy.Menu();
162   popupMenu.append(
163     new lazy.MenuItem({
164       id: "options-origsources",
165       label: getString("showOriginalSources.label"),
166       accesskey: getString("showOriginalSources.accesskey"),
167       type: "checkbox",
168       checked: Services.prefs.getBoolPref(PREF_ORIG_SOURCES),
169       click: () => toggleOrigSources(),
170     })
171   );
172   popupMenu.append(
173     new lazy.MenuItem({
174       id: "options-show-at-rules",
175       label: getString("showAtRulesSidebar.label"),
176       accesskey: getString("showAtRulesSidebar.accesskey"),
177       type: "checkbox",
178       checked: Services.prefs.getBoolPref(PREF_AT_RULES_SIDEBAR),
179       click: () => toggleAtRulesSidebar(),
180     })
181   );
183   return popupMenu;