ZitatUnabhängig von deinem Problem, woher hast du die Version?
Wird wie immer überall angeprießen!
z.B. auf http://www.deskmodder.de
Und ist auf den Servern schon vorhanden.
Ist halt immer die gleiche Leier.
ZitatUnabhängig von deinem Problem, woher hast du die Version?
Wird wie immer überall angeprießen!
z.B. auf http://www.deskmodder.de
Und ist auf den Servern schon vorhanden.
Ist halt immer die gleiche Leier.
Magst Du auch mal die Icons dazu packen?
Nein, ich packe ganz einfach meinen kompletten Ordner,
d.h. alle SVG's die ich habe.
icons.zip
Ach und die zwei "Buttons" auch!![]()
![]()
... mir fehlt als Teil der arbeitenden (!) Bevölkerung einfach die Zeit. Ich gehe auch Samstags ... arbeiten,
Dafür bist Du aber hoffentlich gesund.
Und wenn Dir Deine Arbeit dann auch noch Spaß macht, fast so gut wie ein Sechser im Lotto, oder?
.DeJaVu Es ging um das mehrmalige Löschen des Script-Caches.
So ein Problem hatte ich auch schon mal und da half damals nur die "Holzhammermethode"!
Per Hand löschen und neu aufbauen lassen!
Selbst das mit dem "Fehlerbehebungsmodus ... " wollte nicht.
Allerdings sehe ich Potenzial bei etlichen deiner Themen
![]()
Ne, im Ernst, auf dieser Sache mit dem AV, auch wenn der Themenstarter da etwas angepisst reagiert hat,
war es geklärt und war eine Sache zwischen Andreas, Sören und Carbonbike.
Da muss doch nicht das halbe Board auch noch seinen Senf dazu geben, oder?
Sicher habt Ihr recht, aber das mit dem AV hatte doch mit dem Problem an sich nichts zu tun!
Ich weiß, ist nicht immer so, aber hier war es so.
Aber jetzt muss ich auch was los werden!
ZitatSicherheitslösungen von Drittanbietern lassen sich als Angriffsziel unter Windows missbrauchen. Nun hat Nightmare Eclipse einen weiteren 0-Day veröffentlicht, der Windows-Nutzer tangiert. In Kaspersky Antivirus For Endpoint gibt es eine 0-Day-Schwachstelle, die für normale Benutzer eine Erhöhung der Privilegien auf Systemrechte ermöglicht.
Wo hab' ich's nur gelesen?
Und ...
Zitates [gibt] eine Backdoor namens SLEEPWALKER, die den ESET Management Agenten in Windows-Systemen für Angriffe missbraucht.
Bugfix!
// ==UserScript==
// @name Appmenu.uc.js
// @namespace Appmenu@gmail.com
// @description Basiert auf dem Script externalFuncButtonM.uc.js, Wiederherstellung der Orangenen FF-Menü Schaltfläche
// @include main
// @author defpt
// @charset UTF-8
// @edit 2025.10.05 mit integriertem CSS-Loader-Menü und Konfiguration-Menü,
// @edit zum direkten bearbeiten verschiedener Dateien.
// @edit Sowie der Möglichkeit direkt verschiedene "about:"-Seiten aufrufen zu können.
// @edit 2026.08.29 Aufruf von Verzeichnissen und "about:"-Seiten erweitert.
// @edit 2026.08.30 integriert: Meine Scripte, Meine CSS-Dateien, Meine CSSWeb-Dateien,
// @edit Skriptliste in Zwischenablage (aus extras_config_menu.uc.js)
// @edit Funktionen aus dem JavaScriptLoader hinzugefügt.
// @edit 2026.08.31 Bug im CSS-Loader gefixt! Mittelklick & Rechtsklick waren ohne Funktion.
// Source https://www.camp-firefox.de/forum/thema/139769/?postID=1293421#post1293421
// ==/UserScript==
/* ----------------------------------------------------------------------------------- */
/* Zu beachten ist, dass die Grafiken sich im richtigen Ordner befinden müssen */
/* %appdata%\Mozilla\Firefox\Profiles\"Profilname"\chrome\icons */
/* ----------------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------------------- */
/* IMPORTANT! This script was edited and modified using AI. */
/* ----------------------------------------------------------------------------------- */
// Definiere den Profilpfad für die Symbole
let ProfilePath = PathUtils.toFileURI(
PathUtils.join(PathUtils.profileDir, 'chrome', 'icons')
);
// Standard-Symbol-Dateiname
ButtonIcon01 = 'restart_1.svg'; // Neustart
ButtonIcon02 = 'quit.svg'; // Beenden
Icon01 = 'profile.svg'; // Profil-Verzeichnis
Icon02 = 'chrome.svg'; // Chrome-Ordner
Icon03 = 'css4.svg'; // CSS-Ordner
Icon04 = 'js.svg'; // JS-Ordner
Icon05 = 'folder-plus.svg'; // Icons-Ordner
Icon06 = 'addons.svg'; // Addon-Verzeichnis
Icon07 = 'folder.svg'; // Programm-Verzeichnis
Icon08 = 'folder-1.svg'; // Startup-Cache
Icon11 = 'Themes.svg'; // Anpassen
Icon12 = 'debugging-workers.svg'; // Neustart im abgesicherten Modus
Icon13 = 'command-console.svg'; // Browser-Konsole
Icon14 = 'window-dev-tools.svg'; // Browser-Werkzeuge
Icon15 = 'developer.svg'; // Web-Entwickler
Icon16 = 'sync.svg'; // Firefox synchronisieren
Icon17 = 'passwords.svg'; // Zugangsdaten und Passwörter
Icon18 = 'performance.svg'; // Task Manager
Icon19 = 'plug-disconnected.svg'; // Offline arbeiten
Icon21 = 'firefox.svg'; // about:about
Icon40 = 'extension.svg'; // about:addons
Icon22 = 'info.svg'; // about:cache
Icon23 = 'settings.svg'; // about:config
Icon24 = 'warning.svg'; // about:crashes
Icon25 = 'downloads.svg'; // about:downloads
Icon26 = 'home.svg'; // about:home
Icon27 = 'passwords.svg'; // about:logins
Icon28 = 'debugging-workers.svg'; // about:support
Icon29 = 'settings.svg'; // about:preferences
Icon41 = 'performance.svg'; // about:processes
Icon30 = 'profile.svg'; // about:profiles
Icon31 = 'js.svg'; // Meine Scripte
Icon32 = 'css4.svg'; // Meine CSS-Dateien
Icon33 = 'css4.svg'; // Meine CSSWeb-Dateien
Icon34 = 'command-console.svg'; // Skriptliste in Zwischenablage
var Appmenu = {
// ■■ START UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
// Editor mit angegebenem Pfad verwenden
// editor: 'C:\\Program Files\\Notepad++\\notepad++.exe',
editor: "C:\\Program Files\\Microsoft VS Code\\Code.exe",
// oder
// in 'view_source.editor.path' eingetragenen Editor verwenden
// editor: Services.prefs.getCharPref('view_source.editor.path'),
// Dateimanager mit angegebenem Pfad verwenden oder leer ('') wenn System-Dateimanager verwenden
//fileManager: 'C:\\Program files\\FreeCommander XE\\FreeCommander.exe',
fileManager: "",
// Parameter für Dateimanager oder leer ('')
//FMParameter: '/T',
FMParameter: "",
// Submenüs ohne Inhalt im Hauptmenü automatisch ausblenden
autohideEmptySubDirs: true,
// Submenüs im Hauptmenü nach unten verschieben
moveSubDirstoBottom: false,
// Ort und Aussehen des Menü-Buttons einstellen
// isUrlbar: 1, // 0: TabsToolbar; 1: navbar,
isUrlbar: 2, // 0: TabsToolbar; 1: navbar; 2: toolbar-menubar
isButton: 0, // 0: Hamburger,klein; 1: Firefox,groß,
// Hotkey zum Öffnen des Appmenüs oder leer ('')
hotkey: "f",
hotkeyModifier: "alt",
// ■■ Neu: Einstellungen für Script-/CSS-Listen (aus extras_config_menu.uc.js) ■■
// Unterordner für uc.js-Skripte innerhalb des chrome-Verzeichnisses:
jsSubfolder: 'scripts',
// Zeigt die Datei userChromeShadow.uc.js in der Skriptliste an (1: ja, 0: nein):
showuCS: 0,
// Sortierung der Skript-/CSS-Dateien (1: ja, 0: nein):
sortScripts: 0,
// "Skriptliste in Zwischenablage" (1: ja, 2: mit Nummerierung, 0: deaktiviert):
enableScriptsToClip: 2,
// ■■ END UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
// Submenüs im Hauptmenü nach unten verschieben
subdirPopupHash: [],
subdirMenuHash: [],
// CSS-Loader-Funktionen (integriert)
cssLoader: {
AGENT_SHEET: Ci.nsIStyleSheetService.AGENT_SHEET,
USER_SHEET: Ci.nsIStyleSheetService.USER_SHEET,
AUTHOR_SHEET: Ci.nsIStyleSheetService.AUTHOR_SHEET,
readCSS: {},
get prefs() {
delete this.prefs;
return this.prefs = Services.prefs.getBranch("UserCSSLoader.");
},
get disabled_list() {
try {
return JSON.parse(this.prefs.getCharPref("disabled_css_list")) || [];
} catch (e) {
return [];
}
},
set disabled_list(list) {
this.prefs.setCharPref("disabled_css_list", JSON.stringify(list));
},
get FOLDER() {
let aFolder = Services.dirsvc.get("UChrm", Ci.nsIFile);
aFolder.appendRelativePath("CSS");
if (!aFolder.exists() || !aFolder.isDirectory()) {
aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664);
}
delete this.FOLDER;
return this.FOLDER = aFolder;
},
initCSSLoader: function() {
this.rebuildCSSMenu();
},
rebuildCSSMenu: function() {
let ext = /\.css$/i;
let not = /\.uc\.css/i;
let files = this.FOLDER.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
let popup = Appmenu.subdirPopupHash["CSS-Loader-Menü"];
// Vorhandene Einträge löschen
while (popup && popup.firstChild) {
popup.removeChild(popup.firstChild);
}
// Neue Einträge erstellen
while (files.hasMoreElements()) {
let file = files.getNext().QueryInterface(Ci.nsIFile);
if (!ext.test(file.leafName) || not.test(file.leafName)) continue;
let CSS = this.loadCSS(file);
let menuitem = document.createElementNS(
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"menuitem"
);
menuitem.setAttribute("label", file.leafName);
menuitem.setAttribute("id", "appmenu-css-" + file.leafName);
menuitem.setAttribute("class", "menuitem-iconic");
if (CSS.enabled) {
menuitem.setAttribute("image", `${ProfilePath}/menu-check_lime.svg`);
} else {
menuitem.setAttribute("image", `${ProfilePath}/stop_smal_red.svg`);
}
menuitem.setAttribute("tooltiptext", "Linksklick: an/aus, Mittelklick: an/aus (Menü bleibt offen), Rechtsklick: bearbeiten");
menuitem.addEventListener("command", () => this.toggleCSS(file.leafName));
menuitem.addEventListener("click", (event) => this.cssItemClick(event, file.leafName));
menuitem.addEventListener("mouseup", (event) => { if (event.button === 1) event.preventDefault(); }); // NEU
if (popup) {
popup.appendChild(menuitem);
}
}
},
loadCSS: function(aFile) {
let CSS = this.readCSS[aFile.leafName];
if (!CSS) {
CSS = this.readCSS[aFile.leafName] = new CSSEntry(aFile);
CSS.enabled = !this.disabled_list.includes(aFile.leafName);
}
return CSS;
},
toggleCSS: function(aLeafName) {
let CSS = this.readCSS[aLeafName];
if (!CSS) return;
CSS.enabled = !CSS.enabled;
let currentDisabledList = this.disabled_list;
if (CSS.enabled) {
currentDisabledList = currentDisabledList.filter(name => name !== aLeafName);
} else {
if (!currentDisabledList.includes(aLeafName)) {
currentDisabledList.push(aLeafName);
}
}
this.disabled_list = currentDisabledList;
let menuitem = document.getElementById("appmenu-css-" + aLeafName);
if (menuitem) {
if (CSS.enabled) {
menuitem.setAttribute("image", `${ProfilePath}/menu-check_lime.svg`);
} else {
menuitem.setAttribute("image", `${ProfilePath}/stop_smal_red.svg`);
}
}
},
cssItemClick: function(event, aLeafName) {
event.preventDefault();
event.stopPropagation();
if (event.button === 0) {
return;
} else if (event.button === 1) {
this.toggleCSS(aLeafName);
} else if (event.button === 2) {
let file = this.getFileFromLeafName(aLeafName);
this.editCSS(file);
}
},
getFileFromLeafName: function(aLeafName) {
let f = this.FOLDER.clone();
f.QueryInterface(Ci.nsIFile);
f.appendRelativePath(aLeafName);
return f;
},
editCSS: function(aFile) {
let editor = Appmenu.editor || Services.prefs.getCharPref("view_source.editor.path");
if (!editor) {
alert('Kein Editor konfiguriert! ...');
return;
}
// Rest bleibt gleich
/*editCSS: function(aFile) {
let editor = cssLoaderConfig.Editor || Services.prefs.getCharPref("view_source.editor.path");
if (!editor) {
alert('Kein Editor konfiguriert! Bitte in about:config unter "view_source.editor.path" einen Editor eintragen.');
return;
}
*/
try {
let UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
UI.charset = window.navigator.platform.toLowerCase().includes("win") ? "Shift_JIS" : "UTF-8";
let path = UI.ConvertFromUnicode(aFile.path);
let app = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
app.initWithPath(editor);
let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
process.init(app);
process.run(false, [path], 1);
} catch (e) {
console.error("Fehler beim Öffnen des Editors:", e);
}
},
},
// ■■ JavaScript-Loader-Funktionen (aus rebuild_userChrome.uc.js integriert) ■■
jsLoader: {
init: function() {
this.addPrefListener(this.readLaterPrefListener);
},
fillMenu: function(popup) {
while (popup.hasChildNodes()) popup.removeChild(popup.firstChild);
// --- Debug-Ausgabe ---
let ucjs = window.userChrome_js;
console.debug('[jsLoader] fillMenu aufgerufen. userChrome_js:', ucjs ? 'gefunden' : 'NICHT gefunden');
if (ucjs) {
console.debug('[jsLoader] arrSubdir:', ucjs.arrSubdir);
console.debug('[jsLoader] scripts.length:', ucjs.scripts ? ucjs.scripts.length : 'undefined');
console.debug('[jsLoader] overlays.length:', ucjs.overlays ? ucjs.overlays.length : 'undefined');
console.debug('[jsLoader] dirDisable:', ucjs.dirDisable);
console.debug('[jsLoader] scriptDisable:', ucjs.scriptDisable);
if (ucjs.scripts && ucjs.scripts.length > 0) {
console.debug('[jsLoader] scripts[0].dir:', ucjs.scripts[0].dir, 'filename:', ucjs.scripts[0].filename);
}
}
if (!ucjs || !ucjs.scripts) {
let msg = document.createXULElement('menuitem');
msg.setAttribute('label', 'userChrome.js nicht gefunden oder nicht initialisiert');
msg.setAttribute('disabled', 'true');
popup.appendChild(msg);
return;
}
// Safety: dirDisable/scriptDisable können undefined sein
if (!ucjs.dirDisable) ucjs.dirDisable = {};
if (!ucjs.scriptDisable) ucjs.scriptDisable = {};
if (!ucjs.overlays) ucjs.overlays = [];
try {
// --- Feste Menüeinträge ---
let reuse = this.getPref("userChrome.enable.reuse", 'bool', true);
let mSetting = document.createXULElement('menuitem');
mSetting.setAttribute('label', 'Skript für jedes Fenster neuladen');
mSetting.setAttribute('type', 'checkbox');
mSetting.toggleAttribute('checked', !reuse);
mSetting.addEventListener('command', () => this.setting());
popup.appendChild(mSetting);
popup.appendChild(document.createXULElement('menuseparator'));
// --- Alle UserScripte aktivieren/deaktivieren ---
let mAll = document.createXULElement('menuitem');
mAll.setAttribute('label', 'Alle UserScripte aktivieren/deaktivieren');
mAll.setAttribute('type', 'checkbox');
mAll.toggleAttribute('checked', !userChrome_js.dirDisable['*']);
mAll.dirName = '*';
mAll.addEventListener('command', () => this.chgDirStat("*"));
mAll.addEventListener('click', (event) => this.clickDirMenuitem(event, true));
mAll.addEventListener('mouseup', (event) => { if (event.button == 1) event.preventDefault(); });
popup.appendChild(mAll);
// --- Pro Ordner: Script-Checkboxen direkt im Hauptpopup ---
let foundAnyDir = false;
let firstDir = true;
for (let j = 0; j < ucjs.arrSubdir.length; j++) {
let dirName = ucjs.arrSubdir[j] === "" ? "root" : ucjs.arrSubdir[j];
let hasScripts = false;
for (let i = 0; i < ucjs.scripts.length; i++) {
if (ucjs.scripts[i].dir === dirName) { hasScripts = true; break; }
}
if (!hasScripts) {
for (let i = 0; i < ucjs.overlays.length; i++) {
if (ucjs.overlays[i].dir === dirName) { hasScripts = true; break; }
}
}
if (!hasScripts) continue;
if (firstDir) {
popup.appendChild(document.createXULElement('menuseparator'));
firstDir = false;
}
let displayDir = dirName === "root" ? "" : dirName;
let flg = false;
for (let i = 0; i < ucjs.scripts.length; i++) {
let script = ucjs.scripts[i];
if (script.dir !== dirName) continue;
flg = true;
let mScript = document.createXULElement('menuitem');
mScript.setAttribute('label', script.filename);
mScript.setAttribute('type', 'checkbox');
mScript.setAttribute('autocheck', 'false');
mScript.toggleAttribute('checked', !ucjs.scriptDisable[script.filename]);
if (script.description)
mScript.setAttribute('tooltiptext', script.description);
mScript.script = script;
mScript.addEventListener('command', () => this.chgScriptStat(script.filename));
mScript.addEventListener('click', (event) => this.clickScriptMenu(event, script));
mScript.addEventListener('mouseup', (event) => { if (event.button == 1) event.preventDefault(); });
popup.appendChild(mScript);
}
for (let i = 0; i < ucjs.overlays.length; i++) {
let script = ucjs.overlays[i];
if (script.dir !== dirName) continue;
if (flg) {
popup.appendChild(document.createXULElement('menuseparator'));
}
flg = false;
let mScript = document.createXULElement('menuitem');
mScript.setAttribute('label', script.filename);
mScript.setAttribute('type', 'checkbox');
mScript.setAttribute('autocheck', 'false');
mScript.toggleAttribute('checked', !ucjs.scriptDisable[script.filename]);
if (script.description)
mScript.setAttribute('tooltiptext', script.description);
mScript.script = script;
mScript.addEventListener('command', () => this.chgScriptStat(script.filename));
mScript.addEventListener('click', (event) => this.clickScriptMenu(event, script));
mScript.addEventListener('mouseup', (event) => { if (event.button == 1) event.preventDefault(); });
popup.appendChild(mScript);
}
foundAnyDir = true;
}
// Falls keine Scripts gefunden wurden, Hinweis anzeigen
if (!foundAnyDir) {
let noScripts = document.createXULElement('menuitem');
noScripts.setAttribute('label', 'Keine UserScripte gefunden (Ordner: ' + ucjs.arrSubdir.join(', ') + ')');
noScripts.setAttribute('disabled', 'true');
popup.appendChild(noScripts);
}
} catch (e) {
console.error('[jsLoader] Fehler in fillMenu:', e);
let errMsg = document.createXULElement('menuitem');
errMsg.setAttribute('label', 'Fehler: ' + e.message);
errMsg.setAttribute('disabled', 'true');
popup.appendChild(errMsg);
}
},
setting: function() {
let flag = this.getPref("userChrome.enable.reuse", 'bool', true);
this.setPref("userChrome.enable.reuse", 'bool', !flag);
},
clickDirMenu: function(event) {
if (event.button == 1 || event.button == 2) {
event.stopPropagation();
event.preventDefault();
this.chgDirStat(event.target.dirName);
if (event.target.firstChild && event.target.firstChild.firstChild)
event.target.firstChild.firstChild.toggleAttribute('checked', !userChrome_js.dirDisable[event.target.dirName]);
if (!!userChrome_js.dirDisable[event.target.dirName])
event.target.setAttribute('style', 'font-style:italic;');
else
event.target.removeAttribute('style');
}
},
clickDirMenuitem: function(event, stop) {
if (event.button == 1 || event.button == 2) {
event.stopPropagation();
event.preventDefault();
this.chgDirStat(event.target.dirName);
event.target.toggleAttribute('checked', !userChrome_js.dirDisable[event.target.dirName]);
if (!stop && !!userChrome_js.dirDisable[event.target.dirName])
event.target.parentNode.parentNode.setAttribute('style', 'font-style:italic;');
else
event.target.parentNode.parentNode.removeAttribute('style');
}
},
clickScriptMenu: function(event, script) {
if (event.button == 1) {
event.stopPropagation();
event.preventDefault();
this.chgScriptStat(script.filename);
event.target.toggleAttribute('checked', !userChrome_js.scriptDisable[script.filename]);
} else if (event.button == 2) {
event.stopPropagation();
event.preventDefault();
this.launchEditor(script);
}
},
launchEditor: function(aScript) {
let editor = Appmenu.editor;
let path = Services.io.newURI(aScript.url).QueryInterface(Ci.nsIFileURL).file.path;
let appfile = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
appfile.initWithPath(editor);
let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
process.init(appfile);
process.runw(false, [path], 1, {});
},
chgDirStat: function(adirName) {
let s = this.getPref("userChrome.disable.directory", "str", "");
if (!userChrome_js.dirDisable[adirName]) {
s = (s + ',').replace(adirName + ',', '') + adirName + ',';
} else {
s = (s + ',').replace(adirName + ',', '');
}
s = s.replace(/,,/g, ',').replace(/^,/, '');
this.setPref("userChrome.disable.directory", "str", s);
userChrome_js.dirDisable = this.restoreState(s.split(','));
},
chgScriptStat: function(afilename) {
let s = this.getPref("userChrome.disable.script", "str", "");
if (!userChrome_js.scriptDisable[afilename]) {
s = (s + ',').replace(afilename + ',', '') + afilename + ',';
} else {
s = (s + ',').replace(afilename + ',', '');
}
s = s.replace(/,,/g, ',').replace(/^,/, '');
this.setPref("userChrome.disable.script", "str", s);
userChrome_js.scriptDisable = this.restoreState(s.split(','));
},
restoreState: function(arr) {
let disable = [];
for (let i = 0; i < arr.length; i++) disable[arr[i]] = true;
return disable;
},
getPref: function(aPrefString, aPrefType, aDefault) {
let xpPref = Services.prefs;
try {
switch (aPrefType) {
case 'complex': return xpPref.getComplexValue(aPrefString, Ci.nsIFile);
case 'str': return unescape(xpPref.getCharPref(aPrefString).toString());
case 'int': return xpPref.getIntPref(aPrefString);
case 'bool': default: return xpPref.getBoolPref(aPrefString);
}
} catch (e) {}
return aDefault;
},
setPref: function(aPrefString, aPrefType, aValue) {
let xpPref = Services.prefs;
try {
switch (aPrefType) {
case 'complex': return xpPref.setComplexValue(aPrefString, Ci.nsIFile, aValue);
case 'str': return xpPref.setCharPref(aPrefString, escape(aValue));
case 'int': aValue = parseInt(aValue); return xpPref.setIntPref(aPrefString, aValue);
case 'bool': default: return xpPref.setBoolPref(aPrefString, aValue);
}
} catch (e) {}
return null;
},
addPrefListener: function(aObserver) {
try { Services.prefs.addObserver(aObserver.domain, aObserver, false); }
catch (e) {}
},
removePrefListener: function(aObserver) {
try { Services.prefs.removeObserver(aObserver.domain, aObserver); }
catch (e) {}
},
readLaterPrefListener: {
domain: 'userChrome.disable',
observe: function(aSubject, aTopic, aPrefstring) {
if (aTopic == 'nsPref:changed') {
setTimeout(function() {
let s = Appmenu.jsLoader.getPref("userChrome.disable.directory", "str", "");
userChrome_js.dirDisable = Appmenu.jsLoader.restoreState(s.split(','));
s = Appmenu.jsLoader.getPref("userChrome.disable.script", "str", "");
userChrome_js.scriptDisable = Appmenu.jsLoader.restoreState(s.split(','));
}, 0);
}
}
},
},
toolbar: {
subdirs: [
{
name: 'Firefox Verzeichnisse',
image: `${ProfilePath}/folder_currentColor.svg`,
},
{
name: 'Firefox Funktionen',
image: `${ProfilePath}/settings_currentColor.svg`,
},
{
name: 'separator',
},
{
name: 'Meine Scripte',
image: `${ProfilePath}/${Icon31}`,
},
{
name: 'Meine CSS-Dateien',
image: `${ProfilePath}/${Icon32}`,
},
{
name: 'Meine CSSWeb-Dateien',
image: `${ProfilePath}/${Icon33}`,
},
{
name: 'Skriptliste in Zwischenablage',
image: `${ProfilePath}/${Icon34}`,
command: () => Appmenu.getScripts(1),
tooltiptext: 'Kopiert eine Liste aller uc.js-Skripte in die Zwischenablage',
},
{
name: 'separator',
},
{
name: 'JavaScript-Loader-Menü',
image: `${ProfilePath}/${Icon04}`,
},
{
name: 'CSS-Loader-Menü',
image: `${ProfilePath}/css4_currentColor.svg`,
},
{
name: 'Konfiguration',
image: `${ProfilePath}/Hammer-wrench_currentColor.svg`,
},
{
name: '"about:"-Seiten',
image: `${ProfilePath}/firefox_currentColor.svg`,
},
],
apps: [
{
name: 'Profil-Verzeichnis',
id: 'AMProfil',
root: 'ProfD',
path: '\\',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon01}`,
},
{
name: 'Chrome-Ordner',
id: 'AMchrome',
root: 'ProfD',
path: '\\chrome',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon02}`,
},
{
name: 'CSS-Ordner',
id: 'AMCSS',
root: 'ProfD',
path: '\\chrome\\css',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon03}`,
},
{
name: 'CSS-Web-Ordner',
id: 'AMWEB',
root: 'ProfD',
path: '\\chrome\\cssWeb',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon03}`,
},
{
name: 'JS-Ordner',
id: 'AMJS',
root: 'ProfD',
path: '\\chrome\\scripts',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon04}`,
},
{
name: 'Icons-Ordner',
id: 'AMICO',
root: 'ProfD',
path: '\\chrome\\icons',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon05}`,
},
{
name: 'Addon-Verzeichnis',
id: 'AMAddons',
root: 'ProfD',
path: '\\extensions',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon06}`,
},
{
name: 'Programm-Verzeichnis',
id: 'AMProgramm',
root: 'CurProcD',
path: '\\',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon07}`,
},
{
name: 'Startup-Cache',
id: 'AMCache',
root: 'ProfLD',
path: '\\startupCache',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon08}`,
},
],
configs: [
{
name: 'Anpassen',
id: 'AMAnpassen',
command: 'gCustomizeMode.enter()',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon11}`,
},
{
name: 'Neustart im abgesicherten Modus',
id: 'AMModus',
command: 'safeModeRestart();',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon12}`,
},
{
name: 'Browser-Konsole',
id: 'AMKonsole',
command: 'goKonsole',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon13}`,
},
{
name: 'Browser-Werkzeuge',
id: 'AMWerkzeuge',
command: 'goWerkzeuge',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon14}`,
},
{
name: 'Web-Entwickler',
id: 'AMEntwickler',
command: 'goEntwickler',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon15}`,
},
{
name: 'Firefox synchronisieren',
id: 'AMsynchron',
command: 'gSync',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon16}`,
},
{
name: 'Zugangsdaten und Passwörter',
id: 'AMdaten',
command: 'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })',
tooltiptext: 'about:logins',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon17}`,
},
{
name: 'Task Manager',
id: 'AMManager',
command: 'switchToTabHavingURI("about:processes", true)',
tooltiptext: 'about:processes',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon18}`,
},
{
name: 'Offline arbeiten',
id: 'AMOffline',
command: 'BrowserOffline.toggleOfflineStatus();',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon19}`,
},
{
name: 'Neustart (inkl. Script Cache leeren)',
id: 'AMreboot',
tooltiptext: 'userChrome.js-Cache wird geleert',
command: 'goReeboot',
image: `${ProfilePath}/${ButtonIcon01}`,
},
{
name: 'Beenden',
id: 'AMquit',
command: 'goQuitApplication(event);',
image: `${ProfilePath}/${ButtonIcon02}`,
},
// uProfMenu-Funktionen unter Menüeintrag "Konfiguration"
{
name: 'userChrome.css bearbeiten',
id: 'AMuserChromeCss',
command: () => Appmenu.edit(0, 'userChrome.css'),
subdir: 'Konfiguration',
image: `${ProfilePath}/css4.svg`,
},
{
name: 'userChromeShadow.css bearbeiten',
id: 'AMuserChromeShadowCss',
command: () => Appmenu.edit(0, 'userChromeShadow.css'),
subdir: 'Konfiguration',
image: `${ProfilePath}/css4.svg`,
},
{
name: 'userContent.css bearbeiten',
id: 'AMuserContentCss',
command: () => Appmenu.edit(0, 'userContent.css'),
subdir: 'Konfiguration',
image: `${ProfilePath}/css4.svg`,
},
{
name: 'userChrome.js bearbeiten',
id: 'AMuserChromeJs',
command: () => Appmenu.edit(0, 'userChrome.js'),
subdir: 'Konfiguration',
image: `${ProfilePath}/js.svg`,
},
{
name: 'prefs.js bearbeiten',
id: 'AMprefsJs',
command: () => Appmenu.edit(1, 'prefs.js'),
subdir: 'Konfiguration',
image: `${ProfilePath}/js.svg`,
},
{
name: 'user.js bearbeiten',
id: 'AMuserJs',
command: () => Appmenu.edit(1, 'user.js'),
subdir: 'Konfiguration',
image: `${ProfilePath}/js.svg`,
},
// about:-Seiten
{
name: 'about:about',
id: 'AMaboutAbout',
command: () => openTrustedLinkIn("about:about", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon21}`,
},
{
name: 'about:addons',
id: 'AMaboutAddons',
command: () => openTrustedLinkIn("about:addons", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon40}`,
},
{
name: 'about:cache',
id: 'AMaboutCache',
command: () => openTrustedLinkIn("about:cache", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon22}`,
},
{
name: 'about:config',
id: 'AMaboutConfig',
command: () => openTrustedLinkIn("about:config", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon23}`,
},
{
name: 'about:crashes',
id: 'AMaboutCrashes',
command: () => openTrustedLinkIn("about:crashes", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon24}`,
},
{
name: 'about:downloads',
id: 'AMaboutDownloads',
command: () => openTrustedLinkIn("about:downloads", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon25}`,
},
{
name: 'about:home',
id: 'AMaboutHome',
command: () => openTrustedLinkIn("about:home", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon26}`,
},
{
name: 'about:logins',
id: 'AMaboutLogins',
command: 'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })',
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon27}`,
},
{
name: 'about:support',
id: 'AMaboutSupport',
command: () => openTrustedLinkIn("about:support", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon28}`,
},
{
name: 'about:preferences',
id: 'AMaboutPreferences',
command: () => openTrustedLinkIn("about:preferences", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon29}`,
},
{
name: 'about:processes',
id: 'AMaboutProcesses',
command: () => openTrustedLinkIn("about:processes", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon41}`,
},
{
name: 'about:profiles',
id: 'AMaboutProfiles',
command: () => openTrustedLinkIn("about:profiles", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon30}`,
},
]
},
_externalAppPopup: null,
_isready: false,
// uProfMenu-Funktionen (bereits integriert)
getDirSep: function() {
var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS;
var dirsep = "/";
switch(osString) {
case "WINNT":
dirsep = "\\";
break;
case "Darwin":
dirsep = "/";
break;
}
return dirsep;
},
getPrefDirectoryPath: function(str) {
var file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get(str, Components.interfaces.nsIFile);
if (str == 'CurProcD') {
file = file.parent;
}
return file.path;
},
edit: function(OpenMode, Filename) {
var Path = "";
var dSep = this.getDirSep();
// Wenn der Dateiname einen Pfad enthält (z. B. "chrome/scripts/test.uc.js"),
// vom Profil-Verzeichnis aus auflösen:
if (Filename.includes("/") || Filename.includes("\\")) {
Path = this.getPrefDirectoryPath("ProfD") + dSep + Filename.replace(/\//g, dSep);
} else {
switch (OpenMode) {
case 0:
Path = this.getPrefDirectoryPath("UChrm") + dSep + Filename;
break;
case 1:
Path = this.getPrefDirectoryPath("ProfD") + dSep + Filename;
break;
case 3:
Path = this.getPrefDirectoryPath("UChrm") + dSep + "CSS" + dSep + Filename;
break;
case 4:
Path = this.getPrefDirectoryPath("UChrm") + dSep + "CSSWeb" + dSep + Filename;
break;
case 5:
Path = this.getPrefDirectoryPath("UChrm") + dSep + "CSSShadow" + dSep + Filename;
break;
}
}
this.launch(this.editor, Path);
},
launch: function(RanPath, OpenPath) {
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIFile);
var proc = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
var args = [OpenPath];
file.initWithPath(RanPath);
if (!file.exists()) {
var pref = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
RanPath = pref.getCharPref("view_source.editor.path");
file.initWithPath(RanPath);
}
proc.init(file);
proc.run(false, args, args.length);
},
// ■■ Neu: Script- und CSS-Listen (aus extras_config_menu.uc.js integriert) ■■
getScripts: function(iType) {
let ucJsScripts = [];
let extjs = /\.uc\.js$/i;
// 1. Standard-UChrm-Ordner durchsuchen
let uchrmFolder = Services.dirsvc.get("UChrm", Ci.nsIFile);
if (uchrmFolder.exists()) {
let files = uchrmFolder.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
while (files.hasMoreElements()) {
let file = files.getNext().QueryInterface(Ci.nsIFile);
if (extjs.test(file.leafName)) {
if (file.leafName === "userChromeShadow.uc.js" && !this.showuCS) continue;
ucJsScripts.push(file.leafName);
}
}
}
// 2. chrome/scripts-Unterverzeichnis durchsuchen
if (this.jsSubfolder) {
let scriptsFolder = Services.dirsvc.get("ProfD", Ci.nsIFile);
scriptsFolder.append("chrome");
scriptsFolder.append(this.jsSubfolder);
if (scriptsFolder.exists()) {
let files = scriptsFolder.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
while (files.hasMoreElements()) {
let file = files.getNext().QueryInterface(Ci.nsIFile);
if (extjs.test(file.leafName)) {
ucJsScripts.push("chrome/" + this.jsSubfolder + "/" + file.leafName);
}
}
}
}
if (this.sortScripts) ucJsScripts.sort(this.stringComparison.bind(this));
if (iType === 0) {
// Untermenü "Meine Scripte" befüllen
this.fillFileMenu("Meine Scripte", "Meine Scripte", ucJsScripts, 0);
} else {
// Für Zwischenablage: Nur Dateinamen (ohne Pfad) verwenden
let simpleNames = ucJsScripts.map(f => f.split(/[\\/]/).pop());
let result = this.fillClipboardValue(simpleNames);
Components.classes["@mozilla.org/widget/clipboardhelper;1"]
.getService(Components.interfaces.nsIClipboardHelper).copyString(result);
}
},
getCssFiles: function(iType) {
let cssFiles = [];
let extcss = /\.css$/i;
let folderName = "";
let subdirName = "";
let menuLabel = "";
let sType = 0;
if (iType === 3) {
folderName = "CSS";
subdirName = "Meine CSS-Dateien";
menuLabel = "Meine CSS-Dateien";
sType = 3;
} else if (iType === 4) {
folderName = "CSSWeb";
subdirName = "Meine CSSWeb-Dateien";
menuLabel = "Meine CSSWeb-Dateien";
sType = 4;
} else if (iType === 5) {
folderName = "CSSShadow";
subdirName = "Meine CSSShadow-Dateien";
menuLabel = "Meine CSSShadow-Dateien";
sType = 5;
} else {
return;
}
let aFolder = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path + this.getDirSep() + folderName);
if (aFolder.exists() && aFolder.isDirectory()) {
let files = aFolder.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
while (files.hasMoreElements()) {
let file = files.getNext().QueryInterface(Ci.nsIFile);
if (extcss.test(file.leafName)) cssFiles.push(file.leafName);
}
}
if (this.sortScripts) cssFiles.sort(this.stringComparison.bind(this));
this.fillFileMenu(subdirName, menuLabel, cssFiles, sType);
},
fillFileMenu: function(subdirName, strlabel, fileArray, sType) {
let submenuItem = Appmenu.subdirMenuHash[subdirName];
if (submenuItem) {
submenuItem.setAttribute('label', strlabel + ' (' + fileArray.length + ')');
}
let popup = Appmenu.subdirPopupHash[subdirName];
if (!popup) return;
// Vorhandene Einträge löschen
while (popup.hasChildNodes()) popup.removeChild(popup.firstChild);
// Symbol je nach Dateityp festlegen
let iconPath = '';
if (sType === 0) {
iconPath = ProfilePath + '/' + Icon04; // js.svg
} else {
iconPath = ProfilePath + '/' + Icon03; // css4.svg
}
for (let i = 0; i < fileArray.length; i++) {
let fileName = fileArray[i];
let mitem = document.createXULElement('menuitem');
mitem.setAttribute('class', 'menuitem-iconic');
mitem.setAttribute('image', iconPath);
if (sType === 0) {
// Scripts: Linksklick = Bearbeiten, Mittelklick = GitHub, Rechtsklick = GitHub-Suche
let displayName = fileName.split(/[\\/]/).pop();
mitem.setAttribute('label', displayName);
mitem.addEventListener('command', function() {
Appmenu.edit(0, fileName);
}, true);
mitem.addEventListener('click', function(event) {
Appmenu.openAtGithub(event, displayName);
}, true);
mitem.setAttribute('tooltiptext',
'Linksklick: Bearbeiten,\nMittelklick: GitHub-Seite öffnen,\nRechtsklick: GitHub-Suche');
} else if (sType === 3) {
mitem.setAttribute('label', fileName);
mitem.addEventListener('command', function() {
Appmenu.edit(3, fileName);
}, true);
} else if (sType === 4) {
mitem.setAttribute('label', fileName);
mitem.addEventListener('command', function() {
Appmenu.edit(4, fileName);
}, true);
} else if (sType === 5) {
mitem.setAttribute('label', fileName);
mitem.addEventListener('command', function() {
Appmenu.edit(5, fileName);
}, true);
}
popup.appendChild(mitem);
}
},
fillClipboardValue: function(sArray) {
var retValue = "Meine Skripte (" + sArray.length + "):\n------------------------";
for (var i = 0; i < sArray.length; i++) {
retValue += "\n" + (i + 1) + ". " + sArray[i];
}
return retValue;
},
openAtGithub: function(e, sScript) {
if (e.button == 1) {
var sUrl = "https://github.com/ardiman/userChrome.js/tree/master/" + this.cleanFileName(sScript);
openWebLinkIn(sUrl, 'tab');
}
if (e.button == 2) {
e.preventDefault();
var sUrl = "https://github.com/search?langOverride=&language=&q=" + sScript + "&repo=&start_value=1&type=Code";
openWebLinkIn(sUrl, 'tab');
}
},
cleanFileName: function(sName) {
sName = sName.toLowerCase();
var regs = [/\.uc\.js$/, /\.uc\.xul$/, /^ucjs_/, /_\d.+/, /_fx\d+/, /[-+\.]/g, /_v\d+/];
for (var i = 0; i < regs.length; i++) {
sName = sName.replace(regs[i], "");
}
return sName;
},
stringComparison: function(a, b) {
a = a.toLowerCase().replace(/ä/g,"a").replace(/ö/g,"o").replace(/ü/g,"u").replace(/ß/g,"s");
b = b.toLowerCase().replace(/ä/g,"a").replace(/ö/g,"o").replace(/ü/g,"u").replace(/ß/g,"s");
return (a == b) ? 0 : (a > b) ? 1 : -1;
},
init: function() {
this.handleRelativePath(this.toolbar.apps);
const XULNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
var ExternalAppBtn = document.createElementNS(XULNS, 'toolbarbutton');
ExternalAppBtn.id = 'AppMenuButton';
ExternalAppBtn.setAttribute('label', 'AppButton');
ExternalAppBtn.addEventListener('click', event => {
event.preventDefault();
event.stopPropagation();
});
ExternalAppBtn.setAttribute('tooltiptext', 'Firefox Menü');
ExternalAppBtn.setAttribute('type', 'menu');
ExternalAppBtn.setAttribute('removable', 'true');
let ProfilePath = PathUtils.toFileURI(
PathUtils.join(PathUtils.profileDir, 'chrome', 'image')
);
let DefaultIcon = 'Button_groß.png';
let AlternateIcon = 'Button_klein-5.png';
if (Appmenu.isButton) {
ExternalAppBtn.style.listStyleImage = `url('${ProfilePath}/${DefaultIcon}')`;
ExternalAppBtn.style.width = '94px';
ExternalAppBtn.style.height = '24px';
} else {
ExternalAppBtn.style.listStyleImage = `url('${ProfilePath}/${AlternateIcon}')`;
ExternalAppBtn.style.width = '48px';
ExternalAppBtn.style.height = '21px';
}
if (Appmenu.isUrlbar === 1) {
var navBar = document.getElementById('nav-bar-customization-target');
navBar.insertBefore(ExternalAppBtn, navBar.firstChild);
} else if (Appmenu.isUrlbar === 2) {
var menubar = document.getElementById('toolbar-menubar');
menubar.insertBefore(ExternalAppBtn, menubar.firstChild);
} else {
var TabsToolbar = document.getElementById('TabsToolbar');
TabsToolbar.insertBefore(ExternalAppBtn, TabsToolbar.firstChild);
}
var ExternalAppPopup = document.createElementNS(XULNS, 'menupopup');
ExternalAppPopup.addEventListener('click', event => {
event.stopPropagation();
});
ExternalAppPopup.setAttribute('id', 'AMpopup');
this._externalAppPopup = ExternalAppPopup;
ExternalAppBtn.appendChild(ExternalAppPopup);
Appmenu.onpopupshowing();
// CSS-Loader initialisieren
this.cssLoader.initCSSLoader();
// JS-Loader initialisieren (Pref-Listener registrieren)
this.jsLoader.init();
// Menü mit Tastaturkürzel öffnen
if (Appmenu.hotkey) {
let key = document.createXULElement('key');
key.id = 'key_AppMenuPopup';
key.setAttribute('key', Appmenu.hotkey);
if (Appmenu.hotkeyModifier)
key.setAttribute('modifiers', Appmenu.hotkeyModifier);
key.addEventListener('command', function () {
document.getElementById('AMpopup').openPopup();
});
document.getElementById('mainKeyset').appendChild(key);
}
},
onpopupshowing: function() {
if (this._isready) return;
if (this._externalAppPopup === null) return;
var ExternalAppPopup = this._externalAppPopup;
for (let subdir of this.toolbar.subdirs) {
if (subdir.name == 'separator') {
ExternalAppPopup.appendChild(document.createXULElement('menuseparator'));
} else if (subdir.command) {
var actionItem = ExternalAppPopup.appendChild(document.createXULElement('menuitem'));
actionItem.setAttribute('class', 'menuitem-iconic');
actionItem.setAttribute('label', subdir.name);
actionItem.setAttribute('image', subdir.image);
if (subdir.tooltiptext) {
actionItem.setAttribute('tooltiptext', subdir.tooltiptext);
} else {
actionItem.setAttribute('tooltiptext', subdir.name);
}
actionItem.addEventListener('command', subdir.command);
} else {
var subdirItem = ExternalAppPopup.appendChild(document.createXULElement('menu'));
var subdirItemPopup = subdirItem.appendChild(document.createXULElement('menupopup'));
subdirItem.setAttribute('class', 'menu-iconic');
subdirItem.setAttribute('label', subdir.name);
subdirItem.setAttribute('image', subdir.image);
Appmenu.subdirPopupHash[subdir.name] = subdirItemPopup;
Appmenu.subdirMenuHash[subdir.name] = subdirItem;
// CSS-Loader-Menüeinträge für "CSS-Loader-Menü"
if (subdir.name === "CSS-Loader-Menü") {
Appmenu.cssLoader.rebuildCSSMenu();
}
// Neue dynamische Untermenüs befüllen
if (subdir.name === "Meine Scripte") {
Appmenu.getScripts(0);
}
if (subdir.name === "Meine CSS-Dateien") {
Appmenu.getCssFiles(3);
}
if (subdir.name === "Meine CSSWeb-Dateien") {
Appmenu.getCssFiles(4);
}
// JavaScript-Loader-Menü: popupshowing-Listener für dynamischen Aufbau
// Wichtig: nur bei e.target === e.currentTarget ausführen,
// sonst bubbelt popupshowing von Kind-Popups hoch und führt zu Endlosschleife
if (subdir.name === "JavaScript-Loader-Menü") {
subdirItemPopup.addEventListener('popupshowing', (e) => {
if (e.target === e.currentTarget) Appmenu.jsLoader.fillMenu(e.target);
});
}
}
}
for (let app of this.toolbar.apps) {
var appItem;
if (app.name == 'separator') {
appItem = document.createXULElement('menuseparator');
} else {
appItem = document.createXULElement('menuitem');
appItem.setAttribute('class', 'menuitem-iconic');
appItem.setAttribute('label', app.name);
appItem.setAttribute('image', app.image);
appItem.addEventListener('command', function () {
Appmenu.exec(this.path, this.args);
});
appItem.setAttribute('tooltiptext', app.name);
appItem.path = app.path;
appItem.args = app.args;
}
if (app.subdir && Appmenu.subdirPopupHash[app.subdir])
Appmenu.subdirPopupHash[app.subdir].appendChild(appItem);
else ExternalAppPopup.appendChild(appItem);
}
for (let config of this.toolbar.configs) {
var configItem;
if (config.name == 'separator') {
configItem = document.createXULElement('menuseparator');
} else {
configItem = ExternalAppPopup.appendChild(document.createXULElement('menuitem'));
configItem.setAttribute('class', 'menuitem-iconic');
configItem.setAttribute('label', config.name);
configItem.setAttribute('image', config.image);
configItem.addEventListener('command', () => {
if (typeof config.command === 'function') {
config.command();
} else {
Appmenu.executeCommand(config.command);
}
});
if (config.tooltiptext) {
configItem.setAttribute('tooltiptext', config.tooltiptext);
} else {
configItem.setAttribute('tooltiptext', config.name);
}
configItem.setAttribute('id', config.id);
}
if (config.subdir && Appmenu.subdirPopupHash[config.subdir]) {
Appmenu.subdirPopupHash[config.subdir].appendChild(configItem);
} else {
ExternalAppPopup.appendChild(configItem);
}
}
if (this.autohideEmptySubDirs) {
// Lazy-gefüllte Untermenüs nicht verstecken (werben erst beim Aufklappen befüllt)
let lazySubdirs = ['JavaScript-Loader-Menü'];
for (let key of Object.keys(Appmenu.subdirPopupHash)) {
if (lazySubdirs.includes(key)) continue;
if (Appmenu.subdirPopupHash[key].hasChildNodes()) {
continue;
} else {
Appmenu.subdirMenuHash[key].setAttribute('hidden', 'true');
}
}
}
if (this.moveSubDirstoBottom) {
let i = ExternalAppPopup.childNodes.length;
while (ExternalAppPopup.firstChild.getAttribute('class') != 'menuitem-iconic' && i-- != 0) {
ExternalAppPopup.appendChild(ExternalAppPopup.firstChild);
}
}
this._isready = true;
},
executeCommand: function(command) {
const commandMap = {
'gCustomizeMode.enter()': () => gCustomizeMode.enter(),
'safeModeRestart();': () => safeModeRestart(),
'goKonsole': () => {
var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
var { BrowserConsoleManager } = require('resource://devtools/client/webconsole/browser-console-manager');
BrowserConsoleManager.openBrowserConsoleOrFocus();
},
'goWerkzeuge': () => {
var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
var { BrowserToolboxLauncher } = require('resource://devtools/client/framework/browser-toolbox/Launcher.sys.mjs');
BrowserToolboxLauncher.init();
},
'goEntwickler': () => {
var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
var { gDevToolsBrowser } = require('resource://devtools/client/framework/devtools-browser');
gDevToolsBrowser.toggleToolboxCommand(window.gBrowser, performance.now());
},
'gSync': () => gSync.openPrefs('menubar'),
'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })': () => LoginHelper.openPasswordManager(window, { entryPoint: 'mainmenu' }),
'switchToTabHavingURI("about:processes", true)': () => switchToTabHavingURI('about:processes', true),
'BrowserOffline.toggleOfflineStatus();': () => BrowserOffline.toggleOfflineStatus(),
'goReeboot': () => {
Services.appinfo.invalidateCachesOnRestart();
Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit);
},
'goQuitApplication(event);': () => goQuitApplication(event),
};
if (commandMap[command]) {
commandMap[command]();
} else {
console.warn('Unbekannter Befehl: ', command);
}
},
handleRelativePath: function(apps) {
for (let app of apps) {
if (app.path) {
app.path = app.path.replace(/\//g, '\\');
var ffdir = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties).get(app.root, Ci.nsIFile).path;
if (/^(\\)/.test(app.path)) {
app.path = ffdir + app.path;
}
}
}
},
exec: function(path, args) {
args = args || [];
var args_t = args.slice(0);
for (let arg of args_t) {
arg = arg.replace(/%u/g, gBrowser.currentURI.spec);
}
var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
file.initWithPath(path);
if (!file.exists()) {
alert('Datei nicht gefunden: ' + path);
return;
}
if (file.isExecutable() && !path.endsWith('.js')) {
var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
process.init(file);
process.run(false, args_t, args_t.length);
} else if (file.isFile()) {
if (this.editor) {
let UI = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Ci.nsIScriptableUnicodeConverter);
UI.charset = window.navigator.platform.toLowerCase().includes("win") ? "Shift_JIS" : "UTF-8";
let path = UI.ConvertFromUnicode(file.path);
let app = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
app.initWithPath(this.editor);
let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
process.init(app);
process.run(false, [path], 1);
} else {
file.launch();
}
} else if (file.isDirectory()) {
if (this.fileManager) {
let args=[this.FMParameter,path];
let app = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
app.initWithPath(this.fileManager);
let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
process.init(app);
process.run(false, args, args.length);
} else {
file.launch();
}
}
},
};
/* ***************************************************************************************************************************** */
// CSSEntry-Klasse (aus UserCSSLoader)
function CSSEntry(aFile) {
this.path = aFile.path;
this.leafName = aFile.leafName;
this.lastModifiedTime = 1;
this.SHEET = /^xul-|\.as\.css$/i.test(this.leafName) ?
Ci.nsIStyleSheetService.AGENT_SHEET :
/\.author\.css$/i.test(this.leafName) ?
Ci.nsIStyleSheetService.AUTHOR_SHEET :
Ci.nsIStyleSheetService.USER_SHEET;
}
CSSEntry.prototype = {
sss: Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService),
_enabled: false,
get enabled() {
return this._enabled;
},
set enabled(isEnable) {
let aFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
aFile.initWithPath(this.path);
let isExists = aFile.exists();
let lastModifiedTime = isExists ? aFile.lastModifiedTime : 0;
let isForced = this.lastModifiedTime != lastModifiedTime;
let fileURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromActualFile(aFile);
let uri = Services.io.newURI(fileURL, null, null);
if (this.sss.sheetRegistered(uri, this.SHEET)) {
if (!isEnable || !isExists) {
this.sss.unregisterSheet(uri, this.SHEET);
} else if (isForced) {
this.sss.unregisterSheet(uri, this.SHEET);
this.sss.loadAndRegisterSheet(uri, this.SHEET);
}
} else {
if (isEnable && isExists) {
this.sss.loadAndRegisterSheet(uri, this.SHEET);
}
}
this.lastModifiedTime = lastModifiedTime;
return this._enabled = isEnable;
},
};
(function () {
let sss = Components.classes['@mozilla.org/content/style-sheet-service;1'].getService(Components.interfaces.nsIStyleSheetService);
let uri = Services.io.newURI(
'data:text/css;charset=utf-8,' +
encodeURIComponent(`
menuitem[label="Profil-Verzeichnis"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="Chrome-Ordner"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="CSS-Ordner"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="CSS-Web-Ordner"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="JS-Ordner"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="Icons-Ordner"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="Addon-Verzeichnis"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="Programm-Verzeichnis"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="Startup-Cache"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMAnpassen { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMModus { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMKonsole { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMWerkzeuge { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMEntwickler { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMsynchron { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMdaten { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMManager { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMOffline { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
/* Neustart-Button */
#AMreboot { -moz-context-properties: fill, fill-opacity !important; fill: #fbc96e !important; padding-left: 13px !important; }
#AMreboot > img:nth-child(1) { width: 16px !important; height: 16px !important; }
/* Beenden-Button */
#AMquit { -moz-context-properties: fill, fill-opacity !important; fill: red !important; }
/* Skriptliste in Zwischenablage */
#AMscriptList { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
/* about:-Seiten */
#AMaboutAbout { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutAddons { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutCache { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutConfig { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutCrashes { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutDownloads { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutHome { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutLogins { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutSupport { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutPreferences { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutProcesses { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutProfiles { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
/* uProfMenu-Einträge */
#AMuserChromeCss { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMuserChromeShadowCss { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMuserContentCss { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMuserChromeJs { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMprefsJs { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMuserJs { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
/* 1 */
menuitem[subdir="CSS-Loader-Menü"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menu[label="JavaScript-Loader-Menü"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#appmenu-css-CSS-Ordner-öffnen { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
`),
null,
null
);
sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
})();
if (window.gBrowser) Appmenu.init();
Alles anzeigen
Oh Gott, jetzt lasst es doch gut sein![]()
Das Problem mit der Webpage hat doch überhaupt nichts mit dem AV-Programm zu tun!
Warum muss hier denn immer so abgedriftet werden?
2002Andreas Bitte mach hier zu, bevor es noch weiter eskaliert. Danke.
2002Andreas Du hast absolut recht!
Die Leute lesen nichts mehr.
Das ist auch in ganz anderen Bereichen so
und so etwas regt mich tierisch auf.
Wobei, ich versuche gelassener zu werden, aber DAS beeinflusst halt auch meine Zukunft!
Siehe https://www.wahlrecht.de/umfragen/landt…hsen-anhalt.htm
Nie und nimmer hat irgendwer auch nur EIN Wahlprogramm irgendEINER Partei gelesen!!
Man glaubt lieber an das Stammtischgeschwätz und auf sein Bauchgefühl. Irre.
Zurück zum Script!
Wie 2002Andreas schon schrieb, muss natürlich auch der zu benutzende Editor ausgewählt werden!!
Wenn Notepad++ oder Microsoft Visual Studio Code gar nicht installiert sind, ...
Das klappt dann nicht und ergo wird natürlich auch kein Script zum Bearbeiten geöffnet.
Wie denn dann auch?
Endor Genau daran hatte ich auch gedacht.
Ich hätte das Script heute Nachmittag fertig, gezipt noch mal hoch geladen.
Das ist wieder so eine "feine" Sache.
Ok, laufen andere Skripte?
Hast Du mal einen Test mit einem anderen Profil gemacht?
Ist die Dateiendung im Explorer auch richtig, also => .uc.js
Zum Testen auch mal ausprobieren, was passiert, wenn alle anderen Scripte temporär gelöscht sind!
Erst alle z.B. mit 7-Zip packen und danach entfernen. Kannst sie aber auch ganz einfach in einen anderen Ordner verschieben.
Dennoch das Profil besser vorher mal sichern!!
Mehr Ideen habe ich gerade nicht.
/* ----------------------------------------------------------------------------------- */
/* Zu beachten ist, dass die Grafiken sich im richtigen Ordner befinden müssen */
/* %appdata%\Mozilla\Firefox\Profiles\"Profilname"\chrome\icons */
/* ----------------------------------------------------------------------------------- */
![]()
// In der folgenden Zeile kann festgelegt werden, ob ein verschiebbarer Button erstellt wird:
showAsButton: 1, // 1: ja / Button wird erstellt, 0: nein / Menue unter "Extras"
Mit dieser Einstellung wird ein Button generiert.
// Button-Aussehen (1: flexibles SVG-Icon aus Icon-Ordner, 0: festes Base64-PNG-Icon):
buttonStyle: 0, // Default => 0
Mit dieser Einstellung sollte das Base64-PNG-Icon für den Button genutzt werden.
Schaut so aus => ![]()
und du glaubst wirklich, dass sich das viele User durchlesen
Nö, aber selbst schuld.
Wobei man diesem Fehler ja auch aus der Ferne recht schnell auf die Schliche kommen kann,
bei den ::part() Selektoren, so denke ich, wird man nicht so schnell drauf kommen.
beide Skripte(auch aus dem anderen Thread von dir) funktionieren hier auf die Schnelle, hast du gut gemacht
Danke.
Jetzt muss ich nur mal sehen, ob ich die "Liste" auch Mehrspaltig hinbekomme.
Aber das wird wohl dauern.
In der userChrome.uc.js sollte eigentlich auch diese Warnung stehen:
/*
* userChrome.js
*
* The file userChrome.js can be used to customize the functioning of Mozilla's
* user interface. Usage and syntax follow below; for useful code snippets see
* http://mozilla.zeniko.ch/userchrome.js.html.
*
* Examples:
* setTimeout(function() { document.title = "A new title for every window" }, 2000);
*
* if (location == "chrome://browser/content/browser.xul") {
* alert("Script loaded in main browser only");
* }
*
* // DOMi window
* if (location == "chrome://inspector/content/inspector.xul") {
* // Move Urlbar box to main toolbar
* var tb = document.getElementById('bxURLBar');
* var el = document.getElementById('mbrInspectorMain');
* if (tb && el) el.appendChild(tb, el.firstChild);
* }
*
* NOTE:
* userChromeJS includes an 'import' function to facilitate file management.
* An absolute path or relative path with Directory name property token can be
* used, as follows:
*
* // Single file (javascript .js or overlay .xul file)
* userChrome.import("Full file path");
* userChrome.import("Relative file path", "Token");
* // All .js and .xul files in a folder will be loaded.
* userChrome.import("Full file folder path");
* userChrome.import("Relative file folder path/name", "Token");
* userChrome.import("*", "Token");
*
* NOTE:
* Absolute windows files and folders must be have backslash escaped:
* "C:\\Program Files\\Mozilla\\scripts\\myscript.js"
*
* Examples:
* // Import script in [ProfileDir]/chrome/scripts/myscript.js
* userChrome.import("scripts/myscript.js", "UChrm");
* // Import script in [Profiles]/scripts/myscript.js (share same script in
* // multiple profiles
* userChrome.import("scripts/myscript.js", "DefProfRt");
* // All .js or .xul in profile chrome directory
* userChrome.import("*", "UChrm");
* // Import overlay
* userChrome.import("C:\\Program Files\\Mozilla\\scripts\\myOverlay.xul");
* // Import everything in Desktop folder /scripts
* userChrome.import("scripts", "Desk");
* // Perhaps the only thing you need in this file..
* if (location == "chrome://browser/content/browser.xul") {
* userChrome.import("scripts", "DefProfRt");
* }
*
* NOTE:
* For a full listing of directory tokens see the two links found here:
* https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O#Getting_files_in_special_directories
* // What's the path for a token? This will print it in the console.
* userChrome.log(userChrome.getAbsoluteFile("Desk").path, "getAbsoluteFile:'Desk'");
*
* NOTE:
* userChromeJS includes a log function, invoked as follows:
* userChrome.log("string1"[, "string2"])
* Example:
* userChrome.log("hello world!", "myscript.js");
* Results in a console message:
* 2009-05-22 18:07:40 userChromeJS myscript.js: hello world!
*
* NOTE:
* The date format for the userChrome.log console logger may be user defined:
* Example:
* userChrome.dateFormat = "%Y-%m-%d %H:%M:%S";
*
* NOTE:
* The default charSet is "UTF-8"; for code using the 'import' or
* 'importFolder' functions to manage files, the charSet for subscript loader
* may be user defined, prior to calling the import or importFolder functions:
* Example:
* userChrome.charSet = "UTF-8";
*
* NOTE:
* Scripts are stored in a startup cache and loaded from it.
* After a change in userChrome.js you heve to restart Firefox with clearing
* this cache to make sure the changed file is read.
* By default this applies to imported .js files too. You can bypass the cache
* for these scripts with this statement BEFORE any import statement:
* userChrome.ignoreCache = true;
*
*/
Alles anzeigen
was hast du gegen die Datei bzw. das Skript, warum blendest du das aus bzw. gibst eine Möglichkeit dazu
Ich verweise mal auf meinen Kommentar im anderen Thread.
Wenn dann müsste auch die userChromeShadow.css angezeigt werden.
Die userChromeShadow.css wird doch angezeigt!!
Und zwar immer!
Es geht doch nur um das Anzeigen der userChromeShadow.uc.js.
Diese dient doch nur der Einbindung eben der CSS-Datei,
und ich bin der Meinung, dass da eigentlich niemand dran muss, um diese zu editieren.
Hier mal deren Inhalt:
// userChromeShadow.uc.js by aborix
// 28.07.2022 FF104+ Fix: using PathUtils.join (Sören Hentzschel)
(async function() {
if (location.href !== 'chrome://browser/content/browser.xhtml') return;
try {
let path = PathUtils.join(PathUtils.profileDir, 'chrome', 'userChromeShadow.css');
let cssIn = await IOUtils.readUTF8(path);
let sss = Cc['@mozilla.org/content/style-sheet-service;1'].getService(Ci.nsIStyleSheetService);
let uri = makeURI('data:text/css;charset=UTF=8,' + encodeURIComponent(cssIn));
sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
} catch(e) {
console.log("UserChromeShadow-Error: " + e.name + ': ' + e.message );
};
})();
Alles anzeigen
Solange die funktioniert, sollte man da besser die Finger von lassen.
Nachtrag!
Das Menü dient ja nicht nur zum Anzeigen der eigenen Scripte,
sondern per doppelklick zum direkten bearberiten dieser.
Ich habe mich getraut!
Und,
es hat geklappt![]()
Aus meinem Appmenu.uc.js ist nun eine eierlegende Wollmilchsau geworden!
Man kann direkt verschieden Verzeichnisse öffnen.
Direkt verschieden Firefoxfunktionen aufrufen,
bekommt nicht nur seine Skripte und CSS angezeigt, sondern kann sie auch nach einem Klick
direkt im Editor seiner wahl bearbeiten.
Funktionen des JavaScriptLoaders sowie des CSSLaoders wurden integriert,
damit man diese direkt aktivieren/deaktivieren kann.
Und so einiges mehr!!
// ==UserScript==
// @name Appmenu.uc.js
// @namespace Appmenu@gmail.com
// @description Basiert auf dem Script externalFuncButtonM.uc.js, Wiederherstellung der Orangenen FF-Menü Schaltfläche
// @include main
// @author defpt
// @charset UTF-8
// @edit 2025.10.05 mit integriertem CSS-Loader-Menü und Konfiguration-Menü,
// @edit zum direkten bearbeiten verschiedener Dateien.
// @edit Sowie der Möglichkeit direkt verschiedene "about:"-Seiten aufrufen zu können.
// @edit 2026.08.29 Aufruf von Verzeichnissen und "about:"-Seiten erweitert.
// @edit 2026.08.30 integriert: Meine Scripte, Meine CSS-Dateien, Meine CSSWeb-Dateien,
// @edit Skriptliste in Zwischenablage (aus extras_config_menu.uc.js)
// @edit Funktionen aus dem JavaScriptLoader hinzugefügt
// Source https://www.camp-firefox.de/forum/thema/139769/?postID=1293355#post1293355
// ==/UserScript==
/* ----------------------------------------------------------------------------------- */
/* Zu beachten ist, dass die Grafiken sich im richtigen Ordner befinden müssen */
/* %appdata%\Mozilla\Firefox\Profiles\"Profilname"\chrome\icons */
/* ----------------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------------------- */
/* IMPORTANT! This script was edited and modified using AI. */
/* ----------------------------------------------------------------------------------- */
// Definiere den Profilpfad für die Symbole
let ProfilePath = PathUtils.toFileURI(
PathUtils.join(PathUtils.profileDir, 'chrome', 'icons')
);
// Standard-Symbol-Dateiname
ButtonIcon01 = 'restart_1.svg'; // Neustart
ButtonIcon02 = 'quit.svg'; // Beenden
Icon01 = 'profile.svg'; // Profil-Verzeichnis
Icon02 = 'chrome.svg'; // Chrome-Ordner
Icon03 = 'css4.svg'; // CSS-Ordner
Icon04 = 'js.svg'; // JS-Ordner
Icon05 = 'folder-plus.svg'; // Icons-Ordner
Icon06 = 'addons.svg'; // Addon-Verzeichnis
Icon07 = 'folder.svg'; // Programm-Verzeichnis
Icon08 = 'folder-1.svg'; // Startup-Cache
Icon11 = 'Themes.svg'; // Anpassen
Icon12 = 'debugging-workers.svg'; // Neustart im abgesicherten Modus
Icon13 = 'command-console.svg'; // Browser-Konsole
Icon14 = 'window-dev-tools.svg'; // Browser-Werkzeuge
Icon15 = 'developer.svg'; // Web-Entwickler
Icon16 = 'sync.svg'; // Firefox synchronisieren
Icon17 = 'passwords.svg'; // Zugangsdaten und Passwörter
Icon18 = 'performance.svg'; // Task Manager
Icon19 = 'plug-disconnected.svg'; // Offline arbeiten
Icon21 = 'firefox.svg'; // about:about
Icon40 = 'extension.svg'; // about:addons
Icon22 = 'info.svg'; // about:cache
Icon23 = 'settings.svg'; // about:config
Icon24 = 'warning.svg'; // about:crashes
Icon25 = 'downloads.svg'; // about:downloads
Icon26 = 'home.svg'; // about:home
Icon27 = 'passwords.svg'; // about:logins
Icon28 = 'debugging-workers.svg'; // about:support
Icon29 = 'settings.svg'; // about:preferences
Icon41 = 'performance.svg'; // about:processes
Icon30 = 'profile.svg'; // about:profiles
Icon31 = 'js.svg'; // Meine Scripte
Icon32 = 'css4.svg'; // Meine CSS-Dateien
Icon33 = 'css4.svg'; // Meine CSSWeb-Dateien
Icon34 = 'command-console.svg'; // Skriptliste in Zwischenablage
var Appmenu = {
// ■■ START UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
// Editor mit angegebenem Pfad verwenden
// editor: 'C:\\Program Files\\Notepad++\\notepad++.exe',
editor: "C:\\Program Files\\Microsoft VS Code\\Code.exe",
// oder
// in 'view_source.editor.path' eingetragenen Editor verwenden
// editor: Services.prefs.getCharPref('view_source.editor.path'),
// Dateimanager mit angegebenem Pfad verwenden oder leer ('') wenn System-Dateimanager verwenden
//fileManager: 'C:\\Program files\\FreeCommander XE\\FreeCommander.exe',
fileManager: "",
// Parameter für Dateimanager oder leer ('')
//FMParameter: '/T',
FMParameter: "",
// Submenüs ohne Inhalt im Hauptmenü automatisch ausblenden
autohideEmptySubDirs: true,
// Submenüs im Hauptmenü nach unten verschieben
moveSubDirstoBottom: false,
// Ort und Aussehen des Menü-Buttons einstellen
// isUrlbar: 1, // 0: TabsToolbar; 1: navbar,
isUrlbar: 2, // 0: TabsToolbar; 1: navbar; 2: toolbar-menubar
isButton: 0, // 0: Hamburger,klein; 1: Firefox,groß,
// Hotkey zum Öffnen des Appmenüs oder leer ('')
hotkey: "f",
hotkeyModifier: "alt",
// ■■ Neu: Einstellungen für Script-/CSS-Listen (aus extras_config_menu.uc.js) ■■
// Unterordner für uc.js-Skripte innerhalb des chrome-Verzeichnisses:
jsSubfolder: 'scripts',
// Zeigt die Datei userChromeShadow.uc.js in der Skriptliste an (1: ja, 0: nein):
showuCS: 0,
// Sortierung der Skript-/CSS-Dateien (1: ja, 0: nein):
sortScripts: 0,
// "Skriptliste in Zwischenablage" (1: ja, 2: mit Nummerierung, 0: deaktiviert):
enableScriptsToClip: 2,
// ■■ END UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
// Submenüs im Hauptmenü nach unten verschieben
subdirPopupHash: [],
subdirMenuHash: [],
// CSS-Loader-Funktionen (integriert)
cssLoader: {
AGENT_SHEET: Ci.nsIStyleSheetService.AGENT_SHEET,
USER_SHEET: Ci.nsIStyleSheetService.USER_SHEET,
AUTHOR_SHEET: Ci.nsIStyleSheetService.AUTHOR_SHEET,
readCSS: {},
get prefs() {
delete this.prefs;
return this.prefs = Services.prefs.getBranch("UserCSSLoader.");
},
get disabled_list() {
try {
return JSON.parse(this.prefs.getCharPref("disabled_css_list")) || [];
} catch (e) {
return [];
}
},
set disabled_list(list) {
this.prefs.setCharPref("disabled_css_list", JSON.stringify(list));
},
get FOLDER() {
let aFolder = Services.dirsvc.get("UChrm", Ci.nsIFile);
aFolder.appendRelativePath("CSS");
if (!aFolder.exists() || !aFolder.isDirectory()) {
aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664);
}
delete this.FOLDER;
return this.FOLDER = aFolder;
},
initCSSLoader: function() {
this.rebuildCSSMenu();
},
rebuildCSSMenu: function() {
let ext = /\.css$/i;
let not = /\.uc\.css/i;
let files = this.FOLDER.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
let popup = Appmenu.subdirPopupHash["CSS-Loader-Menü"];
// Vorhandene Einträge löschen
while (popup && popup.firstChild) {
popup.removeChild(popup.firstChild);
}
// Neue Einträge erstellen
while (files.hasMoreElements()) {
let file = files.getNext().QueryInterface(Ci.nsIFile);
if (!ext.test(file.leafName) || not.test(file.leafName)) continue;
let CSS = this.loadCSS(file);
let menuitem = document.createElementNS(
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
"menuitem"
);
menuitem.setAttribute("label", file.leafName);
menuitem.setAttribute("id", "appmenu-css-" + file.leafName);
menuitem.setAttribute("class", "menuitem-iconic");
if (CSS.enabled) {
menuitem.setAttribute("image", `${ProfilePath}/menu-check_lime.svg`);
} else {
menuitem.setAttribute("image", `${ProfilePath}/stop_smal_red.svg`);
}
menuitem.setAttribute("tooltiptext", "Linksklick: an/aus, Mittelklick: an/aus (Menü bleibt offen), Rechtsklick: bearbeiten");
menuitem.addEventListener("command", () => this.toggleCSS(file.leafName));
menuitem.addEventListener("click", (event) => this.cssItemClick(event, file.leafName));
if (popup) {
popup.appendChild(menuitem);
}
}
},
loadCSS: function(aFile) {
let CSS = this.readCSS[aFile.leafName];
if (!CSS) {
CSS = this.readCSS[aFile.leafName] = new CSSEntry(aFile);
CSS.enabled = !this.disabled_list.includes(aFile.leafName);
}
return CSS;
},
toggleCSS: function(aLeafName) {
let CSS = this.readCSS[aLeafName];
if (!CSS) return;
CSS.enabled = !CSS.enabled;
let currentDisabledList = this.disabled_list;
if (CSS.enabled) {
currentDisabledList = currentDisabledList.filter(name => name !== aLeafName);
} else {
if (!currentDisabledList.includes(aLeafName)) {
currentDisabledList.push(aLeafName);
}
}
this.disabled_list = currentDisabledList;
let menuitem = document.getElementById("appmenu-css-" + aLeafName);
if (menuitem) {
if (CSS.enabled) {
menuitem.setAttribute("image", `${ProfilePath}/menu-check_lime.svg`);
} else {
menuitem.setAttribute("image", `${ProfilePath}/stop_smal_red.svg`);
}
}
},
cssItemClick: function(event, aLeafName) {
event.preventDefault();
event.stopPropagation();
if (event.button === 0) {
return;
} else if (event.button === 1) {
this.toggleCSS(aLeafName);
} else if (event.button === 2) {
let file = this.getFileFromLeafName(aLeafName);
this.editCSS(file);
}
},
getFileFromLeafName: function(aLeafName) {
let f = this.FOLDER.clone();
f.QueryInterface(Ci.nsIFile);
f.appendRelativePath(aLeafName);
return f;
},
editCSS: function(aFile) {
let editor = cssLoaderConfig.Editor || Services.prefs.getCharPref("view_source.editor.path");
if (!editor) {
alert('Kein Editor konfiguriert! Bitte in about:config unter "view_source.editor.path" einen Editor eintragen.');
return;
}
try {
let UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
UI.charset = window.navigator.platform.toLowerCase().includes("win") ? "Shift_JIS" : "UTF-8";
let path = UI.ConvertFromUnicode(aFile.path);
let app = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
app.initWithPath(editor);
let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
process.init(app);
process.run(false, [path], 1);
} catch (e) {
console.error("Fehler beim Öffnen des Editors:", e);
}
},
},
// ■■ JavaScript-Loader-Funktionen (aus rebuild_userChrome.uc.js integriert) ■■
jsLoader: {
init: function() {
this.addPrefListener(this.readLaterPrefListener);
},
fillMenu: function(popup) {
while (popup.hasChildNodes()) popup.removeChild(popup.firstChild);
// --- Debug-Ausgabe ---
let ucjs = window.userChrome_js;
console.debug('[jsLoader] fillMenu aufgerufen. userChrome_js:', ucjs ? 'gefunden' : 'NICHT gefunden');
if (ucjs) {
console.debug('[jsLoader] arrSubdir:', ucjs.arrSubdir);
console.debug('[jsLoader] scripts.length:', ucjs.scripts ? ucjs.scripts.length : 'undefined');
console.debug('[jsLoader] overlays.length:', ucjs.overlays ? ucjs.overlays.length : 'undefined');
console.debug('[jsLoader] dirDisable:', ucjs.dirDisable);
console.debug('[jsLoader] scriptDisable:', ucjs.scriptDisable);
if (ucjs.scripts && ucjs.scripts.length > 0) {
console.debug('[jsLoader] scripts[0].dir:', ucjs.scripts[0].dir, 'filename:', ucjs.scripts[0].filename);
}
}
if (!ucjs || !ucjs.scripts) {
let msg = document.createXULElement('menuitem');
msg.setAttribute('label', 'userChrome.js nicht gefunden oder nicht initialisiert');
msg.setAttribute('disabled', 'true');
popup.appendChild(msg);
return;
}
// Safety: dirDisable/scriptDisable können undefined sein
if (!ucjs.dirDisable) ucjs.dirDisable = {};
if (!ucjs.scriptDisable) ucjs.scriptDisable = {};
if (!ucjs.overlays) ucjs.overlays = [];
try {
// --- Feste Menüeinträge ---
let reuse = this.getPref("userChrome.enable.reuse", 'bool', true);
let mSetting = document.createXULElement('menuitem');
mSetting.setAttribute('label', 'Skript für jedes Fenster neuladen');
mSetting.setAttribute('type', 'checkbox');
mSetting.toggleAttribute('checked', !reuse);
mSetting.addEventListener('command', () => this.setting());
popup.appendChild(mSetting);
popup.appendChild(document.createXULElement('menuseparator'));
// --- Alle UserScripte aktivieren/deaktivieren ---
let mAll = document.createXULElement('menuitem');
mAll.setAttribute('label', 'Alle UserScripte aktivieren/deaktivieren');
mAll.setAttribute('type', 'checkbox');
mAll.toggleAttribute('checked', !userChrome_js.dirDisable['*']);
mAll.dirName = '*';
mAll.addEventListener('command', () => this.chgDirStat("*"));
mAll.addEventListener('click', (event) => this.clickDirMenuitem(event, true));
mAll.addEventListener('mouseup', (event) => { if (event.button == 1) event.preventDefault(); });
popup.appendChild(mAll);
// --- Pro Ordner: Script-Checkboxen direkt im Hauptpopup ---
let foundAnyDir = false;
let firstDir = true;
for (let j = 0; j < ucjs.arrSubdir.length; j++) {
let dirName = ucjs.arrSubdir[j] === "" ? "root" : ucjs.arrSubdir[j];
let hasScripts = false;
for (let i = 0; i < ucjs.scripts.length; i++) {
if (ucjs.scripts[i].dir === dirName) { hasScripts = true; break; }
}
if (!hasScripts) {
for (let i = 0; i < ucjs.overlays.length; i++) {
if (ucjs.overlays[i].dir === dirName) { hasScripts = true; break; }
}
}
if (!hasScripts) continue;
if (firstDir) {
popup.appendChild(document.createXULElement('menuseparator'));
firstDir = false;
}
let displayDir = dirName === "root" ? "" : dirName;
let flg = false;
for (let i = 0; i < ucjs.scripts.length; i++) {
let script = ucjs.scripts[i];
if (script.dir !== dirName) continue;
flg = true;
let mScript = document.createXULElement('menuitem');
mScript.setAttribute('label', script.filename);
mScript.setAttribute('type', 'checkbox');
mScript.setAttribute('autocheck', 'false');
mScript.toggleAttribute('checked', !ucjs.scriptDisable[script.filename]);
if (script.description)
mScript.setAttribute('tooltiptext', script.description);
mScript.script = script;
mScript.addEventListener('command', () => this.chgScriptStat(script.filename));
mScript.addEventListener('click', (event) => this.clickScriptMenu(event, script));
mScript.addEventListener('mouseup', (event) => { if (event.button == 1) event.preventDefault(); });
popup.appendChild(mScript);
}
for (let i = 0; i < ucjs.overlays.length; i++) {
let script = ucjs.overlays[i];
if (script.dir !== dirName) continue;
if (flg) {
popup.appendChild(document.createXULElement('menuseparator'));
}
flg = false;
let mScript = document.createXULElement('menuitem');
mScript.setAttribute('label', script.filename);
mScript.setAttribute('type', 'checkbox');
mScript.setAttribute('autocheck', 'false');
mScript.toggleAttribute('checked', !ucjs.scriptDisable[script.filename]);
if (script.description)
mScript.setAttribute('tooltiptext', script.description);
mScript.script = script;
mScript.addEventListener('command', () => this.chgScriptStat(script.filename));
mScript.addEventListener('click', (event) => this.clickScriptMenu(event, script));
mScript.addEventListener('mouseup', (event) => { if (event.button == 1) event.preventDefault(); });
popup.appendChild(mScript);
}
foundAnyDir = true;
}
// Falls keine Scripts gefunden wurden, Hinweis anzeigen
if (!foundAnyDir) {
let noScripts = document.createXULElement('menuitem');
noScripts.setAttribute('label', 'Keine UserScripte gefunden (Ordner: ' + ucjs.arrSubdir.join(', ') + ')');
noScripts.setAttribute('disabled', 'true');
popup.appendChild(noScripts);
}
} catch (e) {
console.error('[jsLoader] Fehler in fillMenu:', e);
let errMsg = document.createXULElement('menuitem');
errMsg.setAttribute('label', 'Fehler: ' + e.message);
errMsg.setAttribute('disabled', 'true');
popup.appendChild(errMsg);
}
},
setting: function() {
let flag = this.getPref("userChrome.enable.reuse", 'bool', true);
this.setPref("userChrome.enable.reuse", 'bool', !flag);
},
clickDirMenu: function(event) {
if (event.button == 1 || event.button == 2) {
event.stopPropagation();
event.preventDefault();
this.chgDirStat(event.target.dirName);
if (event.target.firstChild && event.target.firstChild.firstChild)
event.target.firstChild.firstChild.toggleAttribute('checked', !userChrome_js.dirDisable[event.target.dirName]);
if (!!userChrome_js.dirDisable[event.target.dirName])
event.target.setAttribute('style', 'font-style:italic;');
else
event.target.removeAttribute('style');
}
},
clickDirMenuitem: function(event, stop) {
if (event.button == 1 || event.button == 2) {
event.stopPropagation();
event.preventDefault();
this.chgDirStat(event.target.dirName);
event.target.toggleAttribute('checked', !userChrome_js.dirDisable[event.target.dirName]);
if (!stop && !!userChrome_js.dirDisable[event.target.dirName])
event.target.parentNode.parentNode.setAttribute('style', 'font-style:italic;');
else
event.target.parentNode.parentNode.removeAttribute('style');
}
},
clickScriptMenu: function(event, script) {
if (event.button == 1) {
event.stopPropagation();
event.preventDefault();
this.chgScriptStat(script.filename);
event.target.toggleAttribute('checked', !userChrome_js.scriptDisable[script.filename]);
} else if (event.button == 2) {
event.stopPropagation();
event.preventDefault();
this.launchEditor(script);
}
},
launchEditor: function(aScript) {
let editor = Appmenu.editor;
let path = Services.io.newURI(aScript.url).QueryInterface(Ci.nsIFileURL).file.path;
let appfile = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
appfile.initWithPath(editor);
let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
process.init(appfile);
process.runw(false, [path], 1, {});
},
chgDirStat: function(adirName) {
let s = this.getPref("userChrome.disable.directory", "str", "");
if (!userChrome_js.dirDisable[adirName]) {
s = (s + ',').replace(adirName + ',', '') + adirName + ',';
} else {
s = (s + ',').replace(adirName + ',', '');
}
s = s.replace(/,,/g, ',').replace(/^,/, '');
this.setPref("userChrome.disable.directory", "str", s);
userChrome_js.dirDisable = this.restoreState(s.split(','));
},
chgScriptStat: function(afilename) {
let s = this.getPref("userChrome.disable.script", "str", "");
if (!userChrome_js.scriptDisable[afilename]) {
s = (s + ',').replace(afilename + ',', '') + afilename + ',';
} else {
s = (s + ',').replace(afilename + ',', '');
}
s = s.replace(/,,/g, ',').replace(/^,/, '');
this.setPref("userChrome.disable.script", "str", s);
userChrome_js.scriptDisable = this.restoreState(s.split(','));
},
restoreState: function(arr) {
let disable = [];
for (let i = 0; i < arr.length; i++) disable[arr[i]] = true;
return disable;
},
getPref: function(aPrefString, aPrefType, aDefault) {
let xpPref = Services.prefs;
try {
switch (aPrefType) {
case 'complex': return xpPref.getComplexValue(aPrefString, Ci.nsIFile);
case 'str': return unescape(xpPref.getCharPref(aPrefString).toString());
case 'int': return xpPref.getIntPref(aPrefString);
case 'bool': default: return xpPref.getBoolPref(aPrefString);
}
} catch (e) {}
return aDefault;
},
setPref: function(aPrefString, aPrefType, aValue) {
let xpPref = Services.prefs;
try {
switch (aPrefType) {
case 'complex': return xpPref.setComplexValue(aPrefString, Ci.nsIFile, aValue);
case 'str': return xpPref.setCharPref(aPrefString, escape(aValue));
case 'int': aValue = parseInt(aValue); return xpPref.setIntPref(aPrefString, aValue);
case 'bool': default: return xpPref.setBoolPref(aPrefString, aValue);
}
} catch (e) {}
return null;
},
addPrefListener: function(aObserver) {
try { Services.prefs.addObserver(aObserver.domain, aObserver, false); }
catch (e) {}
},
removePrefListener: function(aObserver) {
try { Services.prefs.removeObserver(aObserver.domain, aObserver); }
catch (e) {}
},
readLaterPrefListener: {
domain: 'userChrome.disable',
observe: function(aSubject, aTopic, aPrefstring) {
if (aTopic == 'nsPref:changed') {
setTimeout(function() {
let s = Appmenu.jsLoader.getPref("userChrome.disable.directory", "str", "");
userChrome_js.dirDisable = Appmenu.jsLoader.restoreState(s.split(','));
s = Appmenu.jsLoader.getPref("userChrome.disable.script", "str", "");
userChrome_js.scriptDisable = Appmenu.jsLoader.restoreState(s.split(','));
}, 0);
}
}
},
},
toolbar: {
subdirs: [
{
name: 'Firefox Verzeichnisse',
image: `${ProfilePath}/folder_currentColor.svg`,
},
{
name: 'Firefox Funktionen',
image: `${ProfilePath}/settings_currentColor.svg`,
},
{
name: 'separator',
},
{
name: 'Meine Scripte',
image: `${ProfilePath}/${Icon31}`,
},
{
name: 'Meine CSS-Dateien',
image: `${ProfilePath}/${Icon32}`,
},
{
name: 'Meine CSSWeb-Dateien',
image: `${ProfilePath}/${Icon33}`,
},
{
name: 'Skriptliste in Zwischenablage',
image: `${ProfilePath}/${Icon34}`,
command: () => Appmenu.getScripts(1),
tooltiptext: 'Kopiert eine Liste aller uc.js-Skripte in die Zwischenablage',
},
{
name: 'separator',
},
{
name: 'JavaScript-Loader-Menü',
image: `${ProfilePath}/${Icon04}`,
},
{
name: 'CSS-Loader-Menü',
image: `${ProfilePath}/css4_currentColor.svg`,
},
{
name: 'Konfiguration',
image: `${ProfilePath}/Hammer-wrench_currentColor.svg`,
},
{
name: '"about:"-Seiten',
image: `${ProfilePath}/firefox_currentColor.svg`,
},
],
apps: [
{
name: 'Profil-Verzeichnis',
id: 'AMProfil',
root: 'ProfD',
path: '\\',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon01}`,
},
{
name: 'Chrome-Ordner',
id: 'AMchrome',
root: 'ProfD',
path: '\\chrome',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon02}`,
},
{
name: 'CSS-Ordner',
id: 'AMCSS',
root: 'ProfD',
path: '\\chrome\\css',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon03}`,
},
{
name: 'CSS-Web-Ordner',
id: 'AMWEB',
root: 'ProfD',
path: '\\chrome\\cssWeb',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon03}`,
},
{
name: 'JS-Ordner',
id: 'AMJS',
root: 'ProfD',
path: '\\chrome\\scripts',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon04}`,
},
{
name: 'Icons-Ordner',
id: 'AMICO',
root: 'ProfD',
path: '\\chrome\\icons',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon05}`,
},
{
name: 'Addon-Verzeichnis',
id: 'AMAddons',
root: 'ProfD',
path: '\\extensions',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon06}`,
},
{
name: 'Programm-Verzeichnis',
id: 'AMProgramm',
root: 'CurProcD',
path: '\\',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon07}`,
},
{
name: 'Startup-Cache',
id: 'AMCache',
root: 'ProfLD',
path: '\\startupCache',
subdir: 'Firefox Verzeichnisse',
image: `${ProfilePath}/${Icon08}`,
},
],
configs: [
{
name: 'Anpassen',
id: 'AMAnpassen',
command: 'gCustomizeMode.enter()',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon11}`,
},
{
name: 'Neustart im abgesicherten Modus',
id: 'AMModus',
command: 'safeModeRestart();',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon12}`,
},
{
name: 'Browser-Konsole',
id: 'AMKonsole',
command: 'goKonsole',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon13}`,
},
{
name: 'Browser-Werkzeuge',
id: 'AMWerkzeuge',
command: 'goWerkzeuge',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon14}`,
},
{
name: 'Web-Entwickler',
id: 'AMEntwickler',
command: 'goEntwickler',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon15}`,
},
{
name: 'Firefox synchronisieren',
id: 'AMsynchron',
command: 'gSync',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon16}`,
},
{
name: 'Zugangsdaten und Passwörter',
id: 'AMdaten',
command: 'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })',
tooltiptext: 'about:logins',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon17}`,
},
{
name: 'Task Manager',
id: 'AMManager',
command: 'switchToTabHavingURI("about:processes", true)',
tooltiptext: 'about:processes',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon18}`,
},
{
name: 'Offline arbeiten',
id: 'AMOffline',
command: 'BrowserOffline.toggleOfflineStatus();',
subdir: 'Firefox Funktionen',
image: `${ProfilePath}/${Icon19}`,
},
{
name: 'Neustart (inkl. Script Cache leeren)',
id: 'AMreboot',
tooltiptext: 'userChrome.js-Cache wird geleert',
command: 'goReeboot',
image: `${ProfilePath}/${ButtonIcon01}`,
},
{
name: 'Beenden',
id: 'AMquit',
command: 'goQuitApplication(event);',
image: `${ProfilePath}/${ButtonIcon02}`,
},
// uProfMenu-Funktionen unter Menüeintrag "Konfiguration"
{
name: 'userChrome.css bearbeiten',
id: 'AMuserChromeCss',
command: () => Appmenu.edit(0, 'userChrome.css'),
subdir: 'Konfiguration',
image: `${ProfilePath}/css4.svg`,
},
{
name: 'userChromeShadow.css bearbeiten',
id: 'AMuserChromeShadowCss',
command: () => Appmenu.edit(0, 'userChromeShadow.css'),
subdir: 'Konfiguration',
image: `${ProfilePath}/css4.svg`,
},
{
name: 'userContent.css bearbeiten',
id: 'AMuserContentCss',
command: () => Appmenu.edit(0, 'userContent.css'),
subdir: 'Konfiguration',
image: `${ProfilePath}/css4.svg`,
},
{
name: 'userChrome.js bearbeiten',
id: 'AMuserChromeJs',
command: () => Appmenu.edit(0, 'userChrome.js'),
subdir: 'Konfiguration',
image: `${ProfilePath}/js.svg`,
},
{
name: 'prefs.js bearbeiten',
id: 'AMprefsJs',
command: () => Appmenu.edit(1, 'prefs.js'),
subdir: 'Konfiguration',
image: `${ProfilePath}/js.svg`,
},
{
name: 'user.js bearbeiten',
id: 'AMuserJs',
command: () => Appmenu.edit(1, 'user.js'),
subdir: 'Konfiguration',
image: `${ProfilePath}/js.svg`,
},
// about:-Seiten
{
name: 'about:about',
id: 'AMaboutAbout',
command: () => openTrustedLinkIn("about:about", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon21}`,
},
{
name: 'about:addons',
id: 'AMaboutAddons',
command: () => openTrustedLinkIn("about:addons", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon40}`,
},
{
name: 'about:cache',
id: 'AMaboutCache',
command: () => openTrustedLinkIn("about:cache", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon22}`,
},
{
name: 'about:config',
id: 'AMaboutConfig',
command: () => openTrustedLinkIn("about:config", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon23}`,
},
{
name: 'about:crashes',
id: 'AMaboutCrashes',
command: () => openTrustedLinkIn("about:crashes", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon24}`,
},
{
name: 'about:downloads',
id: 'AMaboutDownloads',
command: () => openTrustedLinkIn("about:downloads", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon25}`,
},
{
name: 'about:home',
id: 'AMaboutHome',
command: () => openTrustedLinkIn("about:home", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon26}`,
},
{
name: 'about:logins',
id: 'AMaboutLogins',
command: 'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })',
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon27}`,
},
{
name: 'about:support',
id: 'AMaboutSupport',
command: () => openTrustedLinkIn("about:support", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon28}`,
},
{
name: 'about:preferences',
id: 'AMaboutPreferences',
command: () => openTrustedLinkIn("about:preferences", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon29}`,
},
{
name: 'about:processes',
id: 'AMaboutProcesses',
command: () => openTrustedLinkIn("about:processes", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon41}`,
},
{
name: 'about:profiles',
id: 'AMaboutProfiles',
command: () => openTrustedLinkIn("about:profiles", "tab"),
subdir: '"about:"-Seiten',
image: `${ProfilePath}/${Icon30}`,
},
]
},
_externalAppPopup: null,
_isready: false,
// uProfMenu-Funktionen (bereits integriert)
getDirSep: function() {
var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS;
var dirsep = "/";
switch(osString) {
case "WINNT":
dirsep = "\\";
break;
case "Darwin":
dirsep = "/";
break;
}
return dirsep;
},
getPrefDirectoryPath: function(str) {
var file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get(str, Components.interfaces.nsIFile);
if (str == 'CurProcD') {
file = file.parent;
}
return file.path;
},
edit: function(OpenMode, Filename) {
var Path = "";
var dSep = this.getDirSep();
// Wenn der Dateiname einen Pfad enthält (z. B. "chrome/scripts/test.uc.js"),
// vom Profil-Verzeichnis aus auflösen:
if (Filename.includes("/") || Filename.includes("\\")) {
Path = this.getPrefDirectoryPath("ProfD") + dSep + Filename.replace(/\//g, dSep);
} else {
switch (OpenMode) {
case 0:
Path = this.getPrefDirectoryPath("UChrm") + dSep + Filename;
break;
case 1:
Path = this.getPrefDirectoryPath("ProfD") + dSep + Filename;
break;
case 3:
Path = this.getPrefDirectoryPath("UChrm") + dSep + "CSS" + dSep + Filename;
break;
case 4:
Path = this.getPrefDirectoryPath("UChrm") + dSep + "CSSWeb" + dSep + Filename;
break;
case 5:
Path = this.getPrefDirectoryPath("UChrm") + dSep + "CSSShadow" + dSep + Filename;
break;
}
}
this.launch(this.editor, Path);
},
launch: function(RanPath, OpenPath) {
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIFile);
var proc = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
var args = [OpenPath];
file.initWithPath(RanPath);
if (!file.exists()) {
var pref = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
RanPath = pref.getCharPref("view_source.editor.path");
file.initWithPath(RanPath);
}
proc.init(file);
proc.run(false, args, args.length);
},
// ■■ Neu: Script- und CSS-Listen (aus extras_config_menu.uc.js integriert) ■■
getScripts: function(iType) {
let ucJsScripts = [];
let extjs = /\.uc\.js$/i;
// 1. Standard-UChrm-Ordner durchsuchen
let uchrmFolder = Services.dirsvc.get("UChrm", Ci.nsIFile);
if (uchrmFolder.exists()) {
let files = uchrmFolder.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
while (files.hasMoreElements()) {
let file = files.getNext().QueryInterface(Ci.nsIFile);
if (extjs.test(file.leafName)) {
if (file.leafName === "userChromeShadow.uc.js" && !this.showuCS) continue;
ucJsScripts.push(file.leafName);
}
}
}
// 2. chrome/scripts-Unterverzeichnis durchsuchen
if (this.jsSubfolder) {
let scriptsFolder = Services.dirsvc.get("ProfD", Ci.nsIFile);
scriptsFolder.append("chrome");
scriptsFolder.append(this.jsSubfolder);
if (scriptsFolder.exists()) {
let files = scriptsFolder.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
while (files.hasMoreElements()) {
let file = files.getNext().QueryInterface(Ci.nsIFile);
if (extjs.test(file.leafName)) {
ucJsScripts.push("chrome/" + this.jsSubfolder + "/" + file.leafName);
}
}
}
}
if (this.sortScripts) ucJsScripts.sort(this.stringComparison.bind(this));
if (iType === 0) {
// Untermenü "Meine Scripte" befüllen
this.fillFileMenu("Meine Scripte", "Meine Scripte", ucJsScripts, 0);
} else {
// Für Zwischenablage: Nur Dateinamen (ohne Pfad) verwenden
let simpleNames = ucJsScripts.map(f => f.split(/[\\/]/).pop());
let result = this.fillClipboardValue(simpleNames);
Components.classes["@mozilla.org/widget/clipboardhelper;1"]
.getService(Components.interfaces.nsIClipboardHelper).copyString(result);
}
},
getCssFiles: function(iType) {
let cssFiles = [];
let extcss = /\.css$/i;
let folderName = "";
let subdirName = "";
let menuLabel = "";
let sType = 0;
if (iType === 3) {
folderName = "CSS";
subdirName = "Meine CSS-Dateien";
menuLabel = "Meine CSS-Dateien";
sType = 3;
} else if (iType === 4) {
folderName = "CSSWeb";
subdirName = "Meine CSSWeb-Dateien";
menuLabel = "Meine CSSWeb-Dateien";
sType = 4;
} else if (iType === 5) {
folderName = "CSSShadow";
subdirName = "Meine CSSShadow-Dateien";
menuLabel = "Meine CSSShadow-Dateien";
sType = 5;
} else {
return;
}
let aFolder = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path + this.getDirSep() + folderName);
if (aFolder.exists() && aFolder.isDirectory()) {
let files = aFolder.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
while (files.hasMoreElements()) {
let file = files.getNext().QueryInterface(Ci.nsIFile);
if (extcss.test(file.leafName)) cssFiles.push(file.leafName);
}
}
if (this.sortScripts) cssFiles.sort(this.stringComparison.bind(this));
this.fillFileMenu(subdirName, menuLabel, cssFiles, sType);
},
fillFileMenu: function(subdirName, strlabel, fileArray, sType) {
let submenuItem = Appmenu.subdirMenuHash[subdirName];
if (submenuItem) {
submenuItem.setAttribute('label', strlabel + ' (' + fileArray.length + ')');
}
let popup = Appmenu.subdirPopupHash[subdirName];
if (!popup) return;
// Vorhandene Einträge löschen
while (popup.hasChildNodes()) popup.removeChild(popup.firstChild);
// Symbol je nach Dateityp festlegen
let iconPath = '';
if (sType === 0) {
iconPath = ProfilePath + '/' + Icon04; // js.svg
} else {
iconPath = ProfilePath + '/' + Icon03; // css4.svg
}
for (let i = 0; i < fileArray.length; i++) {
let fileName = fileArray[i];
let mitem = document.createXULElement('menuitem');
mitem.setAttribute('class', 'menuitem-iconic');
mitem.setAttribute('image', iconPath);
if (sType === 0) {
// Scripts: Linksklick = Bearbeiten, Mittelklick = GitHub, Rechtsklick = GitHub-Suche
let displayName = fileName.split(/[\\/]/).pop();
mitem.setAttribute('label', displayName);
mitem.addEventListener('command', function() {
Appmenu.edit(0, fileName);
}, true);
mitem.addEventListener('click', function(event) {
Appmenu.openAtGithub(event, displayName);
}, true);
mitem.setAttribute('tooltiptext',
'Linksklick: Bearbeiten,\nMittelklick: GitHub-Seite öffnen,\nRechtsklick: GitHub-Suche');
} else if (sType === 3) {
mitem.setAttribute('label', fileName);
mitem.addEventListener('command', function() {
Appmenu.edit(3, fileName);
}, true);
} else if (sType === 4) {
mitem.setAttribute('label', fileName);
mitem.addEventListener('command', function() {
Appmenu.edit(4, fileName);
}, true);
} else if (sType === 5) {
mitem.setAttribute('label', fileName);
mitem.addEventListener('command', function() {
Appmenu.edit(5, fileName);
}, true);
}
popup.appendChild(mitem);
}
},
fillClipboardValue: function(sArray) {
var retValue = "Meine Skripte (" + sArray.length + "):\n------------------------";
for (var i = 0; i < sArray.length; i++) {
retValue += "\n" + (i + 1) + ". " + sArray[i];
}
return retValue;
},
openAtGithub: function(e, sScript) {
if (e.button == 1) {
var sUrl = "https://github.com/ardiman/userChrome.js/tree/master/" + this.cleanFileName(sScript);
openWebLinkIn(sUrl, 'tab');
}
if (e.button == 2) {
e.preventDefault();
var sUrl = "https://github.com/search?langOverride=&language=&q=" + sScript + "&repo=&start_value=1&type=Code";
openWebLinkIn(sUrl, 'tab');
}
},
cleanFileName: function(sName) {
sName = sName.toLowerCase();
var regs = [/\.uc\.js$/, /\.uc\.xul$/, /^ucjs_/, /_\d.+/, /_fx\d+/, /[-+\.]/g, /_v\d+/];
for (var i = 0; i < regs.length; i++) {
sName = sName.replace(regs[i], "");
}
return sName;
},
stringComparison: function(a, b) {
a = a.toLowerCase().replace(/ä/g,"a").replace(/ö/g,"o").replace(/ü/g,"u").replace(/ß/g,"s");
b = b.toLowerCase().replace(/ä/g,"a").replace(/ö/g,"o").replace(/ü/g,"u").replace(/ß/g,"s");
return (a == b) ? 0 : (a > b) ? 1 : -1;
},
init: function() {
this.handleRelativePath(this.toolbar.apps);
const XULNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
var ExternalAppBtn = document.createElementNS(XULNS, 'toolbarbutton');
ExternalAppBtn.id = 'AppMenuButton';
ExternalAppBtn.setAttribute('label', 'AppButton');
ExternalAppBtn.addEventListener('click', event => {
event.preventDefault();
event.stopPropagation();
});
ExternalAppBtn.setAttribute('tooltiptext', 'Firefox Menü');
ExternalAppBtn.setAttribute('type', 'menu');
ExternalAppBtn.setAttribute('removable', 'true');
let ProfilePath = PathUtils.toFileURI(
PathUtils.join(PathUtils.profileDir, 'chrome', 'image')
);
let DefaultIcon = 'Button_groß.png';
let AlternateIcon = 'Button_klein-5.png';
if (Appmenu.isButton) {
ExternalAppBtn.style.listStyleImage = `url('${ProfilePath}/${DefaultIcon}')`;
ExternalAppBtn.style.width = '94px';
ExternalAppBtn.style.height = '24px';
} else {
ExternalAppBtn.style.listStyleImage = `url('${ProfilePath}/${AlternateIcon}')`;
ExternalAppBtn.style.width = '48px';
ExternalAppBtn.style.height = '21px';
}
if (Appmenu.isUrlbar === 1) {
var navBar = document.getElementById('nav-bar-customization-target');
navBar.insertBefore(ExternalAppBtn, navBar.firstChild);
} else if (Appmenu.isUrlbar === 2) {
var menubar = document.getElementById('toolbar-menubar');
menubar.insertBefore(ExternalAppBtn, menubar.firstChild);
} else {
var TabsToolbar = document.getElementById('TabsToolbar');
TabsToolbar.insertBefore(ExternalAppBtn, TabsToolbar.firstChild);
}
var ExternalAppPopup = document.createElementNS(XULNS, 'menupopup');
ExternalAppPopup.addEventListener('click', event => {
event.stopPropagation();
});
ExternalAppPopup.setAttribute('id', 'AMpopup');
this._externalAppPopup = ExternalAppPopup;
ExternalAppBtn.appendChild(ExternalAppPopup);
Appmenu.onpopupshowing();
// CSS-Loader initialisieren
this.cssLoader.initCSSLoader();
// JS-Loader initialisieren (Pref-Listener registrieren)
this.jsLoader.init();
// Menü mit Tastaturkürzel öffnen
if (Appmenu.hotkey) {
let key = document.createXULElement('key');
key.id = 'key_AppMenuPopup';
key.setAttribute('key', Appmenu.hotkey);
if (Appmenu.hotkeyModifier)
key.setAttribute('modifiers', Appmenu.hotkeyModifier);
key.addEventListener('command', function () {
document.getElementById('AMpopup').openPopup();
});
document.getElementById('mainKeyset').appendChild(key);
}
},
onpopupshowing: function() {
if (this._isready) return;
if (this._externalAppPopup === null) return;
var ExternalAppPopup = this._externalAppPopup;
for (let subdir of this.toolbar.subdirs) {
if (subdir.name == 'separator') {
ExternalAppPopup.appendChild(document.createXULElement('menuseparator'));
} else if (subdir.command) {
var actionItem = ExternalAppPopup.appendChild(document.createXULElement('menuitem'));
actionItem.setAttribute('class', 'menuitem-iconic');
actionItem.setAttribute('label', subdir.name);
actionItem.setAttribute('image', subdir.image);
if (subdir.tooltiptext) {
actionItem.setAttribute('tooltiptext', subdir.tooltiptext);
} else {
actionItem.setAttribute('tooltiptext', subdir.name);
}
actionItem.addEventListener('command', subdir.command);
} else {
var subdirItem = ExternalAppPopup.appendChild(document.createXULElement('menu'));
var subdirItemPopup = subdirItem.appendChild(document.createXULElement('menupopup'));
subdirItem.setAttribute('class', 'menu-iconic');
subdirItem.setAttribute('label', subdir.name);
subdirItem.setAttribute('image', subdir.image);
Appmenu.subdirPopupHash[subdir.name] = subdirItemPopup;
Appmenu.subdirMenuHash[subdir.name] = subdirItem;
// CSS-Loader-Menüeinträge für "CSS-Loader-Menü"
if (subdir.name === "CSS-Loader-Menü") {
Appmenu.cssLoader.rebuildCSSMenu();
}
// Neue dynamische Untermenüs befüllen
if (subdir.name === "Meine Scripte") {
Appmenu.getScripts(0);
}
if (subdir.name === "Meine CSS-Dateien") {
Appmenu.getCssFiles(3);
}
if (subdir.name === "Meine CSSWeb-Dateien") {
Appmenu.getCssFiles(4);
}
// JavaScript-Loader-Menü: popupshowing-Listener für dynamischen Aufbau
// Wichtig: nur bei e.target === e.currentTarget ausführen,
// sonst bubbelt popupshowing von Kind-Popups hoch und führt zu Endlosschleife
if (subdir.name === "JavaScript-Loader-Menü") {
subdirItemPopup.addEventListener('popupshowing', (e) => {
if (e.target === e.currentTarget) Appmenu.jsLoader.fillMenu(e.target);
});
}
}
}
for (let app of this.toolbar.apps) {
var appItem;
if (app.name == 'separator') {
appItem = document.createXULElement('menuseparator');
} else {
appItem = document.createXULElement('menuitem');
appItem.setAttribute('class', 'menuitem-iconic');
appItem.setAttribute('label', app.name);
appItem.setAttribute('image', app.image);
appItem.addEventListener('command', function () {
Appmenu.exec(this.path, this.args);
});
appItem.setAttribute('tooltiptext', app.name);
appItem.path = app.path;
appItem.args = app.args;
}
if (app.subdir && Appmenu.subdirPopupHash[app.subdir])
Appmenu.subdirPopupHash[app.subdir].appendChild(appItem);
else ExternalAppPopup.appendChild(appItem);
}
for (let config of this.toolbar.configs) {
var configItem;
if (config.name == 'separator') {
configItem = document.createXULElement('menuseparator');
} else {
configItem = ExternalAppPopup.appendChild(document.createXULElement('menuitem'));
configItem.setAttribute('class', 'menuitem-iconic');
configItem.setAttribute('label', config.name);
configItem.setAttribute('image', config.image);
configItem.addEventListener('command', () => {
if (typeof config.command === 'function') {
config.command();
} else {
Appmenu.executeCommand(config.command);
}
});
if (config.tooltiptext) {
configItem.setAttribute('tooltiptext', config.tooltiptext);
} else {
configItem.setAttribute('tooltiptext', config.name);
}
configItem.setAttribute('id', config.id);
}
if (config.subdir && Appmenu.subdirPopupHash[config.subdir]) {
Appmenu.subdirPopupHash[config.subdir].appendChild(configItem);
} else {
ExternalAppPopup.appendChild(configItem);
}
}
if (this.autohideEmptySubDirs) {
// Lazy-gefüllte Untermenüs nicht verstecken (werben erst beim Aufklappen befüllt)
let lazySubdirs = ['JavaScript-Loader-Menü'];
for (let key of Object.keys(Appmenu.subdirPopupHash)) {
if (lazySubdirs.includes(key)) continue;
if (Appmenu.subdirPopupHash[key].hasChildNodes()) {
continue;
} else {
Appmenu.subdirMenuHash[key].setAttribute('hidden', 'true');
}
}
}
if (this.moveSubDirstoBottom) {
let i = ExternalAppPopup.childNodes.length;
while (ExternalAppPopup.firstChild.getAttribute('class') != 'menuitem-iconic' && i-- != 0) {
ExternalAppPopup.appendChild(ExternalAppPopup.firstChild);
}
}
this._isready = true;
},
executeCommand: function(command) {
const commandMap = {
'gCustomizeMode.enter()': () => gCustomizeMode.enter(),
'safeModeRestart();': () => safeModeRestart(),
'goKonsole': () => {
var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
var { BrowserConsoleManager } = require('resource://devtools/client/webconsole/browser-console-manager');
BrowserConsoleManager.openBrowserConsoleOrFocus();
},
'goWerkzeuge': () => {
var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
var { BrowserToolboxLauncher } = require('resource://devtools/client/framework/browser-toolbox/Launcher.sys.mjs');
BrowserToolboxLauncher.init();
},
'goEntwickler': () => {
var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
var { gDevToolsBrowser } = require('resource://devtools/client/framework/devtools-browser');
gDevToolsBrowser.toggleToolboxCommand(window.gBrowser, performance.now());
},
'gSync': () => gSync.openPrefs('menubar'),
'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })': () => LoginHelper.openPasswordManager(window, { entryPoint: 'mainmenu' }),
'switchToTabHavingURI("about:processes", true)': () => switchToTabHavingURI('about:processes', true),
'BrowserOffline.toggleOfflineStatus();': () => BrowserOffline.toggleOfflineStatus(),
'goReeboot': () => {
Services.appinfo.invalidateCachesOnRestart();
Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit);
},
'goQuitApplication(event);': () => goQuitApplication(event),
};
if (commandMap[command]) {
commandMap[command]();
} else {
console.warn('Unbekannter Befehl: ', command);
}
},
handleRelativePath: function(apps) {
for (let app of apps) {
if (app.path) {
app.path = app.path.replace(/\//g, '\\');
var ffdir = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties).get(app.root, Ci.nsIFile).path;
if (/^(\\)/.test(app.path)) {
app.path = ffdir + app.path;
}
}
}
},
exec: function(path, args) {
args = args || [];
var args_t = args.slice(0);
for (let arg of args_t) {
arg = arg.replace(/%u/g, gBrowser.currentURI.spec);
}
var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
file.initWithPath(path);
if (!file.exists()) {
alert('Datei nicht gefunden: ' + path);
return;
}
if (file.isExecutable() && !path.endsWith('.js')) {
var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
process.init(file);
process.run(false, args_t, args_t.length);
} else if (file.isFile()) {
if (this.editor) {
let UI = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Ci.nsIScriptableUnicodeConverter);
UI.charset = window.navigator.platform.toLowerCase().includes("win") ? "Shift_JIS" : "UTF-8";
let path = UI.ConvertFromUnicode(file.path);
let app = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
app.initWithPath(this.editor);
let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
process.init(app);
process.run(false, [path], 1);
} else {
file.launch();
}
} else if (file.isDirectory()) {
if (this.fileManager) {
let args=[this.FMParameter,path];
let app = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
app.initWithPath(this.fileManager);
let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
process.init(app);
process.run(false, args, args.length);
} else {
file.launch();
}
}
},
};
/* ***************************************************************************************************************************** */
// CSSEntry-Klasse (aus UserCSSLoader)
function CSSEntry(aFile) {
this.path = aFile.path;
this.leafName = aFile.leafName;
this.lastModifiedTime = 1;
this.SHEET = /^xul-|\.as\.css$/i.test(this.leafName) ?
Ci.nsIStyleSheetService.AGENT_SHEET :
/\.author\.css$/i.test(this.leafName) ?
Ci.nsIStyleSheetService.AUTHOR_SHEET :
Ci.nsIStyleSheetService.USER_SHEET;
}
CSSEntry.prototype = {
sss: Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService),
_enabled: false,
get enabled() {
return this._enabled;
},
set enabled(isEnable) {
let aFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
aFile.initWithPath(this.path);
let isExists = aFile.exists();
let lastModifiedTime = isExists ? aFile.lastModifiedTime : 0;
let isForced = this.lastModifiedTime != lastModifiedTime;
let fileURL = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getURLSpecFromActualFile(aFile);
let uri = Services.io.newURI(fileURL, null, null);
if (this.sss.sheetRegistered(uri, this.SHEET)) {
if (!isEnable || !isExists) {
this.sss.unregisterSheet(uri, this.SHEET);
} else if (isForced) {
this.sss.unregisterSheet(uri, this.SHEET);
this.sss.loadAndRegisterSheet(uri, this.SHEET);
}
} else {
if (isEnable && isExists) {
this.sss.loadAndRegisterSheet(uri, this.SHEET);
}
}
this.lastModifiedTime = lastModifiedTime;
return this._enabled = isEnable;
},
};
(function () {
let sss = Components.classes['@mozilla.org/content/style-sheet-service;1'].getService(Components.interfaces.nsIStyleSheetService);
let uri = Services.io.newURI(
'data:text/css;charset=utf-8,' +
encodeURIComponent(`
menuitem[label="Profil-Verzeichnis"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="Chrome-Ordner"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="CSS-Ordner"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="CSS-Web-Ordner"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="JS-Ordner"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="Icons-Ordner"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="Addon-Verzeichnis"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="Programm-Verzeichnis"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menuitem[label="Startup-Cache"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMAnpassen { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMModus { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMKonsole { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMWerkzeuge { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMEntwickler { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMsynchron { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMdaten { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMManager { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMOffline { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
/* Neustart-Button */
#AMreboot { -moz-context-properties: fill, fill-opacity !important; fill: #fbc96e !important; padding-left: 13px !important; }
#AMreboot > img:nth-child(1) { width: 16px !important; height: 16px !important; }
/* Beenden-Button */
#AMquit { -moz-context-properties: fill, fill-opacity !important; fill: red !important; }
/* Skriptliste in Zwischenablage */
#AMscriptList { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
/* about:-Seiten */
#AMaboutAbout { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutAddons { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutCache { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutConfig { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutCrashes { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutDownloads { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutHome { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutLogins { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutSupport { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutPreferences { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutProcesses { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMaboutProfiles { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
/* uProfMenu-Einträge */
#AMuserChromeCss { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMuserChromeShadowCss { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMuserContentCss { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMuserChromeJs { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMprefsJs { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#AMuserJs { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
/* 1 */
menuitem[subdir="CSS-Loader-Menü"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
menu[label="JavaScript-Loader-Menü"] { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
#appmenu-css-CSS-Ordner-öffnen { -moz-context-properties: fill, fill-opacity; fill: currentColor; }
`),
null,
null
);
sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
})();
if (window.gBrowser) Appmenu.init();
Alles anzeigen