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. FuchsFan

Beiträge von FuchsFan

  • Profilmanager

    • FuchsFan
    • 13. Mai 2026 um 19:09
    Zitat von 2002Andreas

    Sieht hier so aus:

    Ja, genau so ist es.

  • Profilmanager

    • FuchsFan
    • 13. Mai 2026 um 19:01

    Ja, auch, denn ich kann das nicht nachvollziehen. Denn in der profiles.ini steht z.B. für meinen ArbeitsFox das geschrieben:

    [Profile0]
    Name=ArbeitsFox
    IsRelative=1
    Path=Profiles/qtqwpmy7.default-release
    StoreID=b2d0fa71
    ShowSelector=1


    [Install60EDFDC9594E2591]
    Default=Profiles/qtqwpmy7.default-release
    Locked=1

  • Profilmanager

    • FuchsFan
    • 13. Mai 2026 um 18:56

    Ist das wirklich aus der profiles.ini ?

  • Profilmanager

    • FuchsFan
    • 13. Mai 2026 um 08:56
    Zitat von Mira_Belle

    Und da liegt auch "mein" Problem,
    denn das Profil der Nightly wird ja auch angezeigt und ist dann eben nicht nutzbar, da nicht mit der Nightly verknüpft.

    In Zeile 126 ist ja der Pfad zur profiles.ini anzugeben, ich stelle mir vor, dass eine weitere Zeile zur profiles.ini von Nightly das Problem dann lösen könnte.


    Das Script angepasst für mehrere Installationen (Stable/Beta/Nightly). Kann es nicht testen, weil nur Stable installiert ist.

    CSS
    // == PROFILSTARTER.UC.JS v11 ==
    console.log("=== PROFILSTARTER.UC.JS v11 - Stable + Beta + Nightly (Widget Fix) ===");
    
    (function() {
    
      if (!window.gBrowser)
        return;
    
      // User Settings
      let btn_id = 'aboutprofiles-Start';          // Button #id
      const btn_icon = 'p2.png';                   // Symbol
      const iconPath = 'file:///C:/FoxIcons/';     // Icon-Ordner
      const ImagePath = iconPath + btn_icon;
    
      const btn_label = 'Profil zusätzlich starten';
      const btn_tooltiptext = 'Zusätzliche Firefox-Profile starten';
    
      const POPUP_ID = btn_id + '-popup';
    
      // ============== CSS ==============
      function injectUserCSS() {
        try {
          const css = `
            #${btn_id} image.toolbarbutton-icon {
              transform: scale(1.0) !important;
              padding: 6px !important;
            }
            #${POPUP_ID} {
              max-width: 285px !important;
            }
            #${POPUP_ID} menuitem {
              padding-inline-start: 8px !important;
              padding-inline-end: 8px !important;
              margin: 0 !important;
              min-height: 24px !important;
            }
            #${POPUP_ID} menuitem.menuitem-iconic .menu-icon {
              margin-inline-end: 8px !important;
              margin-inline-start: -30px !important;
              width: 16px !important;
              height: 16px !important;
            }
            #${POPUP_ID} menuitem.menuitem-iconic .menu-text {
              margin-left: 8px !important;
              font-weight: 500 !important;
              padding: 2px 0 2px 0 !important;
            }
            #${POPUP_ID} menuitem.menuitem-iconic:hover .menu-text {
              margin-left: 8px !important;
              font-weight: 600 !important;
              color: red !important;
              opacity: 1 !important;
            }
          `;
    
          const Cc = Components.classes;
          const Ci = Components.interfaces;
          const Cu = Components.utils;
    
          const Services = globalThis.Services || Cu.import("resource://gre/modules/Services.jsm").Services;
          const sss = Cc["@mozilla.org/content/style-sheet-service;1"]
                      .getService(Ci.nsIStyleSheetService);
    
          const uri = Services.io.newURI(
            "data:text/css;charset=utf-8," + encodeURIComponent(css)
          );
    
          if (!sss.sheetRegistered(uri, sss.AUTHOR_SHEET)) {
            sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
          }
        } catch (e) {
          console.error("[PROFILSTARTER] CSS Fehler:", e);
        }
      }
    
      // ============== Profil-Daten ==============
      const PROFIL_NAMEN = {
        "ArbeitsFox":        { name: " ArbeitsFox  ( >>Standard<< ) 🏠",     icon: "Finale.png" },
        "Einkauf":           { name: " Einkaufen  ( >>Shops<< ) 🏠",         icon: "s4.png" },
        "default":           { name: " Nicht starten  ( >>Default<< ) 🏠",   icon: "warnung19.png" },
        "Reserve":           { name: " Reserve 1  ( >>Ersatz-Profil<< ) 🏠", icon: "Firefox32.png" },
        "Reserve-Profil 2":  { name: " Reserve 2  ( >>Ersatz-Profil<< ) 🏠", icon: "Firefox32.png" },
        "Reserve 3":         { name: " Reserve 3  ( >>Ersatz-Profil<< ) 🏠", icon: "Firefox32.png" }
      };
    
      function startProfile(profileName, exePath) {
        try {
          const Cc = Components.classes;
          const Ci = Components.interfaces;
    
          let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
          let defaultPath = "C:\\Program Files\\Mozilla Firefox\\firefox.exe";
          file.initWithPath(exePath || defaultPath);
    
          let args = ["-no-remote", "-P", profileName || "", "-foreground"];
          let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
          process.init(file);
          process.run(false, args, args.length);
    
          console.log("[PROFILSTARTER] Start:", profileName, "EXE:", exePath || defaultPath);
        } catch (e) {
          console.error("[PROFILSTARTER] Start Fehler:", e);
        }
      }
    
      function addProfileItem(aDocument, menupopup, label, profileName, exePath, iconURI = null) {
        const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
        let item = aDocument.createElementNS(xulNS, "menuitem");
        item.setAttribute("label", label);
    
        if (iconURI) {
          item.setAttribute("class", "menuitem-iconic");
          item.setAttribute("image", iconURI);
        }
    
        item.addEventListener("command", () => startProfile(profileName, exePath));
        menupopup.appendChild(item);
      }
    
      function isPlaceholderPath(p) {
        if (!p) return true;
        const s = String(p);
        return s.toUpperCase().includes("PUT_BETA_") ||
               s.toUpperCase().includes("PUT_NIGHTLY_") ||
               s.toUpperCase().includes("HIER_EINTRAGEN");
      }
    
      // ============== NEU: Kanal-Instanzen (Stable/Beta/Nightly) ==============
      // iniPath: ...\profiles.ini
      // exePath: ...\firefox.exe (bzw. der echte Channel-Exe-Pfad)
      const FIREFOX_INSTANCES = [
        {
          id: "Stable",
          channelLabel: "Stable",
          iniPath: "C:\\Users\\Old Man\\AppData\\Roaming\\Mozilla\\Firefox\\profiles.ini",
          exePath: "C:\\Program Files\\Mozilla Firefox\\firefox.exe"
        },
        {
          id: "Beta",
          channelLabel: "Beta",
          iniPath: "PUT_BETA_PROFILES_INI_PATH_HIER_EINTRAGEN",
          exePath: "PUT_BETA_FIREFOX_EXE_PATH_HIER_EINTRAGEN"
        },
        {
          id: "Nightly",
          channelLabel: "Nightly",
          iniPath: "PUT_NIGHTLY_PROFILES_INI_PATH_HIER_EINTRAGEN",
          exePath: "PUT_NIGHTLY_FIREFOX_EXE_PATH_HIER_EINTRAGEN"
        }
      ];
    
      function loadProfilesWithNiceNames(aDocument, menupopup, iniPath, exePath, channelLabel, addedKeys) {
        const ICON_BASE = "file:///C:/FoxIcons/";
    
        try {
          if (isPlaceholderPath(iniPath) || isPlaceholderPath(exePath)) {
            return; // Kanal ignorieren, solange Pfade nicht gesetzt sind
          }
    
          let iniFile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIFile);
          iniFile.initWithPath(iniPath);
    
          if (!iniFile.exists()) {
            addProfileItem(aDocument, menupopup,
              `❌ ${channelLabel}: profiles.ini fehlt`,
              "",
              null,
              null
            );
            return;
          }
    
          const iniParser = Components.classes["@mozilla.org/xpcom/ini-parser-factory;1"]
            .getService(Components.interfaces.nsIINIParserFactory)
            .createINIParser(iniFile);
    
          for (let section of iniParser.getSections()) {
            if (!section.startsWith("Profile")) continue;
    
            let profileNameRaw = iniParser.getString(section, "Name") || section.replace("Profile", "");
            let eintrag = PROFIL_NAMEN[profileNameRaw];
    
            let niceName, iconURI = null;
    
            if (eintrag && typeof eintrag === "object") {
              niceName = eintrag.name + ` (${channelLabel})`;
              if (eintrag.icon) iconURI = ICON_BASE + eintrag.icon;
            } else {
              niceName = profileNameRaw + ` (unbekannt, ${channelLabel})`;
            }
    
            const key = channelLabel + "|" + iniPath + "|" + profileNameRaw;
            if (addedKeys.has(key)) continue;
            addedKeys.add(key);
    
            addProfileItem(aDocument, menupopup, niceName, profileNameRaw, exePath, iconURI);
          }
    
        } catch (e) {
          console.error("[PROFILSTARTER] INI Fehler (" + channelLabel + "):", e);
          addProfileItem(aDocument, menupopup,
            `❌ ${channelLabel}: INI Fehler`,
            "",
            null,
            null
          );
        }
      }
    
      function buildPopupIfNeeded() {
        const button = document.getElementById(btn_id);
        if (!button) return null;
    
        if (button.getAttribute("profiles-menu-built") === "true") {
          return document.getElementById(POPUP_ID);
        }
    
        const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
        let popup = document.getElementById(POPUP_ID);
    
        if (!popup) {
          popup = document.createElementNS(xulNS, "menupopup");
          popup.setAttribute("id", POPUP_ID);
          button.appendChild(popup);
        } else {
          while (popup.firstChild) popup.removeChild(popup.firstChild);
        }
    
        const addedKeys = new Set();
    
        // Stable/Beta/Nightly
        for (const inst of FIREFOX_INSTANCES) {
          loadProfilesWithNiceNames(
            document,
            popup,
            inst.iniPath,
            inst.exePath,
            inst.channelLabel,
            addedKeys
          );
        }
    
        // Portable U (Originalteil)
        addProfileItem(document, popup,
          "Portable U Nightly 3 🔥", "profile",
          "G:\\Portable.Firefox.Updater.3\\Firefox Nightly x64 Launcher.exe",
          "file:///C:/FoxIcons/Nightly.png"
        );
        addProfileItem(document, popup,
          "️Portable U Stable 3 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.3\\Firefox Stable x64 Launcher.exe",
          "file:///C:/FoxIcons/Finale.png"
        );
        addProfileItem(document, popup,
          "️Portable U Beta 3 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.3\\Firefox Beta x64 Launcher.exe",
          "file:///C:/FoxIcons/Beta.png"
        );
    
        addProfileItem(document, popup,
          "Portable U Nightly 1 🔥", "profile",
          "G:\\Portable.Firefox.Updater.1\\Firefox Nightly x64 Launcher.exe",
          "file:///C:/FoxIcons/Nightly.png"
        );
        addProfileItem(document, popup,
          "️Portable U Stable 1 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.1\\Firefox Stable x64 Launcher.exe",
          "file:///C:/FoxIcons/Finale.png"
        );
        addProfileItem(document, popup,
          "️Portable U Beta 1 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.1\\Firefox Beta x64 Launcher.exe",
          "file:///C:/FoxIcons/Beta.png"
        );
    
        addProfileItem(document, popup,
          "Portable U Nightly 2 🔥", "profile",
          "G:\\Portable.Firefox.Updater.2\\Firefox Nightly x64 Launcher.exe",
          "file:///C:/FoxIcons/Nightly.png"
        );
        addProfileItem(document, popup,
          "️Portable U Stable 2 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.2\\Firefox Stable x64 Launcher.exe",
          "file:///C:/FoxIcons/Finale.png"
        );
        addProfileItem(document, popup,
          "️Portable U Beta 2 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.2\\Firefox Beta x64 Launcher.exe",
          "file:///C:/FoxIcons/Beta.png"
        );
    
        addProfileItem(document, popup,
          "Portable U Nightly 4 🔥", "profile",
          "G:\\Portable.Firefox.Updater.4\\Firefox Nightly x64 Launcher.exe",
          "file:///C:/FoxIcons/Nightly.png"
        );
        addProfileItem(document, popup,
          "️Portable U Stable 4 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.4\\Firefox Stable x64 Launcher.exe",
          "file:///C:/FoxIcons/Finale.png"
        );
        addProfileItem(document, popup,
          "️Portable U Beta 4 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.4\\Firefox Beta x64 Launcher.exe",
          "file:///C:/FoxIcons/Beta.png"
        );
    
        button.setAttribute("profiles-menu-built", "true");
        return popup;
      }
    
      function click_button() {
        let button = document.getElementById(btn_id);
        if (!button) return;
    
        if (button.hasAttribute("listener-added"))
          return;
    
        button.setAttribute("listener-added", "true");
    
        // Kontextmenü unterdrücken
        button.addEventListener("contextmenu", event => {
          event.preventDefault();
        });
    
        // Klick: Popup öffnen (links oder rechts)
        button.addEventListener('click', event => {
          event.preventDefault();
          event.stopPropagation();
    
          injectUserCSS();
          let popup = buildPopupIfNeeded();
          if (!popup) return;
    
          try {
            popup.openPopup(button, "after_start", 0, 0, false, false);
          } catch (e) {
            console.error("[PROFILSTARTER] openPopup Fehler:", e);
          }
        });
      }
    
      // Widget anlegen (mit Logging statt stummem Catch!)
      function ensureWidget() {
        try {
          if (!window.CustomizableUI) {
            console.error("[PROFILSTARTER] CustomizableUI nicht verfügbar.");
            return;
          }
    
          const existing = window.CustomizableUI.getWidget
            ? window.CustomizableUI.getWidget(btn_id)
            : null;
    
          if (existing) {
            console.log("[PROFILSTARTER] Widget existiert bereits:", btn_id);
            return;
          }
    
          console.log("[PROFILSTARTER] Erstelle Widget:", btn_id);
    
          CustomizableUI.createWidget({
            id: btn_id,
            defaultArea: CustomizableUI.AREA_NAVBAR,
            label: btn_label,
            tooltiptext: btn_tooltiptext,
    
            onCreated: (this_button) => {
              try {
                this_button.style.listStyleImage = 'url("' + ImagePath + '")';
                this_button.style.minWidth = 'fit-content';
              } catch (e) {
                console.error("[PROFILSTARTER] onCreated style Fehler:", e);
              }
              console.log("[PROFILSTARTER] Widget onCreated OK:", btn_id);
            }
          });
    
        } catch (e) {
          console.error("[PROFILSTARTER] Widget FEHLER:", e);
        }
      }
    
      // Listener pro Fenster setzen
      function initForWindow() {
        // Erst Widget erzwingen
        ensureWidget();
    
        if (window.readyState !== "loading") {
          setTimeout(click_button, 300);
        } else {
          window.addEventListener("DOMContentLoaded", () => setTimeout(click_button, 300));
        }
      }
    
      initForWindow();
    
      window.addEventListener('aftercustomization', () => {
        setTimeout(() => click_button(), 100);
      });
    
    })();
    Alles anzeigen

    Was du nur noch anpassen musst•Trage in FIREFOX_INSTANCES die 3 iniPath-Pfade und 3 exePath-Pfade ein (Stable/Beta/Nightly).

  • Profilmanager

    • FuchsFan
    • 12. Mai 2026 um 21:56
    Zitat von Mira_Belle

    Im Script wird aber dann für die Nightly so etwas "C:\\Program Files\\Firefox Nightly\\firefox.exe -P Nightly -foreground", aufgerufen.

    Wie ich oben angab, die installierten Versionen werden über die profiles.ini automatisch ausgelesen und übernommen. Nun habe ich als installierte Version nur die Finale, Beta und Nightly sind portable (auch noch Stable), deswegen kann ich es nicht prüfen, wie es sich verhält, wenn mehrere Versionen installiert sind.

  • Profilmanager

    • FuchsFan
    • 12. Mai 2026 um 19:24

    Das Script legt in der Navbar einen Button an, über den ein Menü mit den Profilen gezeigt wird. Die Profile (Namen der installierten Versionen) werden aus der profiles.ini eingelesen. Für portable Versionen müssen im Script Angaben erfolgen (Beispiele sind enthalten).
    Da die Namen der installierten Profile manchmal sehr verwirrend sind, so gibt es im Script den Block "Profil-Daten", über den aus den kryptischen dann Wunschnamen erstellt werden können. Ganz links muss immer der richtige Name des Profils angegeben werden (about:profiles), rechts dann der Wunschname. Es können beliebig viele Profile damit gestartet werden.

    CSS
    // == PROFILSTARTER.UC.JS v9 ==
    console.log("=== PROFILSTARTER.UC.JS v9 - MULTI-FENSTER FIX ===");
    
    (function() {
    
      if (!window.gBrowser)
        return;
    
      // User Settings
      let btn_id = 'aboutprofiles-Start';          // Button #id
      const btn_icon = 'p2.png';                   // Symbol
      const iconPath = 'file:///C:/FoxIcons/';     // Icon-Ordner
      const ImagePath = iconPath + btn_icon;
    
      const btn_label = 'Profil zusätzlich starten';
      const btn_tooltiptext = 'Zusätzliche Firefox-Profile starten';
    
      const POPUP_ID = btn_id + '-popup';
    
      // ============== CSS ==============
      function injectUserCSS() {
        try {
          const css = `
            #${btn_id} image.toolbarbutton-icon {
              transform: scale(1.0) !important;
              padding: 6px !important;
            }
            #${POPUP_ID} {
              max-width: 285px !important;
            }
            #${POPUP_ID} menuitem {
              padding-inline-start: 8px !important;
              padding-inline-end: 8px !important;
              margin: 0 !important;
              min-height: 24px !important;
            }
            #${POPUP_ID} menuitem.menuitem-iconic .menu-icon {
              margin-inline-end: 8px !important;
              margin-inline-start: -30px !important;
              width: 16px !important;
              height: 16px !important;
            }
            #${POPUP_ID} menuitem.menuitem-iconic .menu-text {
              margin-left: 8px !important;
              font-weight: 500 !important;
              padding: 2px 0 2px 0 !important;
            }
            #${POPUP_ID} menuitem.menuitem-iconic:hover .menu-text {
              margin-left: 8px !important;
              font-weight: 600 !important;
              color: red !important;
              opacity: 1 !important;
            }
          `;
    
          const Cc = Components.classes;
          const Ci = Components.interfaces;
          const Cu = Components.utils;
    
          const Services = globalThis.Services || Cu.import("resource://gre/modules/Services.jsm").Services;
          const sss = Cc["@mozilla.org/content/style-sheet-service;1"]
                      .getService(Ci.nsIStyleSheetService);
    
          const uri = Services.io.newURI(
            "data:text/css;charset=utf-8," + encodeURIComponent(css)
          );
    
          if (!sss.sheetRegistered(uri, sss.AUTHOR_SHEET)) {
            sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
          }
        } catch (e) {
          console.error("[PROFILSTARTER] CSS Fehler:", e);
        }
      }
    
      // ============== Profil-Daten ==============
      const PROFIL_NAMEN = {
    	
        "ArbeitsFox":        { name: " ArbeitsFox  ( >>Standard<< ) 🏠",     icon: "Finale.png" },
        "Einkauf":           { name: " Einkaufen  ( >>Shops<< ) 🏠",         icon: "s4.png" },
        "default":           { name: " Nicht starten  ( >>Default<< ) 🏠",   icon: "warnung19.png" },
        "Reserve":           { name: " Reserve 1  ( >>Ersatz-Profil<< ) 🏠", icon: "Firefox32.png" },
        "Reserve-Profil 2":  { name: " Reserve 2  ( >>Ersatz-Profil<< ) 🏠", icon: "Firefox32.png" },
        "Reserve 3":         { name: " Reserve 3  ( >>Ersatz-Profil<< ) 🏠", icon: "Firefox32.png" }
      };
    
      function startProfile(profileName, exePath) {
        try {
          const Cc = Components.classes;
          const Ci = Components.interfaces;
    
          let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
          let defaultPath = "C:\\Program Files\\Mozilla Firefox\\firefox.exe";
          file.initWithPath(exePath || defaultPath);
    
          let args = ["-no-remote", "-P", profileName || "", "-foreground"];
          let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
          process.init(file);
          process.run(false, args, args.length);
    
          console.log("[PROFILSTARTER] Start:", profileName, "EXE:", exePath || defaultPath);
        } catch (e) {
          console.error("[PROFILSTARTER] Start Fehler:", e);
        }
      }
    
      function addProfileItem(aDocument, menupopup, label, profileName, exePath, iconURI = null) {
        const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
        let item = aDocument.createElementNS(xulNS, "menuitem");
        item.setAttribute("label", label);
    
        if (iconURI) {
          item.setAttribute("class", "menuitem-iconic");
          item.setAttribute("image", iconURI);
        }
    
        item.addEventListener("command", () => startProfile(profileName, exePath));
        menupopup.appendChild(item);
      }
    
      function loadProfilesWithNiceNames(aDocument, menupopup) {
        const Cc = Components.classes;
        const Ci = Components.interfaces;
        const ICON_BASE = "file:///C:/FoxIcons/";
    
        const INI_PATH = "C:\\Users\\Old Man\\AppData\\Roaming\\Mozilla\\Firefox\\profiles.ini";
    
        try {
          let iniFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
          iniFile.initWithPath(INI_PATH);
    
          if (!iniFile.exists()) {
            addProfileItem(aDocument, menupopup, "❌ profiles.ini fehlt", "", null, null);
            return;
          }
    
          const iniParser = Cc["@mozilla.org/xpcom/ini-parser-factory;1"]
            .getService(Ci.nsIINIParserFactory)
            .createINIParser(iniFile);
    
          for (let section of iniParser.getSections()) {
            if (!section.startsWith("Profile")) continue;
    
            let profileNameRaw = iniParser.getString(section, "Name") || section.replace("Profile", "");
            let eintrag = PROFIL_NAMEN[profileNameRaw];
    
            let niceName, iconURI = null;
    
            if (eintrag && typeof eintrag === "object") {
              niceName = eintrag.name;
              if (eintrag.icon) iconURI = ICON_BASE + eintrag.icon;
            } else {
              niceName = profileNameRaw + " (unbekannt)";
            }
    
            addProfileItem(aDocument, menupopup, niceName, profileNameRaw, null, iconURI);
          }
        } catch (e) {
          console.error("[PROFILSTARTER] INI Fehler:", e);
          addProfileItem(aDocument, menupopup, "❌ profiles.ini Fehler", "", null, null);
        }
      }
    
      function buildPopupIfNeeded() {
        const button = document.getElementById(btn_id);
        if (!button) return null;
    
        if (button.getAttribute("profiles-menu-built") === "true") {
          return document.getElementById(POPUP_ID);
        }
    
        const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
        let popup = document.getElementById(POPUP_ID);
    
        if (!popup) {
          popup = document.createElementNS(xulNS, "menupopup");
          popup.setAttribute("id", POPUP_ID);
          button.appendChild(popup);
        } else {
          // ggf. vorherige Einträge löschen
          while (popup.firstChild) popup.removeChild(popup.firstChild);
        }
    
        // Profile aus profiles.ini
        loadProfilesWithNiceNames(document, popup);
    
        // Portable Profile 
        addProfileItem(document, popup,
          "Portable U Nightly 3 🔥", "profile",
          "G:\\Portable.Firefox.Updater.3\\Firefox Nightly x64 Launcher.exe",
          "file:///C:/FoxIcons/Nightly.png"
        );
        addProfileItem(document, popup,
          "️Portable U Stable 3 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.3\\Firefox Stable x64 Launcher.exe",
          "file:///C:/FoxIcons/Finale.png"
        );
        addProfileItem(document, popup,
          "️Portable U Beta 3 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.3\\Firefox Beta x64 Launcher.exe",
          "file:///C:/FoxIcons/Beta.png"
        );
    
        addProfileItem(document, popup,
          "Portable U Nightly 1 🔥", "profile",
          "G:\\Portable.Firefox.Updater.1\\Firefox Nightly x64 Launcher.exe",
          "file:///C:/FoxIcons/Nightly.png"
        );
        addProfileItem(document, popup,
          "️Portable U Stable 1 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.1\\Firefox Stable x64 Launcher.exe",
          "file:///C:/FoxIcons/Finale.png"
        );
        addProfileItem(document, popup,
          "️Portable U Beta 1 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.1\\Firefox Beta x64 Launcher.exe",
          "file:///C:/FoxIcons/Beta.png"
        );
    
        addProfileItem(document, popup,
          "Portable U Nightly 2 🔥", "profile",
          "G:\\Portable.Firefox.Updater.2\\Firefox Nightly x64 Launcher.exe",
          "file:///C:/FoxIcons/Nightly.png"
        );
        addProfileItem(document, popup,
          "️Portable U Stable 2 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.2\\Firefox Stable x64 Launcher.exe",
          "file:///C:/FoxIcons/Finale.png"
        );
        addProfileItem(document, popup,
          "️Portable U Beta 2 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.2\\Firefox Beta x64 Launcher.exe",
          "file:///C:/FoxIcons/Beta.png"
        );
    
        addProfileItem(document, popup,
          "Portable U Nightly 4 🔥", "profile",
          "G:\\Portable.Firefox.Updater.4\\Firefox Nightly x64 Launcher.exe",
          "file:///C:/FoxIcons/Nightly.png"
        );
        addProfileItem(document, popup,
          "️Portable U Stable 4 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.4\\Firefox Stable x64 Launcher.exe",
          "file:///C:/FoxIcons/Finale.png"
        );
        addProfileItem(document, popup,
          "️Portable U Beta 4 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.4\\Firefox Beta x64 Launcher.exe",
          "file:///C:/FoxIcons/Beta.png"
        );
    
        button.setAttribute("profiles-menu-built", "true");
        return popup;
      }
    
      function click_button() {
        let button = document.getElementById(btn_id);
        if (!button) return;
    
        if (button.hasAttribute("listener-added"))
          return;
    
        button.setAttribute("listener-added", "true");
    
        // Kontextmenü unterdrücken
        button.addEventListener("contextmenu", event => {
          event.preventDefault();
        });
    
        // Klick: Popup öffnen (links oder rechts)
        button.addEventListener('click', event => {
          // Linksklick / Rechtsklick gleich behandeln
          event.preventDefault();
          event.stopPropagation();
    
          injectUserCSS();
          let popup = buildPopupIfNeeded();
          if (!popup) return;
    
          // Popup am Button öffnen
          try {
            popup.openPopup(button, "after_start", 0, 0, false, false);
          } catch (e) {
            console.error("[PROFILSTARTER] openPopup Fehler:", e);
          }
        });
      }
    
      // Widget anlegen (nur einmal versuchen, wie im Template)
      try {
        CustomizableUI.createWidget({
          id: btn_id,
          defaultArea: CustomizableUI.AREA_NAVBAR,
          label: btn_label,
          tooltiptext: btn_tooltiptext,
    
          onCreated: (this_button) => {
            this_button.style.listStyleImage = 'url("' + ImagePath + '")';
            this_button.style.minWidth = 'fit-content';
          }
        });
      } catch (e) {
        // Widget existiert evtl. schon -> ignorieren
      }
    
      // Listener pro Fenster setzen
      function initForWindow() {
        if (window.readyState !== "loading") {
          setTimeout(click_button, 300);
        } else {
          window.addEventListener("DOMContentLoaded", () => setTimeout(click_button, 300));
        }
      }
    
      initForWindow();
    
      window.addEventListener('aftercustomization', () => {
        setTimeout(() => click_button(), 100);
      });
    
    })();
    Alles anzeigen

    Nachtrag:

    Sorry, hatte ich nicht mehr dran gedacht, wurde vor langer Zeit mit KI geschaffen.

  • Skript für den Toolbox-Button funktioniert im Nightly nicht mehr

    • FuchsFan
    • 4. Mai 2026 um 21:59
    Zitat von bege

    Vielleicht ist das der bessere Weg das Skript anzupassen.

    Würde ich auch empfehlen, denn das ist für KI eine Nummer zu groß.

  • Skript für den Toolbox-Button funktioniert im Nightly nicht mehr

    • FuchsFan
    • 4. Mai 2026 um 20:00

    Noch mal etliche Versuche gestartet, nun sollte auch der Mittelklick funktionieren:

    JavaScript
    // ==UserScript==
    // @name           Toolbox Button
    // @version        1.5.2-nightly152
    // @author         aminomancer
    // @homepageURL    https://github.com/aminomancer/uc.css.js
    // @description    Adds a toolbar button for content toolbox, browser toolbox, and popup autohide.
    // @downloadURL    https://cdn.jsdelivr.net/gh/aminomancer/uc.css.js@master/JS/atoolboxButton.uc.js
    // @updateURL      https://cdn.jsdelivr.net/gh/aminomancer/uc.css.js@master/JS/atoolboxButton.uc.js
    // @license        CC BY-NC-SA 4.0
    // ==/UserScript==
    
    (() => {
    	const l10n = {
    		alreadyOpenMsg: "Browser Werkzeuge sind bereits geöffnet.",
    		holdingOpenMsg: "Popups werden offen gehalten.",
    		lettingCloseMsg: "Popups werden automatisch geschlossen.",
    		bundles: {},
    		strings: new Map(),
    		getString(name, where) {
    			let string = this.strings.get(name);
    			if (string) return string;
    			string = this.bundles[where].GetStringFromName(name);
    			this.strings.set(name, string);
    			return string;
    		},
    		getFluentValue(id, args) {
    			return this.fluentStrings.formatValueSync(id, args);
    		},
    		get defaultLabel() {
    			return this.getString("toolbox.label", "toolbox");
    		},
    		get defaultTooltip() {
    			return this.defaultLabel;
    		},
    	};
    
    	ChromeUtils.defineLazyGetter(l10n.bundles, "menu", () =>
    		Services.strings.createBundle("chrome://devtools/locale/menus.properties")
    	);
    	ChromeUtils.defineLazyGetter(l10n.bundles, "toolbox", () =>
    		Services.strings.createBundle("chrome://devtools/locale/toolbox.properties")
    	);
    	ChromeUtils.defineLazyGetter(
    		l10n,
    		"fluentStrings",
    		() => new Localization(["devtools/client/toolbox.ftl"], true)
    	);
    
    	if (
    		/^chrome:\/\/browser\/content\/browser\.(xul|xhtml)$/i.test(location.href) &&
    		!CustomizableUI.getPlacementOfWidget("toolbox-button", true)
    	) {
    		const { loader } = ChromeUtils.importESModule(
    			"resource://devtools/shared/loader/Loader.sys.mjs"
    		);
    		const lazy = {};
    		ChromeUtils.defineESModuleGetters(lazy, {
    			BrowserToolboxLauncher:
    				"resource://devtools/client/framework/browser-toolbox/Launcher.sys.mjs",
    		});
    		for (const [key, val] of Object.entries({
    			gDevToolsBrowser:
    				"resource://devtools/client/framework/devtools-browser.js",
    			Actor: "resource://devtools/shared/protocol/Actor.js",
    			dumpn: "resource://devtools/shared/DevToolsUtils.js",
    		})) {
    			loader.lazyRequireGetter(lazy, key, val, true);
    		}
    
    		if (location.href !== "chrome://browser/content/browser.xhtml") return;
    
    		CustomizableUI.createWidget({
    			id: "toolbox-button",
    			type: "custom",
    			defaultArea: CustomizableUI.AREA_NAVBAR,
    			label: l10n.defaultLabel,
    			removable: true,
    			overflows: true,
    			tooltiptext: l10n.defaultTooltip,
    			onBuild(aDoc) {
    				const win = aDoc?.defaultView || aDoc?.ownerGlobal || window;
    				if (!win) {
    					console.error("Toolbox Button: no window available in onBuild()");
    					return null;
    				}
    
    				let CustomHint = {
    					...win.ConfirmationHint,
    					show(anchor, message, options = {}) {
    						this._reset();
    						this._message.removeAttribute("data-l10n-id");
    						this._message.textContent = message;
    
    						if (options.description) {
    							this._description.removeAttribute("data-l10n-id");
    							this._description.textContent = options.description;
    							this._description.hidden = false;
    							this._panel.classList.add("with-description");
    						} else {
    							this._description.hidden = true;
    							this._panel.classList.remove("with-description");
    						}
    
    						if (options.hideArrow) {
    							this._panel.setAttribute("hidearrow", "true");
    						}
    
    						if (options.hideCheck) {
    							this._animationBox.setAttribute("hidden", "true");
    							this._panel.setAttribute("data-message-id", "hideCheckHint");
    						} else {
    							this._animationBox.removeAttribute("hidden");
    							this._panel.setAttribute("data-message-id", "checkmarkHint");
    						}
    
    						const DURATION = options.duration || 1500;
    						this._panel.addEventListener(
    							"popupshown",
    							() => {
    								this._animationBox.setAttribute("animate", "true");
    								this._timerID = setTimeout(
    									() => this._panel.hidePopup(true),
    									DURATION + 120
    								);
    							},
    							{ once: true }
    						);
    
    						this._panel.addEventListener("popuphidden", () => this._reset(), {
    							once: true,
    						});
    
    						let { position, x, y } = options;
    						this._panel.openPopup(null, {
    							position,
    							triggerEvent: options.event,
    						});
    						this._panel.moveToAnchor(anchor, position, x, y);
    					},
    
    					_reset() {
    						if (this._timerID) {
    							clearTimeout(this._timerID);
    							this._timerID = null;
    							this._animationBox.removeAttribute("hidden");
    						}
    						if (this.__panel) {
    							this._panel.removeAttribute("hidearrow");
    							this._animationBox.removeAttribute("animate");
    							this._panel.removeAttribute("data-message-id");
    							this._panel.hidePopup();
    						}
    					},
    
    					_ensurePanel() {
    						if (!this.__panel) {
    							let wrapper = win.document.getElementById("confirmation-hint-wrapper");
    							wrapper?.replaceWith(wrapper.content);
    							this.__panel = ConfirmationHint.__panel =
    								win.document.getElementById("confirmation-hint");
    						}
    					},
    				};
    
    				let toolbarbutton = aDoc.createXULElement("toolbarbutton");
    				let badgeStack = aDoc.createXULElement("stack");
    				let icon = aDoc.createXULElement("image");
    				let label = aDoc.createXULElement("label");
    				let badgeLabel = aDoc.createElement("label");
    				for (const [key, val] of Object.entries({
    					class: "toolbarbutton-1 chromeclass-toolbar-additional",
    					badged: true,
    					label: l10n.defaultLabel,
    					id: "toolbox-button",
    					role: "button",
    					icon: "toolbox",
    					removable: true,
    					overflows: true,
    					tooltiptext: l10n.defaultTooltip,
    				})) {
    					toolbarbutton.setAttribute(key, val);
    				}
    
    				toolbarbutton.appendChild(badgeStack);
    				badgeStack.after(label);
    				badgeStack.appendChild(icon);
    				icon.after(badgeLabel);
    				badgeStack.setAttribute("class", "toolbarbutton-badge-stack");
    				icon.setAttribute("class", "toolbarbutton-icon");
    				badgeLabel.setAttribute("class", "toolbarbutton-badge");
    				for (const [key, val] of Object.entries({
    					class: "toolbarbutton-text",
    					crop: "right",
    					flex: "1",
    					value: l10n.defaultLabel,
    				})) {
    					label.setAttribute(key, val);
    				}
    
    				let prefSvc = Services.prefs;
    				let defaultPrefs = prefSvc.getDefaultBranch("");
    				let obSvc = Services.obs;
    				let toolboxBranch = "userChrome.toolboxButton";
    				let autoHide = "ui.popup.disable_autohide";
    				let autoTogglePopups =
    					"userChrome.toolboxButton.popupAutohide.toggle-on-toolbox-launch";
    				let mouseConfig = "userChrome.toolboxButton.mouseConfig";
    				const BROWSER_TOOLBOX_WINDOW_URL =
    					"chrome://devtools/content/framework/browser-toolbox/window.html";
    
    				toolbarbutton.browserToolboxOpen = false;
    				toolbarbutton.pendingBrowserToolboxOpen = false;
    				toolbarbutton.manualPopupAutohide = false;
    				toolbarbutton.autoTogglePopups = true;
    				toolbarbutton.popupAutoHide = false;
    				toolbarbutton.mouseConfig = {
    					contentToolbox: 0,
    					browserToolbox: 2,
    					popupHide: 1,
    				};
    
    				function getPref(root, pref) {
    					switch (root.getPrefType(pref)) {
    						case root.PREF_BOOL:
    							return root.getBoolPref(pref);
    						case root.PREF_INT:
    							return root.getIntPref(pref);
    						case root.PREF_STRING:
    							return root.getStringPref(pref);
    						default:
    							return null;
    					}
    				}
    
    				function hasBrowserToolboxWindow() {
    					try {
    						for (const win of Services.wm.getEnumerator(null)) {
    							if (!win || win.closed) continue;
    							if (win.location?.href === BROWSER_TOOLBOX_WINDOW_URL) {
    								return true;
    							}
    						}
    					} catch (ex) {
    						console.error("Browser toolbox window scan failed:", ex);
    					}
    					return false;
    				}
    
    				function refreshState() {
    					const open = hasBrowserToolboxWindow() || toolbarbutton.pendingBrowserToolboxOpen;
    					toolbarbutton.browserToolboxOpen = open;
    					badgeLabel.textContent = open ? "1" : "";
    
    					// If the user explicitly toggled the pref via middle click, do not let
    					// the automatic sync logic override that choice anymore.
    					if (toolbarbutton.manualPopupAutohide) {
    						return;
    					}
    
    					if (!toolbarbutton.autoTogglePopups) return;
    					if (open && !toolbarbutton.popupAutoHide) {
    						prefSvc.setBoolPref(autoHide, true);
    					} else if (!open && toolbarbutton.popupAutoHide) {
    						prefSvc.setBoolPref(autoHide, false);
    					}
    				}
    
    				function prefObserver(sub, _top, pref) {
    					let value = getPref(sub, pref);
    					switch (pref) {
    						case autoHide:
    							if (value === null) value = false;
    							toolbarbutton.popupAutoHide = value;
    							if (value) {
    								toolbarbutton.setAttribute("icon", "autohide");
    								icon.style.fill = "var(--toolbarbutton-icon-fill-attention)";
    							} else {
    								toolbarbutton.setAttribute("icon", "toolbox");
    								icon.style.removeProperty("fill");
    							}
    							break;
    						case autoTogglePopups:
    							if (value === null) value = true;
    							toolbarbutton.autoTogglePopups = value;
    							break;
    						case mouseConfig:
    							if (value === null) {
    								value = JSON.stringify({
    									contentToolbox: 0,
    									browserToolbox: 2,
    									popupHide: 1,
    								});
    							}
    							toolbarbutton.mouseConfig = JSON.parse(value);
    							toolbarbutton.setStrings();
    							break;
    					}
    				}
    
    				toolbarbutton.setStrings = function () {
    					let hotkey, labelString;
    					for (const [key, val] of Object.entries(toolbarbutton.mouseConfig)) {
    						if (val === 0) {
    							switch (key) {
    								case "contentToolbox":
    									labelString = l10n.getString("toolbox.label", "toolbox");
    									hotkey = aDoc.getElementById("key_toggleToolbox");
    									break;
    								case "browserToolbox":
    									labelString = l10n.getString("browserToolboxMenu.label", "menu");
    									hotkey = aDoc.getElementById("key_browserToolbox");
    									break;
    								case "popupHide":
    									labelString = l10n.getFluentValue(
    										"toolbox-meatball-menu-noautohide-label"
    									);
    									break;
    							}
    						}
    					}
    					let shortcut = hotkey ? ` (${ShortcutUtils.prettifyShortcut(hotkey)})` : "";
    					toolbarbutton.label = labelString;
    					label.value = labelString;
    					toolbarbutton.tooltipText = labelString + shortcut;
    				};
    
    				toolbarbutton.triggerAnimation = function () {
    					this.addEventListener(
    						"animationend",
    						() => this.removeAttribute("animate"),
    						{ once: true }
    					);
    					this.setAttribute("animate", "true");
    				};
    
    				let onClick = function (e) {
    					if (e.type === "auxclick" && e.button !== 1) {
    						return;
    					}
    
    					let { button } = e;
    					let accel = e.getModifierState("Accel");
    					let shift = e.getModifierState("Shift");
    
    					if (accel) {
    						if (button == 2 && !shift) {
    							return;
    						}
    						if (button == 0 && AppConstants.platform == "macosx") {
    							button = 2;
    							accel = false;
    						}
    					}
    
    					switch (button) {
    						case this.mouseConfig.contentToolbox:
    							lazy.gDevToolsBrowser.toggleToolboxCommand(win.gBrowser);
    							break;
    
    						case this.mouseConfig.browserToolbox:
    							refreshState();
    							if (toolbarbutton.browserToolboxOpen || toolbarbutton.pendingBrowserToolboxOpen) {
    								CustomHint.show(toolbarbutton, l10n.alreadyOpenMsg, {
    									event: e,
    									hideCheck: true,
    								});
    							} else {
    								try {
    									toolbarbutton.pendingBrowserToolboxOpen = true;
    									refreshState();
    									const launcher = lazy.BrowserToolboxLauncher.init({
    										forceMultiprocess: accel && shift,
    										onRun() {
    											toolbarbutton.pendingBrowserToolboxOpen = false;
    											refreshState();
    										},
    									});
    									if (!launcher) {
    										toolbarbutton.pendingBrowserToolboxOpen = false;
    										refreshState();
    										CustomHint.show(
    											toolbarbutton,
    											"Browser Toolbox konnte nicht gestartet werden.",
    											{ event: e, hideCheck: true }
    										);
    									}
    								} catch (ex) {
    									toolbarbutton.pendingBrowserToolboxOpen = false;
    									refreshState();
    									console.error("Browser Toolbox launch failed:", ex);
    									CustomHint.show(
    										toolbarbutton,
    										"Browser Toolbox konnte nicht gestartet werden.",
    										{ event: e, hideCheck: true }
    									);
    								}
    							}
    							break;
    
    						case this.mouseConfig.popupHide:
    							// Middle click should enable popup auto-hide and keep that choice,
    							// without the automatic refresh logic turning it back off.
    							toolbarbutton.manualPopupAutohide = true;
    							prefSvc.setBoolPref(autoHide, true);
    							CustomHint.show(toolbarbutton, l10n.holdingOpenMsg, {
    								event: e,
    								hideCheck: false,
    							});
    							toolbarbutton.triggerAnimation();
    							break;
    
    						default:
    							return;
    					}
    
    					e.preventDefault();
    				};
    
    				if (AppConstants.platform === "macosx") {
    					toolbarbutton.onmousedown = onClick;
    					toolbarbutton.onclick = e => {
    						if (e.getModifierState("Accel")) return;
    						e.preventDefault();
    					};
    				} else {
    					toolbarbutton.onclick = onClick;
    					toolbarbutton.onauxclick = onClick;
    				}
    
    				function toolboxInit() {
    					prefObserver(prefSvc, null, autoHide);
    					prefObserver(prefSvc, null, autoTogglePopups);
    					prefObserver(prefSvc, null, mouseConfig);
    					refreshState();
    				}
    
    				function uninit() {
    					clearInterval(toolbarbutton._syncTimer);
    					toolbarbutton.browserToolboxOpen = false;
    					toolbarbutton.pendingBrowserToolboxOpen = false;
    					toolbarbutton.manualPopupAutohide = false;
    					prefSvc.removeObserver(autoHide, prefObserver);
    					prefSvc.removeObserver(toolboxBranch, prefObserver);
    					window.removeEventListener("unload", uninit);
    				}
    
    				defaultPrefs.setBoolPref(autoTogglePopups, true);
    				defaultPrefs.setStringPref(
    					mouseConfig,
    					'{"contentToolbox": 0, "browserToolbox": 2, "popupHide": 1}'
    				);
    
    				window.addEventListener("unload", uninit);
    				prefSvc.addObserver(autoHide, prefObserver);
    				prefSvc.addObserver(toolboxBranch, prefObserver);
    
    				toolbarbutton._syncTimer = setInterval(refreshState, 1000);
    				refreshState();
    
    				if (gBrowserInit.delayedStartupFinished) {
    					toolboxInit();
    				} else {
    					let delayedListener2 = (subject, topic) => {
    						if (topic == "browser-delayed-startup-finished" && subject == window) {
    							obSvc.removeObserver(delayedListener2, topic);
    							toolboxInit();
    						}
    					};
    					obSvc.addObserver(delayedListener2, "browser-delayed-startup-finished");
    				}
    
    				return toolbarbutton;
    			},
    		});
    	}
    
    	let styleSvc = Cc["@mozilla.org/content/style-sheet-service;1"].getService(
    		Ci.nsIStyleSheetService
    	);
    	let toolboxCSS = /* css */ `
    		.toolbarbutton-1#toolbox-button {
    			--uc-toolbox-button: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAdUlEQVQokZVSwRHAIAgLPYfoXs7RCTpG53Avt7APrhaFU8gLMEEJAkEQgFbc7IxkVjt0r6Sp7VIVITumBpKt00FA2ThmjXzkfMMWO8EZFSj8LrUyjsG9b9DaJXq+qAIVxEUxtLHpaXE95dj1NcK2rmbwaGJ4Af0tIg00j/6iAAAAAElFTkSuQmCC');
    			--uc-autohide-button: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAATCAYAAABlcqYFAAABeUlEQVQ4ja3UMSiEcRjH8Z8jKWU8q03JYEAhZ7PcZDFYrMpOWaTEgsEom4RFBmEjcSaEU0onFN0Rd9dFzr3er+Ut7vV/eS/vU7/l3/s8n/f/PvVKrkKKIm0hJZEoIUmkTaQO90w3MFniYK8MewHRgACQLKRmE7IRIALSkglJBYzcmhDPhrtwGJ6fIZeDTOYrwF5ri2dfSchBZxumOpoY5+mXvpKQ7NzID+Dl4Z6TitCvn8w3kpbIJS5dxBv7TbV/7sU3chOuAssqIqzMOfGZUV5W1yAWIzE4+D9kp6vLGf0KWLjrIx9nO9L4T6SmhrWePs7GI2A/FgHvJ/PEqwNaPBLHPZEi4HB6ipugdoJEQeJqZRYAO59kt7+B1B+AF+L5101UCgppwOYwWmceWubk6+zChKx7IamVXk6XxzgtD/Hh4wZOFkxIO5LtfjgrsdVdRjzkPdAA55HqfyAONIRU8Pmm2ObzPNKAEfgGNSMtIl37xZxcIy2YbvAJBGtcN/WRF/UAAAAASUVORK5CYII');
    			list-style-image: var(--uc-toolbox-button);
    			align-items: center;
    		}
    		.toolbarbutton-1#toolbox-button[icon="autohide"] {
    			list-style-image: var(--uc-autohide-button);
    		}
    		.toolbarbutton-1#toolbox-button .toolbarbutton-badge-stack {
    			justify-items: center;
    		}
    		.toolbarbutton-1#toolbox-button .toolbarbutton-icon {
    			height: 16px;
    			width: 16px;
    			transition: fill 50ms ease-in-out 0s;
    			background-image: var(--uc-toolbox-button), var(--uc-autohide-button);
    			background-size: 0, 0;
    		}
    		@media (prefers-reduced-motion: no-preference) {
    			.toolbarbutton-1#toolbox-button[animate] .toolbarbutton-icon {
    				animation-name: toolboxButtonPulse;
    				animation-duration: 200ms;
    				animation-iteration-count: 1;
    				animation-timing-function: ease-in-out;
    			}
    		}
    		@keyframes toolboxButtonPulse {
    			from { transform: scale(1); }
    			40% { transform: scale(0.7); }
    			to { transform: scale(1); }
    		}
    		#confirmation-hint[data-message-id="hideCheckHint"] #confirmation-hint-message {
    			margin-inline: 0;
    		}
    		#confirmation-hint-checkmark-animation-container {
    			width: 16px !important;
    			height: 16px !important;
    		}
    		#confirmation-hint-checkmark-animation-container[animate] > #confirmation-hint-checkmark-image {
    			background-image: url("file:///E:/ICONS/FF/Checkbox.checked16-2.png") !important;
    			min-width: 16px !important;
    			max-width: 16px !important;
    			min-height: 16px !important;
    			max-height: 16px !important;
    			animation-name: unset !important;
    		}
    	`;
    
    	if (location.href !== "chrome://browser/content/browser.xhtml") return;
    	let styleURI = makeURI(`data:text/css;charset=UTF=8,${encodeURIComponent(toolboxCSS)}`);
    	if (!styleSvc.sheetRegistered(styleURI, styleSvc.AUTHOR_SHEET)) {
    		styleSvc.loadAndRegisterSheet(styleURI, styleSvc.AUTHOR_SHEET);
    	}
    
    	let observer = new MutationObserver(() => {
    		if (document.getElementById("key_toggleToolbox")) {
    			CustomizableUI.getWidget("toolbox-button")
    				.forWindow(window)
    				.node.setStrings();
    			observer.disconnect();
    			observer = null;
    		}
    	});
    	observer.observe(document.body, { childList: true });
    })();
    Alles anzeigen
  • Skript für den Toolbox-Button funktioniert im Nightly nicht mehr

    • FuchsFan
    • 4. Mai 2026 um 19:22
    Zitat von 2002Andreas

    Funktioniert teilweise, der Haken wird nicht mehr automatisch gesetzt:

    Ja, Andreas, die Mittelklick-Funktion arbeitet auch nicht, es wird nur der Tooltip angezeigt.

  • Skript für den Toolbox-Button funktioniert im Nightly nicht mehr

    • FuchsFan
    • 4. Mai 2026 um 18:56

    Habe das mit KI versucht, Button wird angezeigt, und Funktionen reagieren (Links, Mittel, und auch Rechts-Klick). Teste mal bitte:

    JavaScript
    // ==UserScript==
    // @name           Toolbox Button
    // @version        1.5.1-nightly152
    // @author         aminomancer
    // @homepageURL    https://github.com/aminomancer/uc.css.js
    // @long-description
    // @description
    /*
    	Adds a new toolbar button that 1) opens the content toolbox on left click; 2) opens the browser toolbox on right click; 3) toggles "Popup Auto-Hide" on middle click.
    */
    // @downloadURL    https://cdn.jsdelivr.net/gh/aminomancer/uc.css.js@master/JS/atoolboxButton.uc.js
    // @updateURL      https://cdn.jsdelivr.net/gh/aminomancer/uc.css.js@master/JS/atoolboxButton.uc.js
    // @license        CC BY-NC-SA 4.0
    // ==/UserScript==
    
    (() => {
    	const l10n = {
    		alreadyOpenMsg: "Browser Werkzeuge sind bereits geöffnet.",
    		holdingOpenMsg: "Popups werden offen gehalten.",
    		lettingCloseMsg: "Popups werden automatisch geschlossen.",
    		bundles: {},
    		strings: new Map(),
    		getString(name, where) {
    			let string = this.strings.get(name);
    			if (string) return string;
    			string = this.bundles[where].GetStringFromName(name);
    			this.strings.set(name, string);
    			return string;
    		},
    		getFluentValue(id, args) {
    			return this.fluentStrings.formatValueSync(id, args);
    		},
    		get defaultLabel() {
    			return this.getString("toolbox.label", "toolbox");
    		},
    		get defaultTooltip() {
    			return this.defaultLabel;
    		},
    	};
    
    	ChromeUtils.defineLazyGetter(l10n.bundles, "menu", () =>
    		Services.strings.createBundle("chrome://devtools/locale/menus.properties")
    	);
    	ChromeUtils.defineLazyGetter(l10n.bundles, "toolbox", () =>
    		Services.strings.createBundle("chrome://devtools/locale/toolbox.properties")
    	);
    	ChromeUtils.defineLazyGetter(
    		l10n,
    		"fluentStrings",
    		() => new Localization(["devtools/client/toolbox.ftl"], true)
    	);
    
    	if (
    		/^chrome:\/\/browser\/content\/browser\.(xul|xhtml)$/i.test(location.href) &&
    		!CustomizableUI.getPlacementOfWidget("toolbox-button", true)
    	) {
    		const { loader } = ChromeUtils.importESModule(
    			"resource://devtools/shared/loader/Loader.sys.mjs"
    		);
    		const lazy = {};
    		ChromeUtils.defineESModuleGetters(lazy, {
    			BrowserToolboxLauncher:
    				"resource://devtools/client/framework/browser-toolbox/Launcher.sys.mjs",
    		});
    		for (const [key, val] of Object.entries({
    			gDevToolsBrowser:
    				"resource://devtools/client/framework/devtools-browser.js",
    			Actor: "resource://devtools/shared/protocol/Actor.js",
    			dumpn: "resource://devtools/shared/DevToolsUtils.js",
    		})) {
    			loader.lazyRequireGetter(lazy, key, val, true);
    		}
    
    		if (location.href !== "chrome://browser/content/browser.xhtml") return;
    
    		CustomizableUI.createWidget({
    			id: "toolbox-button",
    			type: "custom",
    			defaultArea: CustomizableUI.AREA_NAVBAR,
    			label: l10n.defaultLabel,
    			removable: true,
    			overflows: true,
    			tooltiptext: l10n.defaultTooltip,
    			onBuild(aDoc) {
    				const win = aDoc?.defaultView || aDoc?.ownerGlobal || window;
    				if (!win) {
    					console.error("Toolbox Button: no window available in onBuild()");
    					return null;
    				}
    
    				let CustomHint = {
    					...win.ConfirmationHint,
    					show(anchor, message, options = {}) {
    						this._reset();
    						this._message.removeAttribute("data-l10n-id");
    						this._message.textContent = message;
    
    						if (options.description) {
    							this._description.removeAttribute("data-l10n-id");
    							this._description.textContent = options.description;
    							this._description.hidden = false;
    							this._panel.classList.add("with-description");
    						} else {
    							this._description.hidden = true;
    							this._panel.classList.remove("with-description");
    						}
    
    						if (options.hideArrow) {
    							this._panel.setAttribute("hidearrow", "true");
    						}
    
    						if (options.hideCheck) {
    							this._animationBox.setAttribute("hidden", "true");
    							this._panel.setAttribute("data-message-id", "hideCheckHint");
    						} else {
    							this._animationBox.removeAttribute("hidden");
    							this._panel.setAttribute("data-message-id", "checkmarkHint");
    						}
    
    						const DURATION = options.duration || 1500;
    						this._panel.addEventListener(
    							"popupshown",
    							() => {
    								this._animationBox.setAttribute("animate", "true");
    								this._timerID = setTimeout(
    									() => this._panel.hidePopup(true),
    									DURATION + 120
    								);
    							},
    							{ once: true }
    						);
    
    						this._panel.addEventListener("popuphidden", () => this._reset(), {
    							once: true,
    						});
    
    						let { position, x, y } = options;
    						this._panel.openPopup(null, {
    							position,
    							triggerEvent: options.event,
    						});
    						this._panel.moveToAnchor(anchor, position, x, y);
    					},
    
    					_reset() {
    						if (this._timerID) {
    							clearTimeout(this._timerID);
    							this._timerID = null;
    							this._animationBox.removeAttribute("hidden");
    						}
    						if (this.__panel) {
    							this._panel.removeAttribute("hidearrow");
    							this._animationBox.removeAttribute("animate");
    							this._panel.removeAttribute("data-message-id");
    							this._panel.hidePopup();
    						}
    					},
    
    					_ensurePanel() {
    						if (!this.__panel) {
    							let wrapper = win.document.getElementById("confirmation-hint-wrapper");
    							wrapper?.replaceWith(wrapper.content);
    							this.__panel = ConfirmationHint.__panel =
    								win.document.getElementById("confirmation-hint");
    						}
    					},
    				};
    
    				let toolbarbutton = aDoc.createXULElement("toolbarbutton");
    				let badgeStack = aDoc.createXULElement("stack");
    				let icon = aDoc.createXULElement("image");
    				let label = aDoc.createXULElement("label");
    				let badgeLabel = aDoc.createElement("label");
    				for (const [key, val] of Object.entries({
    					class: "toolbarbutton-1 chromeclass-toolbar-additional",
    					badged: true,
    					label: l10n.defaultLabel,
    					id: "toolbox-button",
    					role: "button",
    					icon: "toolbox",
    					removable: true,
    					overflows: true,
    					tooltiptext: l10n.defaultTooltip,
    				})) {
    					toolbarbutton.setAttribute(key, val);
    				}
    
    				toolbarbutton.appendChild(badgeStack);
    				badgeStack.after(label);
    				badgeStack.appendChild(icon);
    				icon.after(badgeLabel);
    				badgeStack.setAttribute("class", "toolbarbutton-badge-stack");
    				icon.setAttribute("class", "toolbarbutton-icon");
    				badgeLabel.setAttribute("class", "toolbarbutton-badge");
    				for (const [key, val] of Object.entries({
    					class: "toolbarbutton-text",
    					crop: "right",
    					flex: "1",
    					value: l10n.defaultLabel,
    				})) {
    					label.setAttribute(key, val);
    				}
    
    				let prefSvc = Services.prefs;
    				let defaultPrefs = prefSvc.getDefaultBranch("");
    				let obSvc = Services.obs;
    				let toolboxBranch = "userChrome.toolboxButton";
    				let autoHide = "ui.popup.disable_autohide";
    				let autoTogglePopups =
    					"userChrome.toolboxButton.popupAutohide.toggle-on-toolbox-launch";
    				let mouseConfig = "userChrome.toolboxButton.mouseConfig";
    				const BROWSER_TOOLBOX_WINDOW_URL =
    					"chrome://devtools/content/framework/browser-toolbox/window.html";
    
    				toolbarbutton.browserToolboxOpen = false;
    				toolbarbutton.pendingBrowserToolboxOpen = false;
    				toolbarbutton.autoTogglePopups = true;
    				toolbarbutton.popupAutoHide = false;
    				toolbarbutton.mouseConfig = {
    					contentToolbox: 0,
    					browserToolbox: 2,
    					popupHide: 1,
    				};
    
    				function getPref(root, pref) {
    					switch (root.getPrefType(pref)) {
    						case root.PREF_BOOL:
    							return root.getBoolPref(pref);
    						case root.PREF_INT:
    							return root.getIntPref(pref);
    						case root.PREF_STRING:
    							return root.getStringPref(pref);
    						default:
    							return null;
    					}
    				}
    
    				function hasBrowserToolboxWindow() {
    					try {
    						for (const win of Services.wm.getEnumerator(null)) {
    							if (!win || win.closed) continue;
    							if (win.location?.href === BROWSER_TOOLBOX_WINDOW_URL) {
    								return true;
    							}
    						}
    					} catch (ex) {
    						console.error("Browser toolbox window scan failed:", ex);
    					}
    					return false;
    				}
    
    				function refreshState() {
    					const open = hasBrowserToolboxWindow() || toolbarbutton.pendingBrowserToolboxOpen;
    					toolbarbutton.browserToolboxOpen = open;
    					badgeLabel.textContent = open ? "1" : "";
    					if (!toolbarbutton.autoTogglePopups) return;
    					if (open && !toolbarbutton.popupAutoHide) {
    						prefSvc.setBoolPref(autoHide, true);
    					} else if (!open && toolbarbutton.popupAutoHide) {
    						prefSvc.setBoolPref(autoHide, false);
    					}
    				}
    
    				function prefObserver(sub, _top, pref) {
    					let value = getPref(sub, pref);
    					switch (pref) {
    						case autoHide:
    							if (value === null) value = false;
    							toolbarbutton.popupAutoHide = value;
    							if (value) {
    								toolbarbutton.setAttribute("icon", "autohide");
    								icon.style.fill = "var(--toolbarbutton-icon-fill-attention)";
    							} else {
    								toolbarbutton.setAttribute("icon", "toolbox");
    								icon.style.removeProperty("fill");
    							}
    							break;
    						case autoTogglePopups:
    							if (value === null) value = true;
    							toolbarbutton.autoTogglePopups = value;
    							break;
    						case mouseConfig:
    							if (value === null) {
    								value = JSON.stringify({
    									contentToolbox: 0,
    									browserToolbox: 2,
    									popupHide: 1,
    								});
    							}
    							toolbarbutton.mouseConfig = JSON.parse(value);
    							toolbarbutton.setStrings();
    							break;
    					}
    				}
    
    				toolbarbutton.setStrings = function () {
    					let hotkey, labelString;
    					for (const [key, val] of Object.entries(toolbarbutton.mouseConfig)) {
    						if (val === 0) {
    							switch (key) {
    								case "contentToolbox":
    									labelString = l10n.getString("toolbox.label", "toolbox");
    									hotkey = aDoc.getElementById("key_toggleToolbox");
    									break;
    								case "browserToolbox":
    									labelString = l10n.getString("browserToolboxMenu.label", "menu");
    									hotkey = aDoc.getElementById("key_browserToolbox");
    									break;
    								case "popupHide":
    									labelString = l10n.getFluentValue(
    										"toolbox-meatball-menu-noautohide-label"
    									);
    									break;
    							}
    						}
    					}
    					let shortcut = hotkey ? ` (${ShortcutUtils.prettifyShortcut(hotkey)})` : "";
    					toolbarbutton.label = labelString;
    					label.value = labelString;
    					toolbarbutton.tooltipText = labelString + shortcut;
    				};
    
    				toolbarbutton.triggerAnimation = function () {
    					this.addEventListener(
    						"animationend",
    						() => this.removeAttribute("animate"),
    						{ once: true }
    					);
    					this.setAttribute("animate", "true");
    				};
    
    				let onClick = function (e) {
    					let { button } = e;
    					let accel = e.getModifierState("Accel");
    					let shift = e.getModifierState("Shift");
    
    					if (accel) {
    						if (button == 2 && !shift) {
    							return;
    						}
    						if (button == 0 && AppConstants.platform == "macosx") {
    							button = 2;
    							accel = false;
    						}
    					}
    
    					switch (button) {
    						case this.mouseConfig.contentToolbox:
    							lazy.gDevToolsBrowser.toggleToolboxCommand(win.gBrowser);
    							break;
    
    						case this.mouseConfig.browserToolbox:
    							refreshState();
    							if (toolbarbutton.browserToolboxOpen || toolbarbutton.pendingBrowserToolboxOpen) {
    								CustomHint.show(toolbarbutton, l10n.alreadyOpenMsg, {
    									event: e,
    									hideCheck: true,
    								});
    							} else {
    								try {
    									toolbarbutton.pendingBrowserToolboxOpen = true;
    									refreshState();
    									const launcher = lazy.BrowserToolboxLauncher.init({
    										forceMultiprocess: accel && shift,
    										onRun() {
    											toolbarbutton.pendingBrowserToolboxOpen = false;
    											refreshState();
    										},
    									});
    									if (!launcher) {
    										toolbarbutton.pendingBrowserToolboxOpen = false;
    										refreshState();
    										CustomHint.show(
    											toolbarbutton,
    											"Browser Toolbox konnte nicht gestartet werden.",
    											{ event: e, hideCheck: true }
    										);
    									}
    								} catch (ex) {
    									toolbarbutton.pendingBrowserToolboxOpen = false;
    									refreshState();
    									console.error("Browser Toolbox launch failed:", ex);
    									CustomHint.show(
    										toolbarbutton,
    										"Browser Toolbox konnte nicht gestartet werden.",
    										{ event: e, hideCheck: true }
    									);
    								}
    							}
    							break;
    
    						case this.mouseConfig.popupHide:
    							CustomHint.show(
    								toolbarbutton,
    								l10n[toolbarbutton.popupAutoHide ? "lettingCloseMsg" : "holdingOpenMsg"],
    								{ event: e, hideCheck: toolbarbutton.popupAutoHide }
    							);
    							prefSvc.setBoolPref(autoHide, !toolbarbutton.popupAutoHide);
    							toolbarbutton.triggerAnimation();
    							break;
    
    						default:
    							return;
    					}
    
    					e.preventDefault();
    				};
    
    				if (AppConstants.platform === "macosx") {
    					toolbarbutton.onmousedown = onClick;
    					toolbarbutton.onclick = e => {
    						if (e.getModifierState("Accel")) return;
    						e.preventDefault();
    					};
    				} else {
    					toolbarbutton.onclick = onClick;
    				}
    
    				function toolboxInit() {
    					prefObserver(prefSvc, null, autoHide);
    					prefObserver(prefSvc, null, autoTogglePopups);
    					prefObserver(prefSvc, null, mouseConfig);
    					refreshState();
    				}
    
    				function uninit() {
    					clearInterval(toolbarbutton._syncTimer);
    					toolbarbutton.browserToolboxOpen = false;
    					toolbarbutton.pendingBrowserToolboxOpen = false;
    					prefSvc.removeObserver(autoHide, prefObserver);
    					prefSvc.removeObserver(toolboxBranch, prefObserver);
    					window.removeEventListener("unload", uninit);
    				}
    
    				defaultPrefs.setBoolPref(autoTogglePopups, true);
    				defaultPrefs.setStringPref(
    					mouseConfig,
    					'{"contentToolbox": 0, "browserToolbox": 2, "popupHide": 1}'
    				);
    
    				window.addEventListener("unload", uninit);
    				prefSvc.addObserver(autoHide, prefObserver);
    				prefSvc.addObserver(toolboxBranch, prefObserver);
    
    				toolbarbutton._syncTimer = setInterval(refreshState, 1000);
    				refreshState();
    
    				if (gBrowserInit.delayedStartupFinished) {
    					toolboxInit();
    				} else {
    					let delayedListener2 = (subject, topic) => {
    						if (topic == "browser-delayed-startup-finished" && subject == window) {
    							obSvc.removeObserver(delayedListener2, topic);
    							toolboxInit();
    						}
    					};
    					obSvc.addObserver(delayedListener2, "browser-delayed-startup-finished");
    				}
    
    				return toolbarbutton;
    			},
    		});
    	}
    
    	let styleSvc = Cc["@mozilla.org/content/style-sheet-service;1"].getService(
    		Ci.nsIStyleSheetService
    	);
    	let toolboxCSS = /* css */ `
    		.toolbarbutton-1#toolbox-button {
    			--uc-toolbox-button: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAdUlEQVQokZVSwRHAIAgLPYfoXs7RCTpG53Avt7APrhaFU8gLMEEJAkEQgFbc7IxkVjt0r6Sp7VIVITumBpKt00FA2ThmjXzkfMMWO8EZFSj8LrUyjsG9b9DaJXq+qAIVxEUxtLHpaXE95dj1NcK2rmbwaGJ4Af0tIg00j/6iAAAAAElFTkSuQmCC');
    			--uc-autohide-button: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAATCAYAAABlcqYFAAABeUlEQVQ4ja3UMSiEcRjH8Z8jKWU8q03JYEAhZ7PcZDFYrMpOWaTEgsEom4RFBmEjcSaEU0onFN0Rd9dFzr3er+Ut7vV/eS/vU7/l3/s8n/f/PvVKrkKKIm0hJZEoIUmkTaQO90w3MFniYK8MewHRgACQLKRmE7IRIALSkglJBYzcmhDPhrtwGJ6fIZeDTOYrwF5ri2dfSchBZxumOpoY5+mXvpKQ7NzID+Dl4Z6TitCvn8w3kpbIJS5dxBv7TbV/7sU3chOuAssqIqzMOfGZUV5W1yAWIzE4+D9kp6vLGf0KWLjrIx9nO9L4T6SmhrWePs7GI2A/FgHvJ/PEqwNaPBLHPZEi4HB6ipugdoJEQeJqZRYAO59kt7+B1B+AF+L5101UCgppwOYwWmceWubk6+zChKx7IamVXk6XxzgtD/Hh4wZOFkxIO5LtfjgrsdVdRjzkPdAA55HqfyAONIRU8Pmm2ObzPNKAEfgGNSMtIl37xZxcIy2YbvAJBGtcN/WRF/UAAAAASUVORK5CYII');
    			list-style-image: var(--uc-toolbox-button);
    			align-items: center;
    		}
    		.toolbarbutton-1#toolbox-button[icon="autohide"] {
    			list-style-image: var(--uc-autohide-button);
    		}
    		.toolbarbutton-1#toolbox-button .toolbarbutton-badge-stack {
    			justify-items: center;
    		}
    		.toolbarbutton-1#toolbox-button .toolbarbutton-icon {
    			height: 16px;
    			width: 16px;
    			transition: fill 50ms ease-in-out 0s;
    			background-image: var(--uc-toolbox-button), var(--uc-autohide-button);
    			background-size: 0, 0;
    		}
    		@media (prefers-reduced-motion: no-preference) {
    			.toolbarbutton-1#toolbox-button[animate] .toolbarbutton-icon {
    				animation-name: toolboxButtonPulse;
    				animation-duration: 200ms;
    				animation-iteration-count: 1;
    				animation-timing-function: ease-in-out;
    			}
    		}
    		@keyframes toolboxButtonPulse {
    			from { transform: scale(1); }
    			40% { transform: scale(0.7); }
    			to { transform: scale(1); }
    		}
    		#confirmation-hint[data-message-id="hideCheckHint"] #confirmation-hint-message {
    			margin-inline: 0;
    		}
    		#confirmation-hint-checkmark-animation-container {
    			width: 16px !important;
    			height: 16px !important;
    		}
    		#confirmation-hint-checkmark-animation-container[animate] > #confirmation-hint-checkmark-image {
    			background-image: url("file:///E:/ICONS/FF/Checkbox.checked16-2.png") !important;
    			min-width: 16px !important;
    			max-width: 16px !important;
    			min-height: 16px !important;
    			max-height: 16px !important;
    			animation-name: unset !important;
    		}
    	`;
    
    	if (location.href !== "chrome://browser/content/browser.xhtml") return;
    	let styleURI = makeURI(`data:text/css;charset=UTF=8,${encodeURIComponent(toolboxCSS)}`);
    	if (!styleSvc.sheetRegistered(styleURI, styleSvc.AUTHOR_SHEET)) {
    		styleSvc.loadAndRegisterSheet(styleURI, styleSvc.AUTHOR_SHEET);
    	}
    
    	let observer = new MutationObserver(() => {
    		if (document.getElementById("key_toggleToolbox")) {
    			CustomizableUI.getWidget("toolbox-button")
    				.forWindow(window)
    				.node.setStrings();
    			observer.disconnect();
    			observer = null;
    		}
    	});
    	observer.observe(document.body, { childList: true });
    })();
    Alles anzeigen
  • Fx 150 > Searchbar Popup nicht bei focus öffnen

    • FuchsFan
    • 23. April 2026 um 18:48

    Das Script von hier RE: Fx 150 > Searchbar Popup nicht bei focus öffnen habe mit KI überarbeitet, und dabei von Dharkness den css-Code mit eingebaut. 2002Andreas hat getestet, und ist mit dem Ergebnis zufrieden (spart auch noch zwei Scripte ein).

    JavaScript
    // ==UserScript==
    // @name         Searchbar Auto-Clear + Go-Pfeil (Firefox 150+)
    // @description  Auto-leeren + Go/Enter behandelt, Popup für History/Suggestions geschlossen
    // @include      chrome://browser/content/browser.xhtml
    // @async        true
    // @version      2026/04/23
    // ==/UserScript==
    
    (function() {
      const waitingToClear = 15000; // ms | 0 = deaktiviert
      let suppressPopupUntil = 0;
    
      const lazy = {};
      ChromeUtils.defineESModuleGetters(lazy, {
        SearchService: "moz-src:///toolkit/components/search/SearchService.sys.mjs",
      });
    
      // ---- CSS für Go-Pfeil (optional) ----
      try {
        if (Services?.prefs?.getBoolPref("browser.search.widget.new", true)) {
          let style = `
            #searchbar-new[focused] vbox.urlbarView {
              display: none !important;
            }
            #searchbar-new[focused][usertyping] vbox.urlbarView {
              display: block !important;
            }
    
            #searchbar-new {
              .urlbar-go-button {
                display: flex !important;
                opacity: 0.8 !important;
                cursor: pointer !important;
                &:hover { opacity: 1 !important; }
                &:not(:hover) { opacity: 0.8 !important; }
              }
            }
          `;
    
          let sss = Cc["@mozilla.org/content/style-sheet-service;1"]
                    .getService(Ci.nsIStyleSheetService);
    
          let uri = Services.io.newURI(
            "data:text/css;charset=UTF-8," + encodeURIComponent(style)
          );
    
          if (!sss.sheetRegistered(uri, sss.AGENT_SHEET)) {
            sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET);
          }
        }
      } catch (e) {
        console.warn("CSS init failed:", e);
      }
    
      // ---- Helpers ----
      function getSearchbar() {
        return window.document.getElementById("searchbar-new");
      }
    
      function getTextbox(searchbar) {
        // in der neuen UI gibt es meist searchbar.inputField
        return searchbar?.inputField || searchbar?.querySelector("input");
      }
    
      function getGoButton(searchbar) {
        // robust: wir suchen den Button über class/DOM
        return searchbar?.querySelector(
          ".urlbar-go-button, button.urlbar-go-button, .go-button, button.go-button"
        );
      }
    
      function closeUrlbarView(searchbar) {
        try {
          const view = searchbar?.urlbarView;
          // abhängig von UI-Variante:
          view?.close?.();
          view?.hidePopup?.();
          view?.setAttribute?.("hidden", "true");
        } catch (e) {}
      }
    
      function clearSearchbar({ blur = false } = {}) {
        const searchbar = getSearchbar();
        const textbox = getTextbox(searchbar);
        if (!searchbar || !textbox) return;
    
        // Popup schließen (so oft wie nötig, daher suppress-Window + close)
        closeUrlbarView(searchbar);
    
        try { searchbar.removeAttribute("usertyping"); } catch (e) {}
    
        textbox.value = "";
    
        if (blur) {
          try { textbox.blur(); } catch (e) {}
        }
      }
    
      function whereToOpenFromEvent(aEvent) {
        let where = "current";
        const newTabPref = Services.prefs.getBoolPref("browser.search.openintab", false);
    
        const target = aEvent?.originalTarget || aEvent?.target;
        const goEl = target?.closest?.(".urlbar-go-button");
    
        if (goEl) {
          // whereToOpenLink ist in deinem Kontext verfügbar
          where = BrowserUtils.whereToOpenLink(aEvent, false, true);
    
          if (newTabPref && !aEvent.altKey && where == "current" && !gBrowser.selectedTab.isEmpty) {
            where = "tab";
            if ((KeyboardEvent.isInstance(aEvent) && aEvent.ctrlKey) ||
                (MouseEvent.isInstance(aEvent) && aEvent.button == 1))
              where = "tabshifted";
          }
        }
        return where;
      }
    
      async function patchEmptySearch(event) {
        // Nur wenn "leere Suche" ausgelöst wird (z.B. Enter/Go mit leerem Feld)
        const searchbar = getSearchbar();
        const textbox = getTextbox(searchbar);
        if (!searchbar || !textbox) return;
    
        if (textbox.value !== "") return;
    
        const target = event?.originalTarget || event?.target;
        const inputOrGo = target?.closest?.(".urlbar-input, .urlbar-go-button");
        if (!inputOrGo) return;
    
        let searchMode = searchbar.searchMode;
        let engine;
    
        try {
          if (!searchMode) {
            engine = await lazy.SearchService.getDefault();
          } else {
            let label = searchMode.engineName;
            engine = await lazy.SearchService.getEngineByName(label);
          }
        } catch (e) {
          console.warn("Engine resolve failed:", e);
          return;
        }
    
        let where = whereToOpenFromEvent(event);
        let url = engine.searchForm;
    
        window.openTrustedLinkIn(url, where);
      }
    
      function attachPopupSuppress(searchbar) {
        // Falls das Popup "nochmal" aufgeht, schließen wir es im kurzen Zeitfenster.
        const view = searchbar?.urlbarView;
        if (!view) return;
    
        // Vermeide doppelte Listener
        if (view.dataset.popupSuppressAttached) return;
        view.dataset.popupSuppressAttached = "true";
    
        view.addEventListener("popupshown", (e) => {
          if (Date.now() < suppressPopupUntil) {
            try { e.target.hidePopup?.(); } catch (err) {}
            try { e.target.close?.(); } catch (err) {}
            try { e.target.setAttribute?.("hidden", "true"); } catch (err) {}
          }
        }, true);
      }
    
      // ---- Init ----
      function initSearchbar() {
        const searchbar = getSearchbar();
        if (!searchbar || searchbar.dataset.autoClearAttached) return;
    
        searchbar.dataset.autoClearAttached = "true";
    
        const textbox = getTextbox(searchbar);
        if (!textbox) {
          console.warn("Textbox not found");
          return;
        }
    
        console.log("✅ Searchbar Auto-Clear + Go/Enter (Popup-suppress) aktiviert");
    
        attachPopupSuppress(searchbar);
    
        // 1) AUTO-CLEAR (Timeout nach Eingabe)
        let timeoutId;
        if (waitingToClear > 0) {
          textbox.addEventListener("input", () => {
            clearTimeout(timeoutId);
            timeoutId = setTimeout(() => {
              if (textbox.value.trim()) {
                suppressPopupUntil = Date.now() + 800;
                closeUrlbarView(searchbar);
                clearSearchbar({ blur: false });
                console.log("⏰ Auto-Clear aktiviert (Popup geschlossen)");
              }
            }, waitingToClear);
          }, { passive: true });
        }
    
        // 2) ENTER: Suche starten lassen, aber direkt danach Clear + Popup-Suppress
        textbox.addEventListener("keydown", (event) => {
          if (event.keyCode === KeyEvent.DOM_VK_RETURN && textbox.value.trim()) {
            suppressPopupUntil = Date.now() + 1200;
    
            // Enter soll die Suche auslösen -> daher NICHT preventDefault
            setTimeout(() => {
              // Popup kann nach dem Clear nochmal triggern -> daher suppress-Window
              closeUrlbarView(searchbar);
              clearSearchbar({ blur: true });
              console.log("↵ Enter → Geleert (Popup blockiert)");
            }, 50);
          }
    
          // (nur wenn Enter auf leerem Feld passiert)
          if (event.keyCode === KeyEvent.DOM_VK_RETURN && !textbox.value.trim()) {
            // wir lassen patchEmptySearch entscheiden
            patchEmptySearch(event).catch(()=>{});
          }
        }, false);
    
        // 3) GO-Button: per DOM finden + Click behandeln
        const goBtn = getGoButton(searchbar);
        if (!goBtn) {
          console.warn("Go-Button nicht gefunden — Script behandelt trotzdem Enter.");
          return;
        }
    
        // Click auf Go: Popup-Suppress + Clear
        goBtn.addEventListener("click", (event) => {
          // Falls Feld leer ist -> Empty-Search Logik nutzen
          patchEmptySearch(event).catch(()=>{});
    
          // Nur Clear wenn Text da war (sonst würdest du leere Suche stören)
          if (!textbox.value.trim()) return;
    
          suppressPopupUntil = Date.now() + 1200;
    
          setTimeout(() => {
            closeUrlbarView(searchbar);
            clearSearchbar({ blur: true });
            console.log("Go → Geleert (Popup blockiert)");
          }, 50);
        }, false);
      }
    
      // ---- Start / Re-init ----
      setTimeout(() => {
        initSearchbar();
      }, 500);
    
      new MutationObserver(() => initSearchbar())
        .observe(document, { childList: true, subtree: true });
    })();
    Alles anzeigen
  • Fx 150 > Searchbar Popup nicht bei focus öffnen

    • FuchsFan
    • 23. April 2026 um 13:04
    Zitat von 2002Andreas

    Der Pfeil wird damit hier nicht angezeigt:

    Teste mal dieses bitte, das andere war aus einem Testprofil:

    CSS
    // ==UserScript==
    // @name         Searchbar Auto-Clear + Go-Pfeil (Firefox 150+)
    // @description  Auto-leeren + sichtbarer Go-Pfeil
    // @include      chrome://browser/content/browser.xhtml
    // @async        true
    // @version      2026/03/12
    // ==/UserScript==
    
    (function() {
      const waitingToClear = 15000; // Zeit bis automatisches Löschen (ms) | 0 = deaktiviert
      const lazy = {};
      
      ChromeUtils.defineESModuleGetters(lazy, {
        SearchService: "moz-src:///toolkit/components/search/SearchService.sys.mjs",
      });
    
        // === CSS für Go-Pfeil ===
      if (Services.prefs.getBoolPref("browser.search.widget.new", false)) {
        let style = `
          #searchbar-new {
            .urlbar-go-button {
              display: flex !important;
              opacity: 0.8 !important;
              cursor: pointer !important;
              &:hover { 
                opacity: 1 !important; 
              }
              &:not(:hover) { 
                opacity: 0.8 !important; 
              }
            }
          }
        `;
        let sss = Cc["@mozilla.org/content/style-sheet-service;1"]
                    .getService(Ci.nsIStyleSheetService);
        // makeURI ist veraltet → Services.io.newURI benutzen
        let uri = Services.io.newURI(
          "data:text/css;charset=UTF-8," + encodeURIComponent(style)
        );
        if (!sss.sheetRegistered(uri, sss.AGENT_SHEET)) {
          sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET);
        }
      }
    
      // === AUTO-CLEAR + GO-BUTTON ===
      function initSearchbar() {
        let searchbar = window.document.getElementById("searchbar-new");
        if (!searchbar || searchbar.dataset.autoClearAttached) return;
        
        searchbar.dataset.autoClearAttached = "true";
        console.log("✅ Searchbar Auto-Clear + Go-Pfeil aktiviert");
    
        const textbox = searchbar.inputField;
        let timeoutId;
    
        // 1. AUTO-CLEAR nach Timeout
        if (waitingToClear > 0) {
          textbox.addEventListener("input", () => {
            clearTimeout(timeoutId);
            timeoutId = setTimeout(() => {
              if (textbox.value.trim()) {
                textbox.value = "";
                textbox.dispatchEvent(new Event("input", { bubbles: true }));
                console.log("⏰ Auto-Clear aktiviert");
              }
            }, waitingToClear);
          });
        }
    
        // 2. ENTER → Clear nach Suche
        textbox.addEventListener("keydown", (event) => {
          if (event.keyCode === KeyEvent.DOM_VK_RETURN && textbox.value.trim()) {
            setTimeout(() => {
              textbox.value = "";
              textbox.dispatchEvent(new Event("input", { bubbles: true }));
              console.log("↵ Enter → Geleert");
            }, 200);
          }
        }, false);
    
        // 3. GO-BUTTON Patch
        searchbar.goButton?.addEventListener("click", patchEmptySearch, false);
        textbox.addEventListener("keydown", patchEmptySearch, false);
      }
    
      // === LEER-SUCHE ermöglichen ===
      async function patchEmptySearch(event) {
        if (KeyboardEvent.isInstance(event) && event.keyCode !== KeyEvent.DOM_VK_RETURN)
          return;
    
        let searchbar = window.document.getElementById("searchbar-new");
        if (searchbar.value !== "") return;
    
        if (!event.originalTarget.classList.contains("urlbar-input") &&
            !event.originalTarget.classList.contains("urlbar-go-button"))
          return;
       
        let searchMode = searchbar.searchMode;
        let engine;
        if (!searchMode) {
          engine = await lazy.SearchService.getDefault();
        } else {
          let label = searchMode.engineName;
          engine = await lazy.SearchService.getEngineByName(label);
        }
        
        let where = whereToOpen(event);
        let url = engine.searchForm;
        window.openTrustedLinkIn(url, where);
      }
    
      function whereToOpen(aEvent) {
        let where = "current";
        const newTabPref = Services.prefs.getBoolPref("browser.search.openintab", false);
        
        if (aEvent?.originalTarget.classList.contains("urlbar-go-button")) {
          where = BrowserUtils.whereToOpenLink(aEvent, false, true);
          if (newTabPref && !aEvent.altKey && where == "current" && !gBrowser.selectedTab.isEmpty) {
            where = "tab";
            if ((KeyboardEvent.isInstance(aEvent) && aEvent.ctrlKey) || 
                (MouseEvent.isInstance(aEvent) && aEvent.button == 1))
              where = "tabshifted";
          }
        }
        return where;
      }
    
      // === START ===
      setTimeout(initSearchbar, 1000);
      new MutationObserver(initSearchbar).observe(document, { 
        childList: true, 
        subtree: true 
      });
    })();
    Alles anzeigen
  • Fx 150 > Searchbar Popup nicht bei focus öffnen

    • FuchsFan
    • 23. April 2026 um 11:42
    Zitat von 2002Andreas

    Treffer...ganz herzlichen Danke dafür

    Freut mich, dass ich auch mal helfen konnte.

    Dieses Script nutze ich, das funktioniert noch:

    CSS
    /* Searchbar automatisch löschen + Go-Pfeil immer sichtbar */
    
    (function () {
    
        if (!window.gBrowser) return;
    
        const waitingToClear = 15000; // Zeit bis automatisches Löschen (ms) | 0 = deaktiviert
    
        /* CSS für Go-Pfeil einfügen */
    
        function injectCSS() {
    
            let css = `
            /* Go-Pfeil in der Searchbar immer sichtbar */
    
            #searchbar .search-go-button {
                display: flex !important;
                opacity: 1 !important;
                visibility: visible !important;
            }
    
            /* verhindert, dass Firefox ihn bei leerem Feld versteckt */
    
            #searchbar[empty] .search-go-button,
            #searchbar[empty="true"] .search-go-button {
                display: flex !important;
                opacity: 1 !important;
                visibility: visible !important;
            }
            `;
    
            let style = document.createElement("style");
            style.textContent = css;
            document.documentElement.appendChild(style);
        }
    
        function initSearchbar() {
    
            let searchbar = document.getElementById("searchbar");
            if (!searchbar) {
                setTimeout(initSearchbar, 400);
                return;
            }
    
            let textbox = searchbar.querySelector("input");
            if (!textbox) {
                console.log("❌ Searchbar-Textbox nicht gefunden");
                return;
            }
    
            console.log("✅ Searchbar Script aktiv");
    
            let timeoutId;
    
            /* ENTER → sofort löschen */
    
            textbox.addEventListener("keydown", function (event) {
                if (event.key === "Enter" && textbox.value.trim()) {
                    setTimeout(() => {
                        textbox.value = "";
                        textbox.dispatchEvent(new Event("input", { bubbles: true }));
    
                        console.log("↵ Enter → Searchbar geleert");
    
                    }, 120);
                }
            });
    
            /* automatisches Löschen */
    
            if (waitingToClear > 0) {
                textbox.addEventListener("input", function () {
                    clearTimeout(timeoutId);
                    timeoutId = setTimeout(() => {
    
                    if (textbox.value.trim()) {
                        textbox.value = "";
                        textbox.dispatchEvent(new Event("input", { bubbles: true }));
    
                        console.log("⏰ Timeout → Searchbar geleert");
    				    }                
                    }, waitingToClear);
                });
            }
        }
    
        /* CSS laden */
        injectCSS();
    
        setTimeout(initSearchbar, 800);
        setTimeout(initSearchbar, 2000);
    
    })();
    Alles anzeigen
  • Fx 150 > Searchbar Popup nicht bei focus öffnen

    • FuchsFan
    • 23. April 2026 um 10:33

    2002Andreas

    Teste mal bitte:

    browser.search.widget.new auf false

  • Suchleiste automatisch leeren

    • FuchsFan
    • 13. April 2026 um 18:14
    Zitat von Arsen

    kann man das Script so einstellen, dass der Suchbegriff nach drücken von Enter nicht sofort gelöscht wird? Ev. will man ja noch andere Suchmaschinen befragen, dann spart man sich das erneute eintippen.

    Dann müsstest du mal dieses Script testen, ist auf eigene Gefahr, weil mit KI überarbeitet, und die Betriebserlaubnis hierzu noch nicht im Forum beantragt und genehmigt wurde.

    CSS
    // ==UserScript==
    // @name         Searchbar Auto-Clear + Go-Pfeil (Firefox 150+)
    // @description  Auto-leeren + sichtbarer Go-Pfeil
    // @include      chrome://browser/content/browser.xhtml
    // @async        true
    // @version      2026/03/12
    // ==/UserScript==
    
    (function() {
      const waitingToClear = 15000; // Zeit bis automatisches Löschen (ms) | 0 = deaktiviert
      const lazy = {};
      
      ChromeUtils.defineESModuleGetters(lazy, {
        SearchService: "moz-src:///toolkit/components/search/SearchService.sys.mjs",
      });
    
        // === CSS für Go-Pfeil ===
      if (Services.prefs.getBoolPref("browser.search.widget.new", false)) {
        let style = `
          #searchbar-new {
            .urlbar-go-button {
              display: flex !important;
              opacity: 0.8 !important;
              cursor: pointer !important;
              &:hover { 
                opacity: 1 !important; 
              }
              &:not(:hover) { 
                opacity: 0.8 !important; 
              }
            }
          }
        `;
        let sss = Cc["@mozilla.org/content/style-sheet-service;1"]
                    .getService(Ci.nsIStyleSheetService);
        // makeURI ist veraltet → Services.io.newURI benutzen
        let uri = Services.io.newURI(
          "data:text/css;charset=UTF-8," + encodeURIComponent(style)
        );
        if (!sss.sheetRegistered(uri, sss.AGENT_SHEET)) {
          sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET);
        }
      }
    
    
      // === AUTO-CLEAR + GO-BUTTON ===
      function initSearchbar() {
        let searchbar = window.document.getElementById("searchbar-new");
        if (!searchbar || searchbar.dataset.autoClearAttached) return;
        
        searchbar.dataset.autoClearAttached = "true";
        console.log("✅ Searchbar Auto-Clear + Go-Pfeil aktiviert");
    
        const textbox = searchbar.inputField;
        let timeoutId;
    
        // 1. AUTO-CLEAR nach Timeout
        if (waitingToClear > 0) {
          textbox.addEventListener("input", () => {
            clearTimeout(timeoutId);
            timeoutId = setTimeout(() => {
              if (textbox.value.trim()) {
                textbox.value = "";
                textbox.dispatchEvent(new Event("input", { bubbles: true }));
                console.log("⏰ Auto-Clear aktiviert");
              }
            }, waitingToClear);
          });
        }
    
        // 3. GO-BUTTON Patch
        searchbar.goButton?.addEventListener("click", patchEmptySearch, false);
        textbox.addEventListener("keydown", patchEmptySearch, false);
      }
    
      // === LEER-SUCHE ermöglichen ===
      async function patchEmptySearch(event) {
        if (KeyboardEvent.isInstance(event) && event.keyCode !== KeyEvent.DOM_VK_RETURN)
          return;
    
        let searchbar = window.document.getElementById("searchbar-new");
        if (searchbar.value !== "") return;
    
        if (!event.originalTarget.classList.contains("urlbar-input") &&
            !event.originalTarget.classList.contains("urlbar-go-button"))
          return;
       
        let searchMode = searchbar.searchMode;
        let engine;
        if (!searchMode) {
          engine = await lazy.SearchService.getDefault();
        } else {
          let label = searchMode.engineName;
          engine = await lazy.SearchService.getEngineByName(label);
        }
        
        let where = whereToOpen(event);
        let url = engine.searchForm;
        window.openTrustedLinkIn(url, where);
      }
    
      function whereToOpen(aEvent) {
        let where = "current";
        const newTabPref = Services.prefs.getBoolPref("browser.search.openintab", false);
        
        if (aEvent?.originalTarget.classList.contains("urlbar-go-button")) {
          where = BrowserUtils.whereToOpenLink(aEvent, false, true);
          if (newTabPref && !aEvent.altKey && where == "current" && !gBrowser.selectedTab.isEmpty) {
            where = "tab";
            if ((KeyboardEvent.isInstance(aEvent) && aEvent.ctrlKey) || 
                (MouseEvent.isInstance(aEvent) && aEvent.button == 1))
              where = "tabshifted";
          }
        }
        return where;
      }
    
      // === START ===
      setTimeout(initSearchbar, 1000);
      new MutationObserver(initSearchbar).observe(document, { 
        childList: true, 
        subtree: true 
      });
    })();
    Alles anzeigen
  • Ein Script, "QuickLinkButton-about-about.uc.js", habe ich noch.

    • FuchsFan
    • 28. März 2026 um 22:01
    Zitat von Sören Hentzschel

    Zumindest ein Punkt ist aber wahr: Niemand verbietet den KI-Einsatz. Aber es muss in jedem Beitrag, der mit Hilfe von KI entstanden ist, darauf hingewiesen werden.

    Das habe ich verstanden, wird aber nicht mehr vorkommen.

  • Ein Script, "QuickLinkButton-about-about.uc.js", habe ich noch.

    • FuchsFan
    • 28. März 2026 um 20:19
    Zitat von Mitleser

    aber das man solche unqualifizierte Lösungen auch noch verbreitet/veröffentlicht und dann auch noch stolz darauf

    Also haltet euch mit solchen Aussagen hinterm Berg. Wenn ihr beide damit Probleme habt, dann geht in euch und tief durchatmen. Thema erledigt!

  • Ein Script, "QuickLinkButton-about-about.uc.js", habe ich noch.

    • FuchsFan
    • 28. März 2026 um 18:12
    Zitat von Horstmann

    Deine Vorlage hat leider den Elchtest nicht bestanden.

    Pech! Siehe Beitrag #6 Ergänzung.

  • Ein Script, "QuickLinkButton-about-about.uc.js", habe ich noch.

    • FuchsFan
    • 28. März 2026 um 17:15
    Zitat von Horstmann

    an Vorlagen würde ich persönlich die erste bevorzugen

    Ja, kannst du. Ich nehme diese:

    JavaScript
    // aboutaboutButton.uc.js
    // öffnet den Dialog about:about
    
    (function() {
      if (!window.gBrowser) return;
    
      let btn_id = 'about-about-button';
    
      try {
        CustomizableUI.createWidget({
          id: btn_id,
          defaultArea: CustomizableUI.AREA_NAVBAR,
          label: "about:about",
          tooltiptext: "Dialog about:about aufrufen",
          onCreated: (this_button) => {
            this_button.style.MozContextProperties = 'fill, stroke, fill-opacity, stroke-opacity'; 
            this_button.style.listStyleImage = 'url("file:///C:/FoxIcons/a2.ico")';
            this_button.style.minWidth = 'fit-content';
          }
        });
      } catch (e) {}
    
      function addClickListener(btn) {
        if (btn.hasAttribute('listener-added')) return; 
        btn.setAttribute('listener-added', 'true');
        btn.addEventListener("click", event => {
          if (event.button === 0) openTrustedLinkIn("about:about", "tab");
        });
      }
    
      let observer = new MutationObserver(() => {
        let btn = document.getElementById(btn_id);
        if (btn && !btn.hasAttribute('listener-added')) {
          addClickListener(btn);
        }
      });
      observer.observe(document.documentElement, { childList: true, subtree: true });
    
      let btn = document.getElementById(btn_id);
      if (btn) addClickListener(btn);
    })();
    Alles anzeigen

    Geändert für Bestehen Elchtest.

  • Ein Script, "QuickLinkButton-about-about.uc.js", habe ich noch.

    • FuchsFan
    • 28. März 2026 um 15:34
    Zitat von Dharkness

    auch hier ein Dankeschön, funktioniert einwandfrei

    :thumbup:

Unterstütze uns!

Jährlich (2026)

61,9 %

61,9% (479,86 von 775 EUR)

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