1. Nachrichten
  2. Forum
    1. Unerledigte Themen
    2. Forenregeln
  3. Spenden
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. camp-firefox.de
  2. Mira_Belle

Beiträge von Mira_Belle

  • UserCSSLoader (2025)

    • Mira_Belle
    • 6. Oktober 2025 um 21:56
    Zitat von Mitleser

    Das Script vom 30-9-25

    Verstehe ich jetzt nicht! Erste Beitrag ist vom 29. August 2025 und mehr oder weniger das Skript auch.
    Dann habe ich die nächste Version am 11. September 2025 reingestellt.
    Diese kopiert aus dem UserLoader-Skript Funktionen, bzw, ruft diese auf, weshalb auch dieses Skript vorhanden sein muss.

    Die nächste Version, die ich dann neu reinstellte, kam am 2025.10.05! Das war dann aber nur ein zwischen Release,
    wenn man so will.

  • Eigene Zusatzleisten ab ff 143+

    • Mira_Belle
    • 6. Oktober 2025 um 21:36
    Zitat von Horstmann

    Huh? Nicht am Mac... :/

    Nein Windows 10.
    Und Leiste ist vorhanden, aber eben grau und abgelegte Buttons sind auch nicht mehr zusehen.

    Das mit dem Player muss ich dann noch testen.


    Test abgeschlossen, Youtube Player im Vollbildmodus ohne störende Elemente.

    Zum Skript, es ist bei einem Neustart des FF sichtbar, immer.
    Wäre es nicht schön,
    1. es würde sich den letzten Zustand merken
    und/oder 2. man könnte eine Zeit definieren und die Leise würde wieder weg scrollen.

  • Eigene Zusatzleisten ab ff 143+

    • Mira_Belle
    • 6. Oktober 2025 um 20:47

    AH, jetzt ja!
    Vollbildmodus, da verschwinden die abgelegten "Buttons"!

    Auch wird sie grau, die Leiste.

  • UserCSSLoader (2025)

    • Mira_Belle
    • 6. Oktober 2025 um 20:39

    Mitleser Ich kann Dir da mit dem Skript nicht helfen, aber schau Dir doch mal mein Appmenü-Skript an.

    In der neuen Version habe ich so einige Funktionen übernommen, eventuell hilft Dir das ja weiter.
    Oder Du zerlegst "mein" Skript, wenn es denn funktioniert, und schaust, ob Du da Code übernehmen kannst.

  • extras_config_menu.uc.js = Die CSS-Codes in die Zwischenablage implementieren möglich?

    • Mira_Belle
    • 6. Oktober 2025 um 20:32

    Boersenfeger Ich glaube eher, dass es an Deine Formulierung liegt.

    Ich z.B. verstehe nicht, was genau Du möchtest.

  • Eigene Zusatzleisten ab ff 143+

    • Mira_Belle
    • 6. Oktober 2025 um 20:26

    Dein Skript aus #22 funktioniert hier einwandfrei!
    Auch im max. Modus. Wie teste ich den Vollbildmodus?

    FF Version 143.0.4 (64-Bit)

  • Eigene Zusatzleisten ab ff 143+

    • Mira_Belle
    • 6. Oktober 2025 um 16:15

    Horstmann Könntest Du mal ein Gif oder Video mit dem 115esr machen.
    Möchte ungern einfach so ein Skript installieren, wenn es doch eh nicht funktioniert.

  • Es gibt ältere Versionen dieses Beitrages - warum eigentlich?

    • Mira_Belle
    • 6. Oktober 2025 um 13:05
    Zitat von Foxxiator

    EDIT: Bei XenForo hat man ca 5 Minuten Zeit, bevor der entsprechende Beitrag selbständig als editiert markiert wird. Finde ich gut gelöst...

    Kann man so machen, muss man aber nicht!
    Ich wurde erst "jetzt" auf grobe Rechtschreibfehler in meinen Skripten hingewiesen.
    Da es hier jederzeit möglich ist, ältere Beiträge zu editieren, konnte ich dies schleunigst berichtigen.

    Ist ja peinlich, wenn jemand eins meiner Skripte nutz und denkt ich sei irgendwie doof!
    Ok, bin ich manchmal, aber das ist was anderes.

  • Es gibt ältere Versionen dieses Beitrages - warum eigentlich?

    • Mira_Belle
    • 6. Oktober 2025 um 10:32

    Mh, es gibt nicht die eine gute Lösung! Man könnte das nachträgliche Editieren eines Beitrags sperren,
    wenn darauf schon geantwortet wurde.
    Aber so richtig pralle finde ich das auch nicht.

  • Meine Version des App-Menüs (JavaScript)

    • Mira_Belle
    • 5. Oktober 2025 um 23:24

    Ich bin fertig, aber sowas von!
    Da habe ich mich aber gestern und heute ganz schön was von verbissen!

    Also hier nun die derzeitige finale Version meines Appmenü-Skripts.

    Ich habe es erweitert um die Möglichkeit, die aus dem CSSLoader-Skript bekannt sein dürfte.
    Man kann CSS-Dateien laden und auch wieder entladen.
    Dann habe ich noch die Möglichkeit geschaffen, verschiedene wichtige Konfigurationsdateien,
    wie userChrome.css, userChromeShadow.css, userContent.css, userChrome.js, prefs.js und user.js
    direkt, in einem beliebigen Editor, zu bearbeiten.
    Und dann gibt es noch ein weiteres feature, man kann diverse "about"-Seiten aufrufen.

    JavaScript
    // ==UserScript==
    // @name           Appmenu.uc.js
    // @namespace      Appmenu@gmail.com
    // @description    Basiert auf dem Script externalFuncButtonM.uc.js, Wiederherstellung der Orangenen FF-Menü Schaltfläche
    // @include        main
    // @author         defpt
    // @charset        UTF-8
    // @version        2025.10.05 mit integriertem CSS-Loader-Menü und Konfiguration-Menü,
    // @version        zum dirkten bearbeiten verschiedener Dateien.
    // @version        Sowie der Möglichkeit direkt verschiedene "about:"-Seiten aufrüfen zu können.
    // ==/UserScript==
    
        // Definiere den Profilpfad für die Symbole
        let ProfilePath = PathUtils.toFileURI(
          PathUtils.join(PathUtils.profileDir, 'chrome', 'icons')
        );
        // Standard-Symbol-Dateiname
        let ButtonIcon01 = 'restart.svg';       // Neustart
        let ButtonIcon02 = 'quit.svg';          // Beenden
    
        let Icon01 = 'profile.svg';             // Profil-Verzeichnis
        let Icon02 = 'chrome.svg';              // Chrome-Ordner
        let Icon03 = 'css4.svg';                // CSS-Ordner
        let Icon04 = 'js.svg';                  // JS-Ordner
        let Icon05 = 'folder-plus.svg';         // Icons-Ordner
        let Icon06 = 'addons.svg';              // Addon-Verzeichnis
        let Icon07 = 'folder.svg';              // Programm-Verzeichnis
        let Icon08 = 'folder-1.svg';            // Startup-Cache
    
        let Icon11 = 'Themes.svg';              // Anpassen
        let Icon12 = 'debugging-workers.svg';   // Neustart im abgesicherten Modus
        let Icon13 = 'command-console.svg';     // Browser-Konsole
        let Icon14 = 'window-dev-tools.svg';    // Browser-Werkzeuge
        let Icon15 = 'developer.svg';           // Web-Entwickler
        let Icon16 = 'sync.svg';                // Firefox synchronisieren
        let Icon17 = 'passwords.svg';           // Zugangsdaten und Passwörter
        let Icon18 = 'performance.svg';         // Task Manager
        let Icon19 = 'plug-disconnected.svg';   // Offline arbeiten
    
        let Icon21 = 'firefox.svg';             // about:about
        let Icon22 = 'info.svg';                // about:cache
        let Icon23 = 'settings.svg';            // about:config
        let Icon24 = 'warning.svg';             // about:crashes
        let Icon25 = 'downloads.svg';           // about:downloads
        let Icon26 = 'home.svg';                // about:home
        let Icon27 = 'passwords.svg';           // about:logins
        let Icon28 = 'debugging-workers.svg';   // about:support
        let Icon29 = 'settings.svg';            // about:preferences
        let Icon30 = 'profile.svg';             // about:profiles
    
      var Appmenu = {
        // ■■ START UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
    
        // Editor mit angegebenem Pfad verwenden
        // editor: 'C:\\Program Files\\Notepad++\\notepad++.exe',
        editor: "C:\\Program Files\\Microsoft VS Code\\Code.exe",
        // oder
        // in 'view_source.editor.path' eingetragenen Editor verwenden
        //  editor: Services.prefs.getCharPref('view_source.editor.path'),
        // Dateimanager mit angegebenem Pfad verwenden oder leer ('') wenn System-Dateimanager verwenden
        //fileManager: 'C:\\Program files\\FreeCommander XE\\FreeCommander.exe',
        fileManager: "",
        // Parameter für Dateimanager oder leer ('')
        //FMParameter: '/T',
        FMParameter: "",
        // Submenüs ohne Inhalt im Hauptmenü automatisch ausblenden
        autohideEmptySubDirs: true,
        // Submenüs im Hauptmenü nach unten verschieben
        moveSubDirstoBottom: false,
        // Ort und Aussehen des Menü-Buttons einstellen
        //   isUrlbar: 1,  // 0: TabsToolbar; 1: navbar,
        isUrlbar: 2, // 0: TabsToolbar; 1: navbar; 2: toolbar-menubar
        isButton: 0, // 0: Hamburger,klein; 1: Firefox,groß,
        // Hotkey zum Öffnen des Appmenüs oder leer ('')
        hotkey: "f",
        hotkeyModifier: "alt",
    
        // ■■ END UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
    
        // Submenüs im Hauptmenü nach unten verschieben
        subdirPopupHash: [],
        subdirMenuHash: [],
    
        // CSS-Loader-Funktionen (integriert)
        cssLoader: {
            AGENT_SHEET: Ci.nsIStyleSheetService.AGENT_SHEET,
            USER_SHEET: Ci.nsIStyleSheetService.USER_SHEET,
            AUTHOR_SHEET: Ci.nsIStyleSheetService.AUTHOR_SHEET,
            readCSS: {},
    
            get prefs() {
                delete this.prefs;
                return this.prefs = Services.prefs.getBranch("UserCSSLoader.");
            },
    
            get disabled_list() {
                try {
                    return JSON.parse(this.prefs.getCharPref("disabled_css_list")) || [];
                } catch (e) {
                    return [];
                }
            },
    
            set disabled_list(list) {
                this.prefs.setCharPref("disabled_css_list", JSON.stringify(list));
            },
    
            get FOLDER() {
                let aFolder = Services.dirsvc.get("UChrm", Ci.nsIFile);
                aFolder.appendRelativePath("CSS");
                if (!aFolder.exists() || !aFolder.isDirectory()) {
                    aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664);
                }
                delete this.FOLDER;
                return this.FOLDER = aFolder;
            },
    
            initCSSLoader: function() {
                this.rebuildCSSMenu();
            },
    
            rebuildCSSMenu: function() {
                let ext = /\.css$/i;
                let not = /\.uc\.css/i;
                let files = this.FOLDER.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
                let popup = Appmenu.subdirPopupHash["CSS-Loader-Menü"];
    
                // Vorhandene Einträge löschen
                while (popup && popup.firstChild) {
                    popup.removeChild(popup.firstChild);
                }
    
                // Neue Einträge erstellen
                while (files.hasMoreElements()) {
                    let file = files.getNext().QueryInterface(Ci.nsIFile);
                    if (!ext.test(file.leafName) || not.test(file.leafName)) continue;
    
                    let CSS = this.loadCSS(file);
                    let menuitem = document.createElementNS(
                        "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
                        "menuitem"
                    );
                    menuitem.setAttribute("label", file.leafName);
                    menuitem.setAttribute("id", "appmenu-css-" + file.leafName);
                    menuitem.setAttribute("class", "menuitem-iconic");
                    menuitem.setAttribute("type", "checkbox");
                    menuitem.setAttribute("autocheck", "false");
                    menuitem.setAttribute("checked", CSS.enabled);
                    // Icon basierend auf dem Zustand setzen
                    if (CSS.enabled) {
                        menuitem.setAttribute("image", ""); // Standard-Häkchen (kein Icon)
                    } else {
                        menuitem.setAttribute("image", `${ProfilePath}/stop_smal_red.svg`); // Rotes Stop-Icon
                    }
                    menuitem.setAttribute("tooltiptext", "Linksklick: an/aus, Mittelklick: an/aus (Menü bleibt offen), Rechtsklick: bearbeiten");
    
                    menuitem.addEventListener("command", () => this.toggleCSS(file.leafName));
                    menuitem.addEventListener("click", (event) => this.cssItemClick(event, file.leafName));
    
                    if (popup) {
                        popup.appendChild(menuitem);
                    }
                }
            },
    
            loadCSS: function(aFile) {
                let CSS = this.readCSS[aFile.leafName];
                if (!CSS) {
                    CSS = this.readCSS[aFile.leafName] = new CSSEntry(aFile);
                    // Standardmäßig aktiviert, außer sie ist in disabled_list
                    CSS.enabled = !this.disabled_list.includes(aFile.leafName);
                }
                return CSS;
            },
    
            toggleCSS: function(aLeafName) {
                let CSS = this.readCSS[aLeafName];
                if (!CSS) return;
    
                CSS.enabled = !CSS.enabled;
    
                // Aktualisiere disabled_list
                let currentDisabledList = this.disabled_list;
                if (CSS.enabled) {
                    currentDisabledList = currentDisabledList.filter(name => name !== aLeafName);
                } else {
                    if (!currentDisabledList.includes(aLeafName)) {
                        currentDisabledList.push(aLeafName);
                    }
                }
                this.disabled_list = currentDisabledList;
    
                // Aktualisiere das Häkchen im Menü
                let menuitem = document.getElementById("appmenu-css-" + aLeafName);
                if (menuitem) {
                  menuitem.setAttribute("checked", CSS.enabled);
                  if (CSS.enabled) {
                      menuitem.setAttribute("image", ""); // Standard-Häkchen
                  } else {
                      menuitem.setAttribute("image", `${ProfilePath}/stop_smal_red.svg`); // Rotes Stop-Icon
                  }
                }
            },
    
            cssItemClick: function(event, aLeafName) {
                event.preventDefault();
                event.stopPropagation();
                if (event.button === 0) {
                    return;
                } else if (event.button === 1) {
                    this.toggleCSS(aLeafName);
                } else if (event.button === 2) {
                    let file = this.getFileFromLeafName(aLeafName);
                    this.editCSS(file);
                }
            },
    
            getFileFromLeafName: function(aLeafName) {
                let f = this.FOLDER.clone();
                f.QueryInterface(Ci.nsIFile);
                f.appendRelativePath(aLeafName);
                return f;
            },
    
            editCSS: function(aFile) {
                let editor = cssLoaderConfig.Editor || Services.prefs.getCharPref("view_source.editor.path");
                if (!editor) {
                    alert('Kein Editor konfiguriert! Bitte in about:config unter "view_source.editor.path" einen Editor eintragen.');
                    return;
                }
                try {
                    let UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
                    UI.charset = window.navigator.platform.toLowerCase().includes("win") ? "Shift_JIS" : "UTF-8";
                    let path = UI.ConvertFromUnicode(aFile.path);
                    let app = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
                    app.initWithPath(editor);
                    let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
                    process.init(app);
                    process.run(false, [path], 1);
                } catch (e) {
                    console.error("Fehler beim Öffnen des Editors:", e);
                }
            },
        },
    
        toolbar: {
          subdirs: [
            {
              name: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/folder_currentColor.svg`,
            },
            {
              name: 'Firefox Funktionen',
              image: `${ProfilePath}/settings_currentColor.svg`,
            },
            {
              name: 'separator',
            },
            {
              name: 'CSS-Loader-Menü', // CSS-Loader-Menü
              image: `${ProfilePath}/css4_currentColor.svg`,
            },
            {
              name: 'Konfiguration',
              image: `${ProfilePath}/Hammer-wrench_currentColor.svg`,
            },
            {
              name: '"about:"-Seiten',
              image: `${ProfilePath}/firefox_currentColor.svg`,
            },
          ],
    
          apps: [
            {
              name: 'Profil-Verzeichnis',
              id: 'AMProfil',
              root: 'ProfD',
              path: '\\',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon01}`,
            },
            {
              name: 'Chrome-Ordner',
              id: 'AMchrome',
              root: 'ProfD',
              path: '\\chrome',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon02}`,
            },
            {
              name: 'CSS-Ordner',
              id: 'AMCSS',
              root: 'ProfD',
              path: '\\chrome\\css',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon03}`,
            },
            {
              name: 'JS-Ordner',
              id: 'AMJS',
              root: 'ProfD',
              path: '\\chrome\\scripts',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon04}`,
            },
            {
              name: 'Icons-Ordner',
              id: 'AMICO',
              root: 'ProfD',
              path: '\\chrome\\icons',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon05}`,
            },
            {
              name: 'Addon-Verzeichnis',
              id: 'AMAddons',
              root: 'ProfD',
              path: '\\extensions',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon06}`,
            },
            {
              name: 'Programm-Verzeichnis',
              id: 'AMProgramm',
              root: 'CurProcD',
              path: '\\',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon07}`,
            },
            {
              name: 'Startup-Cache',
              id: 'AMCache',
              root: 'ProfLD',
              path: '\\startupCache',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon08}`,
            },
          ],
    
          configs: [
            {
              name: 'Anpassen',
              id: 'AMAnpassen',
              command: 'gCustomizeMode.enter()',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon11}`,
            },
            {
              name: 'Neustart im abgesicherten Modus',
              id: 'AMModus',
              command: 'safeModeRestart();',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon12}`,
            },
            {
              name: 'Browser-Konsole',
              id: 'AMKonsole',
              command: 'goKonsole',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon13}`,
            },
            {
              name: 'Browser-Werkzeuge',
              id: 'AMWerkzeuge',
              command: 'goWerkzeuge',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon14}`,
            },
            {
              name: 'Web-Entwickler',
              id: 'AMEntwickler',
              command: 'goEntwickler',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon15}`,
            },
            {
              name: 'Firefox synchronisieren',
              id: 'AMsynchron',
              command: 'gSync',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon16}`,
            },
            {
              name: 'Zugangsdaten und Passwörter',
              id: 'AMdaten',
              command: 'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })',
              tooltiptext: 'about:logins',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon17}`,
            },
            {
              name: 'Task Manager',
              id: 'AMManager',
              command: 'switchToTabHavingURI("about:processes", true)',
              tooltiptext: 'about:processes',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon18}`,
            },
            {
              name: 'Offline arbeiten',
              id: 'AMOffline',
              command: 'BrowserOffline.toggleOfflineStatus();',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon19}`,
            },
            {
              name: 'Neustart',
              id: 'AMreboot',
              tooltiptext: 'userChrome.js-Cache wird geleert',
              command: 'goReeboot',
              image: `${ProfilePath}/${ButtonIcon01}`,
            },
            {
              name: 'Beenden',
              id: 'AMquit',
              command: 'goQuitApplication(event);',
              image: `${ProfilePath}/${ButtonIcon02}`,
            },
            // uProfMenu-Funktionen unter Menüeintrag "Konfiguration"
            {
              name: 'userChrome.css bearbeiten',
              id: 'AMuserChromeCss',
              command: () => Appmenu.edit(0, 'userChrome.css'),
              subdir: 'Konfiguration',
              image: `${ProfilePath}/css4.svg`,
            },
            {
              name: 'userChromeShadow.css bearbeiten',
              id: 'AMuserChromeShadowCss',
              command: () => Appmenu.edit(0, 'userChromeShadow.css'),
              subdir: 'Konfiguration',
              image: `${ProfilePath}/css4.svg`,
            },
            {
              name: 'userContent.css bearbeiten',
              id: 'AMuserContentCss',
              command: () => Appmenu.edit(0, 'userContent.css'),
              subdir: 'Konfiguration',
              image: `${ProfilePath}/css4.svg`,
            },
            {
              name: 'userChrome.js bearbeiten',
              id: 'AMuserChromeJs',
              command: () => Appmenu.edit(0, 'userChrome.js'),
              subdir: 'Konfiguration',
              image: `${ProfilePath}/js.svg`,
            },
            {
              name: 'prefs.js bearbeiten',
              id: 'AMprefsJs',
              command: () => Appmenu.edit(1, 'prefs.js'),
              subdir: 'Konfiguration',
              image: `${ProfilePath}/js.svg`,
            },
            {
              name: 'user.js bearbeiten',
              id: 'AMuserJs',
              command: () => Appmenu.edit(1, 'user.js'),
              subdir: 'Konfiguration',
              image: `${ProfilePath}/js.svg`,
            },
            // about:-Seiten
            {
              name: 'about:about',
              id: 'AMaboutAbout',
              command: () => openTrustedLinkIn("about:about", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon21}`,
            },
            {
              name: 'about:cache',
              id: 'AMaboutCache',
              command: () => openTrustedLinkIn("about:cache", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon22}`,
            },
            {
              name: 'about:config',
              id: 'AMaboutConfig',
              command: () => openTrustedLinkIn("about:config", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon23}`,
            },
            {
              name: 'about:crashes',
              id: 'AMaboutCrashes',
              command: () => openTrustedLinkIn("about:crashes", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon24}`,
            },
            {
              name: 'about:downloads',
              id: 'AMaboutDownloads',
              command: () => openTrustedLinkIn("about:downloads", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon25}`,
            },
            {
              name: 'about:home',
              id: 'AMaboutHome',
              command: () => openTrustedLinkIn("about:home", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon26}`,
            },
            {
              name: 'about:logins',
              id: 'AMaboutLogins',
              command: 'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon27}`,
            },
            {
              name: 'about:support',
              id: 'AMaboutSupport',
              command: () => openTrustedLinkIn("about:support", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon28}`,
            },
            {
              name: 'about:preferences',
              id: 'AMaboutPreferences',
              command: () => openTrustedLinkIn("about:preferences", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon29}`,
            },
            {
              name: 'about:profiles',
              id: 'AMaboutProfiles',
              command: () => openTrustedLinkIn("about:profiles", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon30}`,
            },
          ]
        },
        _externalAppPopup: null,
        _isready: false,
    
        // uProfMenu-Funktionen (bereits integriert)
        getDirSep: function() {
          var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS;
          var dirsep = "/";
          switch(osString) {
            case "WINNT":
              dirsep = "\\";
              break;
            case "Darwin":
              dirsep = "/";
              break;
          }
          return dirsep;
        },
        getPrefDirectoryPath: function(str) {
          var file = Components.classes["@mozilla.org/file/directory_service;1"]
            .getService(Components.interfaces.nsIProperties)
            .get(str, Components.interfaces.nsIFile);
          if (str == 'CurProcD') {
            file = file.parent;
          }
          return file.path;
        },
        edit: function(OpenMode, Filename) {
          var Path = "";
          var dSep = this.getDirSep();
          switch (OpenMode) {
            case 0:
              Path = this.getPrefDirectoryPath("UChrm") + dSep + Filename;
              break;
            case 1:
              Path = this.getPrefDirectoryPath("ProfD") + dSep + Filename;
              break;
          }
          this.launch(this.editor, Path);
        },
        launch: function(RanPath, OpenPath) {
          var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIFile);
          var proc = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
          var args = [OpenPath];
          file.initWithPath(RanPath);
          if (!file.exists()) {
            var pref = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
            RanPath = pref.getCharPref("view_source.editor.path");
            file.initWithPath(RanPath);
          }
          proc.init(file);
          proc.run(false, args, args.length);
        },
    
        init: function() {
          this.handleRelativePath(this.toolbar.apps);
          const XULNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
          var ExternalAppBtn = document.createElementNS(XULNS, 'toolbarbutton');
          ExternalAppBtn.id = 'AppMenuButton';
          ExternalAppBtn.setAttribute('label', 'AppButton');
          ExternalAppBtn.addEventListener('click', event => {
            event.preventDefault();
            event.stopPropagation();
          });
          ExternalAppBtn.setAttribute('tooltiptext', 'Firefox Menü');
          ExternalAppBtn.setAttribute('type', 'menu');
          ExternalAppBtn.setAttribute('removable', 'true');
    
          let ProfilePath = PathUtils.toFileURI(
            PathUtils.join(PathUtils.profileDir, 'chrome', 'image')
          );
    
          let DefaultIcon = 'Button_groß.png';
          let AlternateIcon = 'Button_klein-5.png';
          if (Appmenu.isButton) {
            ExternalAppBtn.style.listStyleImage = `url('${ProfilePath}/${DefaultIcon}')`;
            ExternalAppBtn.style.width = '94px';
            ExternalAppBtn.style.height = '24px';
          } else {
            ExternalAppBtn.style.listStyleImage = `url('${ProfilePath}/${AlternateIcon}')`;
            ExternalAppBtn.style.width = '48px';
            ExternalAppBtn.style.height = '21px';
          }
    
          if (Appmenu.isUrlbar === 1) {
            var navBar = document.getElementById('nav-bar-customization-target');
            navBar.insertBefore(ExternalAppBtn, navBar.firstChild);
          } else if (Appmenu.isUrlbar === 2) {
            var menubar = document.getElementById('toolbar-menubar');
            menubar.insertBefore(ExternalAppBtn, menubar.firstChild);
          } else {
            var TabsToolbar = document.getElementById('TabsToolbar');
            TabsToolbar.insertBefore(ExternalAppBtn, TabsToolbar.firstChild);
          }
          var ExternalAppPopup = document.createElementNS(XULNS, 'menupopup');
          ExternalAppPopup.addEventListener('click', event => {
            event.stopPropagation();
          });
          ExternalAppPopup.setAttribute('id', 'AMpopup');
          this._externalAppPopup = ExternalAppPopup;
          ExternalAppBtn.appendChild(ExternalAppPopup);
          Appmenu.onpopupshowing();
    
          // CSS-Loader initialisieren
          this.cssLoader.initCSSLoader();
    
          // Menü mit Tastaturkürzel öffnen
          if (Appmenu.hotkey) {
            let key = document.createXULElement('key');
            key.id = 'key_AppMenuPopup';
            key.setAttribute('key', Appmenu.hotkey);
            if (Appmenu.hotkeyModifier)
              key.setAttribute('modifiers', Appmenu.hotkeyModifier);
            key.addEventListener('command', function () {
              document.getElementById('AMpopup').openPopup();
            });
            document.getElementById('mainKeyset').appendChild(key);
          }
        },
    
        onpopupshowing: function() {
          if (this._isready) return;
          if (this._externalAppPopup === null) return;
          var ExternalAppPopup = this._externalAppPopup;
          for (let subdir of this.toolbar.subdirs) {
            if (subdir.name == 'separator') {
              ExternalAppPopup.appendChild(document.createXULElement('menuseparator'));
            } else {
              var subdirItem = ExternalAppPopup.appendChild(document.createXULElement('menu'));
              var subdirItemPopup = subdirItem.appendChild(document.createXULElement('menupopup'));
              subdirItem.setAttribute('class', 'menu-iconic');
              subdirItem.setAttribute('label', subdir.name);
              subdirItem.setAttribute('image', subdir.image);
              Appmenu.subdirPopupHash[subdir.name] = subdirItemPopup;
              Appmenu.subdirMenuHash[subdir.name] = subdirItem;
    
              // CSS-Loader-Menüeinträge für "CSS-Loader-Menü"
              if (subdir.name === "CSS-Loader-Menü") {
                Appmenu.cssLoader.rebuildCSSMenu();
              }
            }
          }
          for (let app of this.toolbar.apps) {
            var appItem;
            if (app.name == 'separator') {
              appItem = document.createXULElement('menuseparator');
            } else {
              appItem = document.createXULElement('menuitem');
              appItem.setAttribute('class', 'menuitem-iconic');
              appItem.setAttribute('label', app.name);
              appItem.setAttribute('image', app.image);
              appItem.addEventListener('command', function () {
                Appmenu.exec(this.path, this.args);
              });
              appItem.setAttribute('tooltiptext', app.name);
              appItem.path = app.path;
              appItem.args = app.args;
            }
            if (app.subdir && Appmenu.subdirPopupHash[app.subdir])
              Appmenu.subdirPopupHash[app.subdir].appendChild(appItem);
            else ExternalAppPopup.appendChild(appItem);
          }
          for (let config of this.toolbar.configs) {
            var configItem;
            if (config.name == 'separator') {
              configItem = document.createXULElement('menuseparator');
            } else {
              configItem = ExternalAppPopup.appendChild(document.createXULElement('menuitem'));
              configItem.setAttribute('class', 'menuitem-iconic');
              configItem.setAttribute('label', config.name);
              configItem.setAttribute('image', config.image);
              configItem.addEventListener('command', () => {
                if (typeof config.command === 'function') {
                  config.command();
                } else {
                  Appmenu.executeCommand(config.command);
                }
              });
              if (config.tooltiptext) {
                configItem.setAttribute('tooltiptext', config.tooltiptext);
              } else {
                configItem.setAttribute('tooltiptext', config.name);
              }
              configItem.setAttribute('id', config.id);
            }
    
            if (config.subdir && Appmenu.subdirPopupHash[config.subdir]) {
              Appmenu.subdirPopupHash[config.subdir].appendChild(configItem);
            } else {
              ExternalAppPopup.appendChild(configItem);
            }
          }
          if (this.autohideEmptySubDirs) {
            for (let i = 0; i < Appmenu.subdirPopupHash.length; i++) {
              if (Appmenu.subdirPopupHash[i].hasChildNodes()) {
                continue;
              } else {
                Appmenu.subdirMenuHash[i].setAttribute('hidden', 'true');
              }
            }
          }
          if (this.moveSubDirstoBottom) {
            let i = ExternalAppPopup.childNodes.length;
            while (ExternalAppPopup.firstChild.getAttribute('class') != 'menuitem-iconic' && i-- != 0) {
              ExternalAppPopup.appendChild(ExternalAppPopup.firstChild);
            }
          }
          this._isready = true;
        },
    
        executeCommand: function(command) {
          const commandMap = {
            'gCustomizeMode.enter()': () => gCustomizeMode.enter(),
            'safeModeRestart();': () => safeModeRestart(),
            'goKonsole': () => {
                    var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                    var { BrowserConsoleManager } = require('resource://devtools/client/webconsole/browser-console-manager');
                    BrowserConsoleManager.openBrowserConsoleOrFocus();
                  },
            'goWerkzeuge': () => {
                    var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                    var { BrowserToolboxLauncher } = require('resource://devtools/client/framework/browser-toolbox/Launcher.sys.mjs');
                    BrowserToolboxLauncher.init();
                  },
            'goEntwickler': () => {
                    var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                    var { gDevToolsBrowser } = require('resource://devtools/client/framework/devtools-browser');
                    gDevToolsBrowser.toggleToolboxCommand(window.gBrowser, performance.now());
                  },
            'gSync': () => gSync.openPrefs('menubar'),
            'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })': () => LoginHelper.openPasswordManager(window, { entryPoint: 'mainmenu' }),
            'switchToTabHavingURI("about:processes", true)': () => switchToTabHavingURI('about:processes', true),
            'BrowserOffline.toggleOfflineStatus();': () => BrowserOffline.toggleOfflineStatus(),
            'goReeboot': () => {
                      Services.appinfo.invalidateCachesOnRestart();
                      Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit);
                    },
            'goQuitApplication(event);': () => goQuitApplication(event),
          };
          if (commandMap[command]) {
            commandMap[command]();
          } else {
            console.warn('Unbekannter Befehl: ', command);
          }
        },
    
        handleRelativePath: function(apps) {
          for (let app of apps) {
            if (app.path) {
              app.path = app.path.replace(/\//g, '\\');
              var ffdir = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties).get(app.root, Ci.nsIFile).path;
              if (/^(\\)/.test(app.path)) {
                app.path = ffdir + app.path;
              }
            }
          }
        },
    
        exec: function(path, args) {
          args = args || [];
          var args_t = args.slice(0);
          for (let arg of args_t) {
            arg = arg.replace(/%u/g, gBrowser.currentURI.spec);
          }
          var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
          file.initWithPath(path);
          if (!file.exists()) {
            alert('Datei nicht gefunden: ' + path);
            return;
          }
          if (file.isExecutable() && !path.endsWith('.js')) {
            var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
            process.init(file);
            process.run(false, args_t, args_t.length);
          } else if (file.isFile()) {
            if (this.editor) {
              let UI = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Ci.nsIScriptableUnicodeConverter);
              UI.charset = window.navigator.platform.toLowerCase().includes('win') ? 'Shift_JIS' : 'UTF-8';
              let path = UI.ConvertFromUnicode(file.path);
              let app = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
              app.initWithPath(this.editor);
              let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
              process.init(app);
              process.run(false, [path], 1);
            } else {
              file.launch();
            }
          } else if (file.isDirectory()) {
            if (this.fileManager) {
              let args=[this.FMParameter,path];
              let app = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
              app.initWithPath(this.fileManager);
              let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
              process.init(app);
              process.run(false, args, args.length);
            } else {
              file.launch();
            }
          }
        },
      };
    
    /* ***************************************************************************************************************************** */
    /* ***************************************************************************************************************************** */
    /* ***************************************************************************************************************************** */
    /* ***************************************************************************************************************************** */
    /* ***************************************************************************************************************************** */
    /* ***************************************************************************************************************************** */
    /* ***************************************************************************************************************************** */
    /* ***************************************************************************************************************************** */
    
      // CSSEntry-Klasse (aus UserCSSLoader)
      function CSSEntry(aFile) {
        this.path = aFile.path;
        this.leafName = aFile.leafName;
        this.lastModifiedTime = 1;
        this.SHEET = /^xul-|\.as\.css$/i.test(this.leafName) ?
          Ci.nsIStyleSheetService.AGENT_SHEET :
          /\.author\.css$/i.test(this.leafName) ?
            Ci.nsIStyleSheetService.AUTHOR_SHEET :
            Ci.nsIStyleSheetService.USER_SHEET;
      }
    
      CSSEntry.prototype = {
        sss: Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService),
        _enabled: false,
        get enabled() {
          return this._enabled;
        },
        set enabled(isEnable) {
            let aFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
            aFile.initWithPath(this.path);
            let isExists = aFile.exists();
            let lastModifiedTime = isExists ? aFile.lastModifiedTime : 0;
            let isForced = this.lastModifiedTime != lastModifiedTime;
            let fileURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromActualFile(aFile);
            let uri = Services.io.newURI(fileURL, null, null);
    
            if (this.sss.sheetRegistered(uri, this.SHEET)) {
                if (!isEnable || !isExists) {
                    this.sss.unregisterSheet(uri, this.SHEET);
                } else if (isForced) {
                    this.sss.unregisterSheet(uri, this.SHEET);
                    this.sss.loadAndRegisterSheet(uri, this.SHEET);
                }
            } else {
                if (isEnable && isExists) {
                    this.sss.loadAndRegisterSheet(uri, this.SHEET);
                }
            }
    
            this.lastModifiedTime = lastModifiedTime;
            return this._enabled = isEnable;
        },
      };
    
      (function () {
        let sss = Components.classes['@mozilla.org/content/style-sheet-service;1'].getService(Components.interfaces.nsIStyleSheetService);
        let uri = Services.io.newURI(
          'data:text/css;charset=utf-8,' +
            encodeURIComponent(`
              menuitem[label="Profil-Verzeichnis"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label="Chrome-Ordner"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label="CSS-Ordner"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label="JS-Ordner"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label="Icons-Ordner"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label="Addon-Verzeichnis"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label="Programm-Verzeichnis"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label="Startup-Cache"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
    
              #AMAnpassen     { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMModus        { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMKonsole      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMWerkzeuge    { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMEntwickler   { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMsynchron     { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMdaten        { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMManager      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMOffline      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
    
              /* Neustart-Button */
              #AMreboot { -moz-context-properties: fill, fill-opacity !important; fill: #fbc96e !important; padding-left: 10px !important; }
              #AMreboot > img:nth-child(1) { width: 20px !important; height: 20px !important; }
              /* Beenden-Button */
              #AMquit { -moz-context-properties: fill, fill-opacity !important; fill: red !important; }
    
              /* about:-Seiten */
              #AMaboutAbout        { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutCache        { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutConfig       { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutCrashes      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutDownloads    { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutHome         { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutLogins       { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutSupport      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutPreferences  { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutProfiles     { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
    
              /* uProfMenu-Einträge */
              #AMuserChromeCss      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMuserChromeShadowCss { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMuserContentCss     { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMuserChromeJs      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMprefsJs            { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMuserJs             { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
    
              /* 1 */
              menuitem[subdir="CSS-Loader-Menü"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #appmenu-css-CSS-Ordner-öffnen { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
            `),
          null,
          null
        );
        sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
      })();
    
      if (window.gBrowser) Appmenu.init();
    Alles anzeigen

    Funktioniert sogar in der Nightly 145.0a1 (2025-10-05) ohne Fehlermeldungen in der Konsole. ;)

  • Meine Version des App-Menüs (JavaScript)

    • Mira_Belle
    • 5. Oktober 2025 um 17:44

    Hat doch etwas gedauert.

    JavaScript
    // ==UserScript==
    // @name           Appmenu.uc.js
    // @namespace      Appmenu@gmail.com
    // @description    Basiert auf dem Script externalFuncButtonM.uc.js, Wiederherstellung der Orangenen FF-Menü Schaltfläche
    // @include        main
    // @author         defpt
    // @charset        UTF-8
    // @version        2025.10.07 Integrierte uProfMenu-Funktionen in Menüeintrag "Konfiguration"
    // ==/UserScript==
    
        // Definiere den Profilpfad für die Symbole
        let ProfilePath = PathUtils.toFileURI(
          PathUtils.join(PathUtils.profileDir, 'chrome', 'icons')
        );
        // Standard-Symbol-Dateiname
        let ButtonIcon01 = 'restart.svg';       // Neustart
        let ButtonIcon02 = 'quit.svg';          // Beenden
    
        let Icon01 = 'profile.svg';             // Profil-Verzeichnis
        let Icon02 = 'chrome.svg';              // Chrome-Ordner
        let Icon03 = 'css4.svg';                // CSS-Ordner
        let Icon04 = 'js.svg';                  // JS-Ordner
        let Icon05 = 'folder-plus.svg';         // Icons-Ordner
        let Icon06 = 'addons.svg';              // Addon-Verzeichnis
        let Icon07 = 'folder.svg';              // Programm-Verzeichnis
        let Icon08 = 'folder-1.svg';            // Startup-Cache
    
        let Icon11 = 'Themes.svg';              // Anpassen
        let Icon12 = 'debugging-workers.svg';   // Neustart im abgesicherten Modus
        let Icon13 = 'command-console.svg';     // Browser-Konsole
        let Icon14 = 'window-dev-tools.svg';    // Browser-Werkzeuge
        let Icon15 = 'developer.svg';           // Web-Entwickler
        let Icon16 = 'sync.svg';                // Firefox synchronisieren
        let Icon17 = 'passwords.svg';           // Zugangsdaten und Passwörter
        let Icon18 = 'performance.svg';         // Task Manager
        let Icon19 = 'plug-disconnected.svg';   // Offline arbeiten
        let Icon21 = 'firefox.svg';             // about:about
        let Icon22 = 'info.svg';                // about:cache
        let Icon23 = 'settings.svg';            // about:config
        let Icon24 = 'warning.svg';             // about:crashes
        let Icon25 = 'downloads.svg';           // about:downloads
        let Icon26 = 'home.svg';                // about:home
        let Icon27 = 'passwords.svg';           // about:logins
        let Icon28 = 'debugging-workers.svg';   // about:support
        let Icon29 = 'settings.svg';            // about:preferences
        let Icon30 = 'profile.svg';             // about:profiles
    
      var Appmenu = {
        // ■■ START UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
    
           // Editor mit angegebenem Pfad verwenden
        // editor: 'C:\\Program Files\\Notepad++\\notepad++.exe',
        editor: "C:\\Program Files\\Microsoft VS Code\\Code.exe",
        // oder
        // in 'view_source.editor.path' eingetragenen Editor verwenden
        editor: Services.prefs.getCharPref('view_source.editor.path'),
        // Dateimanager mit angegebenem Pfad verwenden oder leer ('') wenn System-Dateimanager verwenden
        //fileManager: 'C:\\Program files\\FreeCommander XE\\FreeCommander.exe',
        fileManager: "",
        // Parameter für Dateimanager oder leer ('')
        //FMParameter: '/T',
        FMParameter: "",
        // Submenüs ohne Inhalt im Hauptmenü automatisch ausblenden
        autohideEmptySubDirs: true,
        // Submenüs im Hauptmenü nach unten verschieben
        moveSubDirstoBottom: false,
        // Ort und Aussehen des Menü-Buttons einstellen
        //   isUrlbar: 1,  // 0: TabsToolbar; 1: navbar,
        isUrlbar: 2, // 0: TabsToolbar; 1: navbar; 2: toolbar-menubar
        isButton: 0, // 0: Hamburger,klein; 1: Firefox,groß,
        // Hotkey zum Öffnen des Appmenüs oder leer ('')
        hotkey: "f",
        hotkeyModifier: "alt",
    
        TextOpenExe: 'C:\\Program Files\\Microsoft VS Code\\Code.exe', // Pfad zum Editor (aus uProfMenu)
        // ■■ END UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
    
        // Submenüs im Hauptmenü nach unten verschieben
        subdirPopupHash: [],
        subdirMenuHash: [],
    
        toolbar: {
          subdirs: [
            {
              name: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/folder_currentColor.svg`,
            },
            {
              name: 'Firefox Funktionen',
              image: `${ProfilePath}/settings_currentColor.svg`,
            },
            {
              name: 'separator',
            },
            {
              name: '1',
              image: `${ProfilePath}/1.svg`,
            },
            {
              name: 'Konfiguration',
              image: `${ProfilePath}/Hammer-wrench_currentColor.svg`,
            },
            {
              name: '"about:"-Seiten',
              image: `${ProfilePath}/firefox_currentColor.svg`,
            },
          ],
    
          apps: [
            {
              name: 'Profil-Verzeichnis',
              id: 'AMProfil',
              root: 'ProfD',
              path: '\\',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon01}`,
            },
            {
              name: 'Chrome-Ordner',
              id: 'AMchrome',
              root: 'ProfD',
              path: '\\chrome',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon02}`,
            },
            {
              name: 'CSS-Ordner',
              id: 'AMCSS',
              root: 'ProfD',
              path: '\\chrome\\css',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon03}`,
            },
            {
              name: 'JS-Ordner',
              id: 'AMJS',
              root: 'ProfD',
              path: '\\chrome\\scripts',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon04}`,
            },
            {
              name: 'Icons-Ordner',
              id: 'AMICO',
              root: 'ProfD',
              path: '\\chrome\\icons',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon05}`,
            },
            {
              name: 'Addon-Verzeichnis',
              id: 'AMAddons',
              root: 'ProfD',
              path: '\\extensions',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon06}`,
            },
            {
              name: 'Programm-Verzeichnis',
              id: 'AMProgramm',
              root: 'CurProcD',
              path: '\\',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon07}`,
            },
            {
              name: 'Startup-Cache',
              id: 'AMCache',
              root: 'ProfLD',
              path: '\\startupCache',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon08}`,
            },
          ],
    
          configs: [
            {
              name: 'Anpassen',
              id: 'AMAnpassen',
              command: 'gCustomizeMode.enter()',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon11}`,
            },
            {
              name: 'Neustart im abgesicherten Modus',
              id: 'AMModus',
              command: 'safeModeRestart();',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon12}`,
            },
            {
              name: 'Browser-Konsole',
              id: 'AMKonsole',
              command: 'goKonsole',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon13}`,
            },
            {
              name: 'Browser-Werkzeuge',
              id: 'AMWerkzeuge',
              command: 'goWerkzeuge',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon14}`,
            },
            {
              name: 'Web-Entwickler',
              id: 'AMEntwickler',
              command: 'goEntwickler',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon15}`,
            },
            {
              name: 'Firefox synchronisieren',
              id: 'AMsynchron',
              command: 'gSync',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon16}`,
            },
            {
              name: 'Zugangsdaten und Passwörter',
              id: 'AMdaten',
              command: 'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })',
              tooltiptext: 'about:logins',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon17}`,
            },
            {
              name: 'Task Manager',
              id: 'AMManager',
              command: 'switchToTabHavingURI("about:processes", true)',
              tooltiptext: 'about:processes',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon18}`,
            },
            {
              name: 'Offline arbeiten',
              id: 'AMOffline',
              command: 'BrowserOffline.toggleOfflineStatus();',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon19}`,
            },
            {
              name: 'Neustart',
              id: 'AMreboot',
              tooltiptext: 'userChrome.js-Cache wird geleert',
              command: 'goReeboot',
              image: `${ProfilePath}/${ButtonIcon01}`,
            },
            {
              name: 'Beenden',
              id: 'AMquit',
              command: 'goQuitApplication(event);',
              image: `${ProfilePath}/${ButtonIcon02}`,
            },
            // uProfMenu-Funktionen unter Menüeintrag "Konfiguration"
            {
              name: 'userChrome.css bearbeiten',
              id: 'AMuserChromeCss',
              command: () => Appmenu.edit(0, 'userChrome.css'),
              subdir: 'Konfiguration',
              image: `${ProfilePath}/css4.svg`,
            },
            {
              name: 'userChromeShadow.css bearbeiten',
              id: 'AMuserChromeShadowCss',
              command: () => Appmenu.edit(0, 'userChromeShadow.css'),
              subdir: 'Konfiguration',
              image: `${ProfilePath}/css4.svg`,
            },
            {
              name: 'userContent.css bearbeiten',
              id: 'AMuserContentCss',
              command: () => Appmenu.edit(0, 'userContent.css'),
              subdir: 'Konfiguration',
              image: `${ProfilePath}/css4.svg`,
            },
            {
              name: 'userChrome.js bearbeiten',
              id: 'AMuserChromeJs',
              command: () => Appmenu.edit(0, 'userChrome.js'),
              subdir: 'Konfiguration',
              image: `${ProfilePath}/js.svg`,
            },
            {
              name: 'prefs.js bearbeiten',
              id: 'AMprefsJs',
              command: () => Appmenu.edit(1, 'prefs.js'),
              subdir: 'Konfiguration',
              image: `${ProfilePath}/js.svg`,
            },
            {
              name: 'user.js bearbeiten',
              id: 'AMuserJs',
              command: () => Appmenu.edit(1, 'user.js'),
              subdir: 'Konfiguration',
              image: `${ProfilePath}/js.svg`,
            },
            // about:-Seiten
            {
              name: 'about:about',
              id: 'AMaboutAbout',
              command: () => openTrustedLinkIn("about:about", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon21}`,
            },
            {
              name: 'about:cache',
              id: 'AMaboutCache',
              command: () => openTrustedLinkIn("about:cache", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon22}`,
            },
            {
              name: 'about:config',
              id: 'AMaboutConfig',
              command: () => openTrustedLinkIn("about:config", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon23}`,
            },
            {
              name: 'about:crashes',
              id: 'AMaboutCrashes',
              command: () => openTrustedLinkIn("about:crashes", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon24}`,
            },
            {
              name: 'about:downloads',
              id: 'AMaboutDownloads',
              command: () => openTrustedLinkIn("about:downloads", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon25}`,
            },
            {
              name: 'about:home',
              id: 'AMaboutHome',
              command: () => openTrustedLinkIn("about:home", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon26}`,
            },
            {
              name: 'about:logins',
              id: 'AMaboutLogins',
              command: 'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon27}`,
            },
            {
              name: 'about:support',
              id: 'AMaboutSupport',
              command: () => openTrustedLinkIn("about:support", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon28}`,
            },
            {
              name: 'about:preferences',
              id: 'AMaboutPreferences',
              command: () => openTrustedLinkIn("about:preferences", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon29}`,
            },
            {
              name: 'about:profiles',
              id: 'AMaboutProfiles',
              command: () => openTrustedLinkIn("about:profiles", "tab"),
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon30}`,
            },
          ]
        },
        _externalAppPopup: null,
        _isready: false,
    
        // uProfMenu-Funktionen (integriert)
        getDirSep: function() {
            var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS;
            var dirsep = "/";
            switch(osString) {
                case "WINNT":
                    dirsep = "\\";
                    break;
                case "Darwin":
                    dirsep = "/";
                    break;
            }
            return dirsep;
        },
    
        getPrefDirectoryPath: function(str) {
            var file = Components.classes["@mozilla.org/file/directory_service;1"]
                .getService(Components.interfaces.nsIProperties)
                .get(str, Components.interfaces.nsIFile);
            if (str == 'CurProcD') {
                file = file.parent;
            }
            return file.path;
        },
    
        edit: function(OpenMode, Filename) {
            var Path = "";
            var dSep = this.getDirSep();
            switch (OpenMode) {
                case 0:
                    Path = this.getPrefDirectoryPath("UChrm") + dSep + Filename;
                    break;
                case 1:
                    Path = this.getPrefDirectoryPath("ProfD") + dSep + Filename;
                    break;
            }
            this.launch(this.TextOpenExe, Path);
    //        this.launch(this.editor, Path);        
        },
    
        launch: function(RanPath, OpenPath) {
            var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIFile);
            var proc = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
            var args = [OpenPath];
            file.initWithPath(RanPath);
            if (!file.exists()) {
                var pref = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
                RanPath = pref.getCharPref("view_source.editor.path");
                file.initWithPath(RanPath);
            }
            proc.init(file);
            proc.run(false, args, args.length);
        },
    
        init: function() {
          this.handleRelativePath(this.toolbar.apps);
          const XULNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
          var ExternalAppBtn = document.createElementNS(XULNS, 'toolbarbutton');
          ExternalAppBtn.id = 'AppMenuButton';
          ExternalAppBtn.setAttribute('label', 'AppButton');
          ExternalAppBtn.addEventListener('click', event => {
            event.preventDefault();
            event.stopPropagation();
          });
          ExternalAppBtn.setAttribute('tooltiptext', 'Firefox Menü');
          ExternalAppBtn.setAttribute('type', 'menu');
          ExternalAppBtn.setAttribute('removable', 'true');
    
          let ProfilePath = PathUtils.toFileURI(
            PathUtils.join(PathUtils.profileDir, 'chrome', 'image')
          );
    
          let DefaultIcon = 'Button_groß.png';
          let AlternateIcon = 'Button_klein-5.png';
          if (Appmenu.isButton) {
            ExternalAppBtn.style.listStyleImage = `url('${ProfilePath}/${DefaultIcon}')`;
            ExternalAppBtn.style.width = '94px';
            ExternalAppBtn.style.height = '24px';
          } else {
            ExternalAppBtn.style.listStyleImage = `url('${ProfilePath}/${AlternateIcon}')`;
            ExternalAppBtn.style.width = '48px';
            ExternalAppBtn.style.height = '21px';
          }
    
          if (Appmenu.isUrlbar === 1) {
            var navBar = document.getElementById('nav-bar-customization-target');
            navBar.insertBefore(ExternalAppBtn, navBar.firstChild);
          } else if (Appmenu.isUrlbar === 2) {
            var menubar = document.getElementById('toolbar-menubar');
            menubar.insertBefore(ExternalAppBtn, menubar.firstChild);
          } else {
            var TabsToolbar = document.getElementById('TabsToolbar');
            TabsToolbar.insertBefore(ExternalAppBtn, TabsToolbar.firstChild);
          }
          var ExternalAppPopup = document.createElementNS(XULNS, 'menupopup');
          ExternalAppPopup.addEventListener('click', event => {
            event.stopPropagation();
          });
          ExternalAppPopup.setAttribute('id', 'AMpopup');
          this._externalAppPopup = ExternalAppPopup;
          ExternalAppBtn.appendChild(ExternalAppPopup);
          Appmenu.onpopupshowing();
    
          if (Appmenu.hotkey) {
            let key = document.createXULElement('key');
            key.id = 'key_AppMenuPopup';
            key.setAttribute('key', Appmenu.hotkey);
            if (Appmenu.hotkeyModifier)
              key.setAttribute('modifiers', Appmenu.hotkeyModifier);
            key.addEventListener('command', function () {
              document.getElementById('AMpopup').openPopup();
            });
            document.getElementById('mainKeyset').appendChild(key);
          }
        },
    
        onpopupshowing: function() {
          if (this._isready) return;
          if (this._externalAppPopup === null) return;
          var ExternalAppPopup = this._externalAppPopup;
          for (let subdir of this.toolbar.subdirs) {
            if (subdir.name == 'separator') {
              ExternalAppPopup.appendChild(document.createXULElement('menuseparator'));
            } else {
              var subdirItem = ExternalAppPopup.appendChild(document.createXULElement('menu'));
              var subdirItemPopup = subdirItem.appendChild(document.createXULElement('menupopup'));
              subdirItem.setAttribute('class', 'menu-iconic');
              subdirItem.setAttribute('label', subdir.name);
              subdirItem.setAttribute('image', subdir.image);
              Appmenu.subdirPopupHash[subdir.name] = subdirItemPopup;
              Appmenu.subdirMenuHash[subdir.name] = subdirItem;
            }
          }
          for (let app of this.toolbar.apps) {
            var appItem;
            if (app.name == 'separator') {
              appItem = document.createXULElement('menuseparator');
            } else {
              appItem = document.createXULElement('menuitem');
              appItem.setAttribute('class', 'menuitem-iconic');
              appItem.setAttribute('label', app.name);
              appItem.setAttribute('image', app.image);
              appItem.addEventListener('command', function () {
                Appmenu.exec(this.path, this.args);
              });
              appItem.setAttribute('tooltiptext', app.name);
              appItem.path = app.path;
              appItem.args = app.args;
            }
            if (app.subdir && Appmenu.subdirPopupHash[app.subdir])
              Appmenu.subdirPopupHash[app.subdir].appendChild(appItem);
            else ExternalAppPopup.appendChild(appItem);
          }
          for (let config of this.toolbar.configs) {
            var configItem;
            if (config.name == 'separator') {
              configItem = document.createXULElement('menuseparator');
            } else {
              configItem = ExternalAppPopup.appendChild(document.createXULElement('menuitem'));
              configItem.setAttribute('class', 'menuitem-iconic');
              configItem.setAttribute('label', config.name);
              configItem.setAttribute('image', config.image);
              configItem.addEventListener('command', () => {
                if (typeof config.command === 'function') {
                  config.command();
                } else {
                  Appmenu.executeCommand(config.command);
                }
              });
              if (config.tooltiptext) {
                configItem.setAttribute('tooltiptext', config.tooltiptext);
              } else {
                configItem.setAttribute('tooltiptext', config.name);
              }
              configItem.setAttribute('id', config.id);
            }
    
            if (config.subdir && Appmenu.subdirPopupHash[config.subdir]) {
              Appmenu.subdirPopupHash[config.subdir].appendChild(configItem);
            } else {
              ExternalAppPopup.appendChild(configItem);
            }
          }
          if (this.autohideEmptySubDirs) {
            for (let i = 0; i < Appmenu.subdirPopupHash.length; i++) {
              if (Appmenu.subdirPopupHash[i].hasChildNodes()) {
                continue;
              } else {
                Appmenu.subdirMenuHash[i].setAttribute('hidden', 'true');
              }
            }
          }
          if (this.moveSubDirstoBottom) {
            let i = ExternalAppPopup.childNodes.length;
            while (ExternalAppPopup.firstChild.getAttribute('class') != 'menuitem-iconic' && i-- != 0) {
              ExternalAppPopup.appendChild(ExternalAppPopup.firstChild);
            }
          }
          this._isready = true;
        },
    
        executeCommand: function(command) {
          const commandMap = {
            'gCustomizeMode.enter()': () => gCustomizeMode.enter(),
            'safeModeRestart();': () => safeModeRestart(),
            'goKonsole': () => {
                    var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                    var { BrowserConsoleManager } = require('resource://devtools/client/webconsole/browser-console-manager');
                    BrowserConsoleManager.openBrowserConsoleOrFocus();
                  },
            'goWerkzeuge': () => {
                    var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                    var { BrowserToolboxLauncher } = require('resource://devtools/client/framework/browser-toolbox/Launcher.sys.mjs');
                    BrowserToolboxLauncher.init();
                  },
            'goEntwickler': () => {
                    var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                    var { gDevToolsBrowser } = require('resource://devtools/client/framework/devtools-browser');
                    gDevToolsBrowser.toggleToolboxCommand(window.gBrowser, performance.now());
                  },
            'gSync': () => gSync.openPrefs('menubar'),
            'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })': () => LoginHelper.openPasswordManager(window, { entryPoint: 'mainmenu' }),
            'switchToTabHavingURI("about:processes", true)': () => switchToTabHavingURI('about:processes', true),
            'BrowserOffline.toggleOfflineStatus();': () => BrowserOffline.toggleOfflineStatus(),
            'goReeboot': () => {
                      Services.appinfo.invalidateCachesOnRestart();
                      Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit);
                    },
            'goQuitApplication(event);': () => goQuitApplication(event),
          };
    
          if (commandMap[command]) {
            commandMap[command]();
          } else {
            console.warn('Unbekannter Befehl: ', command);
          }
        },
    
        handleRelativePath: function(apps) {
          for (let app of apps) {
            if (app.path) {
              app.path = app.path.replace(/\//g, '\\');
              var ffdir = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties).get(app.root, Ci.nsIFile).path;
              if (/^(\\)/.test(app.path)) {
                app.path = ffdir + app.path;
              }
            }
          }
        },
    
        exec: function(path, args) {
          args = args || [];
          var args_t = args.slice(0);
          for (let arg of args_t) {
            arg = arg.replace(/%u/g, gBrowser.currentURI.spec);
          }
          var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
          file.initWithPath(path);
          if (!file.exists()) {
            alert('Datei nicht gefunden: ' + path);
            return;
          }
          if (file.isExecutable() && !path.endsWith('.js')) {
            var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
            process.init(file);
            process.run(false, args_t, args_t.length);
          } else if (file.isFile()) {
            if (this.editor) {
              let UI = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Ci.nsIScriptableUnicodeConverter);
              UI.charset = window.navigator.platform.toLowerCase().includes('win') ? 'Shift_JIS' : 'UTF-8';
              let path = UI.ConvertFromUnicode(file.path);
              let app = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
              app.initWithPath(this.editor);
              let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
              process.init(app);
              process.run(false, [path], 1);
            } else {
              file.launch();
            }
          } else if (file.isDirectory()) {
            if (this.fileManager) {
              let args=[this.FMParameter,path];
              let app = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
              app.initWithPath(this.fileManager);
              let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
              process.init(app);
              process.run(false, args, args.length);
            } else {
              file.launch();
            }
          }
        },
      };
    
      (function () {
        let sss = Components.classes['@mozilla.org/content/style-sheet-service;1'].getService(Components.interfaces.nsIStyleSheetService);
        let uri = Services.io.newURI(
          'data:text/css;charset=utf-8,' +
            encodeURIComponent(`
              menuitem[label='Profil-Verzeichnis'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label='Chrome-Ordner'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label='CSS-Ordner'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label='JS-Ordner'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label='Icons-Ordner'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label='Addon-Verzeichnis'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label='Programm-Verzeichnis'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label='Startup-Cache'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
    
              #AMAnpassen     { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMModus        { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMKonsole      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMWerkzeuge    { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMEntwickler   { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMsynchron     { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMdaten        { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMManager      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMOffline      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
    
              /* Neustart-Button */
              #AMreboot { -moz-context-properties: fill, fill-opacity !important; fill: #fbc96e !important; padding-left: 10px !important; }
              #AMreboot > img:nth-child(1) { width: 20px !important; height: 20px !important; }
              /* Beenden-Button */
              #AMquit { -moz-context-properties: fill, fill-opacity !important; fill: red !important; }
    
              /* about:-Seiten */
              #AMaboutAbout        { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutCache        { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutConfig       { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutCrashes      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutDownloads    { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutHome         { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutLogins       { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutSupport      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutPreferences  { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutProfiles     { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
    
              /* uProfMenu-Einträge */
              #AMuserChromeCss      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMuserChromeShadowCss { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMuserContentCss     { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMuserChromeJs      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMprefsJs            { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMuserJs             { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
            `),
          null,
          null
        );
        sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
      })();
    
      if (window.gBrowser) Appmenu.init();
    Alles anzeigen
  • Meine Version des App-Menüs (JavaScript)

    • Mira_Belle
    • 5. Oktober 2025 um 16:34

    Bei "Anpassungen", dachte ich immer an, "Symbolleisten anpassen ..." und im Menü "Firefox Funktionen" heißt gleich der
    erste Eintrag "Anpassen".
    Da bin ich gedanklich ständig hängen geblieben, aber "Konfiguration" finde ich recht gut.
    Danke.
    Die neuere Version kommt dann auch so gleich.

  • Meine Version des App-Menüs (JavaScript)

    • Mira_Belle
    • 5. Oktober 2025 um 16:20

    2002Andreas Wird noch besser. ;)
    Ich sitze nun schon eine ganze weile hier und mir fällt kein "Oberberbegriff" für die Dateien
    userChrome.css, userChromeShadow.css, userContent.css, userChrome.js, prefs.js und user.js ein.

    Denn ich möchte ja den Platzhalter "2" irgendwie benennen.
    Mit der Funktion bin ich eigentlich fertig:!:
    Die Menüschaltfläche "2" öffnet ein Submenü und man zeigt eben diese "Dateien" an,
    und beim Draufklicken öffnet sich der eingestellte "Editor" zum direkten Bearbeiten der ausgewählten Datei.

  • Meine Version des App-Menüs (JavaScript)

    • Mira_Belle
    • 5. Oktober 2025 um 15:43

    Habe es noch einmal etwas überarbeitet, d.h. Kommentare eingefügt
    und für mich das CSS inkl. Symbole angepasst.

    JavaScript
    // ==UserScript==
    // @name           Appmenu.uc.js
    // @namespace      Appmenu@gmail.com
    // @description    Basiert auf dem Script externalFuncButtonM.uc.js, Wiederherstellung der Orangenen FF-Menü Schaltfläche
    // @include        main
    // @author         defpt
    // @charset        UTF-8
    // @version        2025.10.05
    // ==/UserScript==
    
        // Definiere den Profilpfad für die Symbole
        let ProfilePath = PathUtils.toFileURI(
          PathUtils.join(PathUtils.profileDir, 'chrome', 'icons')
        );
    
        // Standard-Symbol-Dateiname
        let ButtonIcon01 = 'restart.svg';       // Neustart
        let ButtonIcon02 = 'quit.svg';          // Beenden
      
        let Icon01 = 'profile.svg';             // Profil-Verzeichnis
        let Icon02 = 'chrome.svg';              // Chrome-Ordner
        let Icon03 = 'css4.svg';                // CSS-Ordner
        let Icon04 = 'js.svg';                  // JS-Ordner
        let Icon05 = 'folder-plus.svg';         // Icons-Ordner
        let Icon06 = 'addons.svg';              // Addon-Verzeichnis
        let Icon07 = 'folder.svg';              // Programm-Verzeichnis
        let Icon08 = 'folder-1.svg';            // Startup-Cache
      
        let Icon11 = 'Themes.svg';              // Anpassen
        let Icon12 = 'debugging-workers.svg';   // Neustart im abgesicherten Modus
        let Icon13 = 'command-console.svg';     // Browser-Konsole
        let Icon14 = 'window-dev-tools.svg';    // Browser-Werkzeuge
        let Icon15 = 'developer.svg';           // Web-Entwickler
        let Icon16 = 'sync.svg';                // Firefox synchronisieren
        let Icon17 = 'passwords.svg';           // Zugangsdaten und Passwörter
        let Icon18 = 'performance.svg';         // Task Manager
        let Icon19 = 'plug-disconnected.svg';   // Offline arbeiten
    
        let Icon21 = 'firefox.svg';             // about:about
        let Icon22 = 'info.svg';                // about:cache
        let Icon23 = 'settings.svg';            // about:config
        let Icon24 = 'warning.svg';             // about:crashes
        let Icon25 = 'downloads.svg';           // about:downloads
        let Icon26 = 'home.svg';                // about:home
        let Icon27 = 'passwords.svg';           // about:logins
        let Icon28 = 'debugging-workers.svg';   // about:support
        let Icon29 = 'settings.svg';            // about:preferences
        let Icon30 = 'profile.svg';             // about:profiles
    
      var Appmenu = {
        // ■■ START UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
      
        // Editor mit angegebenem Pfad verwenden
        // editor: 'C:\\Program Files\\Notepad++\\notepad++.exe',
        editor: "C:\\Program Files\\Microsoft VS Code\\Code.exe",
        // oder
        // in 'view_source.editor.path' eingetragenen Editor verwenden
        editor: Services.prefs.getCharPref('view_source.editor.path'),
        // Dateimanager mit angegebenem Pfad verwenden oder leer ('') wenn System-Dateimanager verwenden
        //fileManager: 'C:\\Program files\\FreeCommander XE\\FreeCommander.exe',
        fileManager: "",
        // Parameter für Dateimanager oder leer ('')
        //FMParameter: '/T',
        FMParameter: "",
        // Submenüs ohne Inhalt im Hauptmenü automatisch ausblenden
        autohideEmptySubDirs: true,
        // Submenüs im Hauptmenü nach unten verschieben
        moveSubDirstoBottom: false,
        // Ort und Aussehen des Menü-Buttons einstellen
        //   isUrlbar: 1,  // 0: TabsToolbar; 1: navbar,
        isUrlbar: 2, // 0: TabsToolbar; 1: navbar; 2: toolbar-menubar
        isButton: 0, // 0: Hamburger,klein; 1: Firefox,groß,
        // Hotkey zum Öffnen des Appmenüs oder leer ('')
        hotkey: "f",
        hotkeyModifier: "alt",
      
        // ■■ END UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
      
        // Submenüs im Hauptmenü nach unten verschieben
        subdirPopupHash: [],
        subdirMenuHash: [],
      
        toolbar: {
          // Submenüs des Hauptmenüs definieren; Separator einfügen mit {name: 'separator'}
          subdirs: [
            {
              name: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/folder_currentColor.svg`, // Der Pfad wird direkt verwendet, ohne `url()`
            },
            {
              name: 'Firefox Funktionen',
              image: `${ProfilePath}/settings_currentColor.svg`, // Der Pfad wird direkt verwendet, ohne 'url()'
            },
            {
              name: 'separator',
            },
            {
              name: '1',
              image: `${ProfilePath}/1.svg`, // Der Pfad wird direkt verwendet, ohne 'url()'
            },
            {
              name: '2',
              image: `${ProfilePath}/2.svg`, // Der Pfad wird direkt verwendet, ohne 'url()'
            },
            {
              name: '"about:"-Seiten',
              image: `${ProfilePath}/firefox_currentColor.svg`, // Der Pfad wird direkt verwendet, ohne 'url()'
            },
          ],
          
          apps: [
    
            // Untermenü Firefox Verzeichnisse
            {
              name: 'Profil-Verzeichnis',
              id: 'AMProfil',
              root: 'ProfD',
              path: '\\',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon01}`,
            },
            {
              name: 'Chrome-Ordner',
              id: 'AMchrome',
              root: 'ProfD',
              path: '\\chrome',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon02}`,
            },
            {
              name: 'CSS-Ordner',
              id: 'AMCSS',
              root: 'ProfD',
              path: '\\chrome\\css',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon03}`,          
            },
            {
              name: 'JS-Ordner',
              id: 'AMJS',
              root: 'ProfD',
              path: '\\chrome\\scripts',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon04}`,
            },
            {
              name: 'Icons-Ordner',
              id: 'AMICO',
              root: 'ProfD',
              path: '\\chrome\\icons',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon05}`,
            },
            {
              name: 'Addon-Verzeichnis',
              id: 'AMAddons',
              root: 'ProfD',
              path: '\\extensions',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon06}`,
             },
             {
              name: 'Programm-Verzeichnis',
              id: 'AMProgramm',
              root: 'CurProcD',
              path: '\\',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon07}`,
             },
             {
              name: 'Startup-Cache',
              id: 'AMCache',
              root: 'ProfLD',
              path: '\\startupCache',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon08}`,
            },
          ],
          
          configs: [
            // Untermenü Firefox Funktionen
            {
              name: 'Anpassen',
              id: 'AMAnpassen',
              command: 'gCustomizeMode.enter()',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon11}`,
            },
            {
              name: 'Neustart im abgesicherten Modus',
              id: 'AMModus',
              command: 'safeModeRestart();',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon12}`,
            },
            {
              name: 'Browser-Konsole',
              id: 'AMKonsole',
              command: 'goKonsole',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon13}`,
            },
            {
              name: 'Browser-Werkzeuge',
              id: 'AMWerkzeuge',
              command: 'goWerkzeuge',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon14}`,
            },
            {
              name: 'Web-Entwickler',
              id: 'AMEntwickler',
              command: 'goEntwickler',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon15}`,
            },
            {
              name: 'Firefox synchronisieren',
              id: 'AMsynchron',
              command: 'gSync',
              subdir: 'Firefox Funktione',
              image: `${ProfilePath}/${Icon16}`,
            },
            {
              name: 'Zugangsdaten und Passwörter',
              id: 'AMdaten',
              command: 'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })',
              tooltiptext: 'about:logins',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon17}`,
            },
            {
              name: 'Task Manager',
              id: 'AMManager',
              command: 'switchToTabHavingURI("about:processes", true)',
              tooltiptext: 'about:processes',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon18}`,
            },
            {
              name: 'Offline arbeiten',
              id: 'AMOffline',
              command: 'BrowserOffline.toggleOfflineStatus();',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon19}`,
            },
              /*
                {
                name: 'separator',
                },
                */
            {
              name: 'Neustart',
              id: 'AMreboot',
              tooltiptext: 'userChrome.js-Cache wird geleert',
              command: 'goReeboot',
              image: `${ProfilePath}/${ButtonIcon01}`,
            },
            {
              name: 'Beenden',
              id: 'AMquit',
              command: 'goQuitApplication(event);',
              image: `${ProfilePath}/${ButtonIcon02}`,
            },
            // about:-Seiten
            {
              name: 'about:about',
              id: 'AMaboutAbout',
              command: 'openTrustedLinkIn("about:about", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon21}`,
            },
            {
              name: 'about:cache',
              id: 'AMaboutCache',
              command: 'openTrustedLinkIn("about:cache", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon22}`,
            },
            {
              name: 'about:config',
              id: 'AMaboutConfig',
              command: 'openTrustedLinkIn("about:config", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon23}`,
            },
            {
              name: 'about:crashes',
              id: 'AMaboutCrashes',
              command: 'openTrustedLinkIn("about:crashes", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon24}`,
            },
            {
              name: 'about:downloads',
              id: 'AMaboutDownloads',
              command: 'openTrustedLinkIn("about:downloads", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon25}`,
            },
            {
              name: 'about:home',
              id: 'AMaboutHome',
              command: 'openTrustedLinkIn("about:home", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon26}`,
            },
            {
              name: 'about:logins',
              id: 'AMaboutLogins',
              command: 'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon27}`,
            },
            {
              name: 'about:support',
              id: 'AMaboutSupport',
              command: 'openTrustedLinkIn("about:support", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon28}`,
            },
            {
              name: 'about:preferences',
              id: 'AMaboutPreferences',
              command: 'openTrustedLinkIn("about:preferences", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon29}`,
            },
            {
              name: 'about:profiles',
              id: 'AMaboutProfiles',
              command: 'openTrustedLinkIn("about:profiles", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon30}`,
            },
          ]
        },
      _externalAppPopup: null,
      _isready: false,
    
      init: function() {
        this.handleRelativePath(this.toolbar.apps);
        const XULNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
    
        var ExternalAppBtn = document.createElementNS(XULNS, 'toolbarbutton');
        ExternalAppBtn.id = 'AppMenuButton';
        ExternalAppBtn.setAttribute('label', 'AppButton');
        //ExternalAppBtn.setAttribute("onclick", "event.preventDefault();event.stopPropagation();");
        ExternalAppBtn.addEventListener('click', event => {
          event.preventDefault();
          event.stopPropagation();
        });
        ExternalAppBtn.setAttribute('tooltiptext', 'Firefox Menü');
        ExternalAppBtn.setAttribute('type', 'menu');
        ExternalAppBtn.setAttribute('removable', 'true');
          
        // Definiere den Profilpfad
        let ProfilePath = PathUtils.toFileURI(
          PathUtils.join(PathUtils.profileDir, 'chrome', 'image')
        );
      
        // Symbole
        let DefaultIcon = 'Button_groß.png';
        let AlternateIcon = 'Button_klein-5.png';
    
    
        if (Appmenu.isButton) {
          ExternalAppBtn.style.listStyleImage = `url('${ProfilePath}/${DefaultIcon}')`; // Großes Symbol
          ExternalAppBtn.style.width = '94px'; // Feste Breite für großes Symbol
          ExternalAppBtn.style.height = '24px'; // Feste Höhe für großes Symbol
        } else {
          ExternalAppBtn.style.listStyleImage = `url('${ProfilePath}/${AlternateIcon}')`; // Kleines Symbol
          //ExternalAppBtn.style.width = "16px"; // Feste Breite für kleines Symbol
          ExternalAppBtn.style.width = '48px';
          ExternalAppBtn.style.height = '21px'; // Feste Höhe für kleines Symbol
        }
          
        if (Appmenu.isUrlbar === 1) {
          var navBar = document.getElementById('nav-bar-customization-target');
          navBar.insertBefore(ExternalAppBtn, navBar.firstChild);
        } else if (Appmenu.isUrlbar === 2) {
          var menubar = document.getElementById('toolbar-menubar');
          menubar.insertBefore(ExternalAppBtn, menubar.firstChild);
        } else {
          var TabsToolbar = document.getElementById('TabsToolbar');
          TabsToolbar.insertBefore(ExternalAppBtn, TabsToolbar.firstChild);
        }
    
        var ExternalAppPopup = document.createElementNS(XULNS, 'menupopup');
        //ExternalAppPopup.setAttribute('onpopupshowing', 'event.stopPropagation(); Appmenu.onpopupshowing();');
        ExternalAppPopup.addEventListener('click', event => {
          event.stopPropagation();
        });
        ExternalAppPopup.setAttribute('id', 'AMpopup');
        this._externalAppPopup = ExternalAppPopup;
        ExternalAppBtn.appendChild(ExternalAppPopup);
        Appmenu.onpopupshowing();
          
        // Menü mit Tastaturkürzel öffnen
        if (Appmenu.hotkey) {
        let key = document.createXULElement('key');
          key.id = 'key_AppMenuPopup';
          key.setAttribute('key', Appmenu.hotkey);
          if (Appmenu.hotkeyModifier)
          key.setAttribute('modifiers', Appmenu.hotkeyModifier);
        //  key.setAttribute('oncommand', 'document.getElementById("AMpopup").openPopup();');
    
          key.addEventListener('command', function () {
            document.getElementById('AMpopup').openPopup();
            });
          document.getElementById('mainKeyset').appendChild(key);
        }
      },
    
      onpopupshowing: function() {
        if (this._isready) return;
        if (this._externalAppPopup === null) return;
        var ExternalAppPopup = this._externalAppPopup;
    
        for (let subdir of this.toolbar.subdirs) {
          if (subdir.name == 'separator') {
            ExternalAppPopup.appendChild(document.createXULElement('menuseparator'));
          } else {
            var subdirItem = ExternalAppPopup.appendChild(document.createXULElement('menu'));
            var subdirItemPopup = subdirItem.appendChild(document.createXULElement('menupopup'));
            subdirItem.setAttribute('class', 'menu-iconic');
            subdirItem.setAttribute('label', subdir.name);
            subdirItem.setAttribute('image', subdir.image);
            Appmenu.subdirPopupHash[subdir.name] = subdirItemPopup;
            Appmenu.subdirMenuHash[subdir.name] = subdirItem;
          }
        }
    
        for (let app of this.toolbar.apps) {
          var appItem;
          if (app.name == 'separator') {
            appItem = document.createXULElement('menuseparator');
          } else {
            appItem = document.createXULElement('menuitem');
            appItem.setAttribute('class', 'menuitem-iconic');
            appItem.setAttribute('label', app.name);
            appItem.setAttribute('image', app.image);
            //appItem.setAttribute('oncommand', "Appmenu.exec(this.path, this.args);");
            appItem.addEventListener('command', function () {
              Appmenu.exec(this.path, this.args);
              });
            appItem.setAttribute('tooltiptext', app.name);
            appItem.path = app.path;
            appItem.args = app.args;
          }
          if (app.subdir && Appmenu.subdirPopupHash[app.subdir])
            Appmenu.subdirPopupHash[app.subdir].appendChild(appItem);
          else ExternalAppPopup.appendChild(appItem);
        }
    
        for (let config of this.toolbar.configs) {
          var configItem;
          if (config.name == 'separator') {
            configItem = document.createXULElement('menuseparator');
          } else {
            configItem = ExternalAppPopup.appendChild(document.createXULElement('menuitem'));
            configItem.setAttribute('class', 'menuitem-iconic');
            configItem.setAttribute('label', config.name);
            configItem.setAttribute('image', config.image);
            //configItem.setAttribute('oncommand', config.command);
    //        configItem.addEventListener('command', () => {
    //          eval(config.command);
    //        });
    
            configItem.addEventListener('command', () => {
              Appmenu.executeCommand(config.command);
            });
    
            if (config.tooltiptext) {
              configItem.setAttribute('tooltiptext', config.tooltiptext);
            } else {
              configItem.setAttribute('tooltiptext', config.name);
            }
            configItem.setAttribute('id', config.id);
          }
              
          if (config.subdir && Appmenu.subdirPopupHash[config.subdir]) {
            Appmenu.subdirPopupHash[config.subdir].appendChild(configItem);
          } else {
            ExternalAppPopup.appendChild(configItem);
          }
        }
    
        if (this.autohideEmptySubDirs) {
          for (let i = 0; i < Appmenu.subdirPopupHash.length; i++) {
            if (Appmenu.subdirPopupHash[i].hasChildNodes()) {
              continue;
            } else {
              Appmenu.subdirMenuHash[i].setAttribute('hidden', 'true');
            }
          }
        }
    
        if (this.moveSubDirstoBottom) {
          let i = ExternalAppPopup.childNodes.length;
          while (ExternalAppPopup.firstChild.getAttribute('class') != 'menuitem-iconic' && i-- != 0) {
            ExternalAppPopup.appendChild(ExternalAppPopup.firstChild);
          }
        }
        this._isready = true;
      },
    
      executeCommand: function(command) {
        const commandMap = { 
          'gCustomizeMode.enter()': () => gCustomizeMode.enter(),
          'safeModeRestart();': () => safeModeRestart(),
          'goKonsole': () => {
                  var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                  var { BrowserConsoleManager } = require('resource://devtools/client/webconsole/browser-console-manager');
                  BrowserConsoleManager.openBrowserConsoleOrFocus();
                },
          'goWerkzeuge': () => {
                  var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                  var { BrowserToolboxLauncher } = require('resource://devtools/client/framework/browser-toolbox/Launcher.sys.mjs');
                  BrowserToolboxLauncher.init();
                },
          'goEntwickler': () => {
                  var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                  var { gDevToolsBrowser } = require('resource://devtools/client/framework/devtools-browser');
                  gDevToolsBrowser.toggleToolboxCommand(window.gBrowser, Cu.now());
                },
          'gSync': () => gSync.openPrefs('menubar'),
          'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })': () => LoginHelper.openPasswordManager(window, { entryPoint: 'mainmenu' }),
          'switchToTabHavingURI("about:processes", true)': () => switchToTabHavingURI('about:processes', true),
          'BrowserOffline.toggleOfflineStatus();': () => BrowserOffline.toggleOfflineStatus(),      
          'goReeboot': () => {
                    Services.appinfo.invalidateCachesOnRestart();
                    Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit);
                  },
          'goQuitApplication(event);': () => goQuitApplication(event),
          'openTrustedLinkIn("about:about", "tab")': () => openTrustedLinkIn("about:about", "tab"),
          'openTrustedLinkIn("about:cache", "tab")': () => openTrustedLinkIn("about:cache", "tab"),
    
          'openTrustedLinkIn("about:config", "tab")': () => openTrustedLinkIn("about:config", "tab"),
          'openTrustedLinkIn("about:crashes", "tab")': () => openTrustedLinkIn("about:crashes", "tab"),
          'openTrustedLinkIn("about:downloads", "tab")': () => openTrustedLinkIn("about:downloads", "tab"),
          'openTrustedLinkIn("about:home", "tab")': () => openTrustedLinkIn("about:home", "tab"),
    
          'openTrustedLinkIn("about:support", "tab")': () => openTrustedLinkIn("about:support", "tab"),
          'openTrustedLinkIn("about:preferences", "tab")': () => openTrustedLinkIn("about:preferences", "tab"),
          'openTrustedLinkIn("about:profiles", "tab")': () => openTrustedLinkIn("about:profiles", "tab"),
          
        };
        
        if (commandMap[command]) {
          commandMap[command]();
        } else {
          console.warn('Unbekannter Befehl: ', command);
        }
      },
    
      handleRelativePath: function(apps) {
        for (let app of apps) {
          if (app.path) {
            app.path = app.path.replace(/\//g, '\\');
            var ffdir = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties).get(app.root, Ci.nsIFile).path;
            if (/^(\\)/.test(app.path)) {
              app.path = ffdir + app.path;
            }
          }
        }
      },
    
      exec: function(path, args) {
        args = args || [];
        var args_t = args.slice(0);
        for (let arg of args_t) {
          arg = arg.replace(/%u/g, gBrowser.currentURI.spec);
        }
        var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
        file.initWithPath(path);
        if (!file.exists()) {
          //Cu.reportError('Datei nicht gefunden: ' + path);
          alert('Datei nicht gefunden: ' + path);
          return;
        }
        if (file.isExecutable() && !path.endsWith('.js')) {
          var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
          process.init(file);
          process.run(false, args_t, args_t.length);
        } else if (file.isFile()) {
          if (this.editor) {
            let UI = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Ci.nsIScriptableUnicodeConverter);
            UI.charset = window.navigator.platform.toLowerCase().includes('win') ? 'Shift_JIS' : 'UTF-8';
            let path = UI.ConvertFromUnicode(file.path);
            let app = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
            app.initWithPath(this.editor);
            let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
            process.init(app);
            process.run(false, [path], 1);
          } else {
            file.launch();
          }
        } else if (file.isDirectory()) {
          if (this.fileManager) {
            let args=[this.FMParameter,path];
            let app = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
            app.initWithPath(this.fileManager);
            let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
            process.init(app);
            process.run(false, args, args.length);
          } else {
            file.launch();
          }
        }
      },
    };
    
    (function () {
      
        // StyleSheetService zum Hinzufügen der CSS-Regeln
        let sss = Components.classes['@mozilla.org/content/style-sheet-service;1'].getService(Components.interfaces.nsIStyleSheetService);
        let uri = Services.io.newURI(
          'data:text/css;charset=utf-8,' +
            encodeURIComponent(`
      
              menuitem[label='Profil-Verzeichnis'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label='Chrome-Ordner'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label='CSS-Ordner'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label='JS-Ordner'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label='Icons-Ordner'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label='Addon-Verzeichnis'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label='Programm-Verzeichnis'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              menuitem[label='Startup-Cache'] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
    
              #AMAnpassen     { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMModus        { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMKonsole      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMWerkzeuge    { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMEntwickler   { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMsynchron     { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMdaten        { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMManager      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMOffline      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }                          
                 
              /* Neustart-Button */
              #AMreboot { -moz-context-properties: fill, fill-opacity !important;
                  fill: #fbc96e !important;
                  padding-left: 10px !important;
              }
              #AMreboot > img:nth-child(1) {
                  width: 20px !important;
                  height: 20px !important;
              }
              /* Beenden-Button */
              #AMquit { -moz-context-properties: fill, fill-opacity !important;
                  fill: red !important;
              }
    
              #AMaboutAbout        { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutCache        { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutConfig       { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutCrashes      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutDownloads    { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutHome         { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutLogins       { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutSupport      { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutPreferences  { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
              #AMaboutProfiles     { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
      
          `),
          null,
          null
        );
      
        // CSS-Regeln registrieren
        sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
      })();
    
      if (window.gBrowser) Appmenu.init();
    Alles anzeigen

    2002Andreas Es ging mir eher um die "about"-Seiten, bzw, deren Aufruf.

  • Meine Version des App-Menüs (JavaScript)

    • Mira_Belle
    • 5. Oktober 2025 um 15:02

    OK.

    "about:"-Seiten funktionieren schon mal.

    Im Menü sind dann noch zwei Platzhalter:!:
    Wird noch daran gearbeitet!

    Wer schon einmal testen mag, ...

    JavaScript
    // ==UserScript==
    // @name           Appmenu.uc.js
    // @namespace      Appmenu@gmail.com
    // @description    Basiert auf dem Script externalFuncButtonM.uc.js, Wiederherstellung der Orangenen FF-Menü Schaltfläche
    // @include        main
    // @author         defpt
    // @charset        UTF-8
    // @version        2025.10.05
    // ==/UserScript==
    
        // Definiere den Profilpfad für die Symbole
        let ProfilePath = PathUtils.toFileURI(
          PathUtils.join(PathUtils.profileDir, 'chrome', 'icons')
        );
    
        // Standard-Symbol-Dateiname
        let ButtonIcon01 = 'restart.svg';
        let ButtonIcon02 = 'quit.svg';
      
        let Icon01 = 'profile.svg';
        let Icon02 = 'chrome.svg';
        let Icon03 = 'css4.svg';
        let Icon04 = 'js.svg';
        let Icon05 = 'folder-plus.svg';
        let Icon06 = 'addons.svg';
        let Icon07 = 'folder.svg';
        let Icon08 = 'folder-1.svg';
      
        let Icon11 = 'Themes.svg';
        let Icon12 = 'debugging-workers.svg';
        let Icon13 = 'command-console.svg';
        let Icon14 = 'window-dev-tools.svg';
        let Icon15 = 'developer.svg';
        let Icon16 = 'sync.svg';
        let Icon17 = 'passwords.svg';
        let Icon18 = 'performance.svg';
        let Icon19 = 'plug-disconnected.svg';
    
        let Icon21 = 'firefox_currentColor.svg';             // about:about
        let Icon22 = 'info_currentColor.svg';                // about:cache
        let Icon23 = 'settings_currentColor.svg';            // about:config
        let Icon24 = 'warning_currentColor.svg';             // about:crashes
        let Icon25 = 'downloads_currentColor.svg';           // about:downloads
        let Icon26 = 'home_currentColor.svg';                // about:home
        let Icon27 = 'passwords_currentColor.svg';           // about:logins
        let Icon28 = 'debugging-workers_currentColor.svg';   // about:support
        let Icon29 = 'settings_currentColor.svg';            // about:preferences
        let Icon30 = 'profile_currentColor.svg';             // about:profiles
    
      var Appmenu = {
        // ■■ START UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
      
        // Editor mit angegebenem Pfad verwenden
        // editor: 'C:\\Program Files\\Notepad++\\notepad++.exe',
        editor: "C:\\Program Files\\Microsoft VS Code\\Code.exe",
        // oder
        // in 'view_source.editor.path' eingetragenen Editor verwenden
        editor: Services.prefs.getCharPref('view_source.editor.path'),
        // Dateimanager mit angegebenem Pfad verwenden oder leer ('') wenn System-Dateimanager verwenden
        //fileManager: 'C:\\Program files\\FreeCommander XE\\FreeCommander.exe',
        fileManager: "",
        // Parameter für Dateimanager oder leer ('')
        //FMParameter: '/T',
        FMParameter: "",
        // Submenüs ohne Inhalt im Hauptmenü automatisch ausblenden
        autohideEmptySubDirs: true,
        // Submenüs im Hauptmenü nach unten verschieben
        moveSubDirstoBottom: false,
        // Ort und Aussehen des Menü-Buttons einstellen
        //   isUrlbar: 1,  // 0: TabsToolbar; 1: navbar,
        isUrlbar: 2, // 0: TabsToolbar; 1: navbar; 2: toolbar-menubar
        isButton: 0, // 0: Hamburger,klein; 1: Firefox,groß,
        // Hotkey zum Öffnen des Appmenüs oder leer ('')
        hotkey: "f",
        hotkeyModifier: "alt",
      
        // ■■ END UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
      
        // Submenüs im Hauptmenü nach unten verschieben
        subdirPopupHash: [],
        subdirMenuHash: [],
      
        toolbar: {
          // Submenüs des Hauptmenüs definieren; Separator einfügen mit {name: 'separator'}
          subdirs: [
            {
              name: 'Firefox Verzeichnise',
              image: `${ProfilePath}/folder_currentColor.svg`, // Der Pfad wird direkt verwendet, ohne `url()`
            },
            {
              name: 'Firefox Funktionen',
              image: `${ProfilePath}/settings_currentColor.svg`, // Der Pfad wird direkt verwendet, ohne 'url()'
            },
            {
              name: 'separator',
            },
            {
              name: '1',
              image: `${ProfilePath}/1.svg`, // Der Pfad wird direkt verwendet, ohne 'url()'
            },
            {
              name: '2',
              image: `${ProfilePath}/2.svg`, // Der Pfad wird direkt verwendet, ohne 'url()'
            },
            {
              name: '"about:"-Seiten',
              image: `${ProfilePath}/firefox_currentColor.svg`, // Der Pfad wird direkt verwendet, ohne 'url()'
            },
          ],
          
          apps: [
    
            // Untermenü Firefox Verzeichnise
            {
              name: 'Profil-Verzeichnis',
              id: 'AMProfil',
              root: 'ProfD',
              path: '\\',
              subdir: 'Firefox Verzeichnise',
              image: `${ProfilePath}/${Icon01}`,
            },
            {
              name: 'Chrome-Ordner',
              id: 'AMchrome',
              root: 'ProfD',
              path: '\\chrome',
              subdir: 'Firefox Verzeichnise',
              image: `${ProfilePath}/${Icon02}`,
            },
            {
              name: 'CSS-Ordner',
              id: 'AMCSS',
              root: 'ProfD',
              path: '\\chrome\\css',
              subdir: 'Firefox Verzeichnise',
              image: `${ProfilePath}/${Icon03}`,          
            },
            {
              name: 'JS-Ordner',
              id: 'AMJS',
              root: 'ProfD',
              path: '\\chrome\\scripts',
              subdir: 'Firefox Verzeichnise',
              image: `${ProfilePath}/${Icon04}`,
            },
            {
              name: 'Icons-Ordner',
              id: 'AMICO',
              root: 'ProfD',
              path: '\\chrome\\icons',
              subdir: 'Firefox Verzeichnise',
              image: `${ProfilePath}/${Icon05}`,
            },
            {
              name: 'Addon-Verzeichnis',
              id: 'AMAddons',
              root: 'ProfD',
              path: '\\extensions',
              subdir: 'Firefox Verzeichnise',
              image: `${ProfilePath}/${Icon06}`,
             },
             {
              name: 'Programm-Verzeichnis',
              id: 'AMProgramm',
              root: 'CurProcD',
              path: '\\',
              subdir: 'Firefox Verzeichnise',
              image: `${ProfilePath}/${Icon07}`,
             },
             {
              name: 'Startup-Cache',
              id: 'AMCache',
              root: 'ProfLD',
              path: '\\startupCache',
              subdir: 'Firefox Verzeichnise',
              image: `${ProfilePath}/${Icon08}`,
            },
          ],
          
          configs: [
            // Untermenü Firefox Funktionen
            {
              name: 'Anpassen',
              id: 'AMAnpassen',
              command: 'gCustomizeMode.enter()',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon11}`,
            },
            {
              name: 'Neustart im abgesicherten Modus',
              id: 'AMModus',
              command: 'safeModeRestart();',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon12}`,
            },
            {
              name: 'Browser-Konsole',
              id: 'AMKonsole',
              command: 'goKonsole',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon13}`,
            },
            {
              name: 'Browser-Werkzeuge',
              id: 'AMWerkzeuge',
              command: 'goWerkzeuge',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon14}`,
            },
            {
              name: 'Web-Entwickler',
              id: 'AMEntwickler',
              command: 'goEntwickler',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon15}`,
            },
            {
              name: 'Firefox synchronisieren',
              id: 'AMsynchron',
              command: 'gSync',
              subdir: 'Firefox Funktione',
              image: `${ProfilePath}/${Icon16}`,
            },
            {
              name: 'Zugangsdaten und Passwörter',
              id: 'AMdaten',
              command: 'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })',
              tooltiptext: 'about:logins',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon17}`,
            },
            {
              name: 'Task Manager',
              id: 'AMManager',
              command: 'switchToTabHavingURI("about:processes", true)',
              tooltiptext: 'about:processes',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon18}`,
            },
            {
              name: 'Offline arbeiten',
              id: 'AMOffline',
              command: 'BrowserOffline.toggleOfflineStatus();',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon19}`,
            },
              /*
                {
                name: 'separator',
                },
                */
            {
              name: 'Neustart',
              id: 'AMreboot',
              tooltiptext: 'userChrome.js-Cache wird geleert',
              command: 'goReeboot',
              image: `${ProfilePath}/${ButtonIcon01}`,
            },
            {
              name: 'Beenden',
              id: 'AMquit',
              command: 'goQuitApplication(event);',
              image: `${ProfilePath}/${ButtonIcon02}`,
            },
            // about:-Seiten
            {
              name: 'about:about',
              id: 'AMaboutAbout',
              command: 'openTrustedLinkIn("about:about", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon21}`,
            },
            {
              name: 'about:cache',
              id: 'AMaboutCache',
              command: 'openTrustedLinkIn("about:cache", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon22}`,
            },
            {
              name: 'about:config',
              id: 'AMaboutConfig',
              command: 'openTrustedLinkIn("about:config", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon23}`,
            },
            {
              name: 'about:crashes',
              id: 'AMaboutCrashes',
              command: 'openTrustedLinkIn("about:crashes", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon24}`,
            },
            {
              name: 'about:downloads',
              id: 'AMaboutDownloads',
              command: 'openTrustedLinkIn("about:downloads", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon25}`,
            },
            {
              name: 'about:home',
              id: 'AMaboutHome',
              command: 'openTrustedLinkIn("about:home", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon26}`,
            },
            {
              name: 'about:logins',
              id: 'AMaboutLogins',
              command: 'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon27}`,
            },
            {
              name: 'about:support',
              id: 'AMaboutSupport',
              command: 'openTrustedLinkIn("about:support", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon28}`,
            },
            {
              name: 'about:preferences',
              id: 'AMaboutPreferences',
              command: 'openTrustedLinkIn("about:preferences", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon29}`,
            },
            {
              name: 'about:profiles',
              id: 'AMaboutProfiles',
              command: 'openTrustedLinkIn("about:profiles", "tab")',
              subdir: '"about:"-Seiten',
              image: `${ProfilePath}/${Icon30}`,
            },
          ]
        },
      _externalAppPopup: null,
      _isready: false,
    
      init: function() {
        this.handleRelativePath(this.toolbar.apps);
        const XULNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
    
        var ExternalAppBtn = document.createElementNS(XULNS, 'toolbarbutton');
        ExternalAppBtn.id = 'AppMenuButton';
        ExternalAppBtn.setAttribute('label', 'AppButton');
        //ExternalAppBtn.setAttribute("onclick", "event.preventDefault();event.stopPropagation();");
        ExternalAppBtn.addEventListener('click', event => {
          event.preventDefault();
          event.stopPropagation();
        });
        ExternalAppBtn.setAttribute('tooltiptext', 'Firefox Menü');
        ExternalAppBtn.setAttribute('type', 'menu');
        ExternalAppBtn.setAttribute('removable', 'true');
          
        // Definiere den Profilpfad
        let ProfilePath = PathUtils.toFileURI(
          PathUtils.join(PathUtils.profileDir, 'chrome', 'image')
        );
      
        // Symbole
        let DefaultIcon = 'Button_groß.png';
        let AlternateIcon = 'Button_klein-5.png';
    
    
        if (Appmenu.isButton) {
          ExternalAppBtn.style.listStyleImage = `url('${ProfilePath}/${DefaultIcon}')`; // Großes Symbol
          ExternalAppBtn.style.width = '94px'; // Feste Breite für großes Symbol
          ExternalAppBtn.style.height = '24px'; // Feste Höhe für großes Symbol
        } else {
          ExternalAppBtn.style.listStyleImage = `url('${ProfilePath}/${AlternateIcon}')`; // Kleines Symbol
          //ExternalAppBtn.style.width = "16px"; // Feste Breite für kleines Symbol
          ExternalAppBtn.style.width = '48px';
          ExternalAppBtn.style.height = '21px'; // Feste Höhe für kleines Symbol
        }
          
        if (Appmenu.isUrlbar === 1) {
          var navBar = document.getElementById('nav-bar-customization-target');
          navBar.insertBefore(ExternalAppBtn, navBar.firstChild);
        } else if (Appmenu.isUrlbar === 2) {
          var menubar = document.getElementById('toolbar-menubar');
          menubar.insertBefore(ExternalAppBtn, menubar.firstChild);
        } else {
          var TabsToolbar = document.getElementById('TabsToolbar');
          TabsToolbar.insertBefore(ExternalAppBtn, TabsToolbar.firstChild);
        }
    
        var ExternalAppPopup = document.createElementNS(XULNS, 'menupopup');
        //ExternalAppPopup.setAttribute('onpopupshowing', 'event.stopPropagation(); Appmenu.onpopupshowing();');
        ExternalAppPopup.addEventListener('click', event => {
          event.stopPropagation();
        });
        ExternalAppPopup.setAttribute('id', 'AMpopup');
        this._externalAppPopup = ExternalAppPopup;
        ExternalAppBtn.appendChild(ExternalAppPopup);
        Appmenu.onpopupshowing();
          
        // Menü mit Tastaturkürzel öffnen
        if (Appmenu.hotkey) {
        let key = document.createXULElement('key');
          key.id = 'key_AppMenuPopup';
          key.setAttribute('key', Appmenu.hotkey);
          if (Appmenu.hotkeyModifier)
          key.setAttribute('modifiers', Appmenu.hotkeyModifier);
        //  key.setAttribute('oncommand', 'document.getElementById("AMpopup").openPopup();');
    
          key.addEventListener('command', function () {
            document.getElementById('AMpopup').openPopup();
            });
          document.getElementById('mainKeyset').appendChild(key);
        }
      },
    
      onpopupshowing: function() {
        if (this._isready) return;
        if (this._externalAppPopup === null) return;
        var ExternalAppPopup = this._externalAppPopup;
    
        for (let subdir of this.toolbar.subdirs) {
          if (subdir.name == 'separator') {
            ExternalAppPopup.appendChild(document.createXULElement('menuseparator'));
          } else {
            var subdirItem = ExternalAppPopup.appendChild(document.createXULElement('menu'));
            var subdirItemPopup = subdirItem.appendChild(document.createXULElement('menupopup'));
            subdirItem.setAttribute('class', 'menu-iconic');
            subdirItem.setAttribute('label', subdir.name);
            subdirItem.setAttribute('image', subdir.image);
            Appmenu.subdirPopupHash[subdir.name] = subdirItemPopup;
            Appmenu.subdirMenuHash[subdir.name] = subdirItem;
          }
        }
    
        for (let app of this.toolbar.apps) {
          var appItem;
          if (app.name == 'separator') {
            appItem = document.createXULElement('menuseparator');
          } else {
            appItem = document.createXULElement('menuitem');
            appItem.setAttribute('class', 'menuitem-iconic');
            appItem.setAttribute('label', app.name);
            appItem.setAttribute('image', app.image);
            //appItem.setAttribute('oncommand', "Appmenu.exec(this.path, this.args);");
            appItem.addEventListener('command', function () {
              Appmenu.exec(this.path, this.args);
              });
            appItem.setAttribute('tooltiptext', app.name);
            appItem.path = app.path;
            appItem.args = app.args;
          }
          if (app.subdir && Appmenu.subdirPopupHash[app.subdir])
            Appmenu.subdirPopupHash[app.subdir].appendChild(appItem);
          else ExternalAppPopup.appendChild(appItem);
        }
    
        for (let config of this.toolbar.configs) {
          var configItem;
          if (config.name == 'separator') {
            configItem = document.createXULElement('menuseparator');
          } else {
            configItem = ExternalAppPopup.appendChild(document.createXULElement('menuitem'));
            configItem.setAttribute('class', 'menuitem-iconic');
            configItem.setAttribute('label', config.name);
            configItem.setAttribute('image', config.image);
            //configItem.setAttribute('oncommand', config.command);
    //        configItem.addEventListener('command', () => {
    //          eval(config.command);
    //        });
    
            configItem.addEventListener('command', () => {
              Appmenu.executeCommand(config.command);
            });
    
            if (config.tooltiptext) {
              configItem.setAttribute('tooltiptext', config.tooltiptext);
            } else {
              configItem.setAttribute('tooltiptext', config.name);
            }
            configItem.setAttribute('id', config.id);
          }
              
          if (config.subdir && Appmenu.subdirPopupHash[config.subdir]) {
            Appmenu.subdirPopupHash[config.subdir].appendChild(configItem);
          } else {
            ExternalAppPopup.appendChild(configItem);
          }
        }
    
        if (this.autohideEmptySubDirs) {
          for (let i = 0; i < Appmenu.subdirPopupHash.length; i++) {
            if (Appmenu.subdirPopupHash[i].hasChildNodes()) {
              continue;
            } else {
              Appmenu.subdirMenuHash[i].setAttribute('hidden', 'true');
            }
          }
        }
    
        if (this.moveSubDirstoBottom) {
          let i = ExternalAppPopup.childNodes.length;
          while (ExternalAppPopup.firstChild.getAttribute('class') != 'menuitem-iconic' && i-- != 0) {
            ExternalAppPopup.appendChild(ExternalAppPopup.firstChild);
          }
        }
        this._isready = true;
      },
    
      executeCommand: function(command) {
        const commandMap = { 
          'gCustomizeMode.enter()': () => gCustomizeMode.enter(),
          'safeModeRestart();': () => safeModeRestart(),
          'goKonsole': () => {
                  var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                  var { BrowserConsoleManager } = require('resource://devtools/client/webconsole/browser-console-manager');
                  BrowserConsoleManager.openBrowserConsoleOrFocus();
                },
          'goWerkzeuge': () => {
                  var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                  var { BrowserToolboxLauncher } = require('resource://devtools/client/framework/browser-toolbox/Launcher.sys.mjs');
                  BrowserToolboxLauncher.init();
                },
          'goEntwickler': () => {
                  var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                  var { gDevToolsBrowser } = require('resource://devtools/client/framework/devtools-browser');
                  gDevToolsBrowser.toggleToolboxCommand(window.gBrowser, Cu.now());
                },
          'gSync': () => gSync.openPrefs('menubar'),
          'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })': () => LoginHelper.openPasswordManager(window, { entryPoint: 'mainmenu' }),
          'switchToTabHavingURI("about:processes", true)': () => switchToTabHavingURI('about:processes', true),
          'BrowserOffline.toggleOfflineStatus();': () => BrowserOffline.toggleOfflineStatus(),      
          'goReeboot': () => {
                    Services.appinfo.invalidateCachesOnRestart();
                    Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit);
                  },
          'goQuitApplication(event);': () => goQuitApplication(event),
          'openTrustedLinkIn("about:about", "tab")': () => openTrustedLinkIn("about:about", "tab"),
          'openTrustedLinkIn("about:cache", "tab")': () => openTrustedLinkIn("about:cache", "tab"),
    
          'openTrustedLinkIn("about:config", "tab")': () => openTrustedLinkIn("about:config", "tab"),
          'openTrustedLinkIn("about:crashes", "tab")': () => openTrustedLinkIn("about:crashes", "tab"),
          'openTrustedLinkIn("about:downloads", "tab")': () => openTrustedLinkIn("about:downloads", "tab"),
          'openTrustedLinkIn("about:home", "tab")': () => openTrustedLinkIn("about:home", "tab"),
    
          'openTrustedLinkIn("about:support", "tab")': () => openTrustedLinkIn("about:support", "tab"),
          'openTrustedLinkIn("about:preferences", "tab")': () => openTrustedLinkIn("about:preferences", "tab"),
          'openTrustedLinkIn("about:profiles", "tab")': () => openTrustedLinkIn("about:profiles", "tab"),
          
        };
        
        if (commandMap[command]) {
          commandMap[command]();
        } else {
          console.warn('Unbekannter Befehl: ', command);
        }
      },
    
      handleRelativePath: function(apps) {
        for (let app of apps) {
          if (app.path) {
            app.path = app.path.replace(/\//g, '\\');
            var ffdir = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties).get(app.root, Ci.nsIFile).path;
            if (/^(\\)/.test(app.path)) {
              app.path = ffdir + app.path;
            }
          }
        }
      },
    
      exec: function(path, args) {
        args = args || [];
        var args_t = args.slice(0);
        for (let arg of args_t) {
          arg = arg.replace(/%u/g, gBrowser.currentURI.spec);
        }
        var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
        file.initWithPath(path);
        if (!file.exists()) {
          //Cu.reportError('Datei nicht gefunden: ' + path);
          alert('Datei nicht gefunden: ' + path);
          return;
        }
        if (file.isExecutable() && !path.endsWith('.js')) {
          var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
          process.init(file);
          process.run(false, args_t, args_t.length);
        } else if (file.isFile()) {
          if (this.editor) {
            let UI = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Ci.nsIScriptableUnicodeConverter);
            UI.charset = window.navigator.platform.toLowerCase().includes('win') ? 'Shift_JIS' : 'UTF-8';
            let path = UI.ConvertFromUnicode(file.path);
            let app = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
            app.initWithPath(this.editor);
            let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
            process.init(app);
            process.run(false, [path], 1);
          } else {
            file.launch();
          }
        } else if (file.isDirectory()) {
          if (this.fileManager) {
            let args=[this.FMParameter,path];
            let app = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
            app.initWithPath(this.fileManager);
            let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
            process.init(app);
            process.run(false, args, args.length);
          } else {
            file.launch();
          }
        }
      },
    };
    
    (function () {
      
        // StyleSheetService zum Hinzufügen der CSS-Regeln
        let sss = Components.classes['@mozilla.org/content/style-sheet-service;1'].getService(Components.interfaces.nsIStyleSheetService);
        let uri = Services.io.newURI(
          'data:text/css;charset=utf-8,' +
            encodeURIComponent(`
      
              menuitem[label='Profil-Verzeichnis'] { -moz-context-properties: fill, fill-opacity;
                            fill: currentColor;
                            }
              menuitem[label='Chrome-Ordner'] { -moz-context-properties: fill, fill-opacity;
                            fill: currentColor; 
                            }
              menuitem[label='CSS-Ordner'] { -moz-context-properties: fill, fill-opacity;
                            fill: currentColor;                       
                            }
              menuitem[label='JS-Ordner'] { -moz-context-properties: fill, fill-opacity;
                            fill: currentColor;                       
                            }
              menuitem[label='Addon-Verzeichnis'] { -moz-context-properties: fill, fill-opacity;
                            fill: currentColor;                       
                            }
              menuitem[label='Programm-Verzeichnis'] { -moz-context-properties: fill, fill-opacity;
                            fill: currentColor;                       
                            }
              menuitem[label='Startup-Cache'] { -moz-context-properties: fill, fill-opacity;
                            fill: currentColor;                       
                            }
      
              #AMAnpassen     { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;                          
                              }
              #AMModus        { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              }
              #AMKonsole      { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              }
              #AMWerkzeuge    { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              }
              #AMEntwickler   { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              }
              #AMsynchron     { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              }
              #AMdaten        { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              }        
              #AMManager      { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              }
              #AMOffline      { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              } 
      
              /* Neustart-Button */
              #AMreboot { -moz-context-properties: fill, fill-opacity !important;
                  fill: #fbc96e !important;
                  padding-left: 10px !important;
              }
              #AMreboot > img:nth-child(1) {
                  width: 20px !important;
                  height: 20px !important;
              }
              /* Beenden-Button */
              #AMquit { -moz-context-properties: fill, fill-opacity !important;
                  fill: red !important;
              }
      
          `),
          null,
          null
        );
      
        // CSS-Regeln registrieren
        sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
      })();
    
      if (window.gBrowser) Appmenu.init();
    Alles anzeigen
  • UserCSSLoader (2025)

    • Mira_Belle
    • 5. Oktober 2025 um 06:57

    Wie angekündigt,

    Zitat von Mira_Belle

    Die Einträge zum Öffnen der "userChromeShadow.css" und der "userChrome.js" werde ich auch noch vornehmen.

    Und das Skript funktioniert auch in der Nightly 145.0a1 (2025-10-04) (64-Bit):!:

    JavaScript
    /* UserCSSLoader 2025-10-05
     *
     * original author: Griever -
     * https://github.com/Griever/userChromeJS/tree/master/UserCSSLoader
     *
     * Enhancements and several other changes including German translation
     * and configuration section by users aborix, Endor, bege, Speravir of
     * Camp Firefox forum - https://www.camp-firefox.de/forum/ - latest version:
     * https://www.camp-firefox.de/forum/thema/138814/?postID=1280504#post1280504
     */
    
    /****** Bedienungsanleitung ******
    
    CSS-Ordner im Chrome-Ordner erstellen, CSS-Dateien dort ablegen - speichern.
    Diejenigen, deren Dateiname mit "xul-" beginnen, diejenigen, die mit ".as.css"
    enden, sind AGENT_SHEET, alle anderen außer USER_SHEET werden gelesen. Da der
    Inhalt der Datei nicht überprüft wird, darauf achten, die Angabe von @namespace
    nicht zu vergessen!
    
    Schaltfläche oder Menü wird in Navigationsleiste eingefügt (einstellbar, siehe
    Variable "position" in unten anschließender Konfiguration).
    
    Dateiordner, Dateimanager und Texteditor können in der unten anschließenden
    Konfiguration geändert werden. Die Verwendung des in "view_source.editor.path"
    angegebenen Editors ist möglich.
    
    Linksklick auf Stil, zum Aktivieren/Deaktivieren
    Mittelklick auf Stil zum Aktivieren/Deaktivieren, ohne Menü zu schließen
    Rechtsklick auf Stil zum Öffnen im Editor
    Strg+Linksklick zum Anzeigen im Dateimanager
    
    Die Tastenkombinationen können im Menü eingeblendet werden, dazu nach 
    "acceltext" suchen und den Zeilenkommentar "//" entfernen.
    
    Ein Symbol für die Schaltfläche muss in der "userChrome.css" festgelegt werden,
    Pfad zum Bild (PNG nur als Beispiel):
    * relativ zur userChrome.css
        background-image: url("Relativer/Pfad/zum/CSS_Symbol.png");
    * eine absolute Pfadangabe zum Symbol muss mit File-Protokoll-Präfix erfolgen:
        background-image: url("file:///Absoluter/Pfad/zum/CSS_Symbol.png");
    
    Absolute Zahlenwerte müssen eventuell etwas an die eigenen Gegebenheiten
    angepasst werden (größeres Symbol, anderer Rand); der Zahlenwert für Höhe
    und Breite des Menütextes ("CSS") sollte nicht größer sein als für das
    Symbol (hier 16px).
    
    #usercssloader-menu-item {
    	background-image: url("Relativer/Pfad/zum/CSS_Symbol.png");
    	background-position: center;
    	background-repeat: no-repeat;
    	background-size: 16px;
    	border-radius: var(--toolbarbutton-border-radius);
    	margin-block: 3px;
    
    	&:hover {
    		background-color: var(--toolbarbutton-hover-background);
    	}
    
    	& #usercssloader-menu > .menu-text[value="CSS"] {
    		opacity: 0;
    		width: calc(2 * var(--toolbarbutton-inner-padding) + 16px);
    		height: calc(2 * var(--toolbarbutton-inner-padding) + 16px);
    	}
    }
    
    **** Ende der Anleitung ****/
    
    (function(){
    
    /***** Konfiguration *****/
    /* Position: als frei verschiebbare-Schaltfläche = 0, als Menü anzeigen = 1 */
    let position = 0;//1
    /* Dateimanager festlegen, Beispiele:
     *    let fileManager = "C:\\Programme\\FreeCommanderXE\\FreeCommander.exe";
     *    let fileManager = "C:\\Programme\\totalcmd\\TOTALCMD.EXE";
     * auch möglich (Achtung, nur mit fileManagerParam = "/select,"!):
     *    let fileManager = "C:\\Windows\\explorer.exe";
     * Bleibt Parameter leer, wird Standardmanager des Systems ohne Parameter
     * verwendet mit leicht eingeschränkter Funktionalität. */
    let fileManager = "C:\\Windows\\explorer.exe";
    /* eventuelle Parameter für den Dateimanager, Beispiele:
     *    let fileManagerParam = "/T";//FreeCommander oder Totalcommander
     *    let fileManagerParam = "/select,";//Windows Explorer, mit Komma korrekt!
     */
    let fileManagerParam = "/select,";
    /* manche Manager benötigen den Parameter nach der Pfadangabe,
       dann "fileManagerParamPost" auf true setzen */
    let fileManagerParamPost = false;
    /* eigener Texteditor mit Pfad - Standard leer, dann wird Wert aus
     * Einstellung "view_source.editor.path" verwendet mit Warnmeldung,
     * wenn auch dieser leer ist, Beispiel:
     *    let customEditor = "C:\\Windows\\System32\\notepad.exe"; */
    let customEditor = "C:\\Program Files\\Microsoft VS Code\\Code.exe";
    /* Unterordner für die CSS-Dateien */
    let cssFolder = "CSS";
    /* zusätzlich Chrome-Ordner im Untermenü anzeigen (true)
       oder verstecken (false) */
    let showChrome = true;
    /* Menüeintrag zum Bearbeiten der userChrome.css anzeigen (true)
       oder verstecken (false) */
    let showUserChromeCSS = true;
    /* Menüeintrag zum Bearbeiten der userContent.css anzeigen (true)
       oder verstecken (false) */
    let showUserContentCSS = true;
    /* Menüeintrag zum Bearbeiten der pref.js anzeigen (true)
       oder verstecken (false) */
    let showPrefsJS = true;
    /* Menüeintrag zum Bearbeiten der user.js anzeigen (true)
       oder verstecken (false) */
    let showUserJS = true;
    
    
    let showUserChromeShadowCSS = true;
    let showUserChromeJS = true;
    
    /***** Ende der Konfiguration *****/
    
    // Wenn beim Start ein weiteres Fenster (zweites Fenster) vorhanden ist, beenden
    let list = Services.wm.getEnumerator("navigator:browser");
    while(list.hasMoreElements()){ if(list.getNext() != window) return; }
    if (window.UCL) {
    	window.UCL.destroy();
    	delete window.UCL;
    }
    let menutooltip = "Linksklick: an/aus, Menü schließt\nMittelklick: an/aus, Menü bleibt offen\nRechtsklick: bearbeiten";
    if (fileManager !== "") {
    		menutooltip = menutooltip + "\nStrg+Rechtsklick: im Dateimanager anzeigen";
    }
    window.UCL = {
    	AGENT_SHEET : Ci.nsIStyleSheetService.AGENT_SHEET,
    	USER_SHEET  : Ci.nsIStyleSheetService.USER_SHEET,
    	AUTHOR_SHEET: Ci.nsIStyleSheetService.AUTHOR_SHEET,
    	readCSS: {},
    	get disabled_list() {
    		let obj = [];
    		try {
    			obj = decodeURIComponent(this.prefs.getCharPref("disabled_list")).split("|");
    		} catch(e) {}
    		delete this.disabled_list;
    		return this.disabled_list = obj;
    	},
    	get prefs() {
    		delete this.prefs;
    		return this.prefs = Services.prefs.getBranch("UserCSSLoader.");
    	},
    	get styleSheetServices() {
    		delete this.styleSheetServices;
    		return this.styleSheetServices = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
    	},
    	get FOLDER() {
    		let aFolder;
    		try {
    			// UserCSSLoader.FOLDER verwenden
    			let folderPath = this.prefs.getCharPref("FOLDER");
    			aFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
    			aFolder.initWithPath(folderPath);
    		} catch (e) {
    			aFolder = Services.dirsvc.get("UChrm", Ci.nsIFile);
    			aFolder.appendRelativePath(cssFolder);
    		}
    		if (!aFolder.exists() || !aFolder.isDirectory()) {
    			aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664);
    		}
    		delete this.FOLDER;
    		return this.FOLDER = aFolder;
    	},
    	get CHRMFOLDER() {
    			let cFolder;
    			try {
    					// UserCSSLoader.CHRMFOLDER verwenden
    					let CHRMfolderPath = this.prefs.getCharPref("CHRMFOLDER");
    					cFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
    					cFolder.initWithPath(CHRMfolderPath);
    			} catch (e) {
    					cFolder = Services.dirsvc.get("UChrm", Ci.nsIFile);
    			}
    			if (!cFolder.exists() || !cFolder.isDirectory()) {
    					cFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664);
    			}
    			delete this.CHRMFOLDER;
    			return this.CHRMFOLDER = cFolder;
    	},
    	init: function() {
    		const cssmenu = $C("menu", {
    			id: "usercssloader-menu",
    			label: "CSS",
    			tooltiptext: "UserCSSLoader\n\nLinksklick: Stylesheets anzeigen\nMittelklick: Styles importieren",
    			accesskey: "Y"
    		});
    		cssmenu.addEventListener("click", (event) => { if (event.button === 1) UCL.rebuild(); });
    		const menupopup = $C("menupopup", {
    			id: "usercssloader-menupopup"
    		});
    		cssmenu.appendChild(menupopup);
    		let menu = $C("menu", {
    			label: "Style-Loader-Menü",
    			id: "style-loader-menu",
    			accesskey: "S",
    			//acceltext: "S"
    		});
    		menupopup.appendChild(menu);
    		menupopup.appendChild($C("menuseparator"));
    		let mp = $C("menupopup", { id: "usercssloader-submenupopup" });
    		menu.appendChild(mp);
    		let rebuildItem = $C("menuitem", {
    			label: "Styles importieren",
    			accesskey: "I",
    			//acceltext: "I"
    		});
    		rebuildItem.addEventListener("command", () => UCL.rebuild());
    		mp.appendChild(rebuildItem);
    		mp.appendChild($C("menuseparator"));
    		//
    		let createCSS = $C("menuitem", {
    			label: "CSS-Datei erstellen",
    			accesskey: "D",
    			//acceltext: "D"
    		});
    		createCSS.addEventListener("command", () => UCL.create());
    		mp.appendChild(createCSS);
    		let openFolder = $C("menuitem", {
    			label: "CSS-Ordner öffnen",
    			accesskey: "O",
    			//acceltext: "O"
    		});
    		openFolder.addEventListener("command", () => UCL.openCSSFolder());
    		mp.appendChild(openFolder);
    		if (showChrome) {
    				let openChromeFolder = $C("menuitem", {
    					label: "Chrome-Ordner öffnen",
    					accesskey: "X",
    					//acceltext: "X"
    				});
    				openChromeFolder.addEventListener("command", () => UCL.openCHRMFolder());
    				mp.appendChild(openChromeFolder);
    		}
    		if (showUserChromeCSS || showUserContentCSS || showUserChromeShadowCSS || showUserChromeJS)// wenigstens eine der Variablen muss …
    				mp.appendChild($C('menuseparator'));// … true sein, damit Trennlinie angezeigt wird
    		if (showUserChromeCSS) {
    				let editChromeItem = $C("menuitem", {
    					label: "userChrome.css bearbeiten"
    				});
    				editChromeItem.addEventListener("command", () => UCL.editUserCSS("userChrome.css"));
    				mp.appendChild(editChromeItem);
    		}
    		if (showUserContentCSS) {
    				let editContentItem = $C("menuitem", {
    					label: "userContent.css bearbeiten"
    				});
    				editContentItem.addEventListener("command", () => UCL.editUserCSS("userContent.css"));
    				mp.appendChild(editContentItem);
    		}
    		if (showUserChromeShadowCSS) {
    				let editContentItem = $C("menuitem", {
    					label: "userChromeShadow.css bearbeiten"
    				});
    				editContentItem.addEventListener("command", () => UCL.editUserCSS("userChromeShadow.css"));
    				mp.appendChild(editContentItem);
    		}
    		if (showUserChromeJS) {
    				let editContentItem = $C("menuitem", {
    					label: "userChrome.js bearbeiten"
    				});
    				editContentItem.addEventListener("command", () => UCL.editUserCSS("userChrome.js"));
    				mp.appendChild(editContentItem);
    		}		
    		if (showPrefsJS || showUserJS)
    			mp.appendChild($C('menuseparator')); // Trennlinie
    
    		if (showPrefsJS) {
    			let editPrefsItem = $C("menuitem", {
    				label: "prefs.js bearbeiten"
    			});
    			editPrefsItem.addEventListener("command", () => UCL.editProfileFile("prefs.js"));
    			mp.appendChild(editPrefsItem);
    		}
    		if (showUserJS) {
    			let editUserJsItem = $C("menuitem", {
    				label: "user.js bearbeiten"
    			});
    			editUserJsItem.addEventListener("command", () => UCL.editProfileFile("user.js"));
    			mp.appendChild(editUserJsItem);
    		}
    		CustomizableUI.createWidget({
    			id: 'usercssloader-menu-item',
    			type: 'custom',
    			defaultArea: CustomizableUI.AREA_NAVBAR,
    			onBuild: function(aDocument) {
    				let toolbaritem = aDocument.createXULElement('toolbaritem');
    				toolbaritem.id = 'usercssloader-menu-item';
    				toolbaritem.className = 'chromeclass-toolbar-additional';
    				return toolbaritem;
    			}
    		});
    		$('usercssloader-menu-item').appendChild(cssmenu);
    		if (position === 1) {
    				let refNode = $('helpMenu');
    				refNode.parentNode.insertBefore(cssmenu, refNode.nextSibling);
    		}
    		// Stile neu laden, ohne Menü zu öffnen
    		let key = $C("key", {
    			id: "usercssloader-rebuild-key",
    			key: "R",
    			modifiers: "alt",
    		});
    		key.addEventListener("command", () => UCL.rebuild());
    		$("mainKeyset").appendChild(key);
    		this.rebuild();
    		this.initialized = true;
    		window.addEventListener("unload", this, false);
    	},
    	uninit: function() {
    		const dis = [];
    		for (let x of Object.keys(this.readCSS)) {
    			if (!this.readCSS[x].enabled)
    				dis.push(x);
    		}
    		this.prefs.setCharPref("disabled_list", encodeURIComponent(dis.join("|")));
    		window.removeEventListener("unload", this, false);
    	},
    	destroy: function() {
    		var i = document.getElementById("usercssloader-menu");
    		if (i) i.parentNode.removeChild(i);
    		var i = document.getElementById("usercssloader-rebuild-key");
    		if (i) i.parentNode.removeChild(i);
    		this.uninit();
    	},
    	handleEvent: function(event) {
    		switch(event.type){
    			case "unload": this.uninit(); break;
    		}
    	},
    	rebuild: function() {
    		let ext = /\.css$/i;
    		let not = /\.uc\.css/i;
    		let files = this.FOLDER.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
    		while (files.hasMoreElements()) {
    			let file = files.getNext().QueryInterface(Ci.nsIFile);
    			if (!ext.test(file.leafName) || not.test(file.leafName)) continue;
    			let CSS = this.loadCSS(file);
    			CSS.flag = true;
    		}
    		for (let leafName of Object.keys(this.readCSS)) {
    			const CSS = this.readCSS[leafName];
    			if (!CSS.flag) {
    				CSS.enabled = false;
    				delete this.readCSS[leafName];
    			}
    			delete CSS.flag;
    			this.rebuildMenu(leafName);
    		}
    		if (this.initialized) {
    			if (typeof(StatusPanel) !== "undefined")
    				StatusPanel._label = "Styles importiert";
    			else
    				XULBrowserWindow.statusTextField.label = "Styles importiert";
    		}
    	},
    	loadCSS: function(aFile) {
    		let CSS = this.readCSS[aFile.leafName];
    		if (!CSS) {
    			CSS = this.readCSS[aFile.leafName] = new CSSEntry(aFile);
    			if (this.disabled_list.indexOf(CSS.leafName) === -1) {
    				CSS.enabled = true;
    			}
    		} else if (CSS.enabled) {
    			CSS.enabled = true;
    		}
    		return CSS;
    	},
    	rebuildMenu: function(aLeafName) {
    		let CSS = this.readCSS[aLeafName];
    		let menuitem = document.getElementById("usercssloader-" + aLeafName);
    		if (!CSS) {
    			if (menuitem)
    				menuitem.parentNode.removeChild(menuitem);
    			return;
    		}
    		if (!menuitem) {
    			menuitem = $C("menuitem", {
    				label: aLeafName,
    				id: "usercssloader-" + aLeafName,
    				class: "usercssloader-item " + (CSS.SHEET == this.AGENT_SHEET? "AGENT_SHEET" : CSS.SHEET == this.AUTHOR_SHEET? "AUTHOR_SHEET": "USER_SHEET"),
    				type: "checkbox",
    				autocheck: "false",
    				tooltiptext: menutooltip
    			});
    			menuitem.addEventListener("command", () => UCL.toggle(aLeafName));
    			menuitem.addEventListener("click", (event) => UCL.itemClick(event));
    			menuitem.addEventListener("mouseup", (event) => { if (event.button === 1) event.preventDefault(); });
    			document.getElementById("usercssloader-menupopup").appendChild(menuitem);
    		}
    		menuitem.setAttribute("checked", CSS.enabled);
    	},
    	toggle: function(aLeafName) {
    		let CSS = this.readCSS[aLeafName];
    		if (!CSS || event.ctrlKey) return;
    		CSS.enabled = !CSS.enabled;
    		this.rebuildMenu(aLeafName);
    	},
    	itemClick: function(event) {
    		let label = event.currentTarget.getAttribute("label");
    		event.preventDefault();
    		event.stopPropagation();
    		if (event.button === 0) {
    				return;
    		} else if (event.button === 1) {
    				this.toggle(label);
    		} else if (event.button === 2) {
    				if (event.ctrlKey && fileManager  !== "") {
    						UCL.showFile(label);
    				} else {
    				closeMenus(event.target);
    				this.edit(this.getFileFromLeafName(label));
    				}
    		}
    	},
    	getFileFromLeafName: function(aLeafName) {
    		let f = this.FOLDER.clone();
    		f.QueryInterface(Ci.nsIFile); // use appendRelativePath
    		f.appendRelativePath(aLeafName);
    		return f;
    	},
    	showFile: function(fname) {
    				const PathSep = AppConstants.platform === "win" ? "\\" : "/";
    				let target= this.FOLDER.path + PathSep + fname;
    				let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
    				let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
    				let args = (!fileManagerParamPost) ? [fileManagerParam,target] :
    				           [target,fileManagerParam];
    				file.initWithPath(fileManager);
    				process.init(file);
    				// Verzeichnis mit anderem Dateimanager öffnen
    				process.run(false, args, args.length);
    	},
    	openCSSFolder:function(){
    		if (fileManager !== "" && fileManagerParam !== "/select,") {
    				let target = this.FOLDER.path;
    				let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
    				let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
    				let args = (!fileManagerParamPost) ? [fileManagerParam,target] :
    				           [target,fileManagerParam];
    				file.initWithPath(fileManager);
    				process.init(file);
    				// Verzeichnis mit anderem Dateimanager öffnen
    				process.run(false, args, args.length);
    		} else {
    				// Verzeichnis mit Dateimanager des Systems öffnen
    				this.FOLDER.launch();
    		}
    	},
    	openCHRMFolder:function(){
    		if (fileManager !== "" && fileManagerParam !== "/select,") {
    				let target = this.CHRMFOLDER.path;
    				let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
    				let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
    				let args = (!fileManagerParamPost) ? [fileManagerParam,target] :
    				           [target,fileManagerParam];
    				file.initWithPath(fileManager);
    				process.init(file);
    				// Verzeichnis mit anderem Dateimanager öffnen
    				process.run(false, args, args.length);
    		} else {
    				// Verzeichnis mit Dateimanager des Systems öffnen
    				this.CHRMFOLDER.launch();
    		}
    	},
    	editUserCSS: function(aLeafName) {
    		let file = Services.dirsvc.get("UChrm", Ci.nsIFile);
    		file.appendRelativePath(aLeafName);
    		this.edit(file);
    	},
        editProfileFile: function(filename) {
            let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
            file.append(filename);
            this.edit(file);
        },
    	edit: function(aFile) {
    		let editor = (customEditor !== "") ? customEditor : Services.prefs.getCharPref("view_source.editor.path");
    		if (!editor) return alert('In der Konfiguration einen Texteditor festlegen ("customEditor") oder\n unter about:config im vorhandenen Schalter "view_source.editor.path"\n den vollständigen Editorpfad eintragen.');
    		try {
    			let UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
    			UI.charset = window.navigator.platform.toLowerCase().indexOf("win") >= 0? "Shift_JIS": "UTF-8";
    			let path = UI.ConvertFromUnicode(aFile.path);
    			let app = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
    			app.initWithPath(editor);
    			let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
    			process.init(app);
    			process.run(false, [path], 1);
    		} catch (e) {}
    	},
    	create: function(aLeafName) {
    		if (!aLeafName) aLeafName = prompt("Name des Styles", dateFormat(new Date(), "%Y_%m%d_%H%M%S"));
    		if (aLeafName) aLeafName = aLeafName.replace(/\s+/g, " ").replace(/[\\/:*?\"<>|]/g, "");
    		if (!aLeafName || !/\S/.test(aLeafName)) return;
    		if (!/\.css$/.test(aLeafName)) aLeafName += ".css";
    		let file = this.getFileFromLeafName(aLeafName);
    		this.edit(file);
    	},
    	UCrebuild: function() {
    		let re = /^file:.*\.uc\.css(?:\?\d+)?$/i;
    		let query = "?" + new Date().getTime();
    		Array.slice(document.styleSheets).forEach(function(css){
    			if (!re.test(css.href)) return;
    			if (css.ownerNode) {
    				css.ownerNode.parentNode.removeChild(css.ownerNode);
    			}
    			let pi = document.createProcessingInstruction('xml-stylesheet','type="text/css" href="'+ css.href.replace(/\?.*/, '') + query +'"');
    			document.insertBefore(pi, document.documentElement);
    		});
    		UCL.UCcreateMenuitem();
    	},
    	UCcreateMenuitem: function() {
    		let sep = $("usercssloader-ucseparator");
    		let popup = sep.parentNode;
    		if (sep.nextSibling) {
    			let range = document.createRange();
    			range.setStartAfter(sep);
    			range.setEndAfter(popup.lastChild);
    			range.deleteContents();
    			range.detach();
    		}
    		let re = /^file:.*\.uc\.css(?:\?\d+)?$/i;
    		Array.slice(document.styleSheets).forEach(function(css) {
    			if (!re.test(css.href)) return;
    			let fileURL = decodeURIComponent(css.href).split("?")[0];
    			let aLeafName = fileURL.split("/").pop();
    			let m = $C("menuitem", {
    				label: aLeafName,
    				tooltiptext: fileURL,
    				id: "usercssloader-" + aLeafName,
    				type: "checkbox",
    				autocheck: "false",
    				checked: "true",
    			});
    			m.css = css;
    			m.addEventListener("command", function() {
    				if (!event.ctrlKey) {this.setAttribute("checked", !(this.css.disabled = !this.css.disabled));}
    			});
    			m.addEventListener("mouseup", function(event) {
    				if (event.button === 1) event.preventDefault();
    			});
    			m.addEventListener("click", function(event) {
    				UCL.UCItemClick(event);
    			});
    			popup.appendChild(m);
    		});
    	},
    	UCItemClick: function(event) {
    		if (event.button === 0) return;
    		event.preventDefault();
    		event.stopPropagation();
    		if (event.button === 1) {
    			event.target.doCommand();
    		}
    		else if (event.button === 2) {
    			closeMenus(event.target);
    			let fileURL = event.currentTarget.getAttribute("tooltiptext");
    			let file = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getFileFromURLSpec(fileURL);
    			this.edit(file);
    		}
    	},
    };
    function CSSEntry(aFile) {
    	this.path = aFile.path;
    	this.leafName = aFile.leafName;
    	this.lastModifiedTime = 1;
    	this.SHEET = /^xul-|\.as\.css$/i.test(this.leafName) ?
    		Ci.nsIStyleSheetService.AGENT_SHEET:
    		/\.author\.css$/i.test(this.leafName)?
    			Ci.nsIStyleSheetService.AUTHOR_SHEET:
    			Ci.nsIStyleSheetService.USER_SHEET;
    }
    CSSEntry.prototype = {
    	sss: Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService),
    	_enabled: false,
    	get enabled() {
    		return this._enabled;
    	},
    	set enabled(isEnable) {
    		let aFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile)
    		aFile.initWithPath(this.path);
    		let isExists = aFile.exists(); // true, wenn die Datei bereits existiert
    		let lastModifiedTime = isExists ? aFile.lastModifiedTime : 0;
    		let isForced = this.lastModifiedTime != lastModifiedTime; //true, wenn es eine Änderung in der Datei gibt
    		let fileURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromActualFile(aFile);
    		let uri = Services.io.newURI(fileURL, null, null);
    		if (this.sss.sheetRegistered(uri, this.SHEET)) {
    			// Wenn diese Datei bereits gelesen wurde
    			if (!isEnable || !isExists) {
    				this.sss.unregisterSheet(uri, this.SHEET);
    			}
    			else if (isForced) {
    				// Nach Stornierung erneut einlesen
    				this.sss.unregisterSheet(uri, this.SHEET);
    				this.sss.loadAndRegisterSheet(uri, this.SHEET);
    			}
    		} else {
    			// Datei wurde nicht gelesen
    			if (isEnable && isExists) {
    				this.sss.loadAndRegisterSheet(uri, this.SHEET);
    			}
    		}
    		if (this.lastModifiedTime !== 1 && isEnable && isForced) {
    			log(this.leafName + " wurde aktualisiert");
    		}
    		this.lastModifiedTime = lastModifiedTime;
    		return this._enabled = isEnable;
    	},
    };
    UCL.init();
    function $(id) { return document.getElementById(id); }
    function $A(arr) { return Array.slice(arr); }
    function $C(name, attr) {
    	const el = document.createXULElement(name);
    	if (attr) Object.keys(attr).forEach(function(n) { el.setAttribute(n, attr[n]) });
    	return el;
    }
    function dateFormat(date, format) {
    	format = format.replace("%Y", ("000" + date.getFullYear()).substr(-4));
    	format = format.replace("%m", ("0" + (date.getMonth()+1)).substr(-2));
    	format = format.replace("%d", ("0" + date.getDate()).substr(-2));
    	format = format.replace("%H", ("0" + date.getHours()).substr(-2));
    	format = format.replace("%M", ("0" + date.getMinutes()).substr(-2));
    	format = format.replace("%S", ("0" + date.getSeconds()).substr(-2));
    	return format;
    }
    function log(mes) { console.log(mes); }
    })();
    Alles anzeigen

    Endor Was hältst Du davon?

  • UserCSSLoader (2025)

    • Mira_Belle
    • 4. Oktober 2025 um 23:06

    Die Einträge zum Öffnen der "userChromeShadow.css" und der "userChrome.js" werde ich auch noch vornehmen.

  • Meine Version des App-Menüs (JavaScript)

    • Mira_Belle
    • 4. Oktober 2025 um 22:57

    Habe das Menü um das Öffnen des Icons-Ordner erweitert.
    Bin aber auch noch am Basteln, um weitere Funktionen hinzuzufügen.

    Es werden Funktionen sein, die aus anderen Skripten stammen.
    Z.B. direkt Aufrufe einiger "about:"-Seiten, aber auch das Öffenen
    mittels eines Editors von diversen Dateien, z.B. userChrome.css oder z.B. prefs.js.

  • UserCSSLoader (2025)

    • Mira_Belle
    • 4. Oktober 2025 um 22:44

    Ich war mal so frei und habe das Menü erweitert!

    Wie man unschwer erkennen kann, können nun auch die Dateien "prefs.js" & "user.js" zum Bearbeiten geöffnet werden.

    JavaScript
    /* UserCSSLoader 2025-10-04
     *
     * original author: Griever -
     * https://github.com/Griever/userChromeJS/tree/master/UserCSSLoader
     *
     * Enhancements and several other changes including German translation
     * and configuration section by users aborix, Endor, bege, Speravir of
     * Camp Firefox forum - https://www.camp-firefox.de/forum/ - latest version:
     * https://www.camp-firefox.de/forum/thema/138814/?postID=1280500#post1280500
     */
    
    /****** Bedienungsanleitung ******
    
    CSS-Ordner im Chrome-Ordner erstellen, CSS-Dateien dort ablegen - speichern.
    Diejenigen, deren Dateiname mit "xul-" beginnen, diejenigen, die mit ".as.css"
    enden, sind AGENT_SHEET, alle anderen außer USER_SHEET werden gelesen. Da der
    Inhalt der Datei nicht überprüft wird, darauf achten, die Angabe von @namespace
    nicht zu vergessen!
    
    Schaltfläche oder Menü wird in Navigationsleiste eingefügt (einstellbar, siehe
    Variable "position" in unten anschließender Konfiguration).
    
    Dateiordner, Dateimanager und Texteditor können in der unten anschließenden
    Konfiguration geändert werden. Die Verwendung des in "view_source.editor.path"
    angegebenen Editors ist möglich.
    
    Linksklick auf Stil, zum Aktivieren/Deaktivieren
    Mittelklick auf Stil zum Aktivieren/Deaktivieren, ohne Menü zu schließen
    Rechtsklick auf Stil zum Öffnen im Editor
    Strg+Linksklick zum Anzeigen im Dateimanager
    
    Die Tastenkombinationen können im Menü eingeblendet werden, dazu nach 
    "acceltext" suchen und den Zeilenkommentar "//" entfernen.
    
    Ein Symbol für die Schaltfläche muss in der "userChrome.css" festgelegt werden,
    Pfad zum Bild (PNG nur als Beispiel):
    * relativ zur userChrome.css
        background-image: url("Relativer/Pfad/zum/CSS_Symbol.png");
    * eine absolute Pfadangabe zum Symbol muss mit File-Protokoll-Präfix erfolgen:
        background-image: url("file:///Absoluter/Pfad/zum/CSS_Symbol.png");
    
    Absolute Zahlenwerte müssen eventuell etwas an die eigenen Gegebenheiten
    angepasst werden (größeres Symbol, anderer Rand); der Zahlenwert für Höhe
    und Breite des Menütextes ("CSS") sollte nicht größer sein als für das
    Symbol (hier 16px).
    
    #usercssloader-menu-item {
    	background-image: url("Relativer/Pfad/zum/CSS_Symbol.png");
    	background-position: center;
    	background-repeat: no-repeat;
    	background-size: 16px;
    	border-radius: var(--toolbarbutton-border-radius);
    	margin-block: 3px;
    
    	&:hover {
    		background-color: var(--toolbarbutton-hover-background);
    	}
    
    	& #usercssloader-menu > .menu-text[value="CSS"] {
    		opacity: 0;
    		width: calc(2 * var(--toolbarbutton-inner-padding) + 16px);
    		height: calc(2 * var(--toolbarbutton-inner-padding) + 16px);
    	}
    }
    
    **** Ende der Anleitung ****/
    
    (function(){
    
    /***** Konfiguration *****/
    /* Position: als frei verschiebbare-Schaltfläche = 0, als Menü anzeigen = 1 */
    let position = 0;//1
    /* Dateimanager festlegen, Beispiele:
     *    let fileManager = "C:\\Programme\\FreeCommanderXE\\FreeCommander.exe";
     *    let fileManager = "C:\\Programme\\totalcmd\\TOTALCMD.EXE";
     * auch möglich (Achtung, nur mit fileManagerParam = "/select,"!):
     *    let fileManager = "C:\\Windows\\explorer.exe";
     * Bleibt Parameter leer, wird Standardmanager des Systems ohne Parameter
     * verwendet mit leicht eingeschränkter Funktionalität. */
    let fileManager = "C:\\Windows\\explorer.exe";
    /* eventuelle Parameter für den Dateimanager, Beispiele:
     *    let fileManagerParam = "/T";//FreeCommander oder Totalcommander
     *    let fileManagerParam = "/select,";//Windows Explorer, mit Komma korrekt!
     */
    let fileManagerParam = "/select,";
    /* manche Manager benötigen den Parameter nach der Pfadangabe,
       dann "fileManagerParamPost" auf true setzen */
    let fileManagerParamPost = false;
    /* eigener Texteditor mit Pfad - Standard leer, dann wird Wert aus
     * Einstellung "view_source.editor.path" verwendet mit Warnmeldung,
     * wenn auch dieser leer ist, Beispiel:
     *    let customEditor = "C:\\Windows\\System32\\notepad.exe"; */
    let customEditor = "C:\\Program Files\\Microsoft VS Code\\Code.exe";
    /* Unterordner für die CSS-Dateien */
    let cssFolder = "CSS";
    /* zusätzlich Chrome-Ordner im Untermenü anzeigen (true)
       oder verstecken (false) */
    let showChrome = true;
    /* Menüeintrag zum Bearbeiten der userChrome.css anzeigen (true)
       oder verstecken (false) */
    let showUserChromeCSS = true;
    /* Menüeintrag zum Bearbeiten der userContent.css anzeigen (true)
       oder verstecken (false) */
    let showUserContentCSS = true;
    /* Menüeintrag zum Bearbeiten der pref.js anzeigen (true)
       oder verstecken (false) */
    let showPrefsJS = true;
    /* Menüeintrag zum Bearbeiten der user.js anzeigen (true)
       oder verstecken (false) */
    let showUserJS = true;
    /***** Ende der Konfiguration *****/
    
    // Wenn beim Start ein weiteres Fenster (zweites Fenster) vorhanden ist, beenden
    let list = Services.wm.getEnumerator("navigator:browser");
    while(list.hasMoreElements()){ if(list.getNext() != window) return; }
    if (window.UCL) {
    	window.UCL.destroy();
    	delete window.UCL;
    }
    let menutooltip = "Linksklick: an/aus, Menü schließt\nMittelklick: an/aus, Menü bleibt offen\nRechtsklick: bearbeiten";
    if (fileManager !== "") {
    		menutooltip = menutooltip + "\nStrg+Rechtsklick: im Dateimanager anzeigen";
    }
    window.UCL = {
    	AGENT_SHEET : Ci.nsIStyleSheetService.AGENT_SHEET,
    	USER_SHEET  : Ci.nsIStyleSheetService.USER_SHEET,
    	AUTHOR_SHEET: Ci.nsIStyleSheetService.AUTHOR_SHEET,
    	readCSS: {},
    	get disabled_list() {
    		let obj = [];
    		try {
    			obj = decodeURIComponent(this.prefs.getCharPref("disabled_list")).split("|");
    		} catch(e) {}
    		delete this.disabled_list;
    		return this.disabled_list = obj;
    	},
    	get prefs() {
    		delete this.prefs;
    		return this.prefs = Services.prefs.getBranch("UserCSSLoader.");
    	},
    	get styleSheetServices() {
    		delete this.styleSheetServices;
    		return this.styleSheetServices = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService);
    	},
    	get FOLDER() {
    		let aFolder;
    		try {
    			// UserCSSLoader.FOLDER verwenden
    			let folderPath = this.prefs.getCharPref("FOLDER");
    			aFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
    			aFolder.initWithPath(folderPath);
    		} catch (e) {
    			aFolder = Services.dirsvc.get("UChrm", Ci.nsIFile);
    			aFolder.appendRelativePath(cssFolder);
    		}
    		if (!aFolder.exists() || !aFolder.isDirectory()) {
    			aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664);
    		}
    		delete this.FOLDER;
    		return this.FOLDER = aFolder;
    	},
    	get CHRMFOLDER() {
    			let cFolder;
    			try {
    					// UserCSSLoader.CHRMFOLDER verwenden
    					let CHRMfolderPath = this.prefs.getCharPref("CHRMFOLDER");
    					cFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
    					cFolder.initWithPath(CHRMfolderPath);
    			} catch (e) {
    					cFolder = Services.dirsvc.get("UChrm", Ci.nsIFile);
    			}
    			if (!cFolder.exists() || !cFolder.isDirectory()) {
    					cFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664);
    			}
    			delete this.CHRMFOLDER;
    			return this.CHRMFOLDER = cFolder;
    	},
    	init: function() {
    		const cssmenu = $C("menu", {
    			id: "usercssloader-menu",
    			label: "CSS",
    			tooltiptext: "UserCSSLoader\n\nLinksklick: Stylesheets anzeigen\nMittelklick: Styles importieren",
    			accesskey: "Y"
    		});
    		cssmenu.addEventListener("click", (event) => { if (event.button === 1) UCL.rebuild(); });
    		const menupopup = $C("menupopup", {
    			id: "usercssloader-menupopup"
    		});
    		cssmenu.appendChild(menupopup);
    		let menu = $C("menu", {
    			label: "Style-Loader-Menü",
    			id: "style-loader-menu",
    			accesskey: "S",
    			//acceltext: "S"
    		});
    		menupopup.appendChild(menu);
    		menupopup.appendChild($C("menuseparator"));
    		let mp = $C("menupopup", { id: "usercssloader-submenupopup" });
    		menu.appendChild(mp);
    		let rebuildItem = $C("menuitem", {
    			label: "Styles importieren",
    			accesskey: "I",
    			//acceltext: "I"
    		});
    		rebuildItem.addEventListener("command", () => UCL.rebuild());
    		mp.appendChild(rebuildItem);
    		mp.appendChild($C("menuseparator"));
    		//
    		let createCSS = $C("menuitem", {
    			label: "CSS-Datei erstellen",
    			accesskey: "D",
    			//acceltext: "D"
    		});
    		createCSS.addEventListener("command", () => UCL.create());
    		mp.appendChild(createCSS);
    		let openFolder = $C("menuitem", {
    			label: "CSS-Ordner öffnen",
    			accesskey: "O",
    			//acceltext: "O"
    		});
    		openFolder.addEventListener("command", () => UCL.openCSSFolder());
    		mp.appendChild(openFolder);
    		if (showChrome) {
    				let openChromeFolder = $C("menuitem", {
    					label: "Chrome-Ordner öffnen",
    					accesskey: "X",
    					//acceltext: "X"
    				});
    				openChromeFolder.addEventListener("command", () => UCL.openCHRMFolder());
    				mp.appendChild(openChromeFolder);
    		}
    		if (showUserChromeCSS || showUserContentCSS)// wenigstens eine der beiden Variablen muss …
    				mp.appendChild($C('menuseparator'));// … true sein, damit Trennlinie angezeigt wird
    		if (showUserChromeCSS) {
    				let editChromeItem = $C("menuitem", {
    					label: "userChrome.css bearbeiten"
    				});
    				editChromeItem.addEventListener("command", () => UCL.editUserCSS("userChrome.css"));
    				mp.appendChild(editChromeItem);
    		}
    		if (showUserContentCSS) {
    				let editContentItem = $C("menuitem", {
    					label: "userContent.css bearbeiten"
    				});
    				editContentItem.addEventListener("command", () => UCL.editUserCSS("userContent.css"));
    				mp.appendChild(editContentItem);
    		}
    		if (showPrefsJS || showUserJS)
    			mp.appendChild($C('menuseparator')); // Trennlinie
    
    		if (showPrefsJS) {
    			let editPrefsItem = $C("menuitem", {
    				label: "prefs.js bearbeiten"
    			});
    			editPrefsItem.addEventListener("command", () => UCL.editProfileFile("prefs.js"));
    			mp.appendChild(editPrefsItem);
    		}
    		if (showUserJS) {
    			let editUserJsItem = $C("menuitem", {
    				label: "user.js bearbeiten"
    			});
    			editUserJsItem.addEventListener("command", () => UCL.editProfileFile("user.js"));
    			mp.appendChild(editUserJsItem);
    		}
    		CustomizableUI.createWidget({
    			id: 'usercssloader-menu-item',
    			type: 'custom',
    			defaultArea: CustomizableUI.AREA_NAVBAR,
    			onBuild: function(aDocument) {
    				let toolbaritem = aDocument.createXULElement('toolbaritem');
    				toolbaritem.id = 'usercssloader-menu-item';
    				toolbaritem.className = 'chromeclass-toolbar-additional';
    				return toolbaritem;
    			}
    		});
    		$('usercssloader-menu-item').appendChild(cssmenu);
    		if (position === 1) {
    				let refNode = $('helpMenu');
    				refNode.parentNode.insertBefore(cssmenu, refNode.nextSibling);
    		}
    		// Stile neu laden, ohne Menü zu öffnen
    		let key = $C("key", {
    			id: "usercssloader-rebuild-key",
    			key: "R",
    			modifiers: "alt",
    		});
    		key.addEventListener("command", () => UCL.rebuild());
    		$("mainKeyset").appendChild(key);
    		this.rebuild();
    		this.initialized = true;
    		window.addEventListener("unload", this, false);
    	},
    	uninit: function() {
    		const dis = [];
    		for (let x of Object.keys(this.readCSS)) {
    			if (!this.readCSS[x].enabled)
    				dis.push(x);
    		}
    		this.prefs.setCharPref("disabled_list", encodeURIComponent(dis.join("|")));
    		window.removeEventListener("unload", this, false);
    	},
    	destroy: function() {
    		var i = document.getElementById("usercssloader-menu");
    		if (i) i.parentNode.removeChild(i);
    		var i = document.getElementById("usercssloader-rebuild-key");
    		if (i) i.parentNode.removeChild(i);
    		this.uninit();
    	},
    	handleEvent: function(event) {
    		switch(event.type){
    			case "unload": this.uninit(); break;
    		}
    	},
    	rebuild: function() {
    		let ext = /\.css$/i;
    		let not = /\.uc\.css/i;
    		let files = this.FOLDER.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
    		while (files.hasMoreElements()) {
    			let file = files.getNext().QueryInterface(Ci.nsIFile);
    			if (!ext.test(file.leafName) || not.test(file.leafName)) continue;
    			let CSS = this.loadCSS(file);
    			CSS.flag = true;
    		}
    		for (let leafName of Object.keys(this.readCSS)) {
    			const CSS = this.readCSS[leafName];
    			if (!CSS.flag) {
    				CSS.enabled = false;
    				delete this.readCSS[leafName];
    			}
    			delete CSS.flag;
    			this.rebuildMenu(leafName);
    		}
    		if (this.initialized) {
    			if (typeof(StatusPanel) !== "undefined")
    				StatusPanel._label = "Styles importiert";
    			else
    				XULBrowserWindow.statusTextField.label = "Styles importiert";
    		}
    	},
    	loadCSS: function(aFile) {
    		let CSS = this.readCSS[aFile.leafName];
    		if (!CSS) {
    			CSS = this.readCSS[aFile.leafName] = new CSSEntry(aFile);
    			if (this.disabled_list.indexOf(CSS.leafName) === -1) {
    				CSS.enabled = true;
    			}
    		} else if (CSS.enabled) {
    			CSS.enabled = true;
    		}
    		return CSS;
    	},
    	rebuildMenu: function(aLeafName) {
    		let CSS = this.readCSS[aLeafName];
    		let menuitem = document.getElementById("usercssloader-" + aLeafName);
    		if (!CSS) {
    			if (menuitem)
    				menuitem.parentNode.removeChild(menuitem);
    			return;
    		}
    		if (!menuitem) {
    			menuitem = $C("menuitem", {
    				label: aLeafName,
    				id: "usercssloader-" + aLeafName,
    				class: "usercssloader-item " + (CSS.SHEET == this.AGENT_SHEET? "AGENT_SHEET" : CSS.SHEET == this.AUTHOR_SHEET? "AUTHOR_SHEET": "USER_SHEET"),
    				type: "checkbox",
    				autocheck: "false",
    				tooltiptext: menutooltip
    			});
    			menuitem.addEventListener("command", () => UCL.toggle(aLeafName));
    			menuitem.addEventListener("click", (event) => UCL.itemClick(event));
    			menuitem.addEventListener("mouseup", (event) => { if (event.button === 1) event.preventDefault(); });
    			document.getElementById("usercssloader-menupopup").appendChild(menuitem);
    		}
    		menuitem.setAttribute("checked", CSS.enabled);
    	},
    	toggle: function(aLeafName) {
    		let CSS = this.readCSS[aLeafName];
    		if (!CSS || event.ctrlKey) return;
    		CSS.enabled = !CSS.enabled;
    		this.rebuildMenu(aLeafName);
    	},
    	itemClick: function(event) {
    		let label = event.currentTarget.getAttribute("label");
    		event.preventDefault();
    		event.stopPropagation();
    		if (event.button === 0) {
    				return;
    		} else if (event.button === 1) {
    				this.toggle(label);
    		} else if (event.button === 2) {
    				if (event.ctrlKey && fileManager  !== "") {
    						UCL.showFile(label);
    				} else {
    				closeMenus(event.target);
    				this.edit(this.getFileFromLeafName(label));
    				}
    		}
    	},
    	getFileFromLeafName: function(aLeafName) {
    		let f = this.FOLDER.clone();
    		f.QueryInterface(Ci.nsIFile); // use appendRelativePath
    		f.appendRelativePath(aLeafName);
    		return f;
    	},
    	showFile: function(fname) {
    				const PathSep = AppConstants.platform === "win" ? "\\" : "/";
    				let target= this.FOLDER.path + PathSep + fname;
    				let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
    				let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
    				let args = (!fileManagerParamPost) ? [fileManagerParam,target] :
    				           [target,fileManagerParam];
    				file.initWithPath(fileManager);
    				process.init(file);
    				// Verzeichnis mit anderem Dateimanager öffnen
    				process.run(false, args, args.length);
    	},
    	openCSSFolder:function(){
    		if (fileManager !== "" && fileManagerParam !== "/select,") {
    				let target = this.FOLDER.path;
    				let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
    				let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
    				let args = (!fileManagerParamPost) ? [fileManagerParam,target] :
    				           [target,fileManagerParam];
    				file.initWithPath(fileManager);
    				process.init(file);
    				// Verzeichnis mit anderem Dateimanager öffnen
    				process.run(false, args, args.length);
    		} else {
    				// Verzeichnis mit Dateimanager des Systems öffnen
    				this.FOLDER.launch();
    		}
    	},
    	openCHRMFolder:function(){
    		if (fileManager !== "" && fileManagerParam !== "/select,") {
    				let target = this.CHRMFOLDER.path;
    				let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
    				let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
    				let args = (!fileManagerParamPost) ? [fileManagerParam,target] :
    				           [target,fileManagerParam];
    				file.initWithPath(fileManager);
    				process.init(file);
    				// Verzeichnis mit anderem Dateimanager öffnen
    				process.run(false, args, args.length);
    		} else {
    				// Verzeichnis mit Dateimanager des Systems öffnen
    				this.CHRMFOLDER.launch();
    		}
    	},
    	editUserCSS: function(aLeafName) {
    		let file = Services.dirsvc.get("UChrm", Ci.nsIFile);
    		file.appendRelativePath(aLeafName);
    		this.edit(file);
    	},
        editProfileFile: function(filename) {
            let file = Services.dirsvc.get("ProfD", Ci.nsIFile);
            file.append(filename);
            this.edit(file);
        },
    	edit: function(aFile) {
    		let editor = (customEditor !== "") ? customEditor : Services.prefs.getCharPref("view_source.editor.path");
    		if (!editor) return alert('In der Konfiguration einen Texteditor festlegen ("customEditor") oder\n unter about:config im vorhandenen Schalter "view_source.editor.path"\n den vollständigen Editorpfad eintragen.');
    		try {
    			let UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
    			UI.charset = window.navigator.platform.toLowerCase().indexOf("win") >= 0? "Shift_JIS": "UTF-8";
    			let path = UI.ConvertFromUnicode(aFile.path);
    			let app = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
    			app.initWithPath(editor);
    			let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
    			process.init(app);
    			process.run(false, [path], 1);
    		} catch (e) {}
    	},
    	create: function(aLeafName) {
    		if (!aLeafName) aLeafName = prompt("Name des Styles", dateFormat(new Date(), "%Y_%m%d_%H%M%S"));
    		if (aLeafName) aLeafName = aLeafName.replace(/\s+/g, " ").replace(/[\\/:*?\"<>|]/g, "");
    		if (!aLeafName || !/\S/.test(aLeafName)) return;
    		if (!/\.css$/.test(aLeafName)) aLeafName += ".css";
    		let file = this.getFileFromLeafName(aLeafName);
    		this.edit(file);
    	},
    	UCrebuild: function() {
    		let re = /^file:.*\.uc\.css(?:\?\d+)?$/i;
    		let query = "?" + new Date().getTime();
    		Array.slice(document.styleSheets).forEach(function(css){
    			if (!re.test(css.href)) return;
    			if (css.ownerNode) {
    				css.ownerNode.parentNode.removeChild(css.ownerNode);
    			}
    			let pi = document.createProcessingInstruction('xml-stylesheet','type="text/css" href="'+ css.href.replace(/\?.*/, '') + query +'"');
    			document.insertBefore(pi, document.documentElement);
    		});
    		UCL.UCcreateMenuitem();
    	},
    	UCcreateMenuitem: function() {
    		let sep = $("usercssloader-ucseparator");
    		let popup = sep.parentNode;
    		if (sep.nextSibling) {
    			let range = document.createRange();
    			range.setStartAfter(sep);
    			range.setEndAfter(popup.lastChild);
    			range.deleteContents();
    			range.detach();
    		}
    		let re = /^file:.*\.uc\.css(?:\?\d+)?$/i;
    		Array.slice(document.styleSheets).forEach(function(css) {
    			if (!re.test(css.href)) return;
    			let fileURL = decodeURIComponent(css.href).split("?")[0];
    			let aLeafName = fileURL.split("/").pop();
    			let m = $C("menuitem", {
    				label: aLeafName,
    				tooltiptext: fileURL,
    				id: "usercssloader-" + aLeafName,
    				type: "checkbox",
    				autocheck: "false",
    				checked: "true",
    			});
    			m.css = css;
    			m.addEventListener("command", function() {
    				if (!event.ctrlKey) {this.setAttribute("checked", !(this.css.disabled = !this.css.disabled));}
    			});
    			m.addEventListener("mouseup", function(event) {
    				if (event.button === 1) event.preventDefault();
    			});
    			m.addEventListener("click", function(event) {
    				UCL.UCItemClick(event);
    			});
    			popup.appendChild(m);
    		});
    	},
    	UCItemClick: function(event) {
    		if (event.button === 0) return;
    		event.preventDefault();
    		event.stopPropagation();
    		if (event.button === 1) {
    			event.target.doCommand();
    		}
    		else if (event.button === 2) {
    			closeMenus(event.target);
    			let fileURL = event.currentTarget.getAttribute("tooltiptext");
    			let file = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getFileFromURLSpec(fileURL);
    			this.edit(file);
    		}
    	},
    };
    function CSSEntry(aFile) {
    	this.path = aFile.path;
    	this.leafName = aFile.leafName;
    	this.lastModifiedTime = 1;
    	this.SHEET = /^xul-|\.as\.css$/i.test(this.leafName) ?
    		Ci.nsIStyleSheetService.AGENT_SHEET:
    		/\.author\.css$/i.test(this.leafName)?
    			Ci.nsIStyleSheetService.AUTHOR_SHEET:
    			Ci.nsIStyleSheetService.USER_SHEET;
    }
    CSSEntry.prototype = {
    	sss: Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService),
    	_enabled: false,
    	get enabled() {
    		return this._enabled;
    	},
    	set enabled(isEnable) {
    		let aFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile)
    		aFile.initWithPath(this.path);
    		let isExists = aFile.exists(); // true, wenn die Datei bereits existiert
    		let lastModifiedTime = isExists ? aFile.lastModifiedTime : 0;
    		let isForced = this.lastModifiedTime != lastModifiedTime; //true, wenn es eine Änderung in der Datei gibt
    		let fileURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromActualFile(aFile);
    		let uri = Services.io.newURI(fileURL, null, null);
    		if (this.sss.sheetRegistered(uri, this.SHEET)) {
    			// Wenn diese Datei bereits gelesen wurde
    			if (!isEnable || !isExists) {
    				this.sss.unregisterSheet(uri, this.SHEET);
    			}
    			else if (isForced) {
    				// Nach Stornierung erneut einlesen
    				this.sss.unregisterSheet(uri, this.SHEET);
    				this.sss.loadAndRegisterSheet(uri, this.SHEET);
    			}
    		} else {
    			// Datei wurde nicht gelesen
    			if (isEnable && isExists) {
    				this.sss.loadAndRegisterSheet(uri, this.SHEET);
    			}
    		}
    		if (this.lastModifiedTime !== 1 && isEnable && isForced) {
    			log(this.leafName + " wurde aktualisiert");
    		}
    		this.lastModifiedTime = lastModifiedTime;
    		return this._enabled = isEnable;
    	},
    };
    UCL.init();
    function $(id) { return document.getElementById(id); }
    function $A(arr) { return Array.slice(arr); }
    function $C(name, attr) {
    	const el = document.createXULElement(name);
    	if (attr) Object.keys(attr).forEach(function(n) { el.setAttribute(n, attr[n]) });
    	return el;
    }
    function dateFormat(date, format) {
    	format = format.replace("%Y", ("000" + date.getFullYear()).substr(-4));
    	format = format.replace("%m", ("0" + (date.getMonth()+1)).substr(-2));
    	format = format.replace("%d", ("0" + date.getDate()).substr(-2));
    	format = format.replace("%H", ("0" + date.getHours()).substr(-2));
    	format = format.replace("%M", ("0" + date.getMinutes()).substr(-2));
    	format = format.replace("%S", ("0" + date.getSeconds()).substr(-2));
    	return format;
    }
    function log(mes) { console.log(mes); }
    })();
    Alles anzeigen
  • Meine Version des App-Menüs (JavaScript)

    • Mira_Belle
    • 4. Oktober 2025 um 13:11

    Problem gelöst!
    Ersetze gDevToolsBrowser.toggleToolboxCommand(window.gBrowser, Cu.now());
    durch gDevToolsBrowser.toggleToolboxCommand(window.gBrowser, performance.now());

Unterstütze uns!

Jährlich (2025)

105,8 %

105,8% (687,41 von 650 EUR)

Jetzt spenden
  1. Kontakt
  2. Datenschutz
  3. Impressum
Community-Software: WoltLab Suite™
Mastodon