123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235 |
- /* vim:set ts=2 sw=2 sts=2 et: */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- /* All top-level definitions here are exports. */
- /* eslint no-unused-vars: [2, {"vars": "local"}] */
- "use strict";
- this.EXPORTED_SYMBOLS = [
- "getString",
- "assert",
- "log",
- "text",
- "wire",
- "showFilePicker"
- ];
- const Cc = Components.classes;
- const Ci = Components.interfaces;
- const Cu = Components.utils;
- const PROPERTIES_URL = "chrome://devtools/locale/styleeditor.properties";
- const {require} = Cu.import("resource://devtools/shared/Loader.jsm", {});
- const Services = require("Services");
- const console = require("resource://gre/modules/Console.jsm").console;
- const gStringBundle = Services.strings.createBundle(PROPERTIES_URL);
- /**
- * Returns a localized string with the given key name from the string bundle.
- *
- * @param name
- * @param ...rest
- * Optional arguments to format in the string.
- * @return string
- */
- function getString(name) {
- try {
- if (arguments.length == 1) {
- return gStringBundle.GetStringFromName(name);
- }
- let rest = Array.prototype.slice.call(arguments, 1);
- return gStringBundle.formatStringFromName(name, rest, rest.length);
- } catch (ex) {
- console.error(ex);
- throw new Error("L10N error. '" + name + "' is missing from " +
- PROPERTIES_URL);
- }
- }
- /**
- * Assert an expression is true or throw if false.
- *
- * @param expression
- * @param message
- * Optional message.
- * @return expression
- */
- function assert(expression, message) {
- if (!expression) {
- let msg = message ? "ASSERTION FAILURE:" + message : "ASSERTION FAILURE";
- log(msg);
- throw new Error(msg);
- }
- return expression;
- }
- /**
- * Retrieve or set the text content of an element.
- *
- * @param DOMElement root
- * The element to use for querySelector.
- * @param string selector
- * Selector string for the element to get/set the text content.
- * @param string textContent
- * Optional text to set.
- * @return string
- * Text content of matching element or null if there were no element
- * matching selector.
- */
- function text(root, selector, textContent) {
- let element = root.querySelector(selector);
- if (!element) {
- return null;
- }
- if (textContent === undefined) {
- return element.textContent;
- }
- element.textContent = textContent;
- return textContent;
- }
- /**
- * Iterates _own_ properties of an object.
- *
- * @param object
- * The object to iterate.
- * @param function callback(aKey, aValue)
- */
- function forEach(object, callback) {
- for (let key in object) {
- if (object.hasOwnProperty(key)) {
- callback(key, object[key]);
- }
- }
- }
- /**
- * Log a message to the console.
- *
- * @param ...rest
- * One or multiple arguments to log.
- * If multiple arguments are given, they will be joined by " "
- * in the log.
- */
- function log() {
- console.logStringMessage(Array.prototype.slice.call(arguments).join(" "));
- }
- /**
- * Wire up element(s) matching selector with attributes, event listeners, etc.
- *
- * @param DOMElement root
- * The element to use for querySelectorAll.
- * Can be null if selector is a DOMElement.
- * @param string|DOMElement selectorOrElement
- * Selector string or DOMElement for the element(s) to wire up.
- * @param object descriptor
- * An object describing how to wire matching selector,
- * supported properties are "events" and "attributes" taking
- * objects themselves.
- * Each key of properties above represents the name of the event or
- * attribute, with the value being a function used as an event handler or
- * string to use as attribute value.
- * If descriptor is a function, the argument is equivalent to :
- * {events: {'click': descriptor}}
- */
- function wire(root, selectorOrElement, descriptor) {
- let matches;
- if (typeof selectorOrElement == "string") {
- // selector
- matches = root.querySelectorAll(selectorOrElement);
- if (!matches.length) {
- return;
- }
- } else {
- // element
- matches = [selectorOrElement];
- }
- if (typeof descriptor == "function") {
- descriptor = {events: {click: descriptor}};
- }
- for (let i = 0; i < matches.length; i++) {
- let element = matches[i];
- forEach(descriptor.events, function (name, handler) {
- element.addEventListener(name, handler, false);
- });
- forEach(descriptor.attributes, element.setAttribute);
- }
- }
- /**
- * Show file picker and return the file user selected.
- *
- * @param mixed file
- * Optional nsIFile or string representing the filename to auto-select.
- * @param boolean toSave
- * If true, the user is selecting a filename to save.
- * @param nsIWindow parentWindow
- * Optional parent window. If null the parent window of the file picker
- * will be the window of the attached input element.
- * @param callback
- * The callback method, which will be called passing in the selected
- * file or null if the user did not pick one.
- * @param AString suggestedFilename
- * The suggested filename when toSave is true.
- */
- function showFilePicker(path, toSave, parentWindow, callback,
- suggestedFilename) {
- if (typeof path == "string") {
- try {
- if (Services.io.extractScheme(path) == "file") {
- let uri = Services.io.newURI(path, null, null);
- let file = uri.QueryInterface(Ci.nsIFileURL).file;
- callback(file);
- return;
- }
- } catch (ex) {
- callback(null);
- return;
- }
- try {
- let file =
- Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
- file.initWithPath(path);
- callback(file);
- return;
- } catch (ex) {
- callback(null);
- return;
- }
- }
- if (path) {
- // "path" is an nsIFile
- callback(path);
- return;
- }
- let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
- let mode = toSave ? fp.modeSave : fp.modeOpen;
- let key = toSave ? "saveStyleSheet" : "importStyleSheet";
- let fpCallback = function (result) {
- if (result == Ci.nsIFilePicker.returnCancel) {
- callback(null);
- } else {
- callback(fp.file);
- }
- };
- if (toSave && suggestedFilename) {
- fp.defaultString = suggestedFilename;
- }
- fp.init(parentWindow, getString(key + ".title"), mode);
- fp.appendFilter(getString(key + ".filter"), "*.css");
- fp.appendFilters(fp.filterAll);
- fp.open(fpCallback);
- return;
- }
|