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
    • 14. Mai 2026 um 19:20

    Das kann ich so nicht stehen lassen, denn die im ersten Script eingetragenen portablen Versionen sind alle mit dem FirefoxUpdater erstellt worden, der Profilordner darin heißt "profile". Damit funktioniert es so, wie sie in dem Script eingetragen sind ohne Probleme. Nun habe ich eine weitere portable Version zum Test eingebaut, und da öffnete sich bei Klick immer der Profilmanager, Firefox wurde nicht gestartet. Diese Form brauchte im Script eine andere Behandlung, und der Eintrag im Script sieht dafür anders aus, und hier heißt er "Profilordner". Hier sind die Unterschiede aufgeführt:

    JavaScript
    addProfileItem(document, popup,
          "️Portable U Beta 4 🔥 ", "profile",
          "G:\\Portable.Firefox.Updater.4\\Firefox Beta x64 Launcher.exe",
          "file:///C:/FoxIcons/Beta.png"
        );
    
        // ✅ Firefox3p: Profilordner direkt starten (kein Profilmanager)
        addProfileItem(document, popup,
          "️Firefox3p 🔥 ",
          "G:\\Firefox Test\\Firefox3p\\Profilordner",
          "G:\\Firefox Test\\Firefox3p\\Firefox64\\firefox.exe",
          "file:///C:/FoxIcons/Finale.png",
          "dir"
        );
    Alles anzeigen

    Das Script wurde deswegen neu angepasst:

    JavaScript
    // == PROFILSTARTER.UC.JS v9-test - CSS SOFORT + MULTI-FENSTER FIX ===
    console.log("=== PROFILSTARTER.UC.JS v9-test - CSS SOFORT + 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 einmalig pro Fenster injizieren
      let cssInjected = false;
    
      // ============== CSS ==============
      function injectUserCSS() {
        try {
          if (cssInjected) return;
    
          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);
          }
    
          cssInjected = true;
          console.log("[PROFILSTARTER] CSS injiziert.");
        } 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" }
      };
    
      // ============== START (angepasst: -profile dir) ==============
      function startProfile(profileValue, exePath, mode = "name") {
        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;
    
          if (mode === "dir") {
            // Profilordner direkt starten
            args = ["-no-remote", "-profile", profileValue, "-foreground"];
          } else {
            // Normal: Profilname (aus profiles.ini)
            args = ["-no-remote", "-P", profileValue || "", "-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:",
            mode,
            profileValue,
            "EXE:",
            exePath || defaultPath,
            "ARGS:",
            args.join(" ")
          );
        } catch (e) {
          console.error("[PROFILSTARTER] Start Fehler:", e);
        }
      }
    
      // ============== MENU ITEM (angepasst: mode weiterreichen) ==============
      function addProfileItem(aDocument, menupopup, label, profileValue, exePath, iconURI = null, mode = "name") {
        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(profileValue, exePath, mode));
        menupopup.appendChild(item);
      }
    
      function loadProfilesWithNiceNames(aDocument, menupopup) {
        const ICON_BASE = "file:///C:/FoxIcons/";
    
        const INI_PATH = "C:\\Users\\Old Man\\AppData\\Roaming\\Mozilla\\Firefox\\profiles.ini";
    
        try {
          let iniFile = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIFile);
          iniFile.initWithPath(INI_PATH);
    
          if (!iniFile.exists()) {
            addProfileItem(aDocument, menupopup, "❌ 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;
              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 (wie bisher: mode default="name")
        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"
        );
    
        // ✅ Firefox3p: Profilordner direkt starten (kein Profilmanager)
        addProfileItem(document, popup,
          "️Firefox3p 🔥 ",
          "G:\\Firefox Test\\Firefox3p\\Profilordner",
          "G:\\Firefox Test\\Firefox3p\\Firefox64\\firefox.exe",
          "file:///C:/FoxIcons/Finale.png",
          "dir"
        );
    
        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();
    
          // CSS ist jetzt schon beim Start aktiv (injectUserCSS ist idempotent),
          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)
      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() {
        // ✅ CSS sofort verfügbar machen (damit das Icon von Anfang an stimmt)
        injectUserCSS();
    
        if (window.readyState !== "loading") {
          setTimeout(click_button, 300);
        } else {
          window.addEventListener("DOMContentLoaded", () => setTimeout(click_button, 300));
        }
      }
    
      initForWindow();
    
      window.addEventListener('aftercustomization', () => {
        injectUserCSS();
        setTimeout(() => click_button(), 100);
      });
    
    })();
    Alles anzeigen
  • Profilmanager

    • FuchsFan
    • 14. Mai 2026 um 17:58

    In allen meinen portablen Versionen wird mit meinem Script die profiles.ini der installierten Version ausgelesen. Der Grund dafür ist der, dass dieser Pfad const INI_PATH = "C:\\Users\\Old Man\\AppData\\Roaming\\Mozilla\\Firefox\\profiles.ini"; dafür aufgerufen wird, egal ob installiert oder portable. Keine Probleme damit hier.

  • Profilmanager

    • FuchsFan
    • 14. Mai 2026 um 15:35
    Zitat von Mira_Belle

    Entschuldige.

    Keine Panik, alles ist gut, Hauptsache du hast es bekommen. Gute Reise!

  • Profilmanager

    • FuchsFan
    • 14. Mai 2026 um 15:00
    Zitat von Mira_Belle

    Deshalb ist jetzt an dieser Stelle erst einmal Schluss.

    Mira_Belle Den Link hast du gesehen?

    Keine Antwort, deshalb stelle ich den Link zum Download hier ein. Es ist meine Reserve, und beinhaltet alle vier portablen Versionen im Original und startbereit. Falls jemand es laden möchte, der Download hat noch 7 Tage Gültigkeit.

    Lufi - Disroot file uploader

  • Profilmanager

    • FuchsFan
    • 14. Mai 2026 um 13:38

    icons.zip

  • Profilmanager

    • FuchsFan
    • 14. Mai 2026 um 12:42
    Zitat von Mira_Belle

    Wie hast Du die portablen Versionen erstellt?
    Warum hast Du verschiedene Launcher.exe?

    Mira_Belle , hier gab es dieses Programm dafür, funktioniert nicht mehr, und wurde auch nicht mehr weiter entwickelt https://github.com/UndertakerBen/PorFirefoxUpd/releases. Die ich damals damit erstellt habe funktionieren immer noch. Welche Version möchtest du denn haben. Übrigens,das erste Script, welches ich gezeigt habe, funktioniert in jeder Version, installiert oder portable. Auch das zweite Script in Nightla portable.

  • Profilmanager

    • FuchsFan
    • 14. Mai 2026 um 10:34
    Zitat von 2002Andreas

    Wenn das Skript in einer port. Version ist, dann ist das hier auch so:

    Danke, Andreas, so war es hier beim Test.

  • Profilmanager

    • FuchsFan
    • 14. Mai 2026 um 09:42
    Zitat von Mira_Belle

    Für das erzeugte Menü wird die profiles.ini ausgelesen.

    Habe dein Script von v150 bis v152 getestet, Button wird erzeugt, Menü ist auch da, aber überall mit der Meldung darin "profiles.ini fehlt". Das ist natürlich nicht der Fall, funktioniert es denn bei dir, dass die *.ini ausgelesen wird?

  • Profilmanager

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

    Das andere ist die compatibility.ini im Profilordner:

    Danke, hatte ich mir auch schon angesehen.

  • 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

Unterstütze uns!

Jährlich (2026)

59,3 %

59,3% (459,86 von 775 EUR)

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