Statt an jede einzelne Antwort ein „Gefällt-mir“-Bapperl anzuhängen einfach mal danke für die gesamte Konversation hier!
Beiträge von Speravir
-
-
Leider funktioniert das Skript mit diesen Konfigurationen nicht:
Windows Explorer ist mit Parameter angegeben: Chrome- und CSS-Ordner werden nicht geöffnet, sondern nur im Elternordner ausgewählt, weil diese Abfrage aus meiner Version fehlt: if (fileManagerParam !== "/select,")
Windows Explorer ist ohne Parameter angegeben: Weder die Ordner lassen sich öffnen noch die Dateien im Explorer anzeigen. Aus der Konfigurationserklärung wird nicht deutlich, dass in deiner Version beim Explorer der Parameter angegeben werden muss.Hmpf. Ich hatte das natürlich explizit getestet vor der letzten Veröffentlichung. Nachdem ich deinen Text gelesen habe, ging es aber bei mir auch nicht mehr – was nicht gut ist, weil das vermuten lässt, dass eine Race Condition vorhanden ist (bei Mira_Belle scheint beispielsweise alles zu funktionieren). Ich hatte die Sonderbehandlung des Windows-Explorer vermeiden wollen, habe nun aber die Bedingung eingebaut. Der Punkt „Chrome- und CSS-Ordner werden nicht geöffnet, sondern nur im Elternordner ausgewählt“ ist jedoch weiterhin gültig. Das erfordert einen einzigen weiteren Klick, damit sollte man leben können. Es kann sein, dass das schon vorher so war und mir nur nie aufgefallen ist.
Kleinigkeiten:
in den Zeilen 408 und 424 kann das Komma nach target weg, glaube ich.
Ich vermisse im Header @version und @compatibility, damit man bei zukünftigen Änderungen gleich sieht, welche Version man hat.Kommata: Upps. So etwas Unscheinbares kann schon die Ursache für Probleme sein. Man sollte zwar denken, dass ein leerer (eigentlich: undefinierter) angehängter Parameter keine Rolle spielt, aber vielleicht wqr genau das die Ursache für die oben genannte Merkwürdigkeit.
Ich hatte den langen Header absichtlich entfernt, die Versionierung stimmte sowieso nicht richtig, ich wäre da eher für eine (ISO-)Datumsangabe. Zur Kompatibilität kann ich überhaupt nichts sagen und deshalb nichts derartiges im Skript eintragen.
Ich hoffe das hilft dir weiter.
Danke, Andreas. Ich hab die entsprechenden Eigenschaften samt Werten eingefügt und diesen Text ergänzt:
ZitatAbsolute Zahlenwerte müssen eventuell etwas an die eigenen Gegebenheiten
angepasst werden (größeres Symbol, anderer Rand); der Zahlenwert für Höhe
und Breite des Menütextes ("CSS") sollte nicht größer sein als für das
Symbol (hier 16px).Man könnte jetzt noch eine eigene angepasste Eigenschaft einführen, damit man nicht dreimal denselben Zahlenwert ändern muss, Es fragt sich nur, inwiefern man damit andere überfordert.
JavaScript
Alles anzeigen/* UserCSSLoader 2025-09-16 * * original author: Griever - * https://github.com/Griever/userChromeJS/tree/master/UserCSSLoader * * Enhancements and several other changes including German translation * and configuration section by users aborix, Endor, bege, Speravir of * Camp Firefox forum - https://www.camp-firefox.de/forum/ - latest version: * https://www.camp-firefox.de/forum/thema/138814/?postID=1279211#post1279211 */ /****** Bedienungsanleitung ****** CSS-Ordner im Chrome-Ordner erstellen, CSS-Dateien dort ablegen - speichern. Diejenigen, deren Dateiname mit "xul-" beginnen, diejenigen, die mit ".as.css" enden, sind AGENT_SHEET, alle anderen außer USER_SHEET werden gelesen. Da der Inhalt der Datei nicht überprüft wird, darauf achten, die Angabe von @namespace nicht zu vergessen! Schaltfläche oder Menü wird in Navigationsleiste eingefügt (einstellbar, siehe Variable "position" in unten anschließender Konfiguration). Dateiordner, Dateimanager und Texteditor können in der unten anschließenden Konfiguration geändert werden. Die Verwendung des in "view_source.editor.path" angegebenen Editors ist möglich. Linksklick auf Stil, zum Aktivieren/Deaktivieren Mittelklick auf Stil zum Aktivieren/Deaktivieren, ohne Menü zu schließen Rechtsklick auf Stil zum Öffnen im Editor Strg+Linksklick zum Anzeigen im Dateimanager Die Tastenkombinationen können im Menü eingeblendet werden, dazu nach "acceltext" suchen und den Zeilenkommentar "//" entfernen. Ein Symbol für die Schaltfläche muss in der "userChrome.css" festgelegt werden, Pfad zum Bild (PNG nur als Beispiel): * relativ zur userChrome.css background-image: url("Relativer/Pfad/zum/CSS_Symbol.png"); * eine absolute Pfadangabe zum Symbol muss mit File-Protokoll-Präfix erfolgen: background-image: url("file:///Absoluter/Pfad/zum/CSS_Symbol.png"); Absolute Zahlenwerte müssen eventuell etwas an die eigenen Gegebenheiten angepasst werden (größeres Symbol, anderer Rand); der Zahlenwert für Höhe und Breite des Menütextes ("CSS") sollte nicht größer sein als für das Symbol (hier 16px). #usercssloader-menu-item { background-image: url("Relativer/Pfad/zum/CSS_Symbol.png"); background-position: center; background-repeat: no-repeat; background-size: 16px; border-radius: var(--toolbarbutton-border-radius); margin-block: 3px; &:hover { background-color: var(--toolbarbutton-hover-background); } & #usercssloader-menu > .menu-text[value="CSS"] { opacity: 0; width: calc(2 * var(--toolbarbutton-inner-padding) + 16px); height: calc(2 * var(--toolbarbutton-inner-padding) + 16px); } } **** Ende der Anleitung ****/ (function(){ /***** Konfiguration *****/ /* Position: als frei verschiebbare-Schaltfläche = 0, als Menü anzeigen = 1 */ let position = 0;//1 /* Dateimanager festlegen, Beispiele: * let fileManager = "C:\\Programme\\FreeCommanderXE\\FreeCommander.exe"; * let fileManager = "C:\\Programme\\totalcmd\\TOTALCMD.EXE"; * auch möglich: * let fileManager = "C:\\Windows\\explorer.exe"; * Bleibt Parameter leer, wird Standardmanager des Systems ohne Parameter * verwendet mit leicht eingeschränkter Funktionalität. */ let fileManager = ""; /* eventuelle Parameter für den Dateimanager, Beispiele: * let fileManagerParam = "/T";//FreeCommander oder Totalcommander * let fileManagerParam = "/select,";//Windows Explorer, mit Komma korrekt! */ let fileManagerParam = ""; /* manche Manager benötigen den Parameter nach der Pfadangabe, dann "fileManagerParamPost" auf true setzen */ let fileManagerParamPost = false; /* eigener Texteditor mit Pfad - Standard leer, dann wird Wert aus * Einstellung "view_source.editor.path" verwendet mit Warnmeldung, * wenn auch dieser leer ist, Beispiel: * let customEditor = "C:\\Windows\\System32\\notepad.exe"; */ let customEditor = ""; /* Unterordner für die CSS-Dateien */ let cssFolder = "CSS"; /* Menüeintrag zum Bearbeiten der userChrome.css anzeigen (true) oder verstecken (false) */ let showUserChromeCSS = true; /* Menüeintrag zum Bearbeiten der userContent.css anzeigen (true) oder verstecken (false) */ let showUserContentCSS = true; /* zusätzlich Chrome-Ordner im Untermenü anzeigen (true) oder verstecken (false) */ let showChrome = true; /***** Ende der Konfiguration *****/ // Wenn beim Start ein weiteres Fenster (zweites Fenster) vorhanden ist, beenden let list = Services.wm.getEnumerator("navigator:browser"); while(list.hasMoreElements()){ if(list.getNext() != window) return; } if (window.UCL) { window.UCL.destroy(); delete window.UCL; } let menutooltip = "Linksklick: an/aus, Menü schließt\nMittelklick: an/aus, Menü bleibt offen\nRechtsklick: bearbeiten"; if (fileManager !== "") { menutooltip = menutooltip + "\nStrg+Rechtsklick: im Dateimanager anzeigen"; } window.UCL = { AGENT_SHEET : Ci.nsIStyleSheetService.AGENT_SHEET, USER_SHEET : Ci.nsIStyleSheetService.USER_SHEET, AUTHOR_SHEET: Ci.nsIStyleSheetService.AUTHOR_SHEET, readCSS: {}, get disabled_list() { let obj = []; try { obj = decodeURIComponent(this.prefs.getCharPref("disabled_list")).split("|"); } catch(e) {} delete this.disabled_list; return this.disabled_list = obj; }, get prefs() { delete this.prefs; return this.prefs = Services.prefs.getBranch("UserCSSLoader."); }, get styleSheetServices() { delete this.styleSheetServices; return this.styleSheetServices = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); }, get FOLDER() { let aFolder; try { // UserCSSLoader.FOLDER verwenden let folderPath = this.prefs.getCharPref("FOLDER"); aFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); aFolder.initWithPath(folderPath); } catch (e) { aFolder = Services.dirsvc.get("UChrm", Ci.nsIFile); aFolder.appendRelativePath(cssFolder); } if (!aFolder.exists() || !aFolder.isDirectory()) { aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664); } delete this.FOLDER; return this.FOLDER = aFolder; }, get CHRMFOLDER() { let cFolder; try { // UserCSSLoader.CHRMFOLDER verwenden let CHRMfolderPath = this.prefs.getCharPref("CHRMFOLDER"); cFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); cFolder.initWithPath(CHRMfolderPath); } catch (e) { cFolder = Services.dirsvc.get("UChrm", Ci.nsIFile); } if (!cFolder.exists() || !cFolder.isDirectory()) { cFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664); } delete this.CHRMFOLDER; return this.CHRMFOLDER = cFolder; }, init: function() { const cssmenu = $C("menu", { id: "usercssloader-menu", label: "CSS", tooltiptext: "UserCSSLoader\n\nLinksklick: Stylesheets anzeigen\nMittelklick: Styles importieren", accesskey: "Y" }); cssmenu.addEventListener("click", (event) => { if (event.button === 1) UCL.rebuild(); }); const menupopup = $C("menupopup", { id: "usercssloader-menupopup" }); cssmenu.appendChild(menupopup); let menu = $C("menu", { label: "Style-Loader-Menü", id: "style-loader-menu", accesskey: "S", //acceltext: "S" }); menupopup.appendChild(menu); menupopup.appendChild($C("menuseparator")); let mp = $C("menupopup", { id: "usercssloader-submenupopup" }); menu.appendChild(mp); let rebuildItem = $C("menuitem", { label: "Styles importieren", accesskey: "I", //acceltext: "I" }); rebuildItem.addEventListener("command", () => UCL.rebuild()); mp.appendChild(rebuildItem); mp.appendChild($C("menuseparator")); // let createCSS = $C("menuitem", { label: "CSS-Datei erstellen", accesskey: "D", //acceltext: "D" }); createCSS.addEventListener("command", () => UCL.create()); mp.appendChild(createCSS); let openFolder = $C("menuitem", { label: "CSS-Ordner öffnen", accesskey: "O", //acceltext: "O" }); openFolder.addEventListener("command", () => UCL.openCSSFolder()); mp.appendChild(openFolder); if (showChrome) { let openChromeFolder = $C("menuitem", { label: "Chrome-Ordner öffnen", accesskey: "X", //acceltext: "X" }); openChromeFolder.addEventListener("command", () => UCL.openCHRMFolder()); mp.appendChild(openChromeFolder); } if (showUserChromeCSS || showUserContentCSS)// wenigstens eine der beiden Variablen muss … mp.appendChild($C('menuseparator'));// … true sein, damit Trennlinie angezeigt wird if (showUserChromeCSS) { let editChromeItem = $C("menuitem", { label: "userChrome.css bearbeiten" }); editChromeItem.addEventListener("command", () => UCL.editUserCSS("userChrome.css")); mp.appendChild(editChromeItem); } if (showUserContentCSS) { let editContentItem = $C("menuitem", { label: "userContent.css bearbeiten" }); editContentItem.addEventListener("command", () => UCL.editUserCSS("userContent.css")); mp.appendChild(editContentItem); } CustomizableUI.createWidget({ id: 'usercssloader-menu-item', type: 'custom', defaultArea: CustomizableUI.AREA_NAVBAR, onBuild: function(aDocument) { let toolbaritem = aDocument.createXULElement('toolbaritem'); toolbaritem.id = 'usercssloader-menu-item'; toolbaritem.className = 'chromeclass-toolbar-additional'; return toolbaritem; } }); $('usercssloader-menu-item').appendChild(cssmenu); if (position === 1) { let refNode = $('helpMenu'); refNode.parentNode.insertBefore(cssmenu, refNode.nextSibling); } // Stile neu laden, ohne Menü zu öffnen let key = $C("key", { id: "usercssloader-rebuild-key", key: "R", modifiers: "alt", }); key.addEventListener("command", () => UCL.rebuild()); $("mainKeyset").appendChild(key); this.rebuild(); this.initialized = true; window.addEventListener("unload", this, false); }, uninit: function() { const dis = []; for (let x of Object.keys(this.readCSS)) { if (!this.readCSS[x].enabled) dis.push(x); } this.prefs.setCharPref("disabled_list", encodeURIComponent(dis.join("|"))); window.removeEventListener("unload", this, false); }, destroy: function() { var i = document.getElementById("usercssloader-menu"); if (i) i.parentNode.removeChild(i); var i = document.getElementById("usercssloader-rebuild-key"); if (i) i.parentNode.removeChild(i); this.uninit(); }, handleEvent: function(event) { switch(event.type){ case "unload": this.uninit(); break; } }, rebuild: function() { let ext = /\.css$/i; let not = /\.uc\.css/i; let files = this.FOLDER.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator); 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); CSS.flag = true; } for (let leafName of Object.keys(this.readCSS)) { const CSS = this.readCSS[leafName]; if (!CSS.flag) { CSS.enabled = false; delete this.readCSS[leafName]; } delete CSS.flag; this.rebuildMenu(leafName); } if (this.initialized) { if (typeof(StatusPanel) !== "undefined") StatusPanel._label = "Styles importiert"; else XULBrowserWindow.statusTextField.label = "Styles importiert"; } }, loadCSS: function(aFile) { let CSS = this.readCSS[aFile.leafName]; if (!CSS) { CSS = this.readCSS[aFile.leafName] = new CSSEntry(aFile); if (this.disabled_list.indexOf(CSS.leafName) === -1) { CSS.enabled = true; } } else if (CSS.enabled) { CSS.enabled = true; } return CSS; }, rebuildMenu: function(aLeafName) { let CSS = this.readCSS[aLeafName]; let menuitem = document.getElementById("usercssloader-" + aLeafName); if (!CSS) { if (menuitem) menuitem.parentNode.removeChild(menuitem); return; } if (!menuitem) { menuitem = $C("menuitem", { label: aLeafName, id: "usercssloader-" + aLeafName, class: "usercssloader-item " + (CSS.SHEET == this.AGENT_SHEET? "AGENT_SHEET" : CSS.SHEET == this.AUTHOR_SHEET? "AUTHOR_SHEET": "USER_SHEET"), type: "checkbox", autocheck: "false", tooltiptext: menutooltip }); menuitem.addEventListener("command", () => UCL.toggle(aLeafName)); menuitem.addEventListener("click", (event) => UCL.itemClick(event)); menuitem.addEventListener("mouseup", (event) => { if (event.button === 1) event.preventDefault(); }); document.getElementById("usercssloader-menupopup").appendChild(menuitem); } menuitem.setAttribute("checked", CSS.enabled); }, toggle: function(aLeafName) { let CSS = this.readCSS[aLeafName]; if (!CSS || event.ctrlKey) return; CSS.enabled = !CSS.enabled; this.rebuildMenu(aLeafName); }, itemClick: function(event) { let label = event.currentTarget.getAttribute("label"); event.preventDefault(); event.stopPropagation(); if (event.button === 0) { return; } else if (event.button === 1) { this.toggle(label); } else if (event.button === 2) { if (event.ctrlKey && fileManager !== "") { UCL.showFile(label); } else { closeMenus(event.target); this.edit(this.getFileFromLeafName(label)); } } }, getFileFromLeafName: function(aLeafName) { let f = this.FOLDER.clone(); f.QueryInterface(Ci.nsIFile); // use appendRelativePath f.appendRelativePath(aLeafName); return f; }, showFile: function(fname) { const PathSep = AppConstants.platform === "win" ? "\\" : "/"; let target= this.FOLDER.path + PathSep + fname; let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess); let args = (!fileManagerParamPost) ? [fileManagerParam,target] : [target,fileManagerParam]; file.initWithPath(fileManager); process.init(file); // Verzeichnis mit anderem Dateimanager öffnen process.run(false, args, args.length); }, openCSSFolder:function(){ if (fileManager !== "" && fileManager !== "/select,") { let target = this.FOLDER.path; let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess); let args = (!fileManagerParamPost) ? [fileManagerParam,target] : [target,fileManagerParam]; file.initWithPath(fileManager); process.init(file); // Verzeichnis mit anderem Dateimanager öffnen process.run(false, args, args.length); } else { // Verzeichnis mit Dateimanager des Systems öffnen this.FOLDER.launch(); } }, openCHRMFolder:function(){ if (fileManager !== "" && fileManager !== "/select,") { let target = this.CHRMFOLDER.path; let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess); let args = (!fileManagerParamPost) ? [fileManagerParam,target] : [target,fileManagerParam]; file.initWithPath(fileManager); process.init(file); // Verzeichnis mit anderem Dateimanager öffnen process.run(false, args, args.length); } else { // Verzeichnis mit Dateimanager des Systems öffnen this.CHRMFOLDER.launch(); } }, editUserCSS: function(aLeafName) { let file = Services.dirsvc.get("UChrm", Ci.nsIFile); file.appendRelativePath(aLeafName); this.edit(file); }, edit: function(aFile) { let editor = (customEditor !== "") ? customEditor : Services.prefs.getCharPref("view_source.editor.path"); if (!editor) return alert('In der Konfiguration einen Texteditor festlegen ("customEditor") oder\n unter about:config im vorhandenen Schalter "view_source.editor.path"\n den vollständigen Editorpfad eintragen.'); try { let UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter); UI.charset = window.navigator.platform.toLowerCase().indexOf("win") >= 0? "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) {} }, create: function(aLeafName) { if (!aLeafName) aLeafName = prompt("Name des Styles", dateFormat(new Date(), "%Y_%m%d_%H%M%S")); if (aLeafName) aLeafName = aLeafName.replace(/\s+/g, " ").replace(/[\\/:*?\"<>|]/g, ""); if (!aLeafName || !/\S/.test(aLeafName)) return; if (!/\.css$/.test(aLeafName)) aLeafName += ".css"; let file = this.getFileFromLeafName(aLeafName); this.edit(file); }, UCrebuild: function() { let re = /^file:.*\.uc\.css(?:\?\d+)?$/i; let query = "?" + new Date().getTime(); Array.slice(document.styleSheets).forEach(function(css){ if (!re.test(css.href)) return; if (css.ownerNode) { css.ownerNode.parentNode.removeChild(css.ownerNode); } let pi = document.createProcessingInstruction('xml-stylesheet','type="text/css" href="'+ css.href.replace(/\?.*/, '') + query +'"'); document.insertBefore(pi, document.documentElement); }); UCL.UCcreateMenuitem(); }, UCcreateMenuitem: function() { let sep = $("usercssloader-ucseparator"); let popup = sep.parentNode; if (sep.nextSibling) { let range = document.createRange(); range.setStartAfter(sep); range.setEndAfter(popup.lastChild); range.deleteContents(); range.detach(); } let re = /^file:.*\.uc\.css(?:\?\d+)?$/i; Array.slice(document.styleSheets).forEach(function(css) { if (!re.test(css.href)) return; let fileURL = decodeURIComponent(css.href).split("?")[0]; let aLeafName = fileURL.split("/").pop(); let m = $C("menuitem", { label: aLeafName, tooltiptext: fileURL, id: "usercssloader-" + aLeafName, type: "checkbox", autocheck: "false", checked: "true", }); m.css = css; m.addEventListener("command", function() { if (!event.ctrlKey) {this.setAttribute("checked", !(this.css.disabled = !this.css.disabled));} }); m.addEventListener("mouseup", function(event) { if (event.button === 1) event.preventDefault(); }); m.addEventListener("click", function(event) { UCL.UCItemClick(event); }); popup.appendChild(m); }); }, UCItemClick: function(event) { if (event.button === 0) return; event.preventDefault(); event.stopPropagation(); if (event.button === 1) { event.target.doCommand(); } else if (event.button === 2) { closeMenus(event.target); let fileURL = event.currentTarget.getAttribute("tooltiptext"); let file = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getFileFromURLSpec(fileURL); this.edit(file); } }, }; 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(); // true, wenn die Datei bereits existiert let lastModifiedTime = isExists ? aFile.lastModifiedTime : 0; let isForced = this.lastModifiedTime != lastModifiedTime; //true, wenn es eine Änderung in der Datei gibt 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)) { // Wenn diese Datei bereits gelesen wurde if (!isEnable || !isExists) { this.sss.unregisterSheet(uri, this.SHEET); } else if (isForced) { // Nach Stornierung erneut einlesen this.sss.unregisterSheet(uri, this.SHEET); this.sss.loadAndRegisterSheet(uri, this.SHEET); } } else { // Datei wurde nicht gelesen if (isEnable && isExists) { this.sss.loadAndRegisterSheet(uri, this.SHEET); } } if (this.lastModifiedTime !== 1 && isEnable && isForced) { log(this.leafName + " wurde aktualisiert"); } this.lastModifiedTime = lastModifiedTime; return this._enabled = isEnable; }, }; UCL.init(); function $(id) { return document.getElementById(id); } function $A(arr) { return Array.slice(arr); } function $C(name, attr) { const el = document.createXULElement(name); if (attr) Object.keys(attr).forEach(function(n) { el.setAttribute(n, attr[n]) }); return el; } function dateFormat(date, format) { format = format.replace("%Y", ("000" + date.getFullYear()).substr(-4)); format = format.replace("%m", ("0" + (date.getMonth()+1)).substr(-2)); format = format.replace("%d", ("0" + date.getDate()).substr(-2)); format = format.replace("%H", ("0" + date.getHours()).substr(-2)); format = format.replace("%M", ("0" + date.getMinutes()).substr(-2)); format = format.replace("%S", ("0" + date.getSeconds()).substr(-2)); return format; } function log(mes) { console.log(mes); } })();
-
Allerdings ist da der Abstand zum linken und rechten Icon größer als bei den anderen in meiner Statuszeile. Vielleicht kann man ja noch da etwas ändern!?
Ausgehend von Deinem zuvor geposteten Stil würde ich als Erstes das hier versuchen:
Code#usercssloader-menu-item #usercssloader-menu > .menu-text[value="CSS"] { opacity: 0; width: calc(2 * var(--toolbarbutton-inner-padding) + 20px); height: calc(2 * var(--toolbarbutton-inner-padding) + 20px); }
Dort ist jeweils der Wert von 24px zu 20px geändert.
Bei der Höhe meiner Leiste ist mir das überhaupt nicht aufgefallen.
Kannst du bitte das mal austesten:
Und, wenn das zu groß ist, als nächstes var(--button-min-height-small)? Ich hab noch nicht herausgefunden, wo die Unterscheidung stattfindet, wann welche Variable aktiviert wird.
Und hier der Radius-Wert
Hmm, stiimmt. Ist mir auch nicht aufgefallen. Aber warum nur bei Hover? Und es gibt eine Variable dafür, also gleich mal mittesten:
Dann würde ich das alles noch in die Anleitung einfügen.
-
in Zeile 404 if (fileManager !== "") {
[…]
So sieht diese Zeile bei mir in der vorherigen Version aus if (fileManager.length !== 0) {
Ist dies eine bewusste Änderung oder ein Kopierfehler oder ähnliches?
Sören hat das Entscheidende schon gesagt. Der Hintergrund ist, dass ich dachte, den Code dahingehend zu vereinheitlichen und die gewählte Variante etwas kürzer und für mich auch etwas besser verständlich ist (und als ich diese eingeführt habe, war mir gar nicht bewusst, dass die andere bereits verwendet wurde).
Zur Nachfrage, Börsi, hattest Du meine Hinweise zur Kürzung Deines CSS-Stils in Beitrag #63 bemerkt und waren diese nachvollziehbar? Oder bist du sogar auf die kürzere Version, wie jetzt im Skript beschrieben, umgestiegen?
-
Leute, Leute, kaum ist man mal ein paar Tage nicht anwesend, kommt man hier nicht mehr mit.
Unten folgt das hoffentlich letzte Update, bevor Endor es bei sich hochladen kann.
Ich habe erstens
JavaScriptconst PathSep = AppConstants.platform === "win" ? "\\" : "/"; let target= this.FOLDER.path + PathSep + fname;
wieder eingefügt. Meine Aussage
Dann müsste ich aber auch
ChromeUtils.importESModule("resource://gre/modules/AppConstants.sys.mjs");
wieder einführen
stimmt übrigens nicht, wie Bege uns mit seiner letzten Skriptversion zeigte und ich dann in der Konsole ausprobierte. Ich meine, es war einmal anders, aber egal.
Zweitens habe ich das hier geändert:
Wobei die Änderung von openFolder zu openFile nicht ganz passt. Die CSS-Dateien werden nicht geöffnet, sondern nur im Dateimanager im Order angezeigt. Geöffnet wird also tatsächlich nur der Ordner.
Heißt jetzt showFile.
Sonst habe ich am Code nichts geändert und damit auch das nicht entfernt, was ich als Backup-Funktion bezeichnet habe. In dem Zusammenhang: Wenn ich explizit den Windows-Explorer (beziehungsweise File-Explorer, wie es in Win11 heißt) samt Parameter auswähle, funktioniert es hier mit der jüngsten Version.
Alles andere sind Änderungen am kommentierten Teil zu Beginn des Skripts:
Ich hab den alten Header entfernt, dafür eine kürzere Angabe zur Urheberschaft eingefügt (bewusst in Englisch). Und dann gibt es Änderungen an Bedienungsanleitung und Konfigurationserläuterungen. Ob der erste Absatz der Bedienungsanleitung noch auf dem aktuellen Stand ist, dessen bin ich mir unsicher.
JavaScript
Alles anzeigen/* UserCSSLoader * original author: Griever - * https://github.com/Griever/userChromeJS/tree/master/UserCSSLoader * * Enhancements and several other changes including German translation * and configuration section by users aborix, Endor, bege, Speravir of * Camp Firefox forum - https://www.camp-firefox.de/forum/ - latest version: * https://www.camp-firefox.de/forum/thema/138814/?postID=1278991#post1278991 */ /****** Bedienungsanleitung ****** CSS-Ordner im Chrome-Ordner erstellen, CSS-Dateien dort ablegen - speichern. Diejenigen, deren Dateiname mit "xul-" beginnen, diejenigen, die mit ".as.css" enden, sind AGENT_SHEET, alle anderen außer USER_SHEET werden gelesen. Da der Inhalt der Datei nicht überprüft wird, darauf achten, die Angabe von @namespace nicht zu vergessen! Schaltfläche oder Menü wird in Navigationsleiste eingefügt (einstellbar, siehe Variable "position" in unten anschließender Konfiguration). Dateiordner, Dateimanager und Texteditor können in der unten anschließenden Konfiguration geändert werden. Die Verwendung des in "view_source.editor.path" angegebenen Editors ist möglich. Linksklick auf Stil, zum Aktivieren/Deaktivieren Mittelklick auf Stil zum Aktivieren/Deaktivieren, ohne Menü zu schließen Rechtsklick auf Stil zum Öffnen im Editor Strg+Linksklick zum Anzeigen im Dateimanager Die Tastenkombinationen können im Menü eingeblendet werden, dazu nach "acceltext" suchen und den Zeilenkommentar "//" entfernen. Ein Symbol für die Schaltfläche muss in der "userChrome.css" festgelegt werden, Pfad zum Bild (PNG nur als Beispiel): * relativ zur userChrome.css background-image: url("Relativer/Pfad/zum/CSS_Symbol.png"); * eine absolute Pfadangabe zum Symbol muss mit File-Protokoll-Präfix erfolgen: background-image: url("file:///Absoluter/Pfad/zum/CSS_Symbol.png"); #usercssloader-menu-item { background-image: url("Relativer/Pfad/zum/CSS_Symbol.png"); background-position: center; background-repeat: no-repeat; background-size: 16px; &:hover { background-color: var(--toolbarbutton-hover-background); } & #usercssloader-menu > .menu-text[value="CSS"] { opacity: 0; width: calc(2 * var(--toolbarbutton-inner-padding) + 16px); height: calc(2 * var(--toolbarbutton-inner-padding) + 16px); } } **** Ende der Anleitung ****/ (function(){ /***** Konfiguration *****/ /* Position: als frei verschiebbare-Schaltfläche = 0, als Menü anzeigen = 1 */ let position = 0;//1 /* Dateimanager festlegen, Beispiele: * let fileManager = "C:\\Programme\\FreeCommanderXE\\FreeCommander.exe"; * let fileManager = "C:\\Programme\\totalcmd\\TOTALCMD.EXE"; * auch möglich: * let fileManager = "C:\\Windows\\explorer.exe"; * Bleibt Parameter leer, wird Standardmanager des Systems ohne Parameter * verwendet mit leicht eingeschränkter Funktionalität. */ let fileManager = ""; /* eventuelle Parameter für den Dateimanager, Beispiele: * let fileManagerParam = "/T";//FreeCommander oder Totalcommander * let fileManagerParam = "/select,";//Windows Explorer, mit Komma korrekt! */ let fileManagerParam = ""; /* manche Manager benötigen den Parameter nach der Pfadangabe, dann "fileManagerParamPost" auf true setzen */ let fileManagerParamPost = false; /* eigener Texteditor mit Pfad - Standard leer, dann wird Wert aus * Einstellung "view_source.editor.path" verwendet mit Warnmeldung, * wenn auch dieser leer ist, Beispiel: * let customEditor = "C:\\Windows\\System32\\notepad.exe"; */ let customEditor = ""; /* Unterordner für die CSS-Dateien */ let cssFolder = "CSS"; /* Menüeintrag zum Bearbeiten der userChrome.css anzeigen (true) oder verstecken (false) */ let showUserChromeCSS = true; /* Menüeintrag zum Bearbeiten der userContent.css anzeigen (true) oder verstecken (false) */ let showUserContentCSS = true; /* zusätzlich Chrome-Ordner im Untermenü anzeigen (true) oder verstecken (false) */ let showChrome = true; /***** Ende der Konfiguration *****/ // Wenn beim Start ein weiteres Fenster (zweites Fenster) vorhanden ist, beenden let list = Services.wm.getEnumerator("navigator:browser"); while(list.hasMoreElements()){ if(list.getNext() != window) return; } if (window.UCL) { window.UCL.destroy(); delete window.UCL; } let menutooltip = "Linksklick: an/aus, Menü schließt\nMittelklick: an/aus, Menü bleibt offen\nRechtsklick: bearbeiten"; if (fileManager !== "") { menutooltip = menutooltip + "\nStrg+Rechtsklick: im Dateimanager anzeigen"; } window.UCL = { AGENT_SHEET : Ci.nsIStyleSheetService.AGENT_SHEET, USER_SHEET : Ci.nsIStyleSheetService.USER_SHEET, AUTHOR_SHEET: Ci.nsIStyleSheetService.AUTHOR_SHEET, readCSS: {}, get disabled_list() { let obj = []; try { obj = decodeURIComponent(this.prefs.getCharPref("disabled_list")).split("|"); } catch(e) {} delete this.disabled_list; return this.disabled_list = obj; }, get prefs() { delete this.prefs; return this.prefs = Services.prefs.getBranch("UserCSSLoader."); }, get styleSheetServices() { delete this.styleSheetServices; return this.styleSheetServices = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); }, get FOLDER() { let aFolder; try { // UserCSSLoader.FOLDER verwenden let folderPath = this.prefs.getCharPref("FOLDER"); aFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); aFolder.initWithPath(folderPath); } catch (e) { aFolder = Services.dirsvc.get("UChrm", Ci.nsIFile); aFolder.appendRelativePath(cssFolder); } if (!aFolder.exists() || !aFolder.isDirectory()) { aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664); } delete this.FOLDER; return this.FOLDER = aFolder; }, get CHRMFOLDER() { let cFolder; try { // UserCSSLoader.CHRMFOLDER verwenden let CHRMfolderPath = this.prefs.getCharPref("CHRMFOLDER"); cFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); cFolder.initWithPath(CHRMfolderPath); } catch (e) { cFolder = Services.dirsvc.get("UChrm", Ci.nsIFile); } if (!cFolder.exists() || !cFolder.isDirectory()) { cFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664); } delete this.CHRMFOLDER; return this.CHRMFOLDER = cFolder; }, init: function() { const cssmenu = $C("menu", { id: "usercssloader-menu", label: "CSS", tooltiptext: "UserCSSLoader\n\nLinksklick: Stylesheets anzeigen\nMittelklick: Styles importieren", accesskey: "Y" }); cssmenu.addEventListener("click", (event) => { if (event.button === 1) UCL.rebuild(); }); const menupopup = $C("menupopup", { id: "usercssloader-menupopup" }); cssmenu.appendChild(menupopup); let menu = $C("menu", { label: "Style-Loader-Menü", id: "style-loader-menu", accesskey: "S", //acceltext: "S" }); menupopup.appendChild(menu); menupopup.appendChild($C("menuseparator")); let mp = $C("menupopup", { id: "usercssloader-submenupopup" }); menu.appendChild(mp); let rebuildItem = $C("menuitem", { label: "Styles importieren", accesskey: "I", //acceltext: "I" }); rebuildItem.addEventListener("command", () => UCL.rebuild()); mp.appendChild(rebuildItem); mp.appendChild($C("menuseparator")); // let createCSS = $C("menuitem", { label: "CSS-Datei erstellen", accesskey: "D", //acceltext: "D" }); createCSS.addEventListener("command", () => UCL.create()); mp.appendChild(createCSS); let openFolder = $C("menuitem", { label: "CSS-Ordner öffnen", accesskey: "O", //acceltext: "O" }); openFolder.addEventListener("command", () => UCL.openCSSFolder()); mp.appendChild(openFolder); if (showChrome) { let openChromeFolder = $C("menuitem", { label: "Chrome-Ordner öffnen", accesskey: "X", //acceltext: "X" }); openChromeFolder.addEventListener("command", () => UCL.openCHRMFolder()); mp.appendChild(openChromeFolder); } if (showUserChromeCSS || showUserContentCSS)// wenigstens eine der beiden Variablen muss … mp.appendChild($C('menuseparator'));// … true sein, damit Trennlinie angezeigt wird if (showUserChromeCSS) { let editChromeItem = $C("menuitem", { label: "userChrome.css bearbeiten" }); editChromeItem.addEventListener("command", () => UCL.editUserCSS("userChrome.css")); mp.appendChild(editChromeItem); } if (showUserContentCSS) { let editContentItem = $C("menuitem", { label: "userContent.css bearbeiten" }); editContentItem.addEventListener("command", () => UCL.editUserCSS("userContent.css")); mp.appendChild(editContentItem); } CustomizableUI.createWidget({ id: 'usercssloader-menu-item', type: 'custom', defaultArea: CustomizableUI.AREA_NAVBAR, onBuild: function(aDocument) { let toolbaritem = aDocument.createXULElement('toolbaritem'); toolbaritem.id = 'usercssloader-menu-item'; toolbaritem.className = 'chromeclass-toolbar-additional'; return toolbaritem; } }); $('usercssloader-menu-item').appendChild(cssmenu); if (position === 1) { let refNode = $('helpMenu'); refNode.parentNode.insertBefore(cssmenu, refNode.nextSibling); } // Stile neu laden, ohne Menü zu öffnen let key = $C("key", { id: "usercssloader-rebuild-key", key: "R", modifiers: "alt", }); key.addEventListener("command", () => UCL.rebuild()); $("mainKeyset").appendChild(key); this.rebuild(); this.initialized = true; window.addEventListener("unload", this, false); }, uninit: function() { const dis = []; for (let x of Object.keys(this.readCSS)) { if (!this.readCSS[x].enabled) dis.push(x); } this.prefs.setCharPref("disabled_list", encodeURIComponent(dis.join("|"))); window.removeEventListener("unload", this, false); }, destroy: function() { var i = document.getElementById("usercssloader-menu"); if (i) i.parentNode.removeChild(i); var i = document.getElementById("usercssloader-rebuild-key"); if (i) i.parentNode.removeChild(i); this.uninit(); }, handleEvent: function(event) { switch(event.type){ case "unload": this.uninit(); break; } }, rebuild: function() { let ext = /\.css$/i; let not = /\.uc\.css/i; let files = this.FOLDER.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator); 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); CSS.flag = true; } for (let leafName of Object.keys(this.readCSS)) { const CSS = this.readCSS[leafName]; if (!CSS.flag) { CSS.enabled = false; delete this.readCSS[leafName]; } delete CSS.flag; this.rebuildMenu(leafName); } if (this.initialized) { if (typeof(StatusPanel) !== "undefined") StatusPanel._label = "Styles importiert"; else XULBrowserWindow.statusTextField.label = "Styles importiert"; } }, loadCSS: function(aFile) { let CSS = this.readCSS[aFile.leafName]; if (!CSS) { CSS = this.readCSS[aFile.leafName] = new CSSEntry(aFile); if (this.disabled_list.indexOf(CSS.leafName) === -1) { CSS.enabled = true; } } else if (CSS.enabled) { CSS.enabled = true; } return CSS; }, rebuildMenu: function(aLeafName) { let CSS = this.readCSS[aLeafName]; let menuitem = document.getElementById("usercssloader-" + aLeafName); if (!CSS) { if (menuitem) menuitem.parentNode.removeChild(menuitem); return; } if (!menuitem) { menuitem = $C("menuitem", { label: aLeafName, id: "usercssloader-" + aLeafName, class: "usercssloader-item " + (CSS.SHEET == this.AGENT_SHEET? "AGENT_SHEET" : CSS.SHEET == this.AUTHOR_SHEET? "AUTHOR_SHEET": "USER_SHEET"), type: "checkbox", autocheck: "false", tooltiptext: menutooltip }); menuitem.addEventListener("command", () => UCL.toggle(aLeafName)); menuitem.addEventListener("click", (event) => UCL.itemClick(event)); menuitem.addEventListener("mouseup", (event) => { if (event.button === 1) event.preventDefault(); }); document.getElementById("usercssloader-menupopup").appendChild(menuitem); } menuitem.setAttribute("checked", CSS.enabled); }, toggle: function(aLeafName) { let CSS = this.readCSS[aLeafName]; if (!CSS || event.ctrlKey) return; CSS.enabled = !CSS.enabled; this.rebuildMenu(aLeafName); }, itemClick: function(event) { let label = event.currentTarget.getAttribute("label"); event.preventDefault(); event.stopPropagation(); if (event.button === 0) { return; } else if (event.button === 1) { this.toggle(label); } else if (event.button === 2) { if (event.ctrlKey) { UCL.showFile(label); } else { closeMenus(event.target); this.edit(this.getFileFromLeafName(label)); } } }, getFileFromLeafName: function(aLeafName) { let f = this.FOLDER.clone(); f.QueryInterface(Ci.nsIFile); // use appendRelativePath f.appendRelativePath(aLeafName); return f; }, showFile: function(fname) { if (fileManager !== "") { const PathSep = AppConstants.platform === "win" ? "\\" : "/"; let target= this.FOLDER.path + PathSep + fname; let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess); let args = (!fileManagerParamPost) ? [fileManagerParam,target] : [target,fileManagerParam]; file.initWithPath(fileManager); process.init(file); // Verzeichnis mit anderem Dateimanager öffnen process.run(false, args, args.length); } else { // Verzeichnis mit Dateimanager des Systems öffnen this.FOLDER.launch(); } }, openCSSFolder:function(){ if (fileManager !== "") { let target = this.FOLDER.path; let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess); let args = (!fileManagerParamPost) ? [fileManagerParam,target,] : [target,fileManagerParam]; file.initWithPath(fileManager); process.init(file); // Verzeichnis mit anderem Dateimanager öffnen process.run(false, args, args.length); } else { // Verzeichnis mit Dateimanager des Systems öffnen this.FOLDER.launch(); } }, openCHRMFolder:function(){ if (fileManager !== "") { let target = this.CHRMFOLDER.path; let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess); let args = (!fileManagerParamPost) ? [fileManagerParam,target,] : [target,fileManagerParam]; file.initWithPath(fileManager); process.init(file); // Verzeichnis mit anderem Dateimanager öffnen process.run(false, args, args.length); } else { // Verzeichnis mit Dateimanager des Systems öffnen this.CHRMFOLDER.launch(); } }, editUserCSS: function(aLeafName) { let file = Services.dirsvc.get("UChrm", Ci.nsIFile); file.appendRelativePath(aLeafName); this.edit(file); }, edit: function(aFile) { let editor = (customEditor !== "") ? customEditor : Services.prefs.getCharPref("view_source.editor.path"); if (!editor) return alert('In der Konfiguration einen Texteditor festlegen ("customEditor") oder\n unter about:config im vorhandenen Schalter "view_source.editor.path"\n den vollständigen Editorpfad eintragen.'); try { let UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter); UI.charset = window.navigator.platform.toLowerCase().indexOf("win") >= 0? "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) {} }, create: function(aLeafName) { if (!aLeafName) aLeafName = prompt("Name des Styles", dateFormat(new Date(), "%Y_%m%d_%H%M%S")); if (aLeafName) aLeafName = aLeafName.replace(/\s+/g, " ").replace(/[\\/:*?\"<>|]/g, ""); if (!aLeafName || !/\S/.test(aLeafName)) return; if (!/\.css$/.test(aLeafName)) aLeafName += ".css"; let file = this.getFileFromLeafName(aLeafName); this.edit(file); }, UCrebuild: function() { let re = /^file:.*\.uc\.css(?:\?\d+)?$/i; let query = "?" + new Date().getTime(); Array.slice(document.styleSheets).forEach(function(css){ if (!re.test(css.href)) return; if (css.ownerNode) { css.ownerNode.parentNode.removeChild(css.ownerNode); } let pi = document.createProcessingInstruction('xml-stylesheet','type="text/css" href="'+ css.href.replace(/\?.*/, '') + query +'"'); document.insertBefore(pi, document.documentElement); }); UCL.UCcreateMenuitem(); }, UCcreateMenuitem: function() { let sep = $("usercssloader-ucseparator"); let popup = sep.parentNode; if (sep.nextSibling) { let range = document.createRange(); range.setStartAfter(sep); range.setEndAfter(popup.lastChild); range.deleteContents(); range.detach(); } let re = /^file:.*\.uc\.css(?:\?\d+)?$/i; Array.slice(document.styleSheets).forEach(function(css) { if (!re.test(css.href)) return; let fileURL = decodeURIComponent(css.href).split("?")[0]; let aLeafName = fileURL.split("/").pop(); let m = $C("menuitem", { label: aLeafName, tooltiptext: fileURL, id: "usercssloader-" + aLeafName, type: "checkbox", autocheck: "false", checked: "true", }); m.css = css; m.addEventListener("command", function() { if (!event.ctrlKey) {this.setAttribute("checked", !(this.css.disabled = !this.css.disabled));} }); m.addEventListener("mouseup", function(event) { if (event.button === 1) event.preventDefault(); }); m.addEventListener("click", function(event) { UCL.UCItemClick(event); }); popup.appendChild(m); }); }, UCItemClick: function(event) { if (event.button === 0) return; event.preventDefault(); event.stopPropagation(); if (event.button === 1) { event.target.doCommand(); } else if (event.button === 2) { closeMenus(event.target); let fileURL = event.currentTarget.getAttribute("tooltiptext"); let file = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getFileFromURLSpec(fileURL); this.edit(file); } }, }; 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(); // true, wenn die Datei bereits existiert let lastModifiedTime = isExists ? aFile.lastModifiedTime : 0; let isForced = this.lastModifiedTime != lastModifiedTime; //true, wenn es eine Änderung in der Datei gibt 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)) { // Wenn diese Datei bereits gelesen wurde if (!isEnable || !isExists) { this.sss.unregisterSheet(uri, this.SHEET); } else if (isForced) { // Nach Stornierung erneut einlesen this.sss.unregisterSheet(uri, this.SHEET); this.sss.loadAndRegisterSheet(uri, this.SHEET); } } else { // Datei wurde nicht gelesen if (isEnable && isExists) { this.sss.loadAndRegisterSheet(uri, this.SHEET); } } if (this.lastModifiedTime !== 1 && isEnable && isForced) { log(this.leafName + " wurde aktualisiert"); } this.lastModifiedTime = lastModifiedTime; return this._enabled = isEnable; }, }; UCL.init(); function $(id) { return document.getElementById(id); } function $A(arr) { return Array.slice(arr); } function $C(name, attr) { const el = document.createXULElement(name); if (attr) Object.keys(attr).forEach(function(n) { el.setAttribute(n, attr[n]) }); return el; } function dateFormat(date, format) { format = format.replace("%Y", ("000" + date.getFullYear()).substr(-4)); format = format.replace("%m", ("0" + (date.getMonth()+1)).substr(-2)); format = format.replace("%d", ("0" + date.getDate()).substr(-2)); format = format.replace("%H", ("0" + date.getHours()).substr(-2)); format = format.replace("%M", ("0" + date.getMinutes()).substr(-2)); format = format.replace("%S", ("0" + date.getSeconds()).substr(-2)); return format; } function log(mes) { console.log(mes); } })();
-
Geh mal oben im Menü Einstellungen auf Optionen. Dort dann auf den Punkt Neues Dokument. Da kannst du rechts die Codierung einstellen auf UTF-8. Danach sollte sich nichts mehr verstellen...
Genau den Punkt meinte ich, Enterhaken.
Genau so ist es bei mir auch eingestellt:
Bei mir auch mit einer Ausnahme: Ich hab „UTF-8 auch beim Öffnen von ANSI-Dokumenten“ deaktiviert und muss dann eben mit den Konsequenzen leben. Zuletzt ist das Problem hier aber nicht mehr vorgekommen.
-
Wenn ich die Skripte mit Notepad++ erstelle, springt die Kodierung nur dann automatisch von UTF-8 um wenn in den Code-Schnipseln Umlaute verbaut sind.
Das ist mir auch schon diverse Male passiert, weshalb ich bei dir sofort daran dachte, nur waren andere schneller mit der Lösung. Was hast du eigentlich für eine Einstellung für neue Dokumente in den Optionen von N++?
-
lenny2, Mira_Belle: Es muss sich um about_button.uc.js oder about_button_generic.uc.js handeln, aber über Anpassungen muss uns tatsächlich der OP Bescheid geben.
juzzlukin, please, post your actual script, so we can see your (necessary) edits. Do other scripts work?
-
Hast Du Dir das schon mal angeschaut?
Ja, aber ich bin auch kein Experte. Das läuft eher wie bei den meisten hier: Blindes Huhn und hochprozentiger Schnaps.
Sehe ich das richtig, dass Deine Version eine Abwandlung von einem Skript ist, dass 2002Andreas hier irgendwo mal gepostet hat, als er Probleme damit hatte?
-
Dazu muss jetzt immer ein Dateimanager angegeben werden, z.B. eben auch der Windows Explorer.
Jetzt scheinen sich unsere Postings überschnitten zu haben. Ernaut danke und ich schau mir das natürlich an, aber ich bleibe dabei: Diesen letzten Ausweg würde ich nicht entfernen, eher darauf hinweisen, dass man auch den Windows Explorer explizit angeben kann.
-
Zunächst: Allgemein danke für die Rückmeldung, Bege!
Bei mir funktioniert der FreeCommander mit der bisherigen Version seit Jahren.
Hmm, interessant: Ich hab mir eine portable Version heruntergeladen und mit der funktioniert es nicht (ich rufe dann die PortableExe auf, die die Parameter weiterreicht). Aber vor allem ist in der Online-Hilfe für Kommandozeilenparameter des Freecommander eindeutig zu erkennen, dass der Parameter /T nachgestellt wird.
Das funktioniert in deiner vorherigen Version, nicht aber in der neuesten in Beitrag #63. Schaust du bitte mal, was geändert werden muss, damit es wieder geht?
Anschauen ja, versprechen nein.
und in openCSSFolder:function() könnte if {} else {} raus, weil dann immer ein Dateimanager eingetragen ist. Auch die Abfrage für menutooltip wäre dann überflüssig.
Nein, das entferne ich nicht. Das ist sozusagen die Backup-Funktion. Du solltest nicht vergessen, dass es noch Linux und MacOS gibt oder allgemein neben Windows noch die unixoiden Systeme.
Oh, vielleicht lag es wirklich genau daran, dass es meine Versuche mit dem Explorer nicht erfolgreich waren, habe ich gar nicht mehr dran gedacht.
Dann müsste ich aber auch
ChromeUtils.importESModule("resource://gre/modules/AppConstants.sys.mjs");
wieder einführen und genau darauf wollte ich verzichten, denn das erzeugt eine Inkompatibilität: Der Aufruf verändert sich vermutlich von Fx 142 zu 143 und jemand, der eine Nightly-Version nutzt ( 2002Andreas, milupo?), müsste mir den neuen Pfad mitteilen.
Wobei die Änderung von openFolder zu openFile nicht ganz passt. Die CSS-Dateien werden nicht geöffnet, sondern nur im Dateimanager im Order angezeigt.
Stimmt, das ist missverständlich.
Hm, ist noch nicht "produktionsreif". /select, führt dazu, dass der Explorer alles nur auswählt. Damit werden auch die Ordner nicht geöffnet, sondern nur ausgewählt.
Auch merkwürdig. Wenn ich direkt von der Kommandozeile C:\Windows\explorer.exe /select, C:\Beispielpfad\Beispiel.txt aufrufe, dann geht das bei mir.
-
Und nochmal eine Ergänzung nur in der Anleitung, dieses Mal nur im CSS-Code (Hover-Regel). Ich poste den Teil einmal im herkömmlichen Stil (nicht verschachtelt, also ohne "&"), vielleicht für Boersenfeger interessant:
CSS
Alles anzeigen#usercssloader-menu-item { background-image: url("Relativer/Pfad/zum/CSS_Symbol.png"); background-position: center; background-repeat: no-repeat; background-size: 16px; } #usercssloader-menu-item:hover { background-color: var(--toolbarbutton-hover-background); } #usercssloader-menu-item #usercssloader-menu > .menu-text[value="CSS"] { opacity: 0; width: calc(2 * var(--toolbarbutton-inner-padding) + 16px); height: calc(2 * var(--toolbarbutton-inner-padding) + 16px); }
Die Hover-Regel und die Deklarationen zu Breite und Höhe entsprechen dem Standard für Toolbar-Buttons mit den jeweiligen Vorgaben der Variablen (angepasste Eigenschaften).
-
Erneute kleine Codeänderung in der Anleitung wegen des Symbols und im Code wegen userChrome/userContent bearbeiten, siehe weiterhin am Ende von Beitrag #63.
seipe, sieh dir bitte die Anleitung ab Zeile 53 an. Ist das verständlich genug für dich?
-
Hinweis: Kleine Änderung am Code: Statt hideUserChromeCSS/hideUserContentCSS heißt es jetzt showUserChromeCSS/showUserContentCSS mit entsprechender Umkehrung der Logik. Ich habe das Skript in #63 angepasst.
-
Endor, BarbaraZ-, bege, Boersenfeger, lenny2, Mira_Belle, seipe (noch jemand
ohne Fahrscheinvergessen?):Bitte die am Ende dieses Postings angehängte Version testen. Mehr kann ich daran nicht mehr ändern, denke ich, außer es fallen Tippfehler auf.
Vorher noch ein paar Anmerkungen:
- Manche Editoren benötigen nach dem Pfad angehängte Parameter, beispielsweise der FreeCommander, Dafür gibt es jetzt die Variable fileManagerParamPost.
- fileManagerParam verträgt anscheinend nur einen einzigen Parameter ohne Leerzeichen. Ich weiß nicht, ob beispielsweise BrokenHeart das ändern kann. Als Ausweg bleibe weiterhin, die Variable im Skript leer zu lassen und als Dateimanager eine Link- beziehungsweise Shell-Datei einzutragen, in der dann die Parameter eingetragen werden.
- Ich habe einige Tastenzuordnungen geändert, bitte Bescheid geben, wenn das nicht gefällt. Bege wollte „Chrome-Ordner öffnen“ zu M ändern, ich habe es auf X gelassen (vergleiche Diskussion auf der vorigen Threadseite). Jeder kann das aber für sich ändern (wie auch die anderen Tasten, man muss nur auf Kollisionen mit bestehenden Verwendungen achten).
Jetzt muss ich nur noch sehen, wie ich das Skript, bzw, die Funktionen in das App-Menü bekomme.
Verlinke bitte mal zum Thread, wo Du das Skript gepostet hast.
Kann man den "überflüssigen" Code dann nicht entfernen?
Hab ich getan. Das heißt für die Zukunft, dass Vergleiche mit der externen Vorlage aufwendiger werden.
Meine CSS-Datei dafür
CSS
Alles anzeigen/* UserStyles Loader Button */ /* weitere Kommentare von Speravir eingefügt */ #usercssloader-menu { /* besser #usercssloader-menu-item */ /* … */ content: '' !important; /* kann entfernt werden */ /* … */ } #usercssloader-menu > .menu-text, #usercssloader-menu > .menu-right { /* .menu-right gibt es nicht mehr */ display: none !important; } #usercssloader-menu:hover { /* besser #usercssloader-menu:hover-item */ /* … */ content: '' !important; /* kann entfernt werden */ /* … */ } /* doppelt: */ #usercssloader-menu > .menu-text, #usercssloader-menu > .menu-right { /* .menu-right gibt es nicht mehr */ display: none !important; } /*… */
Die Eigenschaft content kann jeweils entfernt werden. Ich hielte es auch für besser, das Symbol der ID #usercssloader-menu-item zuzuorden, damit es keine Konflikte mit dem Menü gibt. Die Deklaration zum Ausblenden hast du doppelt eingetragen – einmal reicht, davon kann der Teil mit .menu-right entfernt werden (der erste Teil kann so bleiben, nur Komma entfernen). Beachte meine Kommentare im Stil.
Ich bekam die Windows-Fehlermeldung, dass das System den Pfad "...\CSS\undefined" nicht finden kann.
Das hätte mir sofort zu denken geben müssen. Die Ursache dessen habe ich irgendwann mal eingebaut. Es war wohl von Anfang fehlerhaft, wurde aber stillschweigend ignoriert, jedenfalls funktionierte das, was ich einbaute, so, wie gedacht, wie Du selbst bestätigst. Genau dazu gab es aber in einer der letzten Versionen eine Verhaltensänderung des Fuxes. Ich bin jetzt im Prinzip bei Deiner Lösung gelandet, nachdem ich vergeblich mehrere andere Varianten ausprobiert habe.
Kann man "openFolder" so ergänzen, dass auch im Windows-Explorer die Datei und nicht nur der Ordner angezeigt werden?
Ich wollte erst schreiben, indem man ihn explizit als Dateimanager einträgt, aber ein Test zeigte, dass es mit ihm nicht funktioniert, und zwar überhaupt nicht. Ich bin damit ebenso wie Du überfragt.
JavaScript: UserCSSLoader_2025-08-29
Alles anzeigen// ==UserScript== // @name UserCSSLoader // @description CSS-Codes - Styles laden und verwalten // @namespace http://d.hatena.ne.jp/Griever/ // @author Griever // @include main // @license MIT License // @compatibility Firefox 141+ // @charset UTF-8 // @version 0.0.4r4++ // @note erneute Änderungen von Speravir mit Hilfe von bege, Entfernung von Codeteilen // @note 0.0.4r4 prevent close menu when middleclick // @note Aktualisierungen von BrokenHeart (mit 0.0.4r4 obsolet) und Speravir - www.camp-firefox.de // @note 0.0.4r3 Fx92: getURLSpecFromFile() -> getURLSpecFromActualFile() // @note 0.0.4r2 AUTHOR_SHEET-Unterstützung hinzugefügt, wichtig: Dateiendung muss .author.css sein! // @note Version 0.0.4.g ermöglicht "Styles importieren" per Mittelklick und Verwendung // @note eines anderen Dateimanagers (siehe in Konfiguration), ergänzt um einen // @note Parameter für den Dateimanager, von aborix // @note Frei verschiebbare Schaltfläche eingebaut von aborix // @note 0.0.4 Remove E4X // @note CSS-Entry-Klasse erstellt // @note Style-Test-Funktion überarbeitet // @note Wenn die Datei gelöscht wurde, CSS beim Neu-Erstellen und Löschen des Menüs abbrechen // @note uc einlesen .uc.css temporäre Korrespondenz zum erneuten Lesen // ==/UserScript== /* Endor in https://www.camp-firefox.de/forum/thema/138814/?postID=1277236#post1277236 Speravir in https://www.camp-firefox.de/forum/thema/138814/?postID=1278065#post1278065 */ /****** Bedienungsanleitung ****** CSS-Ordner im Chrome-Ordner erstellen, CSS-Dateien dort ablegen - speichern. Diejenigen, deren Dateiname mit "xul-" beginnen, diejenigen, die mit ".as.css" enden, sind AGENT_SHEET, alle anderen außer USER_SHEET werden gelesen. Da der Inhalt der Datei nicht überprüft wird, darauf achten, die Angabe von @namespace nicht zu vergessen! Schaltfläche wird in Navigationsleiste eingefügt (konfigurierbar, siehe Variable "position"). Linksklick auf Stil, zum Aktivieren/Deaktivieren Mittelklick auf Stil zum Aktivieren/Deaktivieren, ohne Menü zu schließen Rechtsklick auf Stil zum Öffnen im Editor Strg+Linksklick zum Anzeigen im Dateimanager Die Tastenkombinationen können im Menü eingeblendet werden, dazu nach "acceltext" suchen und den Zeilenkommentar "//" entfernen. Verwenden des in "view_source.editor.path" angegebenen Editors. Dateiordner, Dateimanager und Texteditor können in Konfiguration geändert werden. Ein Symbol für die Schaltfläche muss in der "userChrome.css" festgelegt werden, Pfad zum Bild (PNG nur als Beispiel): * relativ zur userChrome.css background-image: url("Relativer/Pfad/zum/CSS_Symbol.png") !important; * eine absolute Pfadangabe zum Symbol muss mit File-Protokoll-Präfix erfolgen: background-image: url("file:///Absoluter/Pfad/zum/CSS_Symbol.png") !important; #usercssloader-menu-item { background-image: url("Relativer/Pfad/zum/CSS_Symbol.png"); background-position: center; background-repeat: no-repeat; background-size: 16px; &:hover { background-color: var(--toolbarbutton-hover-background); } & #usercssloader-menu > .menu-text[value="CSS"] { opacity: 0; width: calc(2 * var(--toolbarbutton-inner-padding) + 16px); height: calc(2 * var(--toolbarbutton-inner-padding) + 16px); } } **** Anleitung Ende ****/ (function(){ /***** Konfiguration *****/ // Position: als frei verschiebbare-Schaltfläche = 0, als Menü anzeigen = 1 let position = 0;//1 /* alternativer Dateimanager, Beispiele: let fileManager = "C:\\Programme\\FreeCommanderXE\\FreeCommander.exe"; let fileManager = "C:\\Programme\\totalcmd\\TOTALCMD.EXE" */ let fileManager = ""; /* eventuelle Parameter für den alternativen Dateimanager; manche Editoren benötigen Parameter nach der Pfadangabe, dann "fileManagerParamPost" auf true setzen */ //let fileManagerParam = "/T";//FreeCommander oder Totalcommander let fileManagerParam = ""; let fileManagerParamPost = false;// beispielsweise FreeCommander benötigt true /* eigener Texteditor mit Pfad - Standard leer, dann wird Wert aus Einstellung "view_source.editor.path" verwendet mit Warnmeldung, wenn auch dieser leer ist */ //let customEditor = "C:\\Windows\\System32\\notepad.exe"; let customEditor = ""; // Unterordner für die CSS-Dateien: let cssFolder = "CSS"; // Menüeintrag zum Bearbeiten der userChrome.css anzeigen (true) oder verstecken (false) let showUserChromeCSS = true; // Menüeintrag zum Bearbeiten der userContent.css anzeigen (true) oder verstecken (false) let showUserContentCSS = true; // zusätzlich Chrome-Ordner im Untermenü anzeigen: 1 = ja, 0 = nein let showChrome = 1; /***** Ende Konfiguration *****/ // Wenn beim Start ein weiteres Fenster (zweites Fenster) vorhanden ist, beenden let list = Services.wm.getEnumerator("navigator:browser"); while(list.hasMoreElements()){ if(list.getNext() != window) return; } if (window.UCL) { window.UCL.destroy(); delete window.UCL; } let menutooltip = "Linksklick: an/aus, Menü schließt\nMittelklick: an/aus, Menü bleibt offen\nRechtsklick: bearbeiten"; if (fileManager !== "") { menutooltip = menutooltip + "\nStrg+Rechtsklick: im Dateimanager anzeigen"; } window.UCL = { AGENT_SHEET : Ci.nsIStyleSheetService.AGENT_SHEET, USER_SHEET : Ci.nsIStyleSheetService.USER_SHEET, AUTHOR_SHEET: Ci.nsIStyleSheetService.AUTHOR_SHEET, readCSS: {}, get disabled_list() { let obj = []; try { obj = decodeURIComponent(this.prefs.getCharPref("disabled_list")).split("|"); } catch(e) {} delete this.disabled_list; return this.disabled_list = obj; }, get prefs() { delete this.prefs; return this.prefs = Services.prefs.getBranch("UserCSSLoader."); }, get styleSheetServices() { delete this.styleSheetServices; return this.styleSheetServices = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); }, get FOLDER() { let aFolder; try { // UserCSSLoader.FOLDER verwenden let folderPath = this.prefs.getCharPref("FOLDER"); aFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); aFolder.initWithPath(folderPath); } catch (e) { aFolder = Services.dirsvc.get("UChrm", Ci.nsIFile); aFolder.appendRelativePath(cssFolder); } if (!aFolder.exists() || !aFolder.isDirectory()) { aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664); } delete this.FOLDER; return this.FOLDER = aFolder; }, get CHRMFOLDER() { let cFolder; try { // UserCSSLoader.CHRMFOLDER verwenden let CHRMfolderPath = this.prefs.getCharPref("CHRMFOLDER"); cFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); cFolder.initWithPath(CHRMfolderPath); } catch (e) { cFolder = Services.dirsvc.get("UChrm", Ci.nsIFile); } if (!cFolder.exists() || !cFolder.isDirectory()) { cFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664); } delete this.CHRMFOLDER; return this.CHRMFOLDER = cFolder; }, init: function() { const cssmenu = $C("menu", { id: "usercssloader-menu", label: "CSS", tooltiptext: "UserCSSLoader\n\nLinksklick: Stylesheets anzeigen\nMittelklick: Styles importieren", accesskey: "Y" }); cssmenu.addEventListener("click", (event) => { if (event.button === 1) UCL.rebuild(); }); const menupopup = $C("menupopup", { id: "usercssloader-menupopup" }); cssmenu.appendChild(menupopup); let menu = $C("menu", { label: "Style-Loader-Menü", id: "style-loader-menu", accesskey: "S", //acceltext: "S" }); menupopup.appendChild(menu); menupopup.appendChild($C("menuseparator")); let mp = $C("menupopup", { id: "usercssloader-submenupopup" }); menu.appendChild(mp); let rebuildItem = $C("menuitem", { label: "Styles importieren", accesskey: "I", //acceltext: "I" }); rebuildItem.addEventListener("command", () => UCL.rebuild()); mp.appendChild(rebuildItem); mp.appendChild($C("menuseparator")); // let createCSS = $C("menuitem", { label: "CSS-Datei erstellen", accesskey: "D", //acceltext: "D" }); createCSS.addEventListener("command", () => UCL.create()); mp.appendChild(createCSS); let openFolder = $C("menuitem", { label: "CSS-Ordner öffnen", accesskey: "O", //acceltext: "O" }); openFolder.addEventListener("command", () => UCL.openCSSFolder()); mp.appendChild(openFolder); if (showChrome === 1) { let openChromeFolder = $C("menuitem", { label: "Chrome-Ordner öffnen", accesskey: "X", //acceltext: "X" }); openChromeFolder.addEventListener("command", () => UCL.openCHRMFolder()); mp.appendChild(openChromeFolder); } if (showUserChromeCSS || showUserContentCSS)// wenigstens eine der beiden Variablen muss … mp.appendChild($C('menuseparator'));// … true sein, damit Trennlinie angezeigt wird if (showUserChromeCSS) { let editChromeItem = $C("menuitem", { label: "userChrome.css bearbeiten" }); editChromeItem.addEventListener("command", () => UCL.editUserCSS("userChrome.css")); mp.appendChild(editChromeItem); } if (showUserContentCSS) { let editContentItem = $C("menuitem", { label: "userContent.css bearbeiten" }); editContentItem.addEventListener("command", () => UCL.editUserCSS("userContent.css")); mp.appendChild(editContentItem); } CustomizableUI.createWidget({ id: 'usercssloader-menu-item', type: 'custom', defaultArea: CustomizableUI.AREA_NAVBAR, onBuild: function(aDocument) { let toolbaritem = aDocument.createXULElement('toolbaritem'); toolbaritem.id = 'usercssloader-menu-item'; toolbaritem.className = 'chromeclass-toolbar-additional'; return toolbaritem; } }); $('usercssloader-menu-item').appendChild(cssmenu); if (position === 1) { let refNode = $('helpMenu'); refNode.parentNode.insertBefore(cssmenu, refNode.nextSibling); } // Stile neu laden, ohne Menü zu öffnen let key = $C("key", { id: "usercssloader-rebuild-key", key: "R", modifiers: "alt", }); key.addEventListener("command", () => UCL.rebuild()); $("mainKeyset").appendChild(key); this.rebuild(); this.initialized = true; window.addEventListener("unload", this, false); }, uninit: function() { const dis = []; for (let x of Object.keys(this.readCSS)) { if (!this.readCSS[x].enabled) dis.push(x); } this.prefs.setCharPref("disabled_list", encodeURIComponent(dis.join("|"))); window.removeEventListener("unload", this, false); }, destroy: function() { var i = document.getElementById("usercssloader-menu"); if (i) i.parentNode.removeChild(i); var i = document.getElementById("usercssloader-rebuild-key"); if (i) i.parentNode.removeChild(i); this.uninit(); }, handleEvent: function(event) { switch(event.type){ case "unload": this.uninit(); break; } }, rebuild: function() { let ext = /\.css$/i; let not = /\.uc\.css/i; let files = this.FOLDER.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator); 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); CSS.flag = true; } for (let leafName of Object.keys(this.readCSS)) { const CSS = this.readCSS[leafName]; if (!CSS.flag) { CSS.enabled = false; delete this.readCSS[leafName]; } delete CSS.flag; this.rebuildMenu(leafName); } if (this.initialized) { if (typeof(StatusPanel) !== "undefined") StatusPanel._label = "Styles importiert"; else XULBrowserWindow.statusTextField.label = "Styles importiert"; } }, loadCSS: function(aFile) { let CSS = this.readCSS[aFile.leafName]; if (!CSS) { CSS = this.readCSS[aFile.leafName] = new CSSEntry(aFile); if (this.disabled_list.indexOf(CSS.leafName) === -1) { CSS.enabled = true; } } else if (CSS.enabled) { CSS.enabled = true; } return CSS; }, rebuildMenu: function(aLeafName) { let CSS = this.readCSS[aLeafName]; let menuitem = document.getElementById("usercssloader-" + aLeafName); if (!CSS) { if (menuitem) menuitem.parentNode.removeChild(menuitem); return; } if (!menuitem) { menuitem = $C("menuitem", { label: aLeafName, id: "usercssloader-" + aLeafName, class: "usercssloader-item " + (CSS.SHEET == this.AGENT_SHEET? "AGENT_SHEET" : CSS.SHEET == this.AUTHOR_SHEET? "AUTHOR_SHEET": "USER_SHEET"), type: "checkbox", autocheck: "false", tooltiptext: menutooltip }); menuitem.addEventListener("command", () => UCL.toggle(aLeafName)); menuitem.addEventListener("click", (event) => UCL.itemClick(event)); menuitem.addEventListener("mouseup", (event) => { if (event.button === 1) event.preventDefault(); }); document.getElementById("usercssloader-menupopup").appendChild(menuitem); } menuitem.setAttribute("checked", CSS.enabled); }, toggle: function(aLeafName) { let CSS = this.readCSS[aLeafName]; if (!CSS || event.ctrlKey) return; CSS.enabled = !CSS.enabled; this.rebuildMenu(aLeafName); }, itemClick: function(event) { let label = event.currentTarget.getAttribute("label"); event.preventDefault(); event.stopPropagation(); if (event.button === 0) { return; } else if (event.button === 1) { this.toggle(label); } else if (event.button === 2) { if (event.ctrlKey) { UCL.openFile(label); } else { closeMenus(event.target); this.edit(this.getFileFromLeafName(label)); } } }, getFileFromLeafName: function(aLeafName) { let f = this.FOLDER.clone(); f.QueryInterface(Ci.nsIFile); // use appendRelativePath f.appendRelativePath(aLeafName); return f; }, openFile: function(fname) { if (fileManager.length !== 0) { let target= this.FOLDER.path + "/" + fname; let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess); let args = (!fileManagerParamPost) ? [fileManagerParam,target,] : [target,fileManagerParam]; file.initWithPath(fileManager); process.init(file); // Verzeichnis mit anderem Dateimanager öffnen process.run(false, args, args.length); } else { // Verzeichnis mit Dateimanager des Systems öffnen this.FOLDER.launch(); } }, openCSSFolder:function(){ if (fileManager.length !== 0) { let target = this.FOLDER.path; let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess); let args = (!fileManagerParamPost) ? [fileManagerParam,target,] : [target,fileManagerParam]; file.initWithPath(fileManager); process.init(file); // Verzeichnis mit anderem Dateimanager öffnen process.run(false, args, args.length); } else { // Verzeichnis mit Dateimanager des Systems öffnen this.FOLDER.launch(); } }, openCHRMFolder:function(){ if (fileManager.length !== 0) { let target = this.CHRMFOLDER.path; let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess); let args = (!fileManagerParamPost) ? [fileManagerParam,target,] : [target,fileManagerParam]; file.initWithPath(fileManager); process.init(file); // Verzeichnis mit anderem Dateimanager öffnen process.run(false, args, args.length); } else { // Verzeichnis mit Dateimanager des Systems öffnen this.CHRMFOLDER.launch(); } }, editUserCSS: function(aLeafName) { let file = Services.dirsvc.get("UChrm", Ci.nsIFile); file.appendRelativePath(aLeafName); this.edit(file); }, edit: function(aFile) { let editor = (customEditor !== "") ? customEditor : Services.prefs.getCharPref("view_source.editor.path"); if (!editor) return alert('In der Konfiguration einen Texteditor festlegen ("customEditor") oder\n unter about:config im vorhandenen Schalter "view_source.editor.path"\n den vollständigen Editorpfad eintragen.'); try { let UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter); UI.charset = window.navigator.platform.toLowerCase().indexOf("win") >= 0? "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) {} }, create: function(aLeafName) { if (!aLeafName) aLeafName = prompt("Name des Styles", dateFormat(new Date(), "%Y_%m%d_%H%M%S")); if (aLeafName) aLeafName = aLeafName.replace(/\s+/g, " ").replace(/[\\/:*?\"<>|]/g, ""); if (!aLeafName || !/\S/.test(aLeafName)) return; if (!/\.css$/.test(aLeafName)) aLeafName += ".css"; let file = this.getFileFromLeafName(aLeafName); this.edit(file); }, UCrebuild: function() { let re = /^file:.*\.uc\.css(?:\?\d+)?$/i; let query = "?" + new Date().getTime(); Array.slice(document.styleSheets).forEach(function(css){ if (!re.test(css.href)) return; if (css.ownerNode) { css.ownerNode.parentNode.removeChild(css.ownerNode); } let pi = document.createProcessingInstruction('xml-stylesheet','type="text/css" href="'+ css.href.replace(/\?.*/, '') + query +'"'); document.insertBefore(pi, document.documentElement); }); UCL.UCcreateMenuitem(); }, UCcreateMenuitem: function() { let sep = $("usercssloader-ucseparator"); let popup = sep.parentNode; if (sep.nextSibling) { let range = document.createRange(); range.setStartAfter(sep); range.setEndAfter(popup.lastChild); range.deleteContents(); range.detach(); } let re = /^file:.*\.uc\.css(?:\?\d+)?$/i; Array.slice(document.styleSheets).forEach(function(css) { if (!re.test(css.href)) return; let fileURL = decodeURIComponent(css.href).split("?")[0]; let aLeafName = fileURL.split("/").pop(); let m = $C("menuitem", { label: aLeafName, tooltiptext: fileURL, id: "usercssloader-" + aLeafName, type: "checkbox", autocheck: "false", checked: "true", }); m.css = css; m.addEventListener("command", function() { if (!event.ctrlKey) {this.setAttribute("checked", !(this.css.disabled = !this.css.disabled));} }); m.addEventListener("mouseup", function(event) { if (event.button === 1) event.preventDefault(); }); m.addEventListener("click", function(event) { UCL.UCItemClick(event); }); popup.appendChild(m); }); }, UCItemClick: function(event) { if (event.button === 0) return; event.preventDefault(); event.stopPropagation(); if (event.button === 1) { event.target.doCommand(); } else if (event.button === 2) { closeMenus(event.target); let fileURL = event.currentTarget.getAttribute("tooltiptext"); let file = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getFileFromURLSpec(fileURL); this.edit(file); } }, }; 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(); // true, wenn die Datei bereits existiert let lastModifiedTime = isExists ? aFile.lastModifiedTime : 0; let isForced = this.lastModifiedTime != lastModifiedTime; //true, wenn es eine Änderung in der Datei gibt 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)) { // Wenn diese Datei bereits gelesen wurde if (!isEnable || !isExists) { this.sss.unregisterSheet(uri, this.SHEET); } else if (isForced) { // Nach Stornierung erneut einlesen this.sss.unregisterSheet(uri, this.SHEET); this.sss.loadAndRegisterSheet(uri, this.SHEET); } } else { // Datei wurde nicht gelesen if (isEnable && isExists) { this.sss.loadAndRegisterSheet(uri, this.SHEET); } } if (this.lastModifiedTime !== 1 && isEnable && isForced) { log(this.leafName + " wurde aktualisiert"); } this.lastModifiedTime = lastModifiedTime; return this._enabled = isEnable; }, }; UCL.init(); function $(id) { return document.getElementById(id); } function $A(arr) { return Array.slice(arr); } function $C(name, attr) { const el = document.createXULElement(name); if (attr) Object.keys(attr).forEach(function(n) { el.setAttribute(n, attr[n]) }); return el; } function dateFormat(date, format) { format = format.replace("%Y", ("000" + date.getFullYear()).substr(-4)); format = format.replace("%m", ("0" + (date.getMonth()+1)).substr(-2)); format = format.replace("%d", ("0" + date.getDate()).substr(-2)); format = format.replace("%H", ("0" + date.getHours()).substr(-2)); format = format.replace("%M", ("0" + date.getMinutes()).substr(-2)); format = format.replace("%S", ("0" + date.getSeconds()).substr(-2)); return format; } function log(mes) { console.log(mes); } })();
-
Mir ist heute nicht nach Grübeln, deshalb kurz:
Der Code ist für die UserCSSLoader.css um dem Menü eine Grafik zu verpassen!
Ja, aber nur, wenn er als Schaltfläche eingefügt ist.
Welchen Wert muss ich in der CSS Datei für User Styles Button aus #28 ändern, damit er mittig in der Leiste angezeigt wird.
Teste mal meinen viel kürzeren Stil aus #53.
Kann man den "überflüssigen" Code dann nicht entfernen?
Denn ich habe es nachgestellt, und es tut sich auch bei mir nichts!Ich denke, das werde ich tun. Und danke für die Bestätigung.
Ich meinte C für die Schaltfläche bzw. das Menü in der Menüleiste. Also "CSS" statt "CSS (Y)".
Alt+C ist in einem deutschsprachigen Firefox schon für die Chronik vergeben und Alt+S geht auch nicht, was mir erst kürzlich auffiel (oder erst seit jüngeren Versionen so ist).
-
(#addonbar #usercssloader-menu), so dass dort kein Konflikt entsteht (ich sehe gerade, dass Teile des Stil nicht mehr wirken, aber .menu-text[value="CSS"] gibt’s noch). Ich habe es selber noch nicht ausprobiert, aber man könnte vermutlich das Symbol auch dem übergeordneten Toolbaritem mit der ID #usercssloader-menu-item zuordnen.
Ich hab das nun so geändert:
CSS#usercssloader-menu-item { background-image: url("./images/CSS.png") !important; background-position: center !important; background-repeat: no-repeat !important; background-size: 16px !important; & #usercssloader-menu > .menu-text[value="CSS"] { opacity: 0 !important } }
(Das & könnte hier auch weggelassen werden, hilft mir aber zu erkennen, dass dort quasi noch etwas davor steht.)
Frei festlegbarer Texteditor:
Funktioniert!
let editor = 'C:\\Windows\\System32\\notepad.exe'; und z.B. userChrome.css wird in Notepad geöffnet.
Bitte nicht umbauen. Ich finde das genial und nutze es seit Jahr und Tag. Das wird bei mir in zwei weiteren Skripten verwendet (extras_config_menu und AppMenu) und so muss ich das nicht in jedem Skript, wo der Editor gebraucht wird, einbauen.
Ist dann wohl eine "Geschmacksfrage"! Denn ich würde es viel lieber in einem Skript definieren, als Hand an Firefoxinterna anzulegen.
Mir kam gestern bereits während des Schreibens eine Idee, die ich auch umgesetzt habe. Man findet jetzt Folgendes in der Konfiguration (und entsprechend angepassten Code):
JavaScript/* eigener Texteditor mit Pfad - Standard leer, dann wird Wert aus Einstellung "view_source.editor.path" verwendet mit Warnmeldung, wenn auch dieser leer ist */ //let customEditor = "C:\\Windows\\System32\\notepad.exe"; let customEditor = "";
Damit sollten beide Positionen zufrieden gestellt sein.
Mal blöd gefragt.
Am welcher Stelle soll den DAS im Menü auftauchen?Nee, nicht blöd. Das ist ein Punkt, der mir selbst nicht klar ist. Das Menü wird angezeigt, wenn sich effektiv hidden: false ergibt – an der Stelle muss also UCL.USE_UC true sein und heißt, wenn "UC" in window true ist. Du kannst ja mal explizit auf false setzen, dann erscheint das Menü, aber das tut bei mir nichts. Dann dachte ich, ich ändere eine CSS zu .uc.css und habe in dieser Testcode eingebaut, aber er wurde nicht aktiviert.
Tastaturkürzel zum Importieren von Stilen funktioniert nur mit Alt+R.
Bei Alt+I tut sich nichts.Alt+R in jedem beliebigen Fenster (ist übrigens risikoreich, die Kombi könnte anderweitig benutzt werden), wenn der Loader als Symbol eingefügt wird. Aber I (ohne Alt) ist doch nur für den Untermenüpunkt festgelegt und das funktioniert auch.
Alt+R wird andernorts als key definiert. Dafür braucht es keinen Eventlistener. Wenn ich den in deiner neuen Version auskommentiere, funktioniert es trotzdem.
Oh, tatsächlich!
Warum dann nicht "C" als accelkey für Schaltfläche/Menü und z.B. "M" bei "Chrome-Ordner öffnen"?
Zweimal C fand ich nicht eindeutig (CSS/Chrome), aber zugegebenermaßen gibt’s Ordner auch zweimal. X halte ich für mnemotechnisch besser als M, das mitten in Chrome steht, zumal es direkt vorher dazu gedrückt werden muss, um das Untermenü aufzuklappen; das birgt die Gefahr des doppelten Tastendrucks. Das könnte man aber zu S ändern, war schon mal so, wenn ich mich nicht irre. Es können sich ja gern mal andere Nutzer dazu melden (für mich selber deaktiviere ich die Kurztasten).
Den Rest muss ich mir nochmal genauer zu Gemüte führen, da steht mir gerade irgendjemand auf dem Schlauch oder so ähnlich, nur eines:
Mich wundert eher, warum es mit dem Windows-Explorer nicht auch eine Fehlermeldung gibt,
Der Windows-Explorer wird ja aufgerufen, wenn kein anderer Dateimanager festgelegt wurde und das ist dann der Else-Zweig, der nur aus this.FOLDER.launch(); besteht.
JavaScript: UserCSSLoader_2025-08-25
Alles anzeigen// ==UserScript== // @name UserCSSLoader // @description CSS-Codes - Styles laden und verwalten // @namespace http://d.hatena.ne.jp/Griever/ // @author Griever // @include main // @license MIT License // @compatibility Firefox 141+ // @charset UTF-8 // @version 0.0.4r4 // @note 0.0.4r4 prevent close menu when middleclick // @note Aktualisierungen von BrokenHeart (mit 0.0.4r4 obsolet) und Speravir - www.camp-firefox.de // @note 0.0.4r3 Fx92: getURLSpecFromFile() -> getURLSpecFromActualFile() // @note 0.0.4r2 AUTHOR_SHEET-Unterstützung hinzugefügt, wichtig: Dateiendung muss .author.css sein! // @note Version 0.0.4.g ermöglicht "Styles importieren" per Mittelklick und Verwendung // @note eines anderen Dateimanagers (siehe in Konfiguration), ergänzt um einen // @note Parameter für den Dateimanager (vFMParameter in der Konfiguration) von aborix // @note Frei verschiebbare Schaltfläche eingebaut von aborix // @note 0.0.4 Remove E4X // @note CSS-Entry-Klasse erstellt // @note Style-Test-Funktion überarbeitet // @note Wenn die Datei gelöscht wurde, CSS beim Neu-Erstellen und Löschen des Menüs abbrechen // @note uc einlesen .uc.css temporäre Korrespondenz zum erneuten Lesen // ==/UserScript== /* Endor in https://www.camp-firefox.de/forum/thema/112673/?postID=1277236#post1277236 */ /****** Bedienungsanleitung ****** CSS-Ordner im Chrome-Ordner erstellen, CSS-Dateien dort ablegen - speichern. Diejenigen, deren Dateiname mit "xul-" beginnen, diejenigen, die mit ".as.css" enden, sind AGENT_SHEET, alle anderen außer USER_SHEET werden gelesen. Da der Inhalt der Datei nicht überprüft wird, darauf achten, die Angabe von @namespace nicht zu vergessen! Schaltfläche wird in Navigationsleiste eingefügt (konfigurierbar, siehe Variable "position"). Linksklick auf Stil, zum Aktivieren/Deaktivieren Mittelklick auf Stil zum Aktivieren/Deaktivieren, ohne Menü zu schließen Rechtsklick auf Stil zum Öffnen im Editor Strg+Linksklick zum Anzeigen im Dateimanager Die Tastenkombinationen können im Menü eingeblendet werden, dazu nach "acceltext" suchen und den Zeilenkommentar "//" entfernen bzw. einfügen. Verwenden des in "view_source.editor.path" angegebenen Editors. Dateiordner, Dateimanager und Texteditor können in Konfiguration geändert werden. Ein Symbol für die Schaltfläche muss in der "userChrome.css" festgelegt werden: #usercssloader-menu-item { background-image: url("Pfad/zu/Symbol_CSS.png") !important; background-position: center !important; background-repeat: no-repeat !important; background-size: 16px !important; & #usercssloader-menu > .menu-text[value="CSS"] { opacity: 0 !important } } **** Anleitung Ende ****/ (function(){ /***** Konfiguration *****/ // Position: als frei verschiebbare-Schaltfläche = 0, als Menü anzeigen = 1 let position = 0;//1 // alternativer Dateimanager, Bsp.: //let filemanager = "C:\\Programme\\totalcmd\\TOTALCMD.EXE"; let filemanager = ""; // eventuelle Parameter für den alternativen Dateimanager, sonst filemanagerParam = ""; //let filemanagerParam = "/O /T";//Totalcommander let filemanagerParam = ""; /* eigener Texteditor mit Pfad - Standard leer, dann wird Wert aus Einstellung "view_source.editor.path" verwendet mit Warnmeldung, wenn auch dieser leer ist */ //let customEditor = "C:\\Windows\\System32\\notepad.exe"; let customEditor = ""; // Unterordner für die CSS-Dateien: let cssFolder = "CSS"; // Menüeintrag zum Bearbeiten der userChrome.css verstecken (true) oder anzeigen (false) let hideUserChromeCSS = false; // Menüeintrag zum Bearbeiten der userContent.css verstecken (true) oder anzeigen (false) let hideUserContentCSS = false; // zusätzlich Chrome-Ordner im Untermenü anzeigen: 1 = ja, 0 = nein let showChrome = 1; /***** Ende Konfiguration *****/ ChromeUtils.importESModule("resource://gre/modules/AppConstants.sys.mjs"); // Wenn beim Start ein weiteres Fenster (zweites Fenster) vorhanden ist, beenden let list = Services.wm.getEnumerator("navigator:browser"); while(list.hasMoreElements()){ if(list.getNext() != window) return; } if (window.UCL) { window.UCL.destroy(); delete window.UCL; } window.UCL = { vFileManager: filemanager, vFMParameter: filemanagerParam, USE_UC: "UC" in window, AGENT_SHEET : Ci.nsIStyleSheetService.AGENT_SHEET, USER_SHEET : Ci.nsIStyleSheetService.USER_SHEET, AUTHOR_SHEET: Ci.nsIStyleSheetService.AUTHOR_SHEET, readCSS: {}, get disabled_list() { let obj = []; try { obj = decodeURIComponent(this.prefs.getCharPref("disabled_list")).split("|"); } catch(e) {} delete this.disabled_list; return this.disabled_list = obj; }, get prefs() { delete this.prefs; return this.prefs = Services.prefs.getBranch("UserCSSLoader."); }, get styleSheetServices(){ delete this.styleSheetServices; return this.styleSheetServices = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); }, get FOLDER() { let aFolder; try { // UserCSSLoader.FOLDER verwenden let folderPath = this.prefs.getCharPref("FOLDER"); aFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); aFolder.initWithPath(folderPath); } catch (e) { aFolder = Services.dirsvc.get("UChrm", Ci.nsIFile); aFolder.appendRelativePath(cssFolder); } if (!aFolder.exists() || !aFolder.isDirectory()) { aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664); } delete this.FOLDER; return this.FOLDER = aFolder; }, get CHRMFOLDER() { let bFolder; try { // UserCSSLoader.CHRMFOLDER verwenden let CHRMfolderPath = this.prefs.getCharPref("CHRMFOLDER"); bFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); bFolder.initWithPath(CHRMfolderPath); } catch (e) { bFolder = Services.dirsvc.get("UChrm", Ci.nsIFile); } if (!bFolder.exists() || !bFolder.isDirectory()) { bFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664); } delete this.CHRMFOLDER; return this.CHRMFOLDER = bFolder; }, getFocusedWindow: function() { let win = document.commandDispatcher.focusedWindow; if (!win || win == window) win = content; return win; }, init: function() { const cssmenu = $C("menu", { id: "usercssloader-menu", label: "CSS", tooltiptext: "UserCSSLoader\n\nLinksklick: Stylesheets anzeigen\nMittelklick: Styles importieren", accesskey: "Y" }); // cssmenu.addEventListener("command", () => UCL.rebuild()); cssmenu.addEventListener("click", (event) => { if (event.button === 1) UCL.rebuild(); }); const menupopup = $C("menupopup", { id: "usercssloader-menupopup" }); cssmenu.appendChild(menupopup); let menu = $C("menu", { label: "Style-Loader-Menü", id: "style-loader-menu", accesskey: "M", //acceltext: "M" }); menupopup.appendChild(menu); menupopup.appendChild($C("menuseparator")); let mp = $C("menupopup", { id: "usercssloader-submenupopup" }); menu.appendChild(mp); let rebuildItem = $C("menuitem", { label: "Styles importieren", accesskey: "I", //acceltext: "I" }); rebuildItem.addEventListener("command", () => UCL.rebuild()); mp.appendChild(rebuildItem); mp.appendChild($C("menuseparator")); let createCSS = $C("menuitem", { label: "CSS-Datei erstellen", accesskey: "E", //acceltext: "E" }); createCSS.addEventListener("command", () => UCL.create()); mp.appendChild(createCSS); let openFolder = $C("menuitem", { label: "CSS-Ordner öffnen", accesskey: "O", //acceltext: "O" }); openFolder.addEventListener("command", () => UCL.openFolder()); mp.appendChild(openFolder); if (showChrome === 1) { let openChromeFolder = $C("menuitem", { label: "Chrome-Ordner öffnen", accesskey: "X", //acceltext: "X" }); openChromeFolder.addEventListener("command", () => UCL.openCHRMFolder()); mp.appendChild(openChromeFolder); } mp.appendChild($C('menuseparator')); let editChromeItem = $C("menuitem", { label: "userChrome.css bearbeiten", hidden: hideUserChromeCSS, }); editChromeItem.addEventListener("command", () => UCL.editUserCSS("userChrome.css")); mp.appendChild(editChromeItem); let editContentItem = $C("menuitem", { label: "userContent.css bearbeiten", hidden: hideUserContentCSS, }); editContentItem.addEventListener("command", () => UCL.editUserCSS("userContent.css")); mp.appendChild(editContentItem); menu = $C("menu", { label: ".uc.css", accesskey: "U", //acceltext: "U", hidden: !UCL.USE_UC }); menupopup.appendChild(menu); mp = $C("menupopup", { id: "usercssloader-ucmenupopup" }); menu.appendChild(mp); let UCrebuild = $C("menuitem", { label: "Importieren (.uc.css)", }); UCrebuild.addEventListener("command", () => UCL.UCrebuild()); mp.appendChild(UCrebuild); mp.appendChild($C("menuseparator", { id: "usercssloader-ucseparator" })); CustomizableUI.createWidget({ id: 'usercssloader-menu-item', type: 'custom', defaultArea: CustomizableUI.AREA_NAVBAR, onBuild: function(aDocument) { let toolbaritem = aDocument.createXULElement('toolbaritem'); toolbaritem.id = 'usercssloader-menu-item'; toolbaritem.className = 'chromeclass-toolbar-additional'; return toolbaritem; } }); $('usercssloader-menu-item').appendChild(cssmenu); if (position === 1) { let refNode = $('helpMenu'); refNode.parentNode.insertBefore(cssmenu, refNode.nextSibling); } let key = $C("key", { id: "usercssloader-rebuild-key", key: "R", modifiers: "alt", }); key.addEventListener("command", () => UCL.rebuild()); $("mainKeyset").appendChild(key); this.rebuild(); this.initialized = true; if (UCL.USE_UC) { setTimeout(function() { UCL.UCcreateMenuitem(); }, 1000); } window.addEventListener("unload", this, false); }, uninit: function() { const dis = []; for (let x of Object.keys(this.readCSS)) { if (!this.readCSS[x].enabled) dis.push(x); } this.prefs.setCharPref("disabled_list", encodeURIComponent(dis.join("|"))); window.removeEventListener("unload", this, false); }, destroy: function() { var i = document.getElementById("usercssloader-menu"); if (i) i.parentNode.removeChild(i); var i = document.getElementById("usercssloader-rebuild-key"); if (i) i.parentNode.removeChild(i); this.uninit(); }, handleEvent: function(event) { switch(event.type){ case "unload": this.uninit(); break; } }, rebuild: function() { let ext = /\.css$/i; let not = /\.uc\.css/i; let files = this.FOLDER.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator); 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); CSS.flag = true; } for (let leafName of Object.keys(this.readCSS)) { const CSS = this.readCSS[leafName]; if (!CSS.flag) { CSS.enabled = false; delete this.readCSS[leafName]; } delete CSS.flag; this.rebuildMenu(leafName); } if (this.initialized) { if (typeof(StatusPanel) !== "undefined") StatusPanel._label = "Styles importiert"; else XULBrowserWindow.statusTextField.label = "Styles importiert"; } }, loadCSS: function(aFile) { let CSS = this.readCSS[aFile.leafName]; if (!CSS) { CSS = this.readCSS[aFile.leafName] = new CSSEntry(aFile); if (this.disabled_list.indexOf(CSS.leafName) === -1) { CSS.enabled = true; } } else if (CSS.enabled) { CSS.enabled = true; } return CSS; }, rebuildMenu: function(aLeafName) { let CSS = this.readCSS[aLeafName]; let menuitem = document.getElementById("usercssloader-" + aLeafName); if (!CSS) { if (menuitem) menuitem.parentNode.removeChild(menuitem); return; } if (!menuitem) { menuitem = $C("menuitem", { label: aLeafName, id: "usercssloader-" + aLeafName, class: "usercssloader-item " + (CSS.SHEET == this.AGENT_SHEET? "AGENT_SHEET" : CSS.SHEET == this.AUTHOR_SHEET? "AUTHOR_SHEET": "USER_SHEET"), type: "checkbox", autocheck: "false", tooltiptext: "Linksklick: an/aus, Menü schließt\nMittelklick: an/aus, Menü bleibt offen\nRechtsklick: bearbeiten\nStrg+Rechtsklick: im Dateimanager anzeigen" }); menuitem.addEventListener("command", () => UCL.toggle(aLeafName)); menuitem.addEventListener("click", (event) => UCL.itemClick(event)); menuitem.addEventListener("mouseup", (event) => { if (event.button === 1) event.preventDefault(); }); document.getElementById("usercssloader-menupopup").appendChild(menuitem); } menuitem.setAttribute("checked", CSS.enabled); }, toggle: function(aLeafName) { let CSS = this.readCSS[aLeafName]; if (!CSS || event.ctrlKey) return; CSS.enabled = !CSS.enabled; this.rebuildMenu(aLeafName); }, itemClick: function(event) { let label = event.currentTarget.getAttribute("label"); event.preventDefault(); event.stopPropagation(); if (event.button === 0) { return; } else if (event.button === 1) { this.toggle(label); } else if (event.button === 2) { if (event.ctrlKey) { UCL.openFolder(label); } else { closeMenus(event.target); this.edit(this.getFileFromLeafName(label)); } } }, getFileFromLeafName: function(aLeafName) { let f = this.FOLDER.clone(); f.QueryInterface(Ci.nsIFile); // use appendRelativePath f.appendRelativePath(aLeafName); return f; }, openFolder: function(label) { const PathSep = AppConstants.platform === "win" ? "\\" : "/"; let target= this.FOLDER.path + PathSep + label; if (this.vFileManager.length !== 0) { let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess); let args = [this.vFMParameter,target]; file.initWithPath(this.vFileManager); process.init(file); // Verzeichnis mit anderem Dateimanager öffnen process.run(false, args, args.length); } else { // Verzeichnis mit Dateimanager des Systems öffnen this.FOLDER.launch(); } }, openCHRMFolder:function(){ if (this.vFileManager.length !== 0) { let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess); let args = [this.vFMParameter,this.CHRMFOLDER.path]; file.initWithPath(this.vFileManager); process.init(file); // Verzeichnis mit anderem Dateimanager öffnen process.run(false, args, args.length); } else { // Verzeichnis mit Dateimanager des Systems öffnen this.CHRMFOLDER.launch(); } }, editUserCSS: function(aLeafName) { let file = Services.dirsvc.get("UChrm", Ci.nsIFile); file.appendRelativePath(aLeafName); this.edit(file); }, edit: function(aFile) { let editor = (customEditor !== "") ? customEditor : Services.prefs.getCharPref("view_source.editor.path"); if (!editor) return alert('In der Konfiguration einen Texteditor festlegen ("customEditor") oder\n unter about:config im vorhandenen Schalter "view_source.editor.path"\n den vollständigen Editorpfad eintragen.'); try { let UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter); UI.charset = window.navigator.platform.toLowerCase().indexOf("win") >= 0? "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) {} }, create: function(aLeafName) { if (!aLeafName) aLeafName = prompt("Name des Styles", dateFormat(new Date(), "%Y_%m%d_%H%M%S")); if (aLeafName) aLeafName = aLeafName.replace(/\s+/g, " ").replace(/[\\/:*?\"<>|]/g, ""); if (!aLeafName || !/\S/.test(aLeafName)) return; if (!/\.css$/.test(aLeafName)) aLeafName += ".css"; let file = this.getFileFromLeafName(aLeafName); this.edit(file); }, UCrebuild: function() { let re = /^file:.*\.uc\.css(?:\?\d+)?$/i; let query = "?" + new Date().getTime(); Array.slice(document.styleSheets).forEach(function(css){ if (!re.test(css.href)) return; if (css.ownerNode) { css.ownerNode.parentNode.removeChild(css.ownerNode); } let pi = document.createProcessingInstruction('xml-stylesheet','type="text/css" href="'+ css.href.replace(/\?.*/, '') + query +'"'); document.insertBefore(pi, document.documentElement); }); UCL.UCcreateMenuitem(); }, UCcreateMenuitem: function() { let sep = $("usercssloader-ucseparator"); let popup = sep.parentNode; if (sep.nextSibling) { let range = document.createRange(); range.setStartAfter(sep); range.setEndAfter(popup.lastChild); range.deleteContents(); range.detach(); } let re = /^file:.*\.uc\.css(?:\?\d+)?$/i; Array.slice(document.styleSheets).forEach(function(css) { if (!re.test(css.href)) return; let fileURL = decodeURIComponent(css.href).split("?")[0]; let aLeafName = fileURL.split("/").pop(); let m = $C("menuitem", { label: aLeafName, tooltiptext: fileURL, id: "usercssloader-" + aLeafName, type: "checkbox", autocheck: "false", checked: "true", }); m.css = css; m.addEventListener("command", function() { if (!event.ctrlKey) {this.setAttribute("checked", !(this.css.disabled = !this.css.disabled));} }); m.addEventListener("mouseup", function(event) { if (event.button === 1) event.preventDefault(); }); m.addEventListener("click", function(event) { UCL.UCItemClick(event); }); popup.appendChild(m); }); }, UCItemClick: function(event) { if (event.button === 0) return; event.preventDefault(); event.stopPropagation(); if (event.button === 1) { event.target.doCommand(); } else if (event.button === 2) { closeMenus(event.target); let fileURL = event.currentTarget.getAttribute("tooltiptext"); let file = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getFileFromURLSpec(fileURL); this.edit(file); } }, }; 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(); // true, wenn die Datei bereits existiert let lastModifiedTime = isExists ? aFile.lastModifiedTime : 0; let isForced = this.lastModifiedTime != lastModifiedTime; //true, wenn es eine Änderung in der Datei gibt 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)) { // Wenn diese Datei bereits gelesen wurde if (!isEnable || !isExists) { this.sss.unregisterSheet(uri, this.SHEET); } else if (isForced) { // Nach Stornierung erneut einlesen this.sss.unregisterSheet(uri, this.SHEET); this.sss.loadAndRegisterSheet(uri, this.SHEET); } } else { // Datei wurde nicht gelesen if (isEnable && isExists) { this.sss.loadAndRegisterSheet(uri, this.SHEET); } } if (this.lastModifiedTime !== 1 && isEnable && isForced) { log(this.leafName + " wurde aktualisiert"); } this.lastModifiedTime = lastModifiedTime; return this._enabled = isEnable; }, }; UCL.init(); function $(id) { return document.getElementById(id); } function $A(arr) { return Array.slice(arr); } function $C(name, attr) { const el = document.createXULElement(name); if (attr) Object.keys(attr).forEach(function(n) { el.setAttribute(n, attr[n]) }); return el; } function dateFormat(date, format) { format = format.replace("%Y", ("000" + date.getFullYear()).substr(-4)); format = format.replace("%m", ("0" + (date.getMonth()+1)).substr(-2)); format = format.replace("%d", ("0" + date.getDate()).substr(-2)); format = format.replace("%H", ("0" + date.getHours()).substr(-2)); format = format.replace("%M", ("0" + date.getMinutes()).substr(-2)); format = format.replace("%S", ("0" + date.getSeconds()).substr(-2)); return format; } function log(mes) { console.log(mes); } })();
-
in unserem Original konnte man auch mit
Mittelklick auf die Schaltfläche die Stile importieren. Das geht weder
bei der von mir noch bei Deiner Version.Bei der Version RE: UserCSSLoader (2025) von Speravir (danke für die "Runderneuerung"!) habe ich die Zeile 155 entsprechend der letzten Version im Github von Endor angepasst. Damit funktioniert das Laden der Styles mit Mittelklick wieder.
Ein ärgerlicher Unaufmerksamkeitsfehler war das von mir.
bege: Ich hab deine Version nicht ausprobiert, aber mit einem Click-Event dürfte die vergebene Tastenkombi Alt+R nicht mehr funktionieren. Ich hab deshalb einen Click- und einen Command-Eventlistener eingefügt.
In der Konfiguration position = 0 zu 1 ändern. Ich hatte das bei mir getestet und da hat es funktioniert.
Das hatte ich gar nicht gemeint!
Sondern =>[…]
Das wäre das Menü "CSS", bzw. der Menüeintrag, der in der Menüleiste erzeugt werden sollte!
Wird er aber nicht und ich weiß nicht, was an dem entsprechenden Code, der diesen erzeugen soll,
kaputt ist, denn offensichtlich wird dieses Menü, bzw. der Eintrag "CSS", gar nicht erzeugt.Wie gesagt, bei mir funktioniert das genau so.
Verwendest Du den CSS Code für die Symbolleistenschaltfläche?
Den muss du deaktivieren dann steht CSS an der Stelle.Nöö, ich muss den Stilcode (siehe erstes Posting) nicht deaktivieren – aber das könnte daran liegen, dass das Symbol bei mir in einer separaten Addonbar liegt und ich das im Stil berücksichtige (#addonbar #usercssloader-menu), so dass dort kein Konflikt entsteht (ich sehe gerade, dass Teile des Stil nicht mehr wirken, aber .menu-text[value="CSS"] gibt’s noch). Ich habe es selber noch nicht ausprobiert, aber man könnte vermutlich das Symbol auch dem übergeordneten Toolbaritem mit der ID #usercssloader-menu-item zuordnen. Wäre nett, wenn ihr das mal testet.
Was ich am Skript aber generell doof finde, dass der Editor im Firefox hinterlegt werden muss!
Wäre es nicht besser es gäbe da eine Variabel im Skript dafür,
so wie der Dateimanager da definiert wird?Such mal nach let editor = Services.prefs.getCharPref("view_source.editor.path"); und ersetze alles nach dem Gleichheitszeichen mit dem Pfad zu einem Editor (Anführungszeichen und Semikolon nicht vergessen), Wenn es funktioniert, sollte man das tatsächlich umbauen können (sollte eigentlich gehen).
Und auch mit const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; komme ich nicht so wirklich zurecht,
Das ist übrigens einfach nur eine Konstante. Sie hätte auch Namensraum_Definition heißen können oder Just_Another_Constant_with_XUL_in_its_name_to_confuse_Mira_Belle. Die wurde an nur einer einzige Stelle verwendet, an einer zweiten, wo die Adresse ebenso vorkam, nicht. Hab ich aber alles vereinheitlicht und die Konstante entfernt.
Bei den acceltext muss jeweils das "Alt + " weg. Der Shortcut ist nur der Buchstabe ohne Alt-Taste.
Weiß jemand, warum der Shortcut (X) für das Öffnen des Chrome-Ordners auch dann angezeigt wird, wenn acceltext auskommentiert ist, bei den anderen Einträgen aber nicht?Upps, danke für den Hinweis zur überflüssigen Alt-Taste. Das X wird angezeigt, weil es im als Label definierten Text nicht vorkommt, dasselbe jetzt, wenn Du dir den Loader als Menü anzeigen lässt (sowohl Alt+C als auch Alt+S sind schon vergeben, an der Stelle benötigt man die Alt-Taste).
Schon mit Endors Version hat seit kurzem komischer Weise das Öffnen des CSS-Ordners mit meinem alternativen Dateimanager nicht mehr funktioniert. Ich kann nicht sagen, wann das begonnen hat, mit Fx 135 ging es auf jeden Fall noch. Ich bekam die Windows-Fehlermeldung, dass das System den Pfad "...\CSS\undefined" nicht finden kann.
Das ist, denke ich, was ich oben mit „Wenn ich mich aber recht erinnere, ging schon beim letzten Mal die Sache mit den Dateimanagerparametern nicht“ meinte. Mir fällt gerade ein, dass ich vergessen habe, was zu testen. In Deiner Version macht STRG+Rechtsklick nicht mehr nicht mehr das, was es tun soll. Und wenn Du bei dir in Zeile 369 noch openFolder durch openCSSFolder ersetztest, könntest Du das gesamte openFolder-Objekt entfernen, weil es dann gar nicht mehr aufgerufen würde.
Sobald du das OK gibst lade ich die dann bei mir hoch.
Wie erkennbar, sehe ich schon noch Verbesserungspotential. Man sollte anscheinend auch mindestens einen Hinweis zum Symbol in das Skript einfügen, oder? Wie mir beim Schreiben auffiel, sollte ich selbst noch einiges testen, ich hänge aber mal meine aktuelle Skriptversion an:
JavaScript: UserCSSÖoader_2025-08-23
Alles anzeigen// ==UserScript== // @name UserCSSLoader // @description CSS-Codes - Styles laden und verwalten // @namespace http://d.hatena.ne.jp/Griever/ // @author Griever // @include main // @license MIT License // @compatibility Firefox 141+ // @charset UTF-8 // @version 0.0.4r4 // @note 0.0.4r4 prevent close menu when middleclick // @note Aktualisierungen von BrokenHeart (mit 0.0.4r4 obsolet) und Speravir - www.camp-firefox.de // @note 0.0.4r3 Fx92: getURLSpecFromFile() -> getURLSpecFromActualFile() // @note 0.0.4r2 AUTHOR_SHEET-Unterstützung hinzugefügt, wichtig: Dateiendung muss .author.css sein! // @note Version 0.0.4.g ermöglicht "Styles importieren" per Mittelklick und Verwendung // @note eines anderen Dateimanagers (siehe in Konfiguration), ergänzt um einen // @note Parameter für den Dateimanager (vFMParameter in der Konfiguration) von aborix // @note Frei verschiebbare Schaltfläche eingebaut von aborix // @note 0.0.4 Remove E4X // @note CSS-Entry-Klasse erstellt // @note Style-Test-Funktion überarbeitet // @note Wenn die Datei gelöscht wurde, CSS beim Neu-Erstellen und Löschen des Menüs abbrechen // @note uc einlesen .uc.css temporäre Korrespondenz zum erneuten Lesen // ==/UserScript== /* Endor in https://www.camp-firefox.de/forum/thema/112673/?postID=1277236#post1277236 */ /****** Bedienungsanleitung ****** CSS-Ordner im Chrome-Ordner erstellen, CSS-Dateien dort ablegen - speichern. Diejenigen, deren Dateiname mit "xul-" beginnen, diejenigen, die mit ".as.css" enden, sind AGENT_SHEET, alle anderen außer USER_SHEET werden gelesen. Da der Inhalt der Datei nicht überprüft wird, darauf achten, die Angabe von @namespace nicht zu vergessen! Schaltfläche wird in Navigationsleiste eingefügt (konfigurierbar, siehe Variable "position") Linksklick auf Stil, zum Aktivieren/Deaktivieren Mittelklick auf Stil zum Aktivieren/Deaktivieren, ohne Menü zu schließen Rechtsklick auf Stil zum Öffnen im Editor Strg+Linksklick zum Anzeigen im Dateimanager Die Tastenkombinationen können im Menü eingeblendet werden, dazu nach "acceltext" suchen und den Zeilenkommentar "//" entfernen bzw. einfügen. Verwenden des in "view_source.editor.path" angegebenen Editors. Dateiordner kann in Konfiguration geändert werden. **** Anleitung Ende ****/ (function(){ /***** Konfiguration *****/ // Position: als frei verschiebbare-Schaltfläche = 0, als Menü anzeigen = 1 let position = 0;//1 // alternativer Dateimanager, Bsp.: // let filemanager = "C:\\Programme\\totalcmd\\TOTALCMD.EXE"; let filemanager = ""; // eventuelle Parameter für den alternativen Dateimanager, sonst filemanagerParam = ""; //let filemanagerParam = "/O /T";//Totalcommander let filemanagerParam = ""; // Unterordner für die CSS-Dateien: let cssFolder = "CSS"; // Menüeintrag zum Bearbeiten der userChrome.css verstecken (true) oder anzeigen (false) let hideUserChromeCSS = false; // Menüeintrag zum Bearbeiten der userContent.css verstecken (true) oder anzeigen (false) let hideUserContentCSS = false; // zusätzlich Chrome-Ordner im Untermenü anzeigen: 1 = ja, 0 = nein let showChrome = 1; /***** Ende Konfiguration *****/ ChromeUtils.importESModule("resource://gre/modules/AppConstants.sys.mjs"); // Wenn beim Start ein weiteres Fenster (zweites Fenster) vorhanden ist, beenden let list = Services.wm.getEnumerator("navigator:browser"); while(list.hasMoreElements()){ if(list.getNext() != window) return; } if (window.UCL) { window.UCL.destroy(); delete window.UCL; } window.UCL = { vFileManager: filemanager, vFMParameter: filemanagerParam, USE_UC: "UC" in window, AGENT_SHEET : Ci.nsIStyleSheetService.AGENT_SHEET, USER_SHEET : Ci.nsIStyleSheetService.USER_SHEET, AUTHOR_SHEET: Ci.nsIStyleSheetService.AUTHOR_SHEET, readCSS: {}, get disabled_list() { let obj = []; try { obj = decodeURIComponent(this.prefs.getCharPref("disabled_list")).split("|"); } catch(e) {} delete this.disabled_list; return this.disabled_list = obj; }, get prefs() { delete this.prefs; return this.prefs = Services.prefs.getBranch("UserCSSLoader."); }, get styleSheetServices(){ delete this.styleSheetServices; return this.styleSheetServices = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService); }, get FOLDER() { let aFolder; try { // UserCSSLoader.FOLDER verwenden let folderPath = this.prefs.getCharPref("FOLDER"); aFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); aFolder.initWithPath(folderPath); } catch (e) { aFolder = Services.dirsvc.get("UChrm", Ci.nsIFile); aFolder.appendRelativePath(cssFolder); } if (!aFolder.exists() || !aFolder.isDirectory()) { aFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664); } delete this.FOLDER; return this.FOLDER = aFolder; }, get CHRMFOLDER() { let bFolder; try { // UserCSSLoader.CHRMFOLDER verwenden let CHRMfolderPath = this.prefs.getCharPref("CHRMFOLDER"); bFolder = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile); bFolder.initWithPath(CHRMfolderPath); } catch (e) { bFolder = Services.dirsvc.get("UChrm", Ci.nsIFile); } if (!bFolder.exists() || !bFolder.isDirectory()) { bFolder.create(Ci.nsIFile.DIRECTORY_TYPE, 0o664); } delete this.CHRMFOLDER; return this.CHRMFOLDER = bFolder; }, getFocusedWindow: function() { let win = document.commandDispatcher.focusedWindow; if (!win || win == window) win = content; return win; }, init: function() { const cssmenu = $C("menu", { id: "usercssloader-menu", label: "CSS", tooltiptext: "UserCSSLoader\n\nLinksklick: Stylesheets anzeigen\nMittelklick: Styles importieren", accesskey: "Y" }); cssmenu.addEventListener("command", () => UCL.rebuild()); cssmenu.addEventListener("click", (event) => { if (event.button === 1) UCL.rebuild(); }); const menupopup = $C("menupopup", { id: "usercssloader-menupopup" }); cssmenu.appendChild(menupopup); let menu = $C("menu", { label: "Style-Loader-Menü", id: "style-loader-menu", accesskey: "M", //acceltext: "M" }); menupopup.appendChild(menu); menupopup.appendChild($C("menuseparator")); let mp = $C("menupopup", { id: "usercssloader-submenupopup" }); menu.appendChild(mp); let rebuildItem = $C("menuitem", { label: "Styles importieren", accesskey: "I", //acceltext: "I" }); rebuildItem.addEventListener("command", () => UCL.rebuild()); mp.appendChild(rebuildItem); mp.appendChild($C("menuseparator")); let createCSS = $C("menuitem", { label: "CSS-Datei erstellen", accesskey: "E", //acceltext: "E" }); createCSS.addEventListener("command", () => UCL.create()); mp.appendChild(createCSS); let openFolder = $C("menuitem", { label: "CSS-Ordner öffnen", accesskey: "O", //acceltext: "O" }); openFolder.addEventListener("command", () => UCL.openFolder()); mp.appendChild(openFolder); if (showChrome === 1) { let openChromeFolder = $C("menuitem", { label: "Chrome-Ordner öffnen", accesskey: "X", //acceltext: "X" }); openChromeFolder.addEventListener("command", () => UCL.openCHRMFolder()); mp.appendChild(openChromeFolder); } mp.appendChild($C('menuseparator')); let editChromeItem = $C("menuitem", { label: "userChrome.css bearbeiten", hidden: hideUserChromeCSS, }); editChromeItem.addEventListener("command", () => UCL.editUserCSS("userChrome.css")); mp.appendChild(editChromeItem); let editContentItem = $C("menuitem", { label: "userContent.css bearbeiten", hidden: hideUserContentCSS, }); editContentItem.addEventListener("command", () => UCL.editUserCSS("userContent.css")); mp.appendChild(editContentItem); menu = $C("menu", { label: ".uc.css", accesskey: "U", //acceltext: "U", hidden: !UCL.USE_UC }); menupopup.appendChild(menu); mp = $C("menupopup", { id: "usercssloader-ucmenupopup" }); menu.appendChild(mp); let UCrebuild = $C("menuitem", { label: "Importieren(.uc.js)", }); UCrebuild.addEventListener("command", () => UCL.UCrebuild()); mp.appendChild(UCrebuild); mp.appendChild($C("menuseparator", { id: "usercssloader-ucseparator" })); CustomizableUI.createWidget({ id: 'usercssloader-menu-item', type: 'custom', defaultArea: CustomizableUI.AREA_NAVBAR, onBuild: function(aDocument) { let toolbaritem = aDocument.createXULElement('toolbaritem'); toolbaritem.id = 'usercssloader-menu-item'; toolbaritem.className = 'chromeclass-toolbar-additional'; return toolbaritem; } }); $('usercssloader-menu-item').appendChild(cssmenu); if (position === 1) { let refNode = $('helpMenu'); refNode.parentNode.insertBefore(cssmenu, refNode.nextSibling); } let key = $C("key", { id: "usercssloader-rebuild-key", key: "R", modifiers: "alt", }); key.addEventListener("command", () => UCL.rebuild()); $("mainKeyset").appendChild(key); this.rebuild(); this.initialized = true; if (UCL.USE_UC) { setTimeout(function() { UCL.UCcreateMenuitem(); }, 1000); } window.addEventListener("unload", this, false); }, uninit: function() { const dis = []; for (let x of Object.keys(this.readCSS)) { if (!this.readCSS[x].enabled) dis.push(x); } this.prefs.setCharPref("disabled_list", encodeURIComponent(dis.join("|"))); window.removeEventListener("unload", this, false); }, destroy: function() { var i = document.getElementById("usercssloader-menu"); if (i) i.parentNode.removeChild(i); var i = document.getElementById("usercssloader-rebuild-key"); if (i) i.parentNode.removeChild(i); this.uninit(); }, handleEvent: function(event) { switch(event.type){ case "unload": this.uninit(); break; } }, rebuild: function() { let ext = /\.css$/i; let not = /\.uc\.css/i; let files = this.FOLDER.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator); 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); CSS.flag = true; } for (let leafName of Object.keys(this.readCSS)) { const CSS = this.readCSS[leafName]; if (!CSS.flag) { CSS.enabled = false; delete this.readCSS[leafName]; } delete CSS.flag; this.rebuildMenu(leafName); } if (this.initialized) { if (typeof(StatusPanel) !== "undefined") StatusPanel._label = "Styles importiert"; else XULBrowserWindow.statusTextField.label = "Styles importiert"; } }, loadCSS: function(aFile) { let CSS = this.readCSS[aFile.leafName]; if (!CSS) { CSS = this.readCSS[aFile.leafName] = new CSSEntry(aFile); if (this.disabled_list.indexOf(CSS.leafName) === -1) { CSS.enabled = true; } } else if (CSS.enabled) { CSS.enabled = true; } return CSS; }, rebuildMenu: function(aLeafName) { let CSS = this.readCSS[aLeafName]; let menuitem = document.getElementById("usercssloader-" + aLeafName); if (!CSS) { if (menuitem) menuitem.parentNode.removeChild(menuitem); return; } if (!menuitem) { menuitem = $C("menuitem", { label : aLeafName, id : "usercssloader-" + aLeafName, class : "usercssloader-item " + (CSS.SHEET == this.AGENT_SHEET? "AGENT_SHEET" : CSS.SHEET == this.AUTHOR_SHEET? "AUTHOR_SHEET": "USER_SHEET"), type : "checkbox", autocheck : "false", tooltiptext : "Linksklick: an/aus, Menü schließt\nMittelklick: an/aus, Menü bleibt offen\nRechtsklick: bearbeiten\nStrg+Rechtsklick: im Dateimanager anzeigen" }); menuitem.addEventListener("command", () => UCL.toggle(aLeafName)); menuitem.addEventListener("click", (event) => UCL.itemClick(event)); menuitem.addEventListener("mouseup", (event) => { if (event.button === 1) event.preventDefault(); }); document.getElementById("usercssloader-menupopup").appendChild(menuitem); } menuitem.setAttribute("checked", CSS.enabled); }, toggle: function(aLeafName) { let CSS = this.readCSS[aLeafName]; if (!CSS || event.ctrlKey) return; CSS.enabled = !CSS.enabled; this.rebuildMenu(aLeafName); }, itemClick: function(event) { let label = event.currentTarget.getAttribute("label"); event.preventDefault(); event.stopPropagation(); if (event.button === 0) { return; } else if (event.button === 1) { this.toggle(label); } else if (event.button === 2) { if (event.ctrlKey) { UCL.openFolder(label); } else { closeMenus(event.target); this.edit(this.getFileFromLeafName(label)); } } }, getFileFromLeafName: function(aLeafName) { let f = this.FOLDER.clone(); f.QueryInterface(Ci.nsIFile); // use appendRelativePath f.appendRelativePath(aLeafName); return f; }, openFolder: function(label) { const PathSep = AppConstants.platform === "win" ? "\\" : "/"; let target= this.FOLDER.path + PathSep + label; if (this.vFileManager.length !== 0) { let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess); let args = [this.vFMParameter,target]; file.initWithPath(this.vFileManager); process.init(file); // Verzeichnis mit anderem Dateimanager öffnen process.run(false, args, args.length); } else { // Verzeichnis mit Dateimanager des Systems öffnen this.FOLDER.launch(); } }, openCHRMFolder:function(){ if (this.vFileManager.length !== 0) { let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile); let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess); let args = [this.vFMParameter,this.CHRMFOLDER.path]; file.initWithPath(this.vFileManager); process.init(file); // Verzeichnis mit anderem Dateimanager öffnen process.run(false, args, args.length); } else { // Verzeichnis mit Dateimanager des Systems öffnen this.CHRMFOLDER.launch(); } }, editUserCSS: function(aLeafName) { let file = Services.dirsvc.get("UChrm", Ci.nsIFile); file.appendRelativePath(aLeafName); this.edit(file); }, edit: function(aFile) { let editor = Services.prefs.getCharPref("view_source.editor.path"); if (!editor) return alert('Unter about:config den vorhandenen Schalter\n "view_source.editor.path" mit dem Editorpfad ergänzen'); try { let UI = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter); UI.charset = window.navigator.platform.toLowerCase().indexOf("win") >= 0? "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) {} }, create: function(aLeafName) { if (!aLeafName) aLeafName = prompt("Name des Styles", dateFormat(new Date(), "%Y_%m%d_%H%M%S")); if (aLeafName) aLeafName = aLeafName.replace(/\s+/g, " ").replace(/[\\/:*?\"<>|]/g, ""); if (!aLeafName || !/\S/.test(aLeafName)) return; if (!/\.css$/.test(aLeafName)) aLeafName += ".css"; let file = this.getFileFromLeafName(aLeafName); this.edit(file); }, UCrebuild: function() { let re = /^file:.*\.uc\.css(?:\?\d+)?$/i; let query = "?" + new Date().getTime(); Array.slice(document.styleSheets).forEach(function(css){ if (!re.test(css.href)) return; if (css.ownerNode) { css.ownerNode.parentNode.removeChild(css.ownerNode); } let pi = document.createProcessingInstruction('xml-stylesheet','type="text/css" href="'+ css.href.replace(/\?.*/, '') + query +'"'); document.insertBefore(pi, document.documentElement); }); UCL.UCcreateMenuitem(); }, UCcreateMenuitem: function() { let sep = $("usercssloader-ucseparator"); let popup = sep.parentNode; if (sep.nextSibling) { let range = document.createRange(); range.setStartAfter(sep); range.setEndAfter(popup.lastChild); range.deleteContents(); range.detach(); } let re = /^file:.*\.uc\.css(?:\?\d+)?$/i; Array.slice(document.styleSheets).forEach(function(css) { if (!re.test(css.href)) return; let fileURL = decodeURIComponent(css.href).split("?")[0]; let aLeafName = fileURL.split("/").pop(); let m = $C("menuitem", { label : aLeafName, tooltiptext : fileURL, id : "usercssloader-" + aLeafName, type : "checkbox", autocheck : "false", checked : "true", }); m.css = css; m.addEventListener("command", function() { if (!event.ctrlKey) {this.setAttribute("checked", !(this.css.disabled = !this.css.disabled));} }); m.addEventListener("mouseup", function(event) { if (event.button === 1) event.preventDefault(); }); m.addEventListener("click", function(event) { UCL.UCItemClick(event); }); popup.appendChild(m); }); }, UCItemClick: function(event) { if (event.button === 0) return; event.preventDefault(); event.stopPropagation(); if (event.button === 1) { event.target.doCommand(); } else if (event.button === 2) { closeMenus(event.target); let fileURL = event.currentTarget.getAttribute("tooltiptext"); let file = Services.io.getProtocolHandler("file").QueryInterface(Ci.nsIFileProtocolHandler).getFileFromURLSpec(fileURL); this.edit(file); } }, }; 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(); // true, wenn die Datei bereits existiert let lastModifiedTime = isExists ? aFile.lastModifiedTime : 0; let isForced = this.lastModifiedTime != lastModifiedTime; //true, wenn es eine Änderung in der Datei gibt 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)) { // Wenn diese Datei bereits gelesen wurde if (!isEnable || !isExists) { this.sss.unregisterSheet(uri, this.SHEET); } else if (isForced) { // Nach Stornierung erneut einlesen this.sss.unregisterSheet(uri, this.SHEET); this.sss.loadAndRegisterSheet(uri, this.SHEET); } } else { // Datei wurde nicht gelesen if (isEnable && isExists) { this.sss.loadAndRegisterSheet(uri, this.SHEET); } } if (this.lastModifiedTime !== 1 && isEnable && isForced) { log(this.leafName + " wurde aktualisiert"); } this.lastModifiedTime = lastModifiedTime; return this._enabled = isEnable; }, }; UCL.init(); function $(id) { return document.getElementById(id); } function $A(arr) { return Array.slice(arr); } function $C(name, attr) { const el = document.createXULElement(name); if (attr) Object.keys(attr).forEach(function(n) { el.setAttribute(n, attr[n]) }); return el; } function dateFormat(date, format) { format = format.replace("%Y", ("000" + date.getFullYear()).substr(-4)); format = format.replace("%m", ("0" + (date.getMonth()+1)).substr(-2)); format = format.replace("%d", ("0" + date.getDate()).substr(-2)); format = format.replace("%H", ("0" + date.getHours()).substr(-2)); format = format.replace("%M", ("0" + date.getMinutes()).substr(-2)); format = format.replace("%S", ("0" + date.getSeconds()).substr(-2)); return format; } function log(mes) { console.log(mes); } })();
-
Bezogen auf meine Frage: Alles klar.
-
Ich habe gerade festgestellt, dass sich in meinen hier publizierten 'Menuscripts' ab Firefox 143 die Iconeinbindung obsolet ist.
Was genau musste geändert werden?