Sieht hier so aus:
Ja, genau so ist es.
Sieht hier so aus:
Ja, genau so ist es.
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
Ist das wirklich aus der profiles.ini ?
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.
// == 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).
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.
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.
// == 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.
Vielleicht ist das der bessere Weg das Skript anzupassen.
Würde ich auch empfehlen, denn das ist für KI eine Nummer zu groß.
Noch mal etliche Versuche gestartet, nun sollte auch der Mittelklick funktionieren:
// ==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
Funktioniert teilweise, der Haken wird nicht mehr automatisch gesetzt:
Ja, Andreas, die Mittelklick-Funktion arbeitet auch nicht, es wird nur der Tooltip angezeigt.
Habe das mit KI versucht, Button wird angezeigt, und Funktionen reagieren (Links, Mittel, und auch Rechts-Klick). Teste mal bitte:
// ==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
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).
// ==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
Der Pfeil wird damit hier nicht angezeigt:
Teste mal dieses bitte, das andere war aus einem Testprofil:
// ==UserScript==
// @name Searchbar Auto-Clear + Go-Pfeil (Firefox 150+)
// @description Auto-leeren + sichtbarer Go-Pfeil
// @include chrome://browser/content/browser.xhtml
// @async true
// @version 2026/03/12
// ==/UserScript==
(function() {
const waitingToClear = 15000; // Zeit bis automatisches Löschen (ms) | 0 = deaktiviert
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
SearchService: "moz-src:///toolkit/components/search/SearchService.sys.mjs",
});
// === CSS für Go-Pfeil ===
if (Services.prefs.getBoolPref("browser.search.widget.new", false)) {
let style = `
#searchbar-new {
.urlbar-go-button {
display: flex !important;
opacity: 0.8 !important;
cursor: pointer !important;
&:hover {
opacity: 1 !important;
}
&:not(:hover) {
opacity: 0.8 !important;
}
}
}
`;
let sss = Cc["@mozilla.org/content/style-sheet-service;1"]
.getService(Ci.nsIStyleSheetService);
// makeURI ist veraltet → Services.io.newURI benutzen
let uri = Services.io.newURI(
"data:text/css;charset=UTF-8," + encodeURIComponent(style)
);
if (!sss.sheetRegistered(uri, sss.AGENT_SHEET)) {
sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET);
}
}
// === AUTO-CLEAR + GO-BUTTON ===
function initSearchbar() {
let searchbar = window.document.getElementById("searchbar-new");
if (!searchbar || searchbar.dataset.autoClearAttached) return;
searchbar.dataset.autoClearAttached = "true";
console.log("✅ Searchbar Auto-Clear + Go-Pfeil aktiviert");
const textbox = searchbar.inputField;
let timeoutId;
// 1. AUTO-CLEAR nach Timeout
if (waitingToClear > 0) {
textbox.addEventListener("input", () => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
if (textbox.value.trim()) {
textbox.value = "";
textbox.dispatchEvent(new Event("input", { bubbles: true }));
console.log("⏰ Auto-Clear aktiviert");
}
}, waitingToClear);
});
}
// 2. ENTER → Clear nach Suche
textbox.addEventListener("keydown", (event) => {
if (event.keyCode === KeyEvent.DOM_VK_RETURN && textbox.value.trim()) {
setTimeout(() => {
textbox.value = "";
textbox.dispatchEvent(new Event("input", { bubbles: true }));
console.log("↵ Enter → Geleert");
}, 200);
}
}, false);
// 3. GO-BUTTON Patch
searchbar.goButton?.addEventListener("click", patchEmptySearch, false);
textbox.addEventListener("keydown", patchEmptySearch, false);
}
// === LEER-SUCHE ermöglichen ===
async function patchEmptySearch(event) {
if (KeyboardEvent.isInstance(event) && event.keyCode !== KeyEvent.DOM_VK_RETURN)
return;
let searchbar = window.document.getElementById("searchbar-new");
if (searchbar.value !== "") return;
if (!event.originalTarget.classList.contains("urlbar-input") &&
!event.originalTarget.classList.contains("urlbar-go-button"))
return;
let searchMode = searchbar.searchMode;
let engine;
if (!searchMode) {
engine = await lazy.SearchService.getDefault();
} else {
let label = searchMode.engineName;
engine = await lazy.SearchService.getEngineByName(label);
}
let where = whereToOpen(event);
let url = engine.searchForm;
window.openTrustedLinkIn(url, where);
}
function whereToOpen(aEvent) {
let where = "current";
const newTabPref = Services.prefs.getBoolPref("browser.search.openintab", false);
if (aEvent?.originalTarget.classList.contains("urlbar-go-button")) {
where = BrowserUtils.whereToOpenLink(aEvent, false, true);
if (newTabPref && !aEvent.altKey && where == "current" && !gBrowser.selectedTab.isEmpty) {
where = "tab";
if ((KeyboardEvent.isInstance(aEvent) && aEvent.ctrlKey) ||
(MouseEvent.isInstance(aEvent) && aEvent.button == 1))
where = "tabshifted";
}
}
return where;
}
// === START ===
setTimeout(initSearchbar, 1000);
new MutationObserver(initSearchbar).observe(document, {
childList: true,
subtree: true
});
})();
Alles anzeigen
Treffer...ganz herzlichen Danke dafür
Freut mich, dass ich auch mal helfen konnte.
Dieses Script nutze ich, das funktioniert noch:
/* Searchbar automatisch löschen + Go-Pfeil immer sichtbar */
(function () {
if (!window.gBrowser) return;
const waitingToClear = 15000; // Zeit bis automatisches Löschen (ms) | 0 = deaktiviert
/* CSS für Go-Pfeil einfügen */
function injectCSS() {
let css = `
/* Go-Pfeil in der Searchbar immer sichtbar */
#searchbar .search-go-button {
display: flex !important;
opacity: 1 !important;
visibility: visible !important;
}
/* verhindert, dass Firefox ihn bei leerem Feld versteckt */
#searchbar[empty] .search-go-button,
#searchbar[empty="true"] .search-go-button {
display: flex !important;
opacity: 1 !important;
visibility: visible !important;
}
`;
let style = document.createElement("style");
style.textContent = css;
document.documentElement.appendChild(style);
}
function initSearchbar() {
let searchbar = document.getElementById("searchbar");
if (!searchbar) {
setTimeout(initSearchbar, 400);
return;
}
let textbox = searchbar.querySelector("input");
if (!textbox) {
console.log("❌ Searchbar-Textbox nicht gefunden");
return;
}
console.log("✅ Searchbar Script aktiv");
let timeoutId;
/* ENTER → sofort löschen */
textbox.addEventListener("keydown", function (event) {
if (event.key === "Enter" && textbox.value.trim()) {
setTimeout(() => {
textbox.value = "";
textbox.dispatchEvent(new Event("input", { bubbles: true }));
console.log("↵ Enter → Searchbar geleert");
}, 120);
}
});
/* automatisches Löschen */
if (waitingToClear > 0) {
textbox.addEventListener("input", function () {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
if (textbox.value.trim()) {
textbox.value = "";
textbox.dispatchEvent(new Event("input", { bubbles: true }));
console.log("⏰ Timeout → Searchbar geleert");
}
}, waitingToClear);
});
}
}
/* CSS laden */
injectCSS();
setTimeout(initSearchbar, 800);
setTimeout(initSearchbar, 2000);
})();
Alles anzeigen
kann man das Script so einstellen, dass der Suchbegriff nach drücken von Enter nicht sofort gelöscht wird? Ev. will man ja noch andere Suchmaschinen befragen, dann spart man sich das erneute eintippen.
Dann müsstest du mal dieses Script testen, ist auf eigene Gefahr, weil mit KI überarbeitet, und die Betriebserlaubnis hierzu noch nicht im Forum beantragt und genehmigt wurde.
// ==UserScript==
// @name Searchbar Auto-Clear + Go-Pfeil (Firefox 150+)
// @description Auto-leeren + sichtbarer Go-Pfeil
// @include chrome://browser/content/browser.xhtml
// @async true
// @version 2026/03/12
// ==/UserScript==
(function() {
const waitingToClear = 15000; // Zeit bis automatisches Löschen (ms) | 0 = deaktiviert
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
SearchService: "moz-src:///toolkit/components/search/SearchService.sys.mjs",
});
// === CSS für Go-Pfeil ===
if (Services.prefs.getBoolPref("browser.search.widget.new", false)) {
let style = `
#searchbar-new {
.urlbar-go-button {
display: flex !important;
opacity: 0.8 !important;
cursor: pointer !important;
&:hover {
opacity: 1 !important;
}
&:not(:hover) {
opacity: 0.8 !important;
}
}
}
`;
let sss = Cc["@mozilla.org/content/style-sheet-service;1"]
.getService(Ci.nsIStyleSheetService);
// makeURI ist veraltet → Services.io.newURI benutzen
let uri = Services.io.newURI(
"data:text/css;charset=UTF-8," + encodeURIComponent(style)
);
if (!sss.sheetRegistered(uri, sss.AGENT_SHEET)) {
sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET);
}
}
// === AUTO-CLEAR + GO-BUTTON ===
function initSearchbar() {
let searchbar = window.document.getElementById("searchbar-new");
if (!searchbar || searchbar.dataset.autoClearAttached) return;
searchbar.dataset.autoClearAttached = "true";
console.log("✅ Searchbar Auto-Clear + Go-Pfeil aktiviert");
const textbox = searchbar.inputField;
let timeoutId;
// 1. AUTO-CLEAR nach Timeout
if (waitingToClear > 0) {
textbox.addEventListener("input", () => {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
if (textbox.value.trim()) {
textbox.value = "";
textbox.dispatchEvent(new Event("input", { bubbles: true }));
console.log("⏰ Auto-Clear aktiviert");
}
}, waitingToClear);
});
}
// 3. GO-BUTTON Patch
searchbar.goButton?.addEventListener("click", patchEmptySearch, false);
textbox.addEventListener("keydown", patchEmptySearch, false);
}
// === LEER-SUCHE ermöglichen ===
async function patchEmptySearch(event) {
if (KeyboardEvent.isInstance(event) && event.keyCode !== KeyEvent.DOM_VK_RETURN)
return;
let searchbar = window.document.getElementById("searchbar-new");
if (searchbar.value !== "") return;
if (!event.originalTarget.classList.contains("urlbar-input") &&
!event.originalTarget.classList.contains("urlbar-go-button"))
return;
let searchMode = searchbar.searchMode;
let engine;
if (!searchMode) {
engine = await lazy.SearchService.getDefault();
} else {
let label = searchMode.engineName;
engine = await lazy.SearchService.getEngineByName(label);
}
let where = whereToOpen(event);
let url = engine.searchForm;
window.openTrustedLinkIn(url, where);
}
function whereToOpen(aEvent) {
let where = "current";
const newTabPref = Services.prefs.getBoolPref("browser.search.openintab", false);
if (aEvent?.originalTarget.classList.contains("urlbar-go-button")) {
where = BrowserUtils.whereToOpenLink(aEvent, false, true);
if (newTabPref && !aEvent.altKey && where == "current" && !gBrowser.selectedTab.isEmpty) {
where = "tab";
if ((KeyboardEvent.isInstance(aEvent) && aEvent.ctrlKey) ||
(MouseEvent.isInstance(aEvent) && aEvent.button == 1))
where = "tabshifted";
}
}
return where;
}
// === START ===
setTimeout(initSearchbar, 1000);
new MutationObserver(initSearchbar).observe(document, {
childList: true,
subtree: true
});
})();
Alles anzeigen
Zumindest ein Punkt ist aber wahr: Niemand verbietet den KI-Einsatz. Aber es muss in jedem Beitrag, der mit Hilfe von KI entstanden ist, darauf hingewiesen werden.
Das habe ich verstanden, wird aber nicht mehr vorkommen.
aber das man solche unqualifizierte Lösungen auch noch verbreitet/veröffentlicht und dann auch noch stolz darauf
Also haltet euch mit solchen Aussagen hinterm Berg. Wenn ihr beide damit Probleme habt, dann geht in euch und tief durchatmen. Thema erledigt!
Deine Vorlage hat leider den Elchtest nicht bestanden.
Pech! Siehe Beitrag #6 Ergänzung.
an Vorlagen würde ich persönlich die erste bevorzugen
Ja, kannst du. Ich nehme diese:
// aboutaboutButton.uc.js
// öffnet den Dialog about:about
(function() {
if (!window.gBrowser) return;
let btn_id = 'about-about-button';
try {
CustomizableUI.createWidget({
id: btn_id,
defaultArea: CustomizableUI.AREA_NAVBAR,
label: "about:about",
tooltiptext: "Dialog about:about aufrufen",
onCreated: (this_button) => {
this_button.style.MozContextProperties = 'fill, stroke, fill-opacity, stroke-opacity';
this_button.style.listStyleImage = 'url("file:///C:/FoxIcons/a2.ico")';
this_button.style.minWidth = 'fit-content';
}
});
} catch (e) {}
function addClickListener(btn) {
if (btn.hasAttribute('listener-added')) return;
btn.setAttribute('listener-added', 'true');
btn.addEventListener("click", event => {
if (event.button === 0) openTrustedLinkIn("about:about", "tab");
});
}
let observer = new MutationObserver(() => {
let btn = document.getElementById(btn_id);
if (btn && !btn.hasAttribute('listener-added')) {
addClickListener(btn);
}
});
observer.observe(document.documentElement, { childList: true, subtree: true });
let btn = document.getElementById(btn_id);
if (btn) addClickListener(btn);
})();
Alles anzeigen
Geändert für Bestehen Elchtest.
auch hier ein Dankeschön, funktioniert einwandfrei
![]()