Dann würde ich es so lassen
Der Tooltip müsste dann noch geändert werden...
Dann würde ich es so lassen
Der Tooltip müsste dann noch geändert werden...
Danke für den Hinweis.![]()
Habe ich hier bereits entsprechend geändert.
Zeile 52: tooltiptext: "Extra Config Menü\nMittelklick öffnet about:config"
Wenn Mira_Belle Ihr Ok gibt lade ich diese Version dann bei mir rauf.
Mfg.
Endor
Danke.
Ist erledigt:
Mfg.
Endor
Ist erledigt:
In der Version fehlen viele Erläuterungen im Vergleich zur Version für FF 135, sowohl für die Konfiguration als auch innerhalb des Skripts zur Funktion einzelner Teile. (Einige sind aber zugefügt.) Ich wüsste nicht, wie ich die Konfiguration einstellen muss, noch, was die einzelnen Skriptteile tun, was künftige Änderungen erschwert. Ich habe allerdings inzwischen eine an einigen Stellen abweichende Version, die ich deshalb beibehalte.
Es gibt einige Änderungen mit der Erklärung (ANGEPASST: sCommand als Funktion). Welchen Vorteil hat das gegenüber der vorherigen Version? In der wird das an nur einer Stelle in den Zeilen 429 - 430 gelöst.
Der Wert helpMenu in Zeile 20 stammt wohl noch aus einer älteren Version, als es den verschiebbaren Button noch nicht gab. Das ist in der Erläuterung der Version für FF 135 falsch. Es gibt es nur noch den Wert menu als Menü im Extras Menü (menu_ToolsPopup in Zeile 35 fest eingestellt) und sonst z.B. leer für Button. Das Skript prüft nur noch auf menu. Wenn das dort nicht steht, egal ob leer oder irgend etwas anderes, wird ein Button erstellt.
Solch kleine Ungereimtheiten kann ich erst später ausbügeln!
Es funktioniert ja erst einmal.
Und ich würde ja schon sagen, dass es noch nicht ganz einer Endversion entspricht
Um den Konigbereich werde ich mich dann auch noch kümmern und mit Sicherheit erweitern, damit niand mehr im Code änderungen vornehmen muss.
So, genug von meiner Seite.
Testet weiter, schreibt, was nicht klappt oder was im Code noch verbessert werden könnte oder ob es da noch Leichen gibt.
So long...
Es gibt einige Änderungen mit der Erklärung (ANGEPASST: sCommand als Funktion). Welchen Vorteil hat das gegenüber der vorherigen Version?
Erklärung einer KI!
Der entscheidende Punkt ist, dass der ursprüngliche Code den Befehl als **Zeichenkette** (`"uProfMenu.getScripts(1)"`) übergibt. Solche Strings wurden früher von `createME` intern typischerweise mit `eval()` oder über das `command`-Attribut des Menüeintrags ausgeführt. Die neue Variante übergibt stattdessen ein **echtes Funktionsobjekt**.
Das bringt mehrere Vorteile:
**1. Sicherheit / CSP-Kompatibilität**
Firefox verbietet in modernen Extensions die Ausführung von Strings via `eval()` oder `setTimeout("…")` – das verstößt gegen die Content Security Policy. Eine echte Funktion ist davon nicht betroffen und läuft auch unter strikten CSP-Regeln.
**2. Performance**
Ein String muss bei jedem Aufruf neu geparst und kompiliert werden. Die Funktion ist bereits beim Definieren kompiliert und wird direkt aufgerufen.
**3. Scope / Variablenbindung**
Die Funktion ist eine echte Closure und hält den richtigen Gültigkeitsbereich (lexikalischer Scope). Ein per `eval` ausgeführter String läuft oft in einem anderen Kontext und kann lokale Variablen nicht zuverlässig sehen.
**4. Refactoring, Linting, Minifying**
Eine Funktion ist echter Code: Sie wird von Lintern analysiert, beim Umbenennen von `getScripts` aktualisiert und von Bundlern/Minifiern mitbearbeitet. Ein String bleibt für all diese Werkzeuge unsichtbar.
**5. Bessere Fehlermeldungen**
Bei einem Fehler in der Funktion zeigt der Stacktrace die echte Zeile im Skript. Bei `eval`-Strings steht oft nur etwas wie „eval code“ – schwerer zu debuggen.
Kurz: Aus dem String wird echter, vorab kompilierter, CSP-konformer Code, der im richtigen Scope läuft und von Werkzeugen richtig erfasst wird.
Alles anzeigen
Um die "Geschichte mit dem helpMenu kümmere ich mich noch!
Habe da so eine Idee.
Ich habe allerdings inzwischen eine an einigen Stellen abweichende Version, die ich deshalb beibehalte.
Wärst Du so nett und postest sie hier?
Eventuell kann ich ja davon etwas lernen und/oder übernehmen.
In der Version fehlen viele Erläuterungen im Vergleich zur Version für FF 135, sowohl für die Konfiguration als auch innerhalb des Skripts zur Funktion einzelner Teile.
Erläuterungen die Konfiguration wie auch innerhalb des Skripts zur Funktion einzelner Teile,
habe ich, so weit mir möglich, alle wieder eingefügt und ergänzt.
Sobald ich mit der Änderung Button/Menü, also der Geschichte helpMenu fertig bin,
gibt es das "neue" Skript.
Was ne Sisyphusarbeit.
Es ist vollbracht.
Die Altlast mit "warpmenuto: 'helpMenu'" habe ich entsorgt und ersetzt durch die Auswahl,
ob ein Button oder ein Menü erstellt werden soll.
Das komplette Gefrickel mit dem CSS habe ich entfernt!
Dafür aber natürlich für den Button JS-Code eingefügt.
Es kann also recht einfach ein eigenes Symbol konfiguriert werden![]()
Und wie immer kann das SVG auch durch ein PNG ersetzt werden.
Wer doch lieber das "alte" Symbol für den Button behalten möchte,
ersetzt halt ganz einfach button.style.listStyleImage = 'url("' + iconUrl + '")'; durch
button.style.listStyleImage = 'url(data:image/png;base64, .... 5CYII=)';
Mh, ich lass das mal komplett auskommentiert im Code.
Fehlt noch etwas?
Achja, für das Symbol, wenn man denn keinen Button, sondern lieber ein Untermenü unter Extras haben möchte,
habe ich externes CSS!
@-moz-document url(chrome://browser/content/browser.xhtml) {
/* ------------------------------ */
/* ------ Extra-Config-Menü ----- */
/* ------------------------------ */
/* Das Symbol (Platzhalter) ausblenden */
#ExtraConfigMenu.menu-iconic img.menu-icon {
display: none !important;
}
/* Symbol vor dem JavaScript-Loader-Menü */
#ExtraConfigMenu {
background-image: url("../icons/edit.svg") !important;
background-repeat: no-repeat !important;
padding-left: 36px !important;
background-position: 12px center !important;
background-size: 16px 16px !important;
-moz-context-properties: fill;
fill: #e0e0e0 !important;
}
}
Alles anzeigen
So, und hier das komplett überarbeitete Skript
und auf vielfachen Wunsch einer einzelnen Person natürlich mit Erläuterungen.
Wäre schön, wenn das noch einmal jemand prüfen könnte,
denn bei aller Sorgfalt kann sich doch mal ein Fehler einschleichen.
/*
// ==UserScript==
// @name extras_config_menu.uc.js
// @compatibility Firefox 153*.*
// @include main
// @version 1.0.20260825
// @edit @aborix 7/21 CSS Dateien als Untermenü eingefügt
// @edit @2002Andreas 8/21 Shadow CSS Dateien als Untermenü + Ordner eingefügt
// @edit @BrokenHeart 1/25 Anpass. wg. Änderung der Sicherheitsrichtlinien bei 'inlineEvents'
// @edit @Mira 8/26 Anpassung für security.allow_unsafe_dangerous_privileged_evil_eval = false
// @edit @Mira 8/26 Anpassung für Userscripte im Unterordner "chrome/scripts", Expliziter Ausschluss von "userChromeShadow.uc.js"
// @edit @Mira 8/26 Anpassung für "Skriptliste in Zwischenablage"
// @edit @Mira 8/26 1. Altlast "warpmenuto: 'helpMenu'" ersetzt durch die Auswahl, ob ein Button oder ein Menü erstellt werden soll.
// @edit @Mira 8/26 2. Das komplette CSS entsorgt! Code für Button ergänzt.
// ==/UserScript==
*/
var uProfMenu = {
// ■■ START UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
// In der folgenden Zeile (20) den Pfad zum Texteditor eintragen (unter Ubuntu 10.04 z.B.: '/usr/bin/gedit'). Bei Fehleintrag wird view_source.editor.path ausgelesen:
//TextOpenExe: 'C:\\Program Files (x86)\\Notepad++\\notepad++.exe',
TextOpenExe: 'C:\\Program Files\\Microsoft VS Code\\Code.exe',
// Falls gewuenscht, in Zeile 24 einen Dateimanager eintragen (komplett leer lassen fuer Dateimanager des Systems) Beispiele:
// vFileManager: 'E:\\Total Commander\\Totalcmd.exe',
// vFileManager: 'C:\\Program Files (x86)\\FreeCommander\\FreeCommander.exe'
vFileManager: '',
// In der folgenden Zeile festlegen, ob ein verschiebbarer Button erstellt wird:
showAsButton: 1, // 1: ja / Button wird erstellt, 0: nein / Menue unter "Extras"0: nein / Menue unter "Extras"
// Unter Linux sollte/kann versucht werden, die userChromeJS-Skripte zu sortieren, unter Windows ist das evtl. nicht noetig (die Sortierung wird Gross- und Kleinschreibung *nicht* beruecksichtigen - dazu wird die sort()-Funktion entsprechend mit einer Vergleichsfunktion aufgerufen)
sortScripts: 0, // 1 zum Erzwingen der Sortierung
// Einbindung GM-Skripte-Ordner (0: nein, 1: Greasemonkey [Profil-Verzeichnis], 2: UserScriptLoader [Chrome-Verzeichnis], 3: Scriptish [Profil-Verzeichnis]):
gmOrdner: 0,
// Einbindung CSS-Ordner (0: nein, 1: UserCSSLoader-Ordner im Chrome-Verzeichnis):
cssOrdner: 1,
// In Zeile 37 gueltige about:Adressen eintragen, die ebenfalls aufgerufen werden sollen.
// - Zum Ausblenden: abouts: [],
// - Damit die about:-Seiten nicht als Untermenue, sondern direkt als Menuepunkte aufgefuehrt werden, muss das erste Element '0' sein:
// abouts: ['0','about:about','about:addons','about:cache','about:config','about:support'],
abouts: ['about:about','about:addons','about:cache','about:config','about:crashes',
'about:downloads','about:home','about:logins','about:memory','about:support',
'about:preferences','about:performance','about:profiles'
],
// Die normalen Firefox-Einstellungen auch zur Verfuegung stellen (0: nein, 1: ja):
showNormalPrefs: 1,
// Stellt "Skriptliste in Zwischenablage" zur Verfuegung (1: ja, 2: mit getrennter Nummerierung, 3: mit gemeinsamer Nummerierung) oder nicht (0):
enableScriptsToClip: 2,
// Um den Eintrag "Neustart" zu erzwingen (falls z.B. das andere Skript zu spaet eingebunden und nicht erkannt wird), auf 1 setzen:
enableRestart: 1,
// Symbol (Icon) nur fuer Button:
icon: 'edit.svg', // [Name.Dateiendung] des Symbols
iconColour: '#ff0000', // Farbe fuer das SVG-Icon setzen (leer fuer Originalfarbe)
iconPath: '/chrome/icons/', // Pfad zum Ordner der das Icon beinhaltet
// ■■ END UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
// --- INIT (ANGEPASST) ---
init: function() {
// Profil-URI und Icon-URL einmalig bereitstellen
var curProfDir = PathUtils.toFileURI(PathUtils.join(PathUtils.profileDir));
var iconUrl = curProfDir + this.iconPath + this.icon;
var iconColour = this.iconColour;
if (this.showAsButton) {
// als verschiebbaren Button anlegen
if (window.__SSi == "window0") {
CustomizableUI.createWidget({
id: "ExtraConfigMenu-button",
defaultArea: CustomizableUI.AREA_NAVBAR,
label: "Extra Config Menü",
tooltiptext: "Extra Config Menü\nRechtsklick öffnet about:config",
onCreated: function(button) {
// Optik direkt am Button-Element setzen
button.style.MozContextProperties = 'fill, stroke, fill-opacity';
button.style.listStyleImage = 'url("' + iconUrl + '")';
// button.style.listStyleImage = 'url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACnElEQVR4Xm2RzYtbZRSHn/fr3pvJzTB3qiNM2k2pMBUGhEHaqsUqdeFGQalCobgREaFu/B/cqCtxVSjoQhBEQRBmIfWDKgNGJUPt0Nhah9JJ4iSd5E6+bu5972tAO4SS5/DjXZ1znsMrNiq1eikMQqYYJCmjxNH5+zdW777L0J5KKl9VPmnf+ut9KWkwhbheuzNcOVYOmGKc5iRO0r1ykeXCx0h7kt4fC3z5wfqbQnAJwQHa5S7jAZSRuJ0mkf81cheobhBXZa+ri1uptQjHAZoZCEC1PiPgDuwxCfwerBU7b73zXn//3usCcdt4HkZ7SGZg431U51NUCgwlO3cV/bVXhR/6p9ut+nP9QYeNn7/n8qUPZxvQ/Q6VVWHk4ZqWRvlJjpx9hcGfW2wO95N2q8m3618A2WwDt/0RplSAXsBed57eyossHl5GYdHacG3zGpADM06wjQ1UUIN+CLHPvfAxojPnKLiE+bDE1R9+5GatAmgPeGCAteQ7l5GBhGSyuROyd/gFouUyWkqEErR2mwXAAA8BRS0AgMQBjSra30ZkEeDzz9Dn4ZcvMO51SMcJcTdGChmA0ABA6cAgzyG3I8jLEBylV4fWoaeIc0V7t0Uv7pFbC+CA+28mp/8+SwXKnMVmz1O9HpE+eobMZdjcoY1GIHD/NwIdoH1fBaNguzlg88pVyoUi4vTbFI8eJxsNAIfSkrliESllH/L0v0jktNNomFGv1TFrL3Fo9QSMR3jaEEXzLC09gjaKp595No0WjyCEB4zRclICUMDxtRMce/wJ1MIi2SglXShhfI/cOjxPoZRmbq4gXzt/gVrtBrdvbiG+Wf+p/mvll1BpiVAGhCDPxuAUDotz4HKHlIJON6bRbL4hhPjcMx5mkn8BBLEUrsVZbq0AAAAASUVORK5CYII=)';
if (iconColour) {
button.style.color = iconColour;
}
}
});
}
var menu = document.getElementById("ExtraConfigMenu-button");
// KORREKTUR:
if (!menu) {
return;
}
menu.setAttribute("type", "menu");
// Dropmarker ausblenden (ersetzt ehemaliges CSS-Stylesheet)
menu.querySelectorAll("dropmarker, .toolbarbutton-menu-dropmarker").forEach(function(d) {
d.style.display = "none";
});
menu.addEventListener('click', function(event) {
if (event.button == 2 && !this.open) {
openTrustedLinkIn("about:config", "tab");
event.preventDefault();
}
}, true);
} else {
var zielmenu = document.getElementById('menu_ToolsPopup');
// da showAsButton nicht gesetzt ist, als Untermenue von Extras anlegen
if (zielmenu == null) {
userChrome.log("extras_config_menu.uc.js findet Zielmenue nicht, evtl. weil ein anderes Fenster als das Hauptfenster geoeffnet wurde.");
return;
}
var menu = zielmenu.appendChild(this.createME("menu", "Extra Config Men\u00FC", null, 0, "ExtraConfigMenu"));
menu.setAttribute("class", "menu-iconic");
// Ersetze ondblclick durch addEventListener
menu.addEventListener('dblclick', function() {
openTrustedLinkIn('about:config', 'tab');
}, true);
}
// ab hier ist alles gleich, egal ob Button oder Menue
// Menü-Popup erstellen
var menupopup = menu.appendChild(this.createME("menupopup", null, null, 0, "ExtraConfigMenu-popup"));
// Event-Listener für popupshowing (unchanged, aber sicher)
menu.addEventListener('popupshowing', function(event) {
uProfMenu.getScripts(0);
uProfMenu.getCss(3);
uProfMenu.getCss(4);
uProfMenu.getCss(5);
}, true);
// --- UNTERMENÜS (unchanged) ---
var submenu = menupopup.appendChild(this.createME("menu", "Meine Scripte", null, 0, "submenu-ucjs"));
// Anlegen von Untermenues fuer userChromeJS-Skripte und CSS-Dateien (befuellen spaeter)
var submenupopup = submenu.appendChild(this.createME("menupopup", null, null, 0, "submenu-ucjs-items"));
var submenu = menupopup.appendChild(this.createME("menu", "css", null, 0, "submenu-css"));
var submenupopup = submenu.appendChild(this.createME("menupopup", null, null, 0, "submenu-css-items"));
var submenu = menupopup.appendChild(this.createME("menu", "CSSShadow", null, 0, "submenu-CSSShadow"));
var submenupopup = submenu.appendChild(this.createME("menupopup", null, null, 0, "submenu-CSSShadow-items"));
var submenu = menupopup.appendChild(this.createME("menu", "cssweb", null, 0, "submenu-cssweb"));
var submenupopup = submenu.appendChild(this.createME("menupopup", null, null, 0, "submenu-cssweb-items"));
// Ende Anlegen von Untermenues
// Skriptliste in Zwischenablage (ANGEPASST: sCommand als Funktion)
if (this.enableScriptsToClip) {
menupopup.appendChild(this.createME(
"menuitem",
"Skriptliste in Zwischenablage",
function() { uProfMenu.getScripts(1); },
"uProfMenu_clipboard",
0
));
}
menupopup.appendChild(document.createXULElement('menuseparator'));
// --- KONFIGDATEIEN (ANGEPASST: sCommand als Funktion) ---
// Einbindung von Konfigdateien
menupopup.appendChild(this.createME(
"menuitem", "Bild Url",
function() { uProfMenu.edit(0, 'Bild Url.css'); },
"uProfMenu_edit", 0
));
menupopup.appendChild(this.createME(
"menuitem", "config Einträge.css",
function() { uProfMenu.edit(0, 'config Einträge.css'); },
"uProfMenu_edit", 0
));
menupopup.appendChild(this.createME(
"menuitem", "userChrome.css",
function() { uProfMenu.edit(0, 'userChrome.css'); },
"uProfMenu_edit", 0
));
menupopup.appendChild(this.createME(
"menuitem", "userChromeShadow.css",
function() { uProfMenu.edit(0, 'userChromeShadow.css'); },
"uProfMenu_edit", 0
));
menupopup.appendChild(this.createME(
"menuitem", "userContent.css",
function() { uProfMenu.edit(0, 'userContent.css'); },
"uProfMenu_edit", 0
));
menupopup.appendChild(this.createME(
"menuitem", "userChrome.js",
function() { uProfMenu.edit(0, 'userChrome.js'); },
"uProfMenu_edit", 0
));
menupopup.appendChild(this.createME(
"menuitem", "prefs.js",
function() { uProfMenu.edit(1, 'prefs.js'); },
"uProfMenu_edit", 0
));
menupopup.appendChild(this.createME(
"menuitem", "user.js",
function() { uProfMenu.edit(1, 'user.js'); },
"uProfMenu_edit", 0
));
// Ende Einbindung von Konfigdateien
// --- ORDNER (ANGEPASST: sCommand als Funktion) ---
menupopup.appendChild(document.createXULElement('menuseparator'));
// Einbindung von Ordnern
switch (this.gmOrdner) {
case 1:
menupopup.appendChild(this.createME(
"menuitem", "GM-skripty",
function() { uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfD') + uProfMenu.getDirSep() + 'gm_scripts'); },
"uProfMenu_folder", 0
));
break;
case 2:
menupopup.appendChild(this.createME(
"menuitem", "USL-skripty",
function() { uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm') + uProfMenu.getDirSep() + 'UserScriptLoader'); },
"uProfMenu_folder", 0
));
break;
case 3:
menupopup.appendChild(this.createME(
"menuitem", "Skripty Scriptish",
function() { uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfD') + uProfMenu.getDirSep() + 'scriptish_scripts'); },
"uProfMenu_folder", 0
));
break;
}
menupopup.appendChild(this.createME(
"menuitem", "CSS-Ordner",
function() { uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm') + uProfMenu.getDirSep() + 'css'); },
"uProfMenu_folder", 0
));
menupopup.appendChild(this.createME(
"menuitem", "CSSShadow-Ordner",
function() { uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm') + uProfMenu.getDirSep() + 'CSSShadow'); },
"uProfMenu_folder", 0
));
menupopup.appendChild(this.createME(
"menuitem", "CSSWeb-Ordner",
function() { uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm') + uProfMenu.getDirSep() + 'CSSWeb'); },
"uProfMenu_folder", 0
));
menupopup.appendChild(this.createME(
"menuitem", "Chromeordner",
function() { uProfMenu.prefDirOpen('UChrm'); },
"uProfMenu_folder", 0
));
menupopup.appendChild(this.createME(
"menuitem", "Profilordner",
function() { uProfMenu.prefDirOpen('ProfD'); },
"uProfMenu_folder", 0
));
menupopup.appendChild(this.createME(
"menuitem", "Icons-Ordner",
function() { uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm') + uProfMenu.getDirSep() + 'Icons'); },
"uProfMenu_folder", 0
));
menupopup.appendChild(this.createME(
"menuitem", "Installationsordner",
function() { uProfMenu.prefDirOpen('CurProcD'); },
"uProfMenu_folder", 0
));
menupopup.appendChild(this.createME(
"menuitem", "Addonordner",
function() { uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfD') + uProfMenu.getDirSep() + 'extensions'); },
"uProfMenu_folder", 0
));
menupopup.appendChild(this.createME(
"menuitem", "Startup-Cacheordner",
function() { uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfLD') + uProfMenu.getDirSep() + 'startupCache'); },
"uProfMenu_folder", 0
));
// Ende Einbindung von Ordnern
// --- ABOUT-SEITEN (ANGEPASST: Closure-Problem gelöst) ---
// Einbindung von abouts
if (this.abouts.length > 0) {
menupopup.appendChild(document.createXULElement('menuseparator'));
// falls der erste Eintrag des Arrays = '0' ist, dann kein Untermenue anlegen, sondern direkt als Menuepunkte einbinden
if (this.abouts[0] == '0') {
for (var i = 1; i < this.abouts.length; i++) {
(function(index) {
var about = uProfMenu.abouts[index];
menupopup.appendChild(uProfMenu.createME(
"menuitem", about,
function() { openTrustedLinkIn(about, 'tab'); },
"uProfMenu_about", 0
));
})(i);
}
} else {
// der erste Eintrag des arrays ist ungleich '0', deshalb als Untermenue einrichten
var submenu = menupopup.appendChild(this.createME("menu", "uc.js", null, 0, "submenu-about"));
var submenupopup = submenu.appendChild(this.createME("menupopup", null, null, 0, "submenu-about-items"));
this.fillMenu("submenu-about", "submenu-about-items", "about:", this.abouts, "uProfMenu_about", 1);
}
}
// Ende Einbindung von abouts
// Separator, falls dieser nicht schon durch abouts generiert wurde und weitere Menuepunkte folgen werden
// --- EINSTELLUNGEN & NEUSTART (ANGEPASST) ---
if (this.abouts.length == 0 && (this.showNormalPrefs || typeof(ToolRstartMod) != "undefined")) {
menupopup.appendChild(document.createXULElement('menuseparator'));
}
// Falls gewuenscht (s. Konfigurationsabschnitt), Zugriff auf die normalen Einstellungen
if (this.showNormalPrefs) {
menupopup.appendChild(this.createME(
"menuitem", "Einstellungen",
function() { try { openOptionsDialog(); } catch(e) { openPreferences(); } },
"uProfMenu_prefs", 0
));
}
// Falls addRestartButton installiert ist, Neustart zur Verfuegung stellen (addRestartButton 1.0.20120105mod erforderlich)
if (this.enableRestart) {
menupopup.appendChild(this.createME(
"menuitem", "Neustart",
function() {
Services.appinfo.invalidateCachesOnRestart();
Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit, 0);
},
0, 0
));
}
},
// --- HILFSFUNKTIONEN (unchanged) ---
// Betriebssystem nach https://developer.mozilla.org/en/Code_snippets/Miscellaneous ermitteln
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 "Linux": dirsep = "/"; break;
case "Darwin": dirsep = "/"; break;
}
return dirsep;
},
// --- EDIT (changed by Mira) ---
edit: function(OpenMode, Filename) {
var Path = "";
var dSep = this.getDirSep(); // die Trennzeichen zwischen Ordnern abhaengig vom Betriebssystem machen
// --- Pfad-Handling für chrome/scripts/ ---
if (Filename.includes("/") || Filename.includes("\\")) {
Path = this.getPrefDirectoryPath("ProfD") + dSep + Filename;
} else {
// Original-Logik
switch (OpenMode) {
//Current is Chrome Directory
case 0: Path = this.getPrefDirectoryPath("UChrm") + dSep + Filename; break;
//Current is Profile Directory
case 1: Path = this.getPrefDirectoryPath("ProfD") + dSep + Filename; break;
//Current is Root
case 2: Path = Filename; break;
//Current is CSS folder
case 3: Path = this.getPrefDirectoryPath("UChrm") + dSep + "CSS" + dSep + Filename; break;
//Current is CSSWeb folder
case 4: Path = this.getPrefDirectoryPath("UChrm") + dSep + "CSSWeb" + dSep + Filename; break;
//Current is CSSShadow folder
case 5: Path = this.getPrefDirectoryPath("UChrm") + dSep + "CSSShadow" + dSep + Filename; break;
}
}
this.launch(this.TextOpenExe, Path);
},
dirOpen: function(Path) {
if (this.vFileManager.length != 0) {
var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
var args = [Path];
file.initWithPath(this.vFileManager);
process.init(file);
// Verzeichnis mit anderem Dateimanager oeffnen
process.run(false, args, args.length);
} else {
// Verzeichnis mit Dateimanager des Systems oeffnen
var dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
dir.initWithPath(Path);
dir.launch();
}
},
prefDirOpen: function(prefDir) {
var Path = this.getPrefDirectoryPath(prefDir);
this.dirOpen(Path);
},
getPrefDirectoryPath: function(str) {
// get profile directory
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;
},
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);
// falls der im Konfigurationsabschnitt definierte Editor nicht gefunden wird, auf Einstellung in about:config ausweichen:
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);
},
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;
},
// --- GETSCRIPTS (changed by Mira) ---
getScripts: function(iType) {
// Array nimmt Namen der gefundenen Skripte auf
let ucJsScripts = [];
// Suchmuster, also die Dateierweiterungen uc.js
let extjs = /\.uc\.js$/i;
// --- 1. Standard-UChrm-Ordner durchsuchen (ohne userChromeShadow.uc.js) ---
let uchrmFolder = Services.dirsvc.get("UChrm", Ci.nsIFile);
if (uchrmFolder.exists()) {
// files mit Eintraegen im Chrome-Ordner befuellen
let files = uchrmFolder.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
// Ordner bzw. files durchlaufen und kontrollieren, ob gesuchte Dateien dabei sind
while (files.hasMoreElements()) {
let file = files.getNext().QueryInterface(Ci.nsIFile);
// uc.js gefunden -> im Array ablegen
if (extjs.test(file.leafName) && file.leafName !== "userChromeShadow.uc.js") {
ucJsScripts.push(file.leafName);
}
}
}
// --- 2. chrome/scripts-Ordner durchsuchen (falls vorhanden) ---
let chromeScriptsFolder = Services.dirsvc.get("ProfD", Ci.nsIFile);
chromeScriptsFolder.append("chrome");
chromeScriptsFolder.append("scripts");
if (chromeScriptsFolder.exists()) {
// files mit Eintraegen im Scripts-Ordner befuellen
let files = chromeScriptsFolder.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
// Ordner bzw. files durchlaufen und kontrollieren, ob gesuchte Dateien dabei sind
while (files.hasMoreElements()) {
let file = files.getNext().QueryInterface(Ci.nsIFile);
// uc.js gefunden -> im Array ablegen
if (extjs.test(file.leafName)) {
ucJsScripts.push("chrome/scripts/" + file.leafName); // Pfad-Präfix für spätere Verarbeitung
}
}
}
if (this.sortScripts) ucJsScripts.sort(this.stringComparison);
// Aufruf der naechsten Methoden um die beiden Untermenues oder die Zwischenablage zu befuellen
if (iType == 0) {
this.fillMenu("submenu-ucjs", "submenu-ucjs-items", "Meine Scripte", ucJsScripts, "uProfMenu_ucjs", 0);
} else {
// Für Zwischenablage: Nur Dateinamen (ohne Pfad) verwenden
var simpleNames = ucJsScripts.map(f => f.split(/[\\/]/).pop());
var result = this.fillClipboardValue(simpleNames, []);
Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper).copyString(result);
}
},
// --- GETCSS (unchanged) ---
getCss: function(iType) {
// Array nimmt Namen der gefundenen css-Dateien auf
let cssFiles = [];
// Suchmuster, also die Dateierweiterung css
let extcss = /\.css$/i;
let aFolder = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
if (iType == 3) aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path + this.getDirSep() + "CSS");
else if (iType == 4) aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path + this.getDirSep() + "CSSWeb");
else if (iType == 5) aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path + this.getDirSep() + "CSSShadow");
// files mit Eintraegen im CSS- bzw. CSSWeb-Ordner befuellen
let files = aFolder.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
// Ordner bzw. files durchlaufen und kontrollieren, ob gesuchte Dateien dabei sind
while (files.hasMoreElements()) {
let file = files.getNext().QueryInterface(Ci.nsIFile);
// css gefunden -> im Array ablegen
if (extcss.test(file.leafName)) cssFiles.push(file.leafName);
}
if (this.sortScripts) cssFiles.sort(this.stringComparison);
// Untermenue befuellen
if (iType == 3) this.fillMenu("submenu-css", "submenu-css-items", "Meine CSS-Dateien", cssFiles, "uProfMenu_css", 3);
else if (iType == 4) this.fillMenu("submenu-cssweb", "submenu-cssweb-items", "Meine CSSWeb-Dateien", cssFiles, "uProfMenu_css", 4);
else if (iType == 5) this.fillMenu("submenu-CSSShadow", "submenu-CSSShadow-items", "Meine CSSShadow-Dateien", cssFiles, "uProfMenu_css", 5);
},
// --- FILLMENU (ANGEPASST: Closure-Problem gelöst + Event-Handler korrigiert) ---
fillMenu: function(whichsubmenu, whichsubmenuitems, strlabel, scriptArray, sClass, sTyp) {
// Beschriftung des Untermenues mit Anzahl der gefundenen Dateien ergaenzen
var e = document.getElementById(whichsubmenu);
e.setAttribute('label', strlabel + ' (' + scriptArray.length + ')');
var popup = document.getElementById(whichsubmenuitems);
// zunaechst Untermenue zuruecksetzen
while (popup.hasChildNodes()) popup.removeChild(popup.firstChild);
var uProfMenu = this; // Für Closure
// Untermenue endlich befuellen
for (var i = scriptArray.length - 1; i > -1; i--) {
(function(index) {
var fileName = scriptArray[index];
var mitem;
// Korrektur durch Mira
if (sTyp == 0) {
mitem = uProfMenu.createME("menuitem", fileName, null, sClass, 0);
// Extrahiere Dateinamen für Anzeige (z. B. "chrome/scripts/test.uc.js" → "test.uc.js")
var displayName = fileName.split(/[\\/]/).pop();
mitem.setAttribute('label', displayName);
mitem.addEventListener('command', function() {
uProfMenu.edit(0, fileName); // Original-Pfad (mit Präfix) an edit() übergeben
}, true);
mitem.addEventListener('click', function(event) {
uProfMenu.openAtGithub(event, displayName);
}, true);
mitem.setAttribute("tooltiptext", "Linksklick: Bearbeiten,\nMittelklick: https://github.com/.../" + uProfMenu.cleanFileName(displayName) + " öffnen,\nRechtsklick: Suche auf GitHub");
}
// Korrektur ENDE
else if (sTyp == 1) {
mitem = uProfMenu.createME("menuitem", fileName, function() {
openTrustedLinkIn(fileName, 'tab');
}, sClass, 0);
}
else if (sTyp == 3) {
mitem = uProfMenu.createME("menuitem", fileName, function() {
uProfMenu.edit(3, fileName);
}, sClass, 0);
}
else if (sTyp == 4) {
mitem = uProfMenu.createME("menuitem", fileName, function() {
uProfMenu.edit(4, fileName);
}, sClass, 0);
}
else if (sTyp == 5) {
mitem = uProfMenu.createME("menuitem", fileName, function() {
uProfMenu.edit(5, fileName);
}, sClass, 0);
}
popup.insertBefore(mitem, popup.firstChild);
})(i);
}
},
// --- FILLCLIPBOARDVALUE (changed by Mira) --- ganz neu !!
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;
},
// --- CREATEME (ANGEPASST: sCommand als Funktion) ---
createME: function(sTyp, sLabel, sCommand, sClass, sId) {
// Anlegen von menuitem, menu oder menupop - fuer bestimmte Typen nicht eingesetzte Parameter werden als 0 uebergeben
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var m = document.createElementNS(XUL_NS, sTyp);
switch (sTyp) {
case "menuitem":
// this.createME("menuitem","Label des Items","ZuzuweisenderCodeFueroncommand","GewuenschteKlasseDesItems",0)
m.setAttribute('label', sLabel);
m.setAttribute('class', sClass);
if (sCommand && typeof sCommand === 'function') {
m.addEventListener('command', sCommand, true);
}
break;
case "menu":
// this.createME("menu","Label des Menues",0,0,"GewuenschteIdDesMenues")
m.setAttribute('label', sLabel);
m.setAttribute('id', sId);
break;
case "menupopup":
//this.createME("menupopup",0,0,0,"GewuenschteIdDesMenupopups");
m.setAttribute('id', sId);
break;
}
return m;
},
// --- OPENATGITHUB (unchanged) ---
openAtGithub: function(e, sScript) {
if (e.button == 1) {
// Mittelklick - Seite auf GitHub oeffnen (funktioniert nur, wenn Ordner- und bereinigter Dateiname [ohne Erweiterung] uebereinstimmen):
var sUrl = "https://github.com/ardiman/userChrome.js/tree/master/" + this.cleanFileName(sScript);
openWebLinkIn(sUrl, 'tab');
}
if (e.button == 2) {
// Rechtsklick - Suche auf GitHub starten (funktioniert nur, wenn der Dateiname im Code hinterlegt ist):
e.preventDefault();
var sUrl = "https://github.com/search?langOverride=&language=&q=" + sScript + "&repo=&start_value=1&type=Code";
openWebLinkIn(sUrl, 'tab');
}
},
// --- CLEANFILENAME (unchanged) ---
cleanFileName: function(sName) {
/* Das folgende Array enthaelt regulaere Ausdruecke, um ungueltige Zeichenfolgen entfernen:
/Datei-Erweiterungen am Ende/, /"ucjs_" am Anfang/, /"_"gefolgtVonZahlUndDanachBeliebigenZeichen/
/ "_fx"gefolgtVonZahl(en)/, /"-" oder "+" oder "."/, /"_v"gefolgtVonZahlen
*/
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;
}
};
// Initialisierung
uProfMenu.init();
Alles anzeigen
Wer mag, kann auch einige Menüeinträge ausblenden!
Ich brauche z.B. jene nicht und habe DAS dann doch per CSS im Skript umgesetzt.
Einfach in Zeile 120 eingefügt.
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(`
/*--------------------------------------------------------------------------*/
/*------------------- Einige Menüeinträge ausgeblendet ---------------------*/
/*--------------------------------------------------------------------------*/
#submenu-CSSShadow,
#submenu-cssweb,
menuitem.uProfMenu_edit[label="Bild Url"],
menuitem.uProfMenu_edit[label="config Einträge.css"],
menuitem.uProfMenu_folder[label="CSSShadow-Ordner"],
menuitem.uProfMenu_folder[label="CSSWeb-Ordner"] {
display: none !important;
}
`), null, null);
sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
Alles anzeigen
Natürlich funktioniert das auch per externem CSS, siehe oben!!
Gibt ja Anwender die strickt JS und CSS getrennt haben wollen. ![]()
Mira_Belle Unten ist meine bisherige, unveränderte Version, die auch im FF 154 funktioniert. Die Symbole für Button und Menü habe ich jetzt nicht getestet, weil ich das Menü zusammen mit anderen Skripten und Menüs ins App-Menü verschiebe und dafür die Symbol mit einem eigenen CSS anpassen muss. Ansonsten ist es mir lieber, wenn die Symbole im Skript enthalten sind und nicht mit einem separaten CSS hinzugefügt werden müssen. Das wird für mich leicht unübersichtlich. (Ich habe ein anderes Symbol, weil ich das Skript hauptsächlich für das Untermenü mit den Skripten verwende, die meisten anderen Menüs sind bei mir ausgeblendet.)
Alle Einstellungen, was angezeigt wird und was nicht, finden im Konfigurationsabschnitt am Anfang statt. Zusätzlich etwas per CSS auszublenden ist für mich unübersichtlich.
In den Erläuterungen für die Konfiguration habe ich vermieden, Zeilennummern anzugeben (passt bei dir z.B. in Zeile 21 nicht), weil die sich mit jeder Änderung verschieben. Stattdessen so etwas wie "im Folgenden ...".
Was hier, glaube ich, schon diskutiert wurde, ist, ob userChromeShadow.uc.js aufgelistet werden soll. Ich nutze das bisher nicht, es würde mich aber stören, wenn ich nicht alle Skripte angezeigt bekomme, die geladen werden. Deshalb würde ich das die Nutzer auch in der Konfiguration steuern lassen, anstatt es "hart zu verdrahten".
Wesentliche Ergänzungen in meiner Version sind
Beim Überfliegen deiner Version war ich mir nicht sicher, ob alle menuseparator in die if-Abfragen eingebunden sind, sodass sie jeweils nur angezeigt werden, wenn der jeweilige Menüpunkt auch angezeigt wird.
Mit etwas mehr Muße schaue ich mir deine Version genauer an.
// ==UserScript==
// @name extras_config_menu.uc.js
// @compatibility Firefox 135*.*
// @include main
// @version 1.0.20250112
// @edit @aborix 7/21 CSS Dateien als Untermenü eingefügt
// @edit @2002Andreas 8/21 Shadow CSS Dateien als Untermenü + Ordner eingefügt
// @edit @BrokenHeart 1/25 Anpass. wg. Änderung der Sicherheitsrichtlinien bei 'inlineEvents'
// @edit @bege, eigene Änderungen
// ==/UserScript==
var uProfMenu = {
// Beginn der Konfiguration -------------------------------------------------------------------
// In der folgenden Zeile den Pfad zum Texteditor eintragen (unter Ubuntu 10.04 z.B.: '/usr/bin/gedit'). Bei Fehleintrag wird view_source.editor.path ausgelesen:
//TextOpenExe: 'C:\\Program Files (x86)\\Notepad++\\notepad++.exe',
TextOpenExe: 'C:\\Program Files\\Notepad++\\notepad++.exe',
// Falls gewuenscht, in der Zeile nach den Beispielen einen Dateimanager eintragen (komplett leer lassen fuer Dateimanager des Systems) Beispiele:
// vFileManager: 'E:\\Total Commander\\Totalcmd.exe',
// vFileManager: 'C:\\Program Files (x86)\\FreeCommander\\FreeCommander.exe'
vFileManager: 'C:\\Program Files\\FreeCommander XE\\FreeCommander.exe',
// eventuelle Parameter für den alternativen Dateimanager, sonst vFilemanagerParam = "";
//vFilemanagerParam = "/O /T";//Totalcommander, Freecommander
vFMParam: "/T",
// Falls die JavaScript-Scripte nicht im chrome-Verzeichnis, sondern einem Unterverzeichnis sind,
// in der folgenden Zeile das Unterverzeichnis eintragen, sonst '':
jsSubfolder: 'JS',
// Im Folgenden bei "location" 'menu' eintragen, damit es in der Menueleiste erscheint, sonst '', damit es als Button erscheint:
location: 'menu',
// Für die Einstellung 'menu' wird hier der Ort festgelegt, wo das Menue angezeigt werden soll.
// (0: in der Menueleiste, 1: im Extras-Menue)
menuLocation: 0,
// Unter Linux sollte/kann versucht werden, die userChromeJS-Skripte zu sortieren, unter Windows ist das evtl. nicht noetig (die Sortierung wird Gross- und Kleinschreibung *nicht* beruecksichtigen - dazu wird die sort()-Funktion entsprechend mit einer Vergleichsfunktion aufgerufen)
sortScripts: 0, // 1 zum Erzwingen der Sortierung
// Einbindung GM-Skripte-Ordner (0: nein, 1: Greasemonkey [Profil-Verzeichnis], 2: UserScriptLoader [Chrome-Verzeichnis], 3: Scriptish [Profil-Verzeichnis]):
gmOrdner: 0,
// Einbindung CSS-Ordner (0: nein, 1: ja, Chrome-Unterordner, 2: ja, anderer Pfad):
cssOrdner: 0,
// Wenn cssOrdner = 1 oder 2, hier entweder Chrome-Unterordner (z.B. 'CSS') oder andere vollständige Pfade (z.B. 'C:\\Dropbox\\Chrome\\Thunderbird\\CSS-Ordner\\css-dateien') entragen, sonst '':
cssLocation1: 'CSS',
cssLocation2: '',
cssLocation3: '',
//Anzeigenamen für die CSS-Ordner
cssLocation1Name: 'CSS-Ordner',
cssLocation2Name: 'CSS-Ordner2',
cssLocation3Name: 'CSS-Ordner3',
// In einer der folgenden Zeilen gueltige about:Adressen eintragen, die ebenfalls aufgerufen werden sollen.
// - Zum Ausblenden: abouts: [],
// - Damit die about:-Seiten nicht als Untermenue, sondern direkt als Menuepunkte aufgefuehrt werden, muss das erste Element '0' sein:
// abouts: ['0','about:config','about:about','about:cache','about:certificate','about:checkerboard','about:crashes','about:debugging','about:devtools','about:memory','about:networking','about:performance','about:policies','about:profiles','about:serviceworkers','about:support','about:telemetry','about:url-classifier','about:webrtc'],
// abouts: ['about:config','about:about','about:cache','about:certificate','about:checkerboard','about:crashes','about:debugging','about:devtools','about:memory','about:networking','about:performance','about:policies','about:profiles','about:serviceworkers','about:support','about:telemetry','about:url-classifier','about:webrtc'],
abouts: [],
// Einbindung config-Dateien wie user.js etc. (0: nein, 1: ja)
configFiles: 0,
// Die Firefox-Ordner anzeigen (0: nein, 1: ja):
firefoxOrdner: 0,
// Die normalen Firefox-Einstellungen auch zur Verfuegung stellen (0: nein, 1: ja):
showNormalPrefs: 0,
// Stellt "Skriptliste in Zwischenablage" zur Verfuegung (1: ja, 2: mit getrennter Nummerierung, 3: mit gemeinsamer Nummerierung) oder nicht (0):
enableScriptsToClip: 3,
// Den Eintrag "Neustart" anzeigen (0: nein, 1: ja):
enableRestart: 0,
// Ende der Konfiguration ---------------------------------------------------------------------------
init: function() {
if (this.location.toLowerCase() == 'menu') {
// aufgrund des gewaehlten 'location' als Menue anlegen
if (this.menuLocation) {
var zielmenu = document.getElementById('menu_ToolsPopup');
} else {
var zielmenu = document.getElementById('main-menubar');
}
if (zielmenu==null) {
userChrome.log("extras_config_menu.uc.js findet Zielmenue nicht, evtl. weil ein anderes Fenster als das Hauptfenster " +
"geoeffnet wurde. Falls dieser Fehler auch im Hauptfenster auftritt, bitte die vorgehende Definition " +
"von 'zielmenu' kontrollieren.");
return
}
var menu = zielmenu.appendChild(this.createME("menu","Config-Menü",0,0,"ExtraConfigMenu"));
//menu.setAttribute("class","menu-iconic");
menu.setAttribute("tooltiptext","Mittelklick öffnet about:config");
menu.setAttribute("accesskey", "M");
menu.addEventListener('click',function(event) {
if (event.button == 1 && !this.open) {
openTrustedLinkIn('about:config', 'tab');
}
});
} else {
// als verschiebbaren Button anlegen
if (window.__SSi == "window0") {
CustomizableUI.createWidget({
id: "ExtraConfigMenu-button",
defaultArea: CustomizableUI.AREA_NAVBAR,
label: "Extra Config Menü",
tooltiptext: "Extra Config Menü\nRechtsklick \öffnet about:config"
});
}
var menu = document.getElementById("ExtraConfigMenu-button");
menu.setAttribute("type", "menu");
menu.addEventListener('click', function(event) {
if (event.button == 2 && !this.open) {
openTrustedLinkIn("about:config", "tab");
event.preventDefault();
};
},true);
}
var css = " \
#ExtraConfigMenu-button { \
list-style-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAC4gAAAuIAeWOKUkAAAEZSURBVDhP7ZMxLENRFIa/c2l5ESrFI+KpoUQTRoOYTJp0NBgsFpP5xSAxWNgkNlYJo72L3SIhMRiaaCxdRKIRkfQet+81FhUPsTnLvfnPzfefc3Ku6MW08oswrfPH8Q/4c8DohjKyFt+7AmVix5I/ULIlG4tfAfoXlb75eE+mDiGzIBgPctuG9HCkJ2tBOpTunPB4DrfrwvWS8lqTZioZQBvCQ9nirwqFU6Vn9n17kw+xEhqqu5a079o5MgwuR3NoD0j5sYO4tLbMmq61Y8NVUXipKAOlT1oINi0zZ8L4lsWbjB/3zlkKJ+KclSB0VYw5/S4if/yNKVdiECpeHp5vlOqe0HgSskXL0IrQmYH6JdzvO73eBvCtgDf14FTmcYgI3gAAAABJRU5ErkJggg==); \
margin-top: 0px !important; \); \
margin-top: 0px !important; \
opacity: 1 !important;\
} \
#ExtraConfigMenu-button > dropmarker, #ExtraConfigMenu-button > hbox > .toolbarbutton-menu-dropmarker { \
display: none !important; \
} \
#ExtraConfigMenu .menubar-text { \
margin-inline-start: 0px !important;\
}";
//ab hier ist alles gleich, egal ob Button oder Menue
var sss = Cc['@mozilla.org/content/style-sheet-service;1'].getService(Ci.nsIStyleSheetService);
var uri = makeURI('data:text/css;charset=UTF=8,' + encodeURIComponent(css));
sss.loadAndRegisterSheet(uri,sss.AGENT_SHEET);
menu.addEventListener('popupshowing', function(event) {
uProfMenu.getScripts(0);
// uProfMenu.getCss(3);
// uProfMenu.getCss(4);
// uProfMenu.getCss(5);
},true);
var menupopup = menu.appendChild(this.createME("menupopup",0,0,0,"ExtraConfigMenu-popup"));
// Anlegen von Untermenues fuer userChromeJS-Skripte (befuellt werden sie spaeter)
var submenu = menupopup.appendChild(this.createME("menu","uc.js",0,0,"submenu-ucjs"));
var submenupopup = submenu.appendChild(this.createME("menupopup",0,0,0,"submenu-ucjs-items"));
// var submenu = menupopup.appendChild(this.createME("menu","uc.xul",0,0,"submenu-ucxul"));
// var submenupopup = submenu.appendChild(this.createME("menupopup",0,0,0,"submenu-ucxul-items"));
menupopup.appendChild(this.createME("menuitem","uc.js-Datei erstellen","uProfMenu.createJSfile()","uProfMenu_createJSfile",0));
if (this.enableScriptsToClip) menupopup.appendChild(this.createME("menuitem","Skriptliste in Zwischenablage","uProfMenu.getScripts(1)","uProfMenu_clipboard",0));
// Ende Anlegen von Untermenues fuer die userChromeJS-Skripte
if (this.configFiles)menupopup.appendChild(document.createXULElement('menuseparator'));
// Einbindung von Konfigdateien
if (this.configFiles) {
menupopup.appendChild(this.createME("menuitem","userChrome.js","uProfMenu.edit(3,'userChrome.js');","uProfMenu_edit",0));
menupopup.appendChild(this.createME("menuitem","userChrome.css","uProfMenu.edit(3,'userChrome.css');","uProfMenu_edit",0));
menupopup.appendChild(this.createME("menuitem","userContent.css","uProfMenu.edit(3,'userContent.css');","uProfMenu_edit",0));
menupopup.appendChild(this.createME("menuitem","prefs.js","uProfMenu.edit(1,'prefs.js');","uProfMenu_edit",0));
menupopup.appendChild(this.createME("menuitem","user.js","uProfMenu.edit(1,'user.js');","uProfMenu_edit"),0);
};
// Ende Einbindung von Konfigdateien
if (this.gmOrdner || this.cssOrdner) menupopup.appendChild(document.createXULElement('menuseparator'));
// Einbindung von Ordnern
switch (this.gmOrdner) {
case 1:
menupopup.appendChild(this.createME("menuitem","GM-Skripte","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfD')+uProfMenu.getDirSep()+'gm_scripts');","uProfMenu_folder"),0);
break;
case 2:
menupopup.appendChild(this.createME("menuitem","USL-Skripte","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'UserScriptLoader');","uProfMenu_folder"),0);
break;
case 3:
menupopup.appendChild(this.createME("menuitem","Scriptish-Skripte","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfD')+uProfMenu.getDirSep()+'scriptish_scripts');","uProfMenu_folder"),0);
break;
}
if (this.cssOrdner) {
if (this.cssOrdner == 1) {
menupopup.appendChild(this.createME("menuitem",this.cssLocation1Name,"uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+uProfMenu.cssLocation1);","uProfMenu_folder"),0);
if (this.cssLocation2.length>0) {
menupopup.appendChild(this.createME("menuitem",this.cssLocation2Name,"uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+uProfMenu.cssLocation2);","uProfMenu_folder"),0);
};
if (this.cssLocation3.length>0) {
menupopup.appendChild(this.createME("menuitem",this.cssLocation3Name,"uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+uProfMenu.cssLocation2);","uProfMenu_folder"),0);
};
} else {menupopup.appendChild(this.createME("menuitem",this.cssLocation1Name,"uProfMenu.dirOpen(uProfMenu.cssLocation1);","uProfMenu_folder"),0);
if (this.cssLocation2.length>0) {
menupopup.appendChild(this.createME("menuitem",this.cssLocation2Name,"uProfMenu.dirOpen(uProfMenu.cssLocation2);","uProfMenu_folder"),0);
};
if (this.cssLocation3.length>0) {
menupopup.appendChild(this.createME("menuitem",this.cssLocation3Name,"uProfMenu.dirOpen(uProfMenu.cssLocation3);","uProfMenu_folder"),0);
};
}
}
if (this.firefoxOrdner) menupopup.appendChild(document.createXULElement('menuseparator'));
if (this.firefoxOrdner) {
menupopup.appendChild(this.createME("menuitem","Chromeordner","uProfMenu.prefDirOpen('UChrm');","uProfMenu_folder"),0);
menupopup.appendChild(this.createME("menuitem","Profilordner","uProfMenu.prefDirOpen('ProfD');","uProfMenu_folder"),0);
// menupopup.appendChild(this.createME("menuitem","Icons-Ordner","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'Icons');","uProfMenu_folder"),0);
menupopup.appendChild(this.createME("menuitem","Installationsordner","uProfMenu.prefDirOpen('CurProcD');","uProfMenu_folder"),0);
menupopup.appendChild(this.createME("menuitem","Addonordner","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfD')+uProfMenu.getDirSep()+'extensions');","uProfMenu_folder"),0);
menupopup.appendChild(this.createME("menuitem","Startup-Cacheordner","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfLD')+uProfMenu.getDirSep()+'startupCache');","uProfMenu_folder"),0);
/* menupopup.appendChild(this.createME("menuitem","Ordner about","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'about');","uProfMenu_folder"),0); */
}
// Ende Einbindung von Ordnern
if (this.abouts.length>0 || this.showNormalPrefs) menupopup.appendChild(document.createXULElement('menuseparator'));
// Einbindung von abouts
if (this.abouts.length>0) {
// falls der erste Eintrag des Arrays = '0' ist, dann kein Untermenue anlegen, sondern direkt als Menuepunkte einbinden
if (this.abouts[0]=='0') {
for (var i = 1; i < this.abouts.length; i++) {
menupopup.appendChild(this.createME("menuitem",this.abouts[i],"openTrustedLinkIn('"+this.abouts[i]+"','tab')","uProfMenu_about"),0);
}
} else {
// der erste Eintrag des arrays ist ungleich '0', deshalb als Untermenue einrichten
var submenu = menupopup.appendChild(this.createME("menu","uc.js",0,0,"submenu-about"));
var submenupopup = submenu.appendChild(this.createME("menupopup",0,0,0,"submenu-about-items"));
this.fillMenu("submenu-about","submenu-about-items", "about:",this.abouts,"uProfMenu_about",1);
}
};
// Ende Einbindung von abouts
// Separator, falls dieser nicht schon durch abouts generiert wurde und weitere Menuepunkte folgen werden
// if (this.abouts.length==0 && (this.showNormalPrefs || typeof(ToolRstartMod) != "undefined")) menupopup.appendChild(document.createXULElement('menuseparator'));
// Falls gewuenscht (s. Konfigurationsabschnitt), Zugriff auf die normalen Einstellungen
if (this.showNormalPrefs) menupopup.appendChild(this.createME("menuitem","Einstellungen","try{openOptionsDialog();}catch(e){openPreferences();}","uProfMenu_prefs"),0);
if (this.enableRestart) menupopup.appendChild(document.createXULElement('menuseparator'));
// Falls enableRestart = 1, Neustart-Menuepunkt zur Verfügung stellen
if(this.enableRestart) menupopup.appendChild(this.createME("menuitem","Neustart",
"Services.appinfo.invalidateCachesOnRestart(); Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit,0);"));
},
getDirSep:function() {
// Betriebssystem nach https://developer.mozilla.org/en/Code_snippets/Miscellaneous ermitteln
var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS;
var dirsep = "/";
switch(osString) {
case "WINNT":
dirsep = "\\";
break;
case "Linux":
dirsep = "/";
break;
case "Darwin":
dirsep = "/";
break;
}
return dirsep;
},
edit:function(OpenMode,Filename){
var Path = "";
var dSep = this.getDirSep(); // die Trennzeichen zwischen Ordnern abhaengig vom Betriebssystem machen
switch (OpenMode){
//Current is Chrome Directory or Subfolder
case 0:
if (this.jsSubfolder.length != 0) {
var Path = this.getPrefDirectoryPath("UChrm") + dSep + this.jsSubfolder + dSep + Filename;
} else {
var Path = this.getPrefDirectoryPath("UChrm") + dSep + Filename;
}
break;
//Current is Profile Directory
case 1:
var Path = this.getPrefDirectoryPath("ProfD") + dSep + Filename;
break;
//Current is Root
case 2:
var Path = Filename;
break;
//Current is Chrome Directory
case 3:
var Path = this.getPrefDirectoryPath("UChrm") + dSep + Filename;
break;
}
this.launch(this.TextOpenExe,Path);
},
dirOpen:function(Path){
var dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
if (this.vFileManager.length != 0) {
var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
var args = [this.vFMParam,Path];
dir.initWithPath(this.vFileManager);
process.init(dir);
// Verzeichnis mit anderem Dateimanager oeffnen
process.run(false, args, args.length);
} else {
// Verzeichnis mit Dateimanager des Systems oeffnen
dir.initWithPath(Path);
dir.launch();
}
},
prefDirOpen:function(prefDir){
Path = this.getPrefDirectoryPath(prefDir);
this.dirOpen(Path);
},
getPrefDirectoryPath:function(str){
// get profile directory
var file = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get(str, Components.interfaces.nsIFile);
// folgende 3 Zeilen nur für Firefox, nicht für Thunderbird
if (str == 'CurProcD') {
file = file.parent;
};
return file.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);
// falls der im Konfigurationsabschnitt definierte Editor nicht gefunden wird, auf Einstellung in about:config ausweichen:
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);
},
stringComparison:function(a, b){
a = a.toLowerCase();
a = a.replace(/ä/g,"a");
a = a.replace(/ö/g,"o");
a = a.replace(/ü/g,"u");
a = a.replace(/ß/g,"s");
b = b.toLowerCase();
b = b.replace(/ä/g,"a");
b = b.replace(/ö/g,"o");
b = b.replace(/ü/g,"u");
b = b.replace(/ß/g,"s");
return(a==b)?0:(a>b)?1:-1;
},
getScripts:function(iType) {
// Arrays (jeweils ein Array fuer uc.js und uc.xul) nehmen Namen der gefundenen Skripte auf
let ucJsScripts = [];
// let ucXulScripts = [];
// Suchmuster, also die Dateierweiterungen uc.js und uc.xul
let extjs = /\.uc\.js$/i;
//let extxul = /\.uc\.xul$/i;
let aFolder = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
if (this.jsSubfolder.length != 0) {
aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path+uProfMenu.getDirSep()+this.jsSubfolder);
} else {
aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path);
};
// files mit Eintraegen im Chrome-Ordner befuellen
let files = aFolder.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
// Ordner bzw. files durchlaufen und kontrollieren, ob gesuchte Dateien dabei sind
while (files.hasMoreElements()) {
let file = files.getNext().QueryInterface(Ci.nsIFile);
// keine gewuenschte Datei, deshalb continue
// if (!extjs.test(file.leafName) && !extxul.test(file.leafName)) continue;
// uc.js gefunden -> im Array ablegen
if (extjs.test(file.leafName)) ucJsScripts.push(file.leafName);
// uc.xul gefunden -> im Array ablegen
// if (extxul.test(file.leafName)) ucXulScripts.push(file.leafName);
}
if (this.sortScripts) {
ucJsScripts.sort(this.stringComparison);
// ucXulScripts.sort(this.stringComparison);
}
// Aufruf der naechsten Methoden um die beiden Untermenues oder die Zwischenablage zu befuellen
if (iType==0) {
this.fillMenu("submenu-ucjs","submenu-ucjs-items", "uc.js",ucJsScripts,"uProfMenu_ucjs",0);
// this.fillMenu("submenu-ucxul","submenu-ucxul-items", "uc.xul",ucXulScripts,"uProfMenu_ucxul",0);
} else {
var result = this.fillClipboardValue(ucJsScripts/*,ucXulScripts*/);
Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper).copyString(result);
}
},
/* getCss:function(iType) {
// Array nimmt Namen der gefundenen css-Dateien auf
let cssFiles = [];
// Suchmuster, also die Dateierweiterung css
let extcss = /\.css$/i;
let aFolder = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
if (iType==3) {
aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path+this.getDirSep()+"CSS");
} else if (iType==4) {
aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path+this.getDirSep()+"CSSWeb");
} else if (iType==5) {
aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path+this.getDirSep()+"CSSShadow");
}
// files mit Eintraegen im CSS- bzw. CSSWeb-Ordner befuellen
let files = aFolder.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
// Ordner bzw. files durchlaufen und kontrollieren, ob gesuchte Dateien dabei sind
while (files.hasMoreElements()) {
let file = files.getNext().QueryInterface(Ci.nsIFile);
// css gefunden -> im Array ablegen
if (extcss.test(file.leafName)) cssFiles.push(file.leafName);
}
if (this.sortScripts) {
cssFiles.sort(this.stringComparison);
}
// Untermenue befuellen
if (iType==3) {
this.fillMenu("submenu-css","submenu-css-items","Meine CSS-Dateien",cssFiles,"uProfMenu_css",3);
} else if (iType==4) {
this.fillMenu("submenu-cssweb","submenu-cssweb-items","Meine CSSWeb-Dateien",cssFiles,"uProfMenu_css",4);
} else if (iType==5) {
this.fillMenu("submenu-CSSShadow","submenu-CSSShadow-items","Meine CSSShadow-Dateien",cssFiles,"uProfMenu_css",5);
}
},
*/
fillMenu:function(whichsubmenu, whichsubmenuitems, strlabel, scriptArray,sClass,sTyp) {
// Beschriftung des Untermenues mit Anzahl der gefundenen Dateien ergaenzen
var e = document.getElementById(whichsubmenu);
e.setAttribute('label',strlabel + ' (' + scriptArray.length + ')');
var popup = document.getElementById(whichsubmenuitems);
// zunaechst Untermenue zuruecksetzen
while(popup.hasChildNodes()){
popup.removeChild(popup.firstChild);
}
// Untermenue endlich befuellen
for (var i = scriptArray.length-1; i > -1; i--) {
// Typunterscheidung (userChromeJS-Skript oder about:)
if (sTyp==0){
var mitem = this.createME("menuitem",scriptArray[i],"uProfMenu.edit(0,'"+scriptArray[i]+"')",sClass,0);
mitem.addEventListener('click', function(event) {
uProfMenu.openAtGithub(event,'"+scriptArray[i]+"');
event.preventDefault();
},true);
mitem.setAttribute("tooltiptext"," Linksklick: Bearbeiten,\n Mittelklick: https://github.com/.../"+this.cleanFileName(scriptArray[i])+" oeffnen,\n Rechtsklick: Suche auf GitHub");
} else if (sTyp==1){
var mitem = this.createME("menuitem",scriptArray[i],"openTrustedLinkIn('"+scriptArray[i]+"','tab')",sClass,0);
} /* else if (sTyp==3){
var mitem = this.createME("menuitem",scriptArray[i],"uProfMenu.edit(3,'"+scriptArray[i]+"')",sClass,0);
} else if (sTyp==4){
var mitem = this.createME("menuitem",scriptArray[i],"uProfMenu.edit(4,'"+scriptArray[i]+"')",sClass,0);
}
else if (sTyp==5){
var mitem = this.createME("menuitem",scriptArray[i],"uProfMenu.edit(5,'"+scriptArray[i]+"')",sClass,0);
} */
popup.insertBefore(mitem, popup.firstChild);
}
},
fillClipboardValue:function(sArray/* ,xArray */) {
var retValue;
var s = 0;
// var x = 0;
s = sArray.length;
// x = xArray.length;
switch(this.enableScriptsToClip) {
case 1:
retValue = "userChromeJS/uc.js ("+s+"):\n------------------------\n"+sArray.join("\n"); // +
// "\n\nuserChromeJS/uc.xul ("+x+"):\n-------------------------\n"+xArray.join("\n");
break;
default:
retValue = "userChromeJS/uc.js ("+s+"):\n------------------------";
for (var i = 0; i < s ; i++) {
j = i + 1;
retValue = retValue + "\n" + j + ". " + sArray[i];
}
/* retValue = retValue + "\n\nuserChromeJS/uc.xul ("+x+"):\n-------------------------";
if (this.enableScriptsToClip==2) s = 0;
for (var i = 0; i < x ; i++) {
j = i + s + 1;
retValue = retValue + "\n" + j + ". " + xArray[i];
} */
break;
}
return retValue;
},
createME:function(sTyp,sLabel,sCommand,sClass,sId) {
// Anlegen von menuitem, menu oder menupop - fuer bestimmte Typen nicht eingesetzte Parameter werden als 0 uebergeben
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var m = document.createElementNS(XUL_NS, sTyp);
switch (sTyp) {
case "menuitem":
// this.createME("menuitem","Label des Items","ZuzuweisenderCodeFueroncommand","GewuenschteKlasseDesItems",0)
m.setAttribute('label', sLabel);
m.setAttribute('class',sClass);
m.addEventListener('command', function(event) {
Function(sCommand)();
}, true);
break;
case "menu":
// this.createME("menu","Label des Menues",0,0,"GewuenschteIdDesMenues")
m.setAttribute('label', sLabel);
m.setAttribute('id', sId);
break;
case "menupopup":
//this.createME("menupopup",0,0,0,"GewuenschteIdDesMenupopups");
m.setAttribute('id', sId);
break;
}
return m;
},
openAtGithub:function(e,sScript) {
if (e.button==1){
// Mittelklick - Seite auf GitHub oeffnen (funktioniert nur, wenn Ordner- und bereinigter Dateiname [ohne Erweiterung] uebereinstimmen):
var sUrl = "https://github.com/Endor8/userChrome.js/tree/master/"+this.cleanFileName(sScript);
openWebLinkIn(sUrl, 'tab');
}
if (e.button==2){
// Rechtsklick - Suche auf GitHub starten (funktioniert nur, wenn der Dateiname im Code hinterlegt ist):
e.preventDefault();
var sUrl = "https://github.com/search?langOverride=&language=&q="+this.cleanFileName(sScript)+"&repo=&start_value=1&type=Code";
openWebLinkIn(sUrl, 'tab');
}
},
createJSfile: function(Filename) {
if (!Filename) Filename = prompt("Name des Skripts", "skriptName");
if (Filename) Filename = Filename.replace(/\s+/g, " ").replace(/[\\/:*?\"<>|]/g, "");
if (!Filename || !/\S/.test(Filename)) return;
if (!/\.uc.js$/.test(Filename)) Filename += ".uc.js";
this.edit(0, Filename);
},
cleanFileName:function(sName) {
sName = sName.toLowerCase();
/* Das folgende Array enthaelt regulaere Ausdruecke, um ungueltige Zeichenfolgen entfernen:
/Datei-Erweiterungen am Ende/, /"ucjs_" am Anfang/, /"_"gefolgtVonZahlUndDanachBeliebigenZeichen/
/ "_fx"gefolgtVonZahl(en)/, /"-" oder "+" oder "."/, /"_v"gefolgtVonZahlen
*/
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;
}
};
uProfMenu.init();
Alles anzeigen
bege Erst einmal vielen lieben Dank für Dein Skript.
Da muss ich mich mal näher mit befassen, aber so beim drüberfliegen,
habe ich schon so ein zwei Sachen gesehen, die ich richtig gut finde.
In Deinen Anmerkungen hast Du erwähnt, dass Du lieber das CSS im Code hast.
Das geht mir eigentlich genau so und ich werde da auch nochmal drüber schlafen,
denn das wird wirklich sehr unübersichtlich, Code hier, Code da,
und alles greift irgendwie ineinander, wenn es crasht, geht die Suche los.
Das ist ätzend.
Und das mit der Angabe von Zeilennummern, da hast Du auch völlig recht,
das stimmte ja schon im originalen Skript nicht mehr!
userChromeShadow.uc.js, Du hast recht! Ich nutze sie, da sie für das Laden der userChromeShadow.css gebraucht wird,
aber selbst keinen weiteren Code darin "verewigt" habe.
Ich dachte mir halt, lieber ausschließen, damit nicht jemand Unbedarftes diese ändert oder gar einfach löscht!
Denn dann ist das Gejammere wieder groß, weil der Firefox nicht mehr so ausschaut wie gewünscht,
und wer kommt schon darauf, dass es an Selektoren liegt, die einen ::part() Selektor benötigen?
Und da haben wir es dann wieder, liegt der Fehler am Skript, oder im CSS![]()
Sitze ich selbst am Rechner, finde ich den Fehler recht schnell, aber so aus der Ferne?
Aber okay, ich werde das nochmals überdenken und eventuell per Grundeinstellung ausblenden,
Also per "Schalter" ON, OFF. (1/0).
lieber ausschließen, damit nicht jemand Unbedarftes diese ändert oder gar einfach löscht!
Hallo Mira...mit der Datei stehst du wohl auf Kriegsfuß wie man so sagt![]()
Diese Datei muss ja erst selber erstellt werden, und dann mit einem Code gefüllt werden, wenn man z.B. etwas mit ::part benötigt.
Weiterhin muss das Skript userChromeShadow.uc.js noch installiert werden.
Und dann weiß der Nutzer das auch alles.
Wer sie nicht nutzt, der kann auch nichts kaputt machen, wenn er sie löscht, bzw. hat diese beiden Dateien dann ja auch nicht.
Und nur weil jemand den Eintrag im Skript extras_config_menu.uc.js löscht, macht er ja nichts kaputt.
Also per "Schalter" ON, OFF. (1/0).
Das finde ich dann eine gute Idee. Dann ist der Eintrag schon im Skript enthalten, und muss nur aktiviert, und nicht nachträglich eingetragen werden.
Ein zusätzlicher Hinweis dass dann auch die userChromeShadow.uc.js Datei noch installiert werden muss, und die Datei userChromeShadow.css im Ordner chrome erstellt werden muss, kann auch nicht schaden.
2002Andreas Danke für den Hinweis.
Habe mir über alles noch keine Gedanken gemacht,
aber natürlich werde ich in den Erläuterungen genauer darauf eingehen!
Und du hast recht, wer die userChromeShadow.uc.js gar nicht angelegt hat,
bekommt diese ja auch gar nicht gezeigt!
Wer die userChromeShadow.css zwecks ::part benötigt, wird, sollte, wissen wofür
die userChromeShadow.uc.js vorhanden ist.
Meine Tendenz, per "default" ausgeblendet, da in der Regel diese Datei eh nie bearbeitet werden muss.
Und die "Liste" ist ja nicht nur zur Auflistung der Skripte da, sondern eher dafür, diese direkt in einem Editor
aufrufen und bearbeiten zu können.
So sehe ich das zumindest.
Oder?
da in der Regel diese Datei eh nie bearbeitet werden muss.
Naja, du musst sie bearbeiten, wenn du weitere Codes eintragen willst. Oder du musst sie mit einer @import url befüllen, und diese dann erweitern wenn nötig. Wobei du dann allerdings noch einen weiteren Ordner erst selber erstellen musst.
Aber etwas anderes noch![]()
Bisher hat noch niemand wirklich gefragt, wozu diese beiden Dateien sind:
Die habe ich vor zig Jahren mal in das Skript eingefügt, und bis jetzt sind sie immer enthalten. Die wurden von mir mal als (Notizzettel) erstellt für mein Testprofil, damit ich z.B. schnell mal eine Url für ein Icon kopieren kann. Also solltest du die evtl. dann auch auf on/off setzen!?
Oder auch diese Dateien, die ja wohl gar nicht mehr gebraucht werden![]()
Naja, du musst sie bearbeiten, wenn du weitere Codes eintragen willst. Oder du musst sie mit einer @import url befüllen, und diese dann erweitern wenn nötig. Wobei du dann allerdings noch einen weiteren Ordner erst selber erstellen musst.
"Reden" wir beide vom Skript?
Denn um dieses geht es mir, das muss in der Regel nicht mehr bearbeitet werden,
denn es ist ja nur dazu da, dass die userChromeShadow.css geladen wird.
Bisher hat noch niemand wirklich gefragt, wozu diese beiden Dateien sind:
Mh, habe ich mich schon gefragt.
Aber da ich deren Nutzen noch nicht erkannt habe, habe ich diese Menüeinträge einfach per externem CSS einfach ausgeblendet.
Bin aber froh, dass Du dafür jetzt aber eine Erklärung nachreichst.
Ob diese Funktion überhaupt von irgendwem genutzt wird?
Wenn nicht, könnte man den Skriptcode bereinigen.
Dann wäre das Skript etwas "schlanker"!
Kann aber alles belassen und eben per internem CSS ein oder ausblenden.
Was meinst Du? Was wäre wohl die "bessere" Variante?
Oder auch diese Dateien, die ja wohl gar nicht mehr gebraucht werden
Sind die nicht für "Einbindung GM-Skripte-Ordner", also Greasemonkey [Profil-Verzeichnis], UserScriptLoader [Chrome-Verzeichnis] oder Scriptish [Profil-Verzeichnis]) vonnöten?
Oder?
Denkst Du, das kann "raus"?
Für Entschlackung des Codes wäre es ja gut.
Sind die nicht für "Einbindung GM-Skripte-Ordner", also Greasemonkey
Dann muss der Nutzer auch Gm Skripte bzw. die Erweiterung nutzen. Ob das (noch) funktioniert bin ich überfragt.
UserScriptLoader
Das muss jemand sagen, der den Loader nutzt.
oder Scriptish
Gehört das nicht auch zu Greasemonkey![]()
Denkst Du, das kann "raus"?
Das möchte ich nicht entscheiden, nur ich habe das noch nie genutzt/gebraucht. Evtl. können ja andere User etwas dazu sagen.
habe ich diese Menüeinträge einfach per externem CSS einfach ausgeblendet.
Ich denke, niemand braucht diese beiden Einträge wirklich.
denn es ist ja nur dazu da, dass die userChromeShadow.css geladen wird.
Richtig, evtl. hatte ich dich auch falsch verstanden, sorry. In dem Skript extra_config muss nichts verändert/angepasst werden. Am besten wie du schon gesagt hast, auf on/off setzen.
Bin aber froh, dass Du dafür jetzt aber eine Ernährung nachreichst.
Na dann - guten Appetit... ![]()
![]()
Mh, danke für den Hinweis.
Kommt davon, wenn man mehrere Sachen gleichzeitig macht, machen will.
Und im Hintergrund hatte ich schon einen ellenlangen Text, der nun verloren geagangen ist,
weil der Browser einfach neu startete. DAS muss ich mal beobachten,
eventuell war das ja auch nur ein Bedienfehler.
einen ellenlangen Text, der nun verloren geagangen ist,
weil der Browser einfach neu startete
OT: Ich nutze dieses Addon, das mich schon x Mal gerettet hat.
Die Einstellungen für das folgende Script habe ich von hier übernommen, und weitere Anpassungen vorgenommen (mit KI), wie z.B. den CSSShadow-Ordner mit ON/OFF ausgestattet. Wenn CSS-Ordner gelistet werden, so haben sie ein Submenü mit den enthaltenen Dateien ( dazu mit Zähler). Eine weitere Variante zum testen.
// ==UserScript==
// @name extras_config_menu.uc.js
// @compatibility Firefox 154+
// @include main
// @version 2.0.20260826
// @edit CSS-Ordner als dynamische Untermenüs
// @edit CSS-Dateizähler sofort anzeigen
// @edit CSSShadow eigener Ein/Aus-Schalter
// @edit Ordner öffnen mit System-Dateimanager oder alternativem Dateimanager
// @edit GM/USL/Scriptish entfernt
// @edit Einstellungen für aktuelle Firefox-Versionen angepasst
// ==/UserScript==
var uProfMenu = {
// ==================== KONFIGURATION ====================
// In der folgenden Zeile den Pfad zum Texteditor eintragen
// (unter Ubuntu 10.04 z.B.: '/usr/bin/gedit').
// Bei Fehleintrag wird view_source.editor.path ausgelesen:
// TextOpenExe: 'C:\\Program Files (x86)\\Notepad++\\notepad++.exe',
// TextOpenExe: 'C:\\Program Files\\Notepad++\\notepad++.exe',
TextOpenExe: 'C:\\notepad++\\notepad++.exe',
// Falls gewuenscht, hier einen Dateimanager eintragen.
// Leer lassen = Dateimanager des Systems.
// Beispiele:
// vFileManager: 'E:\\Total Commander\\Totalcmd.exe',
// vFileManager: 'C:\\Program Files (x86)\\FreeCommander\\FreeCommander.exe',
// vFileManager: 'C:\\Program Files\\FreeCommander XE\\FreeCommander.exe',
vFileManager: '',
// Eventuelle Parameter für den alternativen Dateimanager.
// vFilemanagerParam = "";
// vFilemanagerParam = "/O /T"; // TotalCommander, FreeCommander
// vFMParam: "/T",
vFMParam: '',
// Falls die JavaScript-Scripte nicht im chrome-Verzeichnis,
// sondern einem Unterverzeichnis sind, hier das Unterverzeichnis eintragen.
// Sonst '':
jsSubfolder: 'Scripte',
// 'menu' = Menüleiste, sonst '' = Button
location: '',
// Bei location = 'menu':
// 0 = Menüleiste, 1 = Extras-Menü
menuLocation: 0,
// Unter Linux sollte/kann versucht werden, die userChromeJS-Skripte
// zu sortieren. Die Sortierung berücksichtigt Gross-/Kleinschreibung nicht.
sortScripts: 0, // 1 zum Erzwingen der Sortierung
// Einbindung CSS-Ordner:
// 0 = nein, 1 = ja, Chrome-Unterordner, 2 = ja, anderer Pfad
cssOrdner: 1,
// CSSShadow-Ordner:
// 0 = ausblenden, 1 = anzeigen
cssShadowOrdner: 0,
// Wenn cssOrdner = 1 oder 2:
// Chrome-Unterordner oder vollständige Pfade eintragen.
cssLocation1: 'CSS',
cssLocation2: 'CSSWeb',
cssLocation3: 'CSSAbout',
cssLocation4: 'CSSShadow',
// Anzeigenamen für die CSS-Ordner
cssLocation1Name: 'CSS-Ordner',
cssLocation2Name: 'CSSWeb-Ordner',
cssLocation3Name: 'CSSAbout-Ordner',
cssLocation4Name: 'CSSShadow-Ordner',
// Gültige about:-Adressen eintragen.
// Zum Ausblenden: abouts: []
// Bei '0' als erstem Element werden die Seiten direkt angezeigt.
abouts: [
'about:about',
'about:config',
'about:preferences',
'about:addons'
],
// Einbindung Konfigurationsdateien:
// 0 = nein, 1 = ja
configFiles: 1,
// Firefox-Ordner anzeigen:
// 0 = nein, 1 = ja
firefoxOrdner: 1,
// Normale Firefox-Einstellungen:
// 0 = nein, 1 = ja
showNormalPrefs: 1,
// Skriptliste in Zwischenablage:
// 0 = nein, 1 = ja, 2 = getrennte Nummerierung,
// 3 = gemeinsame Nummerierung
enableScriptsToClip: 3,
// Neustart anzeigen:
// 0 = nein, 1 = ja
enableRestart: 1,
// ==================== INITIALISIERUNG ====================
init: function() {
var menu;
// --- MENÜ ---
if (this.location.toLowerCase() == 'menu') {
var zielmenu = this.menuLocation
? document.getElementById('menu_ToolsPopup')
: document.getElementById('main-menubar');
if (!zielmenu) return;
menu = zielmenu.appendChild(
this.createME('menu', 'Config-Menü', '', '', 'ExtraConfigMenu')
);
menu.setAttribute('tooltiptext', 'Mittelklick öffnet about:config');
menu.setAttribute('accesskey', 'M');
menu.addEventListener('click', function(event) {
if (event.button == 1 && !this.open)
openTrustedLinkIn('about:config', 'tab');
});
}
// --- BUTTON ---
else {
if (window.__SSi == 'window0') {
CustomizableUI.createWidget({
id: 'ExtraConfigMenu-button',
defaultArea: CustomizableUI.AREA_NAVBAR,
label: 'Extra Config Menü',
tooltiptext: 'Extra Config Menü\nRechtsklick öffnet about:config'
});
}
menu = document.getElementById('ExtraConfigMenu-button');
if (!menu) return;
menu.setAttribute('type', 'menu');
menu.addEventListener('click', function(event) {
if (event.button == 2 && !this.open) {
openTrustedLinkIn('about:config', 'tab');
event.preventDefault();
}
}, true);
}
// --- CSS FÜR BUTTON ---
var css =
'#ExtraConfigMenu, #ExtraConfigMenu-button {' +
'list-style-image: url("file:///C:/FoxIcons/1206.png") !important;' +
'margin-right: 10px !important;' +
'margin-bottom: 2px !important;' +
'margin-top: 2px !important;' +
'}' +
'#ExtraConfigMenu-button > dropmarker,' +
'#ExtraConfigMenu-button > hbox > .toolbarbutton-menu-dropmarker {' +
'display: none !important;' +
'}';
var sss =
Cc['@mozilla.org/content/style-sheet-service;1']
.getService(Ci.nsIStyleSheetService);
var uri = makeURI(
'data:text/css;charset=UTF-8,' + encodeURIComponent(css)
);
if (!sss.sheetRegistered(uri, sss.AGENT_SHEET))
sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET);
// --- HAUPTMENÜ ---
var menupopup = menu.appendChild(
this.createME(
'menupopup',
'',
'',
'',
'ExtraConfigMenu-popup'
)
);
// --- MEINE SCRIPTE ---
var submenu = menupopup.appendChild(
this.createME(
'menu',
'Meine Scripte',
'',
'',
'submenu-ucjs'
)
);
submenu.appendChild(
this.createME(
'menupopup',
'',
'',
'',
'submenu-ucjs-items'
)
);
submenu.addEventListener(
'popupshowing',
function() {
uProfMenu.getScripts(0);
},
true
);
this.getScripts(0); // Zähler sofort beim Start setzen
// --- NEUES SKRIPT ---
menupopup.appendChild(
this.createME(
'menuitem',
'uc.js-Datei erstellen',
'uProfMenu.createJSfile()',
'uProfMenu_createJSfile',
0
)
);
// --- SKRIPTLISTE ---
if (this.enableScriptsToClip) {
menupopup.appendChild(
this.createME(
'menuitem',
'Skriptliste in Zwischenablage',
'uProfMenu.getScripts(1)',
'uProfMenu_clipboard',
0
)
);
}
// --- KONFIGURATIONSDATEIEN ---
if (this.configFiles) {
menupopup.appendChild(
document.createXULElement('menuseparator')
);
[
'userChrome.js',
'userChrome.css',
'userContent.css',
'prefs.js',
'user.js',
'Bild Url.css',
'config Einträge.css'
].forEach(function(file) {
var mode =
(file == 'prefs.js' || file == 'user.js') ? 1 : 3;
menupopup.appendChild(
uProfMenu.createME(
'menuitem',
file,
"uProfMenu.edit(" + mode + ",'" + file + "')",
'uProfMenu_edit',
0
)
);
});
}
// --- CSS-ORDNER ---
if (this.cssOrdner) {
menupopup.appendChild(
document.createXULElement('menuseparator')
);
[
this.cssLocation1,
this.cssLocation2,
this.cssLocation3,
this.cssLocation4
].forEach(function(loc, i) {
if (
loc &&
loc.length > 0 &&
(i != 3 || uProfMenu.cssShadowOrdner)
) {
uProfMenu.addCSSSubmenu(
menupopup,
uProfMenu['cssLocation' + (i + 1) + 'Name'],
loc
);
}
});
}
// --- FIREFOX-ORDNER ---
if (this.firefoxOrdner) {
menupopup.appendChild(
document.createXULElement('menuseparator')
);
[
{
label: 'Ordner Scripte',
path: function() {
return uProfMenu.getPrefDirectoryPath('UChrm') +
uProfMenu.getDirSep() +
uProfMenu.jsSubfolder;
}
},
{
label: 'Chromeordner',
path: function() {
return uProfMenu.getPrefDirectoryPath('UChrm');
}
},
{
label: 'Profilordner',
path: function() {
return uProfMenu.getPrefDirectoryPath('ProfD');
}
},
{
label: 'Installationsordner',
path: function() {
return uProfMenu.getPrefDirectoryPath('CurProcD');
}
},
{
label: 'Addonordner',
path: function() {
return uProfMenu.getPrefDirectoryPath('ProfD') +
uProfMenu.getDirSep() +
'extensions';
}
},
{
label: 'Startup-Cacheordner',
path: function() {
return uProfMenu.getPrefDirectoryPath('ProfLD') +
uProfMenu.getDirSep() +
'startupCache';
}
}
].forEach(function(folder) {
uProfMenu.addFolderMenu(
menupopup,
folder.label,
folder.path
);
});
}
// --- ABOUT / EINSTELLUNGEN ---
if (this.abouts.length > 0 || this.showNormalPrefs) {
menupopup.appendChild(
document.createXULElement('menuseparator')
);
}
// --- ABOUT ---
if (this.abouts.length > 0) {
var aboutSubmenu = menupopup.appendChild(
this.createME(
'menu',
'about:',
'',
'',
'submenu-about'
)
);
aboutSubmenu.appendChild(
this.createME(
'menupopup',
'',
'',
'',
'submenu-about-items'
)
);
this.fillMenu(
'submenu-about',
'submenu-about-items',
'about:',
this.abouts,
'uProfMenu_about',
1
);
}
// --- EINSTELLUNGEN ---
if (this.showNormalPrefs) {
menupopup.appendChild(
this.createME(
'menuitem',
'Einstellungen',
'uProfMenu.openSettings()',
'uProfMenu_prefs',
0
)
);
}
// --- NEUSTART ---
if (this.enableRestart) {
menupopup.appendChild(
document.createXULElement('menuseparator')
);
menupopup.appendChild(
this.createME(
'menuitem',
'Neustart',
'uProfMenu.restart()',
'',
0
)
);
}
},
// ==================== HILFSFUNKTIONEN ====================
addFolderMenu: function(parent, label, pathFunction) {
var item = this.createME(
'menuitem',
label,
'',
'uProfMenu_folder',
0
);
item.addEventListener(
'command',
function() {
try {
uProfMenu.dirOpen(pathFunction());
} catch (e) {
console.error(
'extras_config_menu.uc.js: Ordner konnte nicht geöffnet werden:',
e
);
}
},
true
);
parent.appendChild(item);
},
addCSSSubmenu: function(parent, label, folder) {
var count = this.getCSSFileCount(folder);
var submenu = this.createME(
'menu',
label + ' (' + count + ')',
'',
'',
''
);
var popup = this.createME(
'menupopup',
'',
'',
'',
''
);
submenu.appendChild(popup);
parent.appendChild(submenu);
popup.addEventListener(
'popupshowing',
function() {
uProfMenu.fillCSSMenu(popup, folder);
uProfMenu.updateCSSCount(submenu, label, folder);
},
true
);
},
getCSSFileCount: function(folder) {
var folderPath = (this.cssOrdner == 1)
? this.getPrefDirectoryPath('UChrm') +
this.getDirSep() +
folder
: folder;
var cssFolder =
Cc['@mozilla.org/file/local;1']
.createInstance(Ci.nsIFile);
try {
cssFolder.initWithPath(folderPath);
} catch (e) {
return 0;
}
if (!cssFolder.exists() || !cssFolder.isDirectory())
return 0;
var count = 0;
try {
var entries =
cssFolder.directoryEntries
.QueryInterface(Ci.nsISimpleEnumerator);
while (entries.hasMoreElements()) {
var file =
entries.getNext().QueryInterface(Ci.nsIFile);
if (file.isFile() && /\.css$/i.test(file.leafName))
count++;
}
} catch (e) {
return 0;
}
return count;
},
updateCSSCount: function(submenu, label, folder) {
var count = this.getCSSFileCount(folder);
submenu.setAttribute(
'label',
label + ' (' + count + ')'
);
},
fillCSSMenu: function(popup, folder) {
while (popup.hasChildNodes())
popup.removeChild(popup.firstChild);
var folderPath = (this.cssOrdner == 1)
? this.getPrefDirectoryPath('UChrm') +
this.getDirSep() +
folder
: folder;
var cssFolder =
Cc['@mozilla.org/file/local;1']
.createInstance(Ci.nsIFile);
try {
cssFolder.initWithPath(folderPath);
} catch (e) {
this.addDisabledMenuItem(
popup,
'(ungültiger Pfad)'
);
return;
}
if (!cssFolder.exists() || !cssFolder.isDirectory()) {
this.addDisabledMenuItem(
popup,
'(Ordner nicht gefunden)'
);
return;
}
var cssFiles = [];
var entries =
cssFolder.directoryEntries
.QueryInterface(Ci.nsISimpleEnumerator);
while (entries.hasMoreElements()) {
var file =
entries.getNext().QueryInterface(Ci.nsIFile);
if (file.isFile() && /\.css$/i.test(file.leafName))
cssFiles.push(file.leafName);
}
cssFiles.sort(this.stringComparison);
if (cssFiles.length == 0) {
this.addDisabledMenuItem(
popup,
'(keine CSS-Dateien)'
);
return;
}
for (var i = 0; i < cssFiles.length; i++) {
var filename = cssFiles[i];
var item = this.createME(
'menuitem',
filename,
'',
'uProfMenu_css',
0
);
var fullPath =
folderPath +
this.getDirSep() +
filename;
item.setAttribute(
'data-css-path',
fullPath
);
item.setAttribute(
'tooltiptext',
'Öffnen: ' + fullPath
);
item.addEventListener(
'command',
function() {
var path =
this.getAttribute('data-css-path');
uProfMenu.launch(
uProfMenu.TextOpenExe,
path
);
},
true
);
popup.appendChild(item);
}
},
addDisabledMenuItem: function(popup, label) {
var item = this.createME(
'menuitem',
label,
'',
'',
0
);
item.setAttribute('disabled', 'true');
popup.appendChild(item);
},
getDirSep: function() {
return Services.appinfo.OS == 'WINNT'
? '\\'
: '/';
},
edit: function(OpenMode, Filename) {
var Path = '';
var dSep = this.getDirSep();
switch (OpenMode) {
case 0:
Path =
this.getPrefDirectoryPath('UChrm') +
dSep +
(this.jsSubfolder.length != 0
? this.jsSubfolder + dSep
: '') +
Filename;
break;
case 1:
Path =
this.getPrefDirectoryPath('ProfD') +
dSep +
Filename;
break;
case 2:
Path = Filename;
break;
case 3:
Path =
this.getPrefDirectoryPath('UChrm') +
dSep +
Filename;
break;
}
this.launch(this.TextOpenExe, Path);
},
dirOpen: function(Path) {
if (!Path) return;
if (this.vFileManager && this.vFileManager.length > 0) {
var manager =
Cc['@mozilla.org/file/local;1']
.createInstance(Ci.nsIFile);
try {
manager.initWithPath(this.vFileManager);
} catch (e) {
console.error(
'extras_config_menu.uc.js: Ungültiger Dateimanager:',
this.vFileManager
);
return;
}
if (!manager.exists()) {
console.error(
'extras_config_menu.uc.js: Dateimanager nicht gefunden:',
this.vFileManager
);
return;
}
var process =
Cc['@mozilla.org/process/util;1']
.createInstance(Ci.nsIProcess);
process.init(manager);
var args =
(this.vFMParam && this.vFMParam.trim())
? this.vFMParam.trim().split(/\s+/)
: [];
args.push(Path);
process.run(false, args, args.length);
return;
}
var dir =
Cc['@mozilla.org/file/local;1']
.createInstance(Ci.nsIFile);
try {
dir.initWithPath(Path);
} catch (e) {
console.error(
'extras_config_menu.uc.js: Ungültiger Ordner:',
Path
);
return;
}
if (!dir.exists()) {
console.error(
'extras_config_menu.uc.js: Ordner existiert nicht:',
Path
);
return;
}
dir.launch();
},
getPrefDirectoryPath: function(str) {
var file = Services.dirsvc.get(str, Ci.nsIFile);
if (str == 'CurProcD')
file = file.parent;
return file.path;
},
launch: function(RanPath, OpenPath) {
var file =
Cc['@mozilla.org/file/local;1']
.createInstance(Ci.nsIFile);
var proc =
Cc['@mozilla.org/process/util;1']
.createInstance(Ci.nsIProcess);
var args = [OpenPath];
try {
file.initWithPath(RanPath);
} catch (e) {
file = null;
}
if (!file || !file.exists()) {
try {
RanPath =
Services.prefs.getCharPref(
'view_source.editor.path'
);
file =
Cc['@mozilla.org/file/local;1']
.createInstance(Ci.nsIFile);
file.initWithPath(RanPath);
} catch (e) {
console.error(
'extras_config_menu.uc.js: Kein Editor gefunden.'
);
return;
}
}
if (!file.exists()) return;
proc.init(file);
proc.run(false, args, args.length);
},
openSettings: function() {
try {
openTrustedLinkIn(
'about:preferences',
'tab'
);
return;
} catch (e) {
console.error(
'about:preferences konnte nicht geöffnet werden:',
e
);
}
try {
if (typeof openPreferences == 'function') {
openPreferences();
return;
}
} catch (e) {
console.error(
'openPreferences() fehlgeschlagen:',
e
);
}
},
getScripts: function(iType) {
var ucJsScripts = [];
var extjs = /\.uc\.js$/i;
var aFolder =
Cc['@mozilla.org/file/local;1']
.createInstance(Ci.nsIFile);
var chromePath =
Services.dirsvc.get(
'UChrm',
Ci.nsIFile
).path;
if (this.jsSubfolder.length != 0)
chromePath +=
this.getDirSep() +
this.jsSubfolder;
try {
aFolder.initWithPath(chromePath);
} catch (e) {
return;
}
if (!aFolder.exists() || !aFolder.isDirectory())
return;
var files =
aFolder.directoryEntries
.QueryInterface(Ci.nsISimpleEnumerator);
while (files.hasMoreElements()) {
var file =
files.getNext().QueryInterface(Ci.nsIFile);
if (extjs.test(file.leafName))
ucJsScripts.push(file.leafName);
}
if (this.sortScripts)
ucJsScripts.sort(this.stringComparison);
if (iType == 0) {
this.fillMenu(
'submenu-ucjs',
'submenu-ucjs-items',
'Meine Scripte',
ucJsScripts,
'uProfMenu_ucjs',
0
);
} else {
var result =
this.fillClipboardValue(ucJsScripts);
Cc['@mozilla.org/widget/clipboardhelper;1']
.getService(Ci.nsIClipboardHelper)
.copyString(result);
}
},
fillMenu: function(
whichsubmenu,
whichsubmenuitems,
strlabel,
scriptArray,
sClass,
sTyp
) {
var e =
document.getElementById(whichsubmenu);
if (!e) return;
e.setAttribute(
'label',
strlabel + ' (' + scriptArray.length + ')'
);
var popup =
document.getElementById(whichsubmenuitems);
if (!popup) return;
while (popup.hasChildNodes())
popup.removeChild(popup.firstChild);
if (scriptArray.length == 0) {
this.addDisabledMenuItem(
popup,
'(keine Skripte gefunden)'
);
return;
}
for (var i = scriptArray.length - 1; i >= 0; i--) {
var filename = scriptArray[i];
var mitem = this.createME(
'menuitem',
filename,
'',
sClass,
0
);
if (sTyp == 0) {
mitem.addEventListener(
'command',
function() {
uProfMenu.edit(
0,
this.getAttribute('label')
);
},
true
);
mitem.addEventListener(
'click',
function(event) {
uProfMenu.openAtGithub(
event,
this.getAttribute('label')
);
if (event.button == 1 || event.button == 2)
event.preventDefault();
},
true
);
mitem.setAttribute(
'tooltiptext',
'Linksklick: Bearbeiten\n' +
'Mittelklick: GitHub öffnen\n' +
'Rechtsklick: Suche auf GitHub'
);
} else {
mitem.addEventListener(
'command',
function() {
openTrustedLinkIn(
this.getAttribute('label'),
'tab'
);
},
true
);
}
popup.insertBefore(
mitem,
popup.firstChild
);
}
},
fillClipboardValue: function(sArray) {
var retValue;
var s = sArray.length;
if (this.enableScriptsToClip == 1) {
retValue =
'userChromeJS/uc.js (' +
s +
'):\n------------------------\n' +
sArray.join('\n');
} else {
retValue =
'userChromeJS/uc.js (' +
s +
'):\n------------------------';
for (var i = 0; i < s; i++)
retValue +=
'\n' +
(i + 1) +
'. ' +
sArray[i];
}
return retValue;
},
createME: function(
sTyp,
sLabel,
sCommand,
sClass,
sId
) {
var XUL_NS =
'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
var m =
document.createElementNS(XUL_NS, sTyp);
switch (sTyp) {
case 'menuitem':
m.setAttribute('label', sLabel);
if (sClass)
m.setAttribute('class', sClass);
if (sCommand) {
m.addEventListener(
'command',
function() {
var command =
sCommand.replace(/;\s*$/, '');
if (command == 'uProfMenu.createJSfile()') {
uProfMenu.createJSfile();
return;
}
if (command == 'uProfMenu.getScripts(1)') {
uProfMenu.getScripts(1);
return;
}
if (command == 'uProfMenu.openSettings()') {
uProfMenu.openSettings();
return;
}
if (command == 'uProfMenu.restart()') {
uProfMenu.restart();
return;
}
var editMatch =
command.match(
/^uProfMenu\.edit\((\d+),'([\s\S]*)'\)$/
);
if (editMatch) {
uProfMenu.edit(
Number(editMatch[1]),
editMatch[2]
);
return;
}
var aboutMatch =
command.match(
/^openTrustedLinkIn\('([\s\S]*)','tab'\)$/
);
if (aboutMatch) {
openTrustedLinkIn(
aboutMatch[1],
'tab'
);
return;
}
},
true
);
}
break;
case 'menu':
m.setAttribute('label', sLabel);
if (sId) m.setAttribute('id', sId);
break;
case 'menupopup':
if (sId) m.setAttribute('id', sId);
break;
}
return m;
},
openAtGithub: function(e, sScript) {
if (e.button == 1) {
var sUrl =
'https://github.com/Endor8/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=' +
this.cleanFileName(sScript) +
'&repo=&start_value=1&type=Code';
openWebLinkIn(sUrl, 'tab');
}
},
createJSfile: function(Filename) {
if (!Filename)
Filename = prompt(
'Name des Skripts',
'skriptName'
);
if (Filename)
Filename = Filename
.replace(/\s+/g, ' ')
.replace(/[\\/:*?"<>|]/g, '');
if (!Filename || !/\S/.test(Filename))
return;
if (!/\.uc\.js$/i.test(Filename))
Filename += '.uc.js';
this.edit(0, Filename);
},
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;
},
restart: function() {
Services.appinfo.invalidateCachesOnRestart();
Services.startup.quit(
Ci.nsIAppStartup.eRestart |
Ci.nsIAppStartup.eAttemptQuit,
0
);
},
stringComparison: function(a, b) {
return a.localeCompare(b);
}
};
// ==================== START ====================
uProfMenu.init();
Alles anzeigen