1. Nachrichten
  2. Forum
    1. Unerledigte Themen
    2. Forenregeln
  3. Spenden
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. camp-firefox.de
  2. bege

Beiträge von bege

  • Zugang Firefox Konto nicht möglich

    • bege
    • 4. September 2026 um 23:34

    Ich bin überrascht, dass dieser Beitrag schon vom Januar ist. Bei mir passiert das heute zum ersten Mal.

    Auch hier brauchen die Mails z.T. sehr lange, bis sie ankommen, aber bei mancher Anmeldung komme ich ins Konto und werde nicht nach dem Autorisierungscode gefragt, kann ihn also nicht eingeben.

    Bei addons.mozilla.org hatte ich Glück, da konnte ich mich nach dem Abmelden wieder anmelden - wieder ohne nach dem Code gefragt zu werden. Erst bei der dritten Anmeldung kam die Abfrage.

    Bei addons.thunderbird.net habe ich mich auch ohne Code anmelden können, konnte also dem Code, der per Mail kam, gar nicht eingeben. Als ich mich nach dem Abmelden wieder anmelden wollte, war der Zugang zu thunderbird.net gesperrt mit dem "freundlichen" Hinweis, ich könnte mich per E-Mail beim Website-Betreiber melden.

    Das ist echt gruselig. Weiß jemand, wo ich mich da melden kann, um den Zugang wieder freischalten zu lassen?

  • Dateierweiterung am Icon erkennen

    • bege
    • 4. September 2026 um 21:52

    Uralt, aber funkioniert:

    Link Alert – Holen Sie sich diese Erweiterung für 🦊 Firefox (de)
    Laden Sie Link Alert für Firefox herunter. Displays an icon in the tooltip or next to the cursor indicating the target of a link.
    addons.mozilla.org
  • Skript "OpenbookModoki" klappt die Lesezeichenliste nicht mehr auf

    • bege
    • 4. September 2026 um 21:47

    Das ist die Version, die ich nutze, da geht es. Habe ich nicht mit deiner verglichen, Falls sie gleich sind, funkt was anderes dazwischen.

    JavaScript: openbookModoki.uc.js
    // ==UserScript==
    // @name           openbookModoki.uc.js
    // @namespace      https://github.com/Endor8/userChrome.js/blob/master/openbookmodoki/OpenBookModoki.uc.js
    // @description    Lesezeichen Bearbeiten Panel: Veränderbare Panelgröße hinzugefügt. Schlüsselwort und Ordner-Struktur
    // @description    Felder sind geschlossen. Weitere Einstellungen: Beschreibung, Ordner, Dieses Lesezeichen in der Sidebar laden,
    // @description    und Schlüsselwort können ein-/ausgeblendet werden.
    // @include        main
    // @source         https://www.camp-firefox.de/forum/thema/135858-skript-openbookmodoki-funktioniert-nicht-mehr/?postID=1218464#post1218464
    // @author         Alice0775
    // @version        2023/11/15 17:00 Fenster schließen, Zeitanpassung nach @Aborix aus 2019; https://www.camp-firefox.de/forum/thema/127571-lesezeichen-speichern-anzeigedauer-gr%C3%B6%C3%9Fe-des-dialogfensters-zur-bearbeitung/?postID=1108858#post1108858
    // @version        2023/01/27 14:30 Fx109 by Sören Hentzschel
    // @version        2020/05/11 10:30 Fx76 by aborix
    // @version        2018/03/15 10:30 Fx59 by aborix
    // @version        2017/11/17 02:30 Fx57
    // @version        2016/03/20 02:30 remove tst hack
    // @version        2015/08/31 02:30 Fx40
    // @version        2013/07/07 02:30 fix onFolderMenuListCommand
    // @version        2012/12/08 22:30 Bug 788290 Bug 788293 Remove E4X
    // @version        2012/07/24 14:30 Bug 761723 implement toString of function objects by saving source
    // @version        2010/12/06 10:30 Bug Bug 597557 - Bookmarks & Identity panels should use an Arrowpanel
    // @version        2010/04/01 00:00 Bug 556342  - Invalid Treeview in bookmark menu via star pane
    // @version        2009/12/22 00:00 namePicker in front
    // @version        2009/12/21 14:00 BETTER WORKAROUND FIX  Bug 536024 -  When i expand folder-tree on Edit This Bookmark, the bookmarked folder is changed.
    // @version        2009/12/20 16:00 WORKAROUND FIX  Bug 536024 -  When i expand folder-tree on Edit This Bookmark, the bookmarked folder is changed.
    // @version        2009/08/11 18:00 Tree Style Tab0.8.2009081101 Unterstützung für das Umbenennen von Objekten
    // @version        2009/08/07 00:00 Tree Style Tab0.8.2009073102 Treestyletab-Tabzeile ausblenden, wenn vorhanden
    // @version        2009/08/06 19:00 Tree Style Tab0.8.2009073102 Problem, dass der übergeordnete Tab für einen Moment angezeigt wird, behoben 
    // @version        2009/08/06 18:00 Tree Style Tab0.8.2009073102 entsprechend
    // @version        2009/06/24 00:00 Firefox3.5 Es wurde ein Fehler behoben, durch den der Offen / Geschlossen Status des Expanders in der 
    // @version        2009/06/24 00:00 Ordnerstruktur und der Tag-Auswahl nicht gespeichert wurde
    // @version        2009/01/02 02:00 Beschreibung, Position, loadInSidebar, Schlüsselwort und Einstellung anzeigen / ausblenden
    // @version        2009/01/01 22:28
    // ==/UserScript==
    
    var openbookResizer = {
    
      drag  : false,
      height: null,
      width : null,
      eventOffset: null,
      timer: null,
      PREHIDEROW    : "userChrome.openbook.hideRow",  // description, location, loadInSidebar, keyword
      PREFTREEHEIGHT: "userChrome.openbook.treeHeight",
      PREFTREEWIDTH : "userChrome.openbook.treeWidth",
      PREFOPENTREE  : "userChrome.openbook.openTree",
      PREFOPENTAG   : "userChrome.openbook.openTag",
    
      get tree(){
        return gEditItemOverlay._folderTree;
      },
    
      get getHideRow(){
        try {
          return Services.prefs.getCharPref(this.PREHIDEROW).replace(/\s/g,'').slice(',');
        } catch(e) {
          return [];
        }
      },
    
      get getPrefTreeHeight(){
        try {
          return Services.prefs.getIntPref(this.PREFTREEHEIGHT);
        } catch(e) {
          return 150;
        }
      },
      get getPrefTreeWidth(){
        try {
          return Services.prefs.getIntPref(this.PREFTREEWIDTH);
        } catch(e) {
          return 250;
        }
      },
    
      get editBookmarkPanel(){
        return StarUI.panel;
      },
    
      get treeExpander(){
        return gEditItemOverlay._element('foldersExpander');
      },
    
      get tagExpander(){
        return gEditItemOverlay._element('tagsSelectorExpander');
      },
    
      get getPrefOpenTree(){
        try {
          return Services.prefs.getBoolPref(this.PREFOPENTREE);
        } catch(e) {
          return false;
        }
      },
    
      get getPrefOpenTag(){
        try {
          return Services.prefs.getBoolPref(this.PREFOPENTAG);
        } catch(e) {
          return false;
        }
      },
    
      init: function(){
        //window.removeEventListener('load', this, false);
        window.addEventListener('unload', this, false);
    
        var style = " \
          .openbookResizerGripper { \
            list-style-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAApklEQVQokY3QK4uCURCA4QeDLCoIXoIYNFiUFVZBq2JQEEx+UcTmpi1b121eosX/a5lg8jvTzsy8M+8cGGKNusQY44QMlRTgAzOcsUqBitH0FVCWpzeNpmZsytUb4oY9qil6BfRxDaiZp1eO5OBl01u9JX7QxiRFr4XfmNbFZ+gdojbCBbt4a6CDP/wH1McDR9SwwB1b+I4bejG1ER8xxwaluHOJ8RM+9xjk9q2RpwAAAABJRU5ErkJggg=='); \
            cursor: sw-resize; \
          }";
        var sspi = document.createProcessingInstruction(
          'xml-stylesheet',
          'type="text/css" href="data:text/css,' + encodeURIComponent(style) + '"'
        );
        document.insertBefore(sspi, document.documentElement);
        sspi.getAttribute = function(name) {
        return document.documentElement.getAttribute(name);
        };
    
        this.folderTreeRow   = "folderTreeRow";
        this.tagsSelectorRow = "tagsSelectorRow";
    
        gEditItemOverlay.initPanel_org = gEditItemOverlay.initPanel;
        gEditItemOverlay.initPanel = function(aInfo) {
          aInfo.hiddenRows = openbookResizer.getHideRow;
          gEditItemOverlay.initPanel_org(aInfo);
        }
    
        // selected tree visible
        func = gEditItemOverlay.toggleFolderTreeVisibility.toString();
        func = func.replace(
          'var currentFolder = this._getFolderIdFromMenuList();',
          ''
        );
        func = func.replace(
          /expander.className = "expander-up";*/,
          'var currentFolder = this._getFolderIdFromMenuList(); \
          var onselect = this._folderTree.getAttribute("onselect"); \
          this._folderTree.removeAttribute("onselect"); \
          $&;'
        );
        func = func.replace(
          'this._folderTree.focus();',
          '$&; \
          setTimeout(function(tree){ \
            var start = new Object(); \
            var end = new Object(); \
            var numRanges = tree.view.selection.getRangeCount(); \
            if (numRanges > 0) { \
              tree.view.selection.getRangeAt(0,start,end); \
              var v = start.value; \
              tree.treeBoxObject.ensureRowIsVisible(v); \
            } \
            tree.setAttribute("onselect", onselect); \
          }, 0, this._folderTree);'
        );
        try{
          gEditItemOverlay.toggleFolderTreeVisibility = new Function(
             func.match(/\((.*)\)\s*\{/)[1],
             func.replace(/^function\s*.*\s*\(.*\)\s*\{/, '').replace(/}$/, '')
          );
        } catch(ex){}
    
        // selected tree visible
        func = gEditItemOverlay.onFolderMenuListCommand.toString();
        func = func.replace(
          'this._folderTree.selectItems([container]);',
          '{var onselect = this._folderTree.getAttribute("onselect"); \
          this._folderTree.removeAttribute("onselect"); \
          $&; \
          setTimeout(function(tree){ \
            var start = new Object(); \
            var end = new Object(); \
            var numRanges = tree.view.selection.getRangeCount(); \
            if (numRanges > 0) { \
              tree.view.selection.getRangeAt(0,start,end); \
              var v = start.value; \
              tree.treeBoxObject.ensureRowIsVisible(v); \
            } \
            tree.setAttribute("onselect", onselect); \
          }, 0, this._folderTree);}'
        );
        try{
          gEditItemOverlay.onFolderMenuListCommand = new Function(
             func.match(/\((.*)\)\s*\{/)[1],
             func.replace(/^function\s*.*\s*\(.*\)\s*\{/, '').replace(/}$/, '')
          );
        } catch(ex){}
    
        this.editBookmarkPanel.addEventListener('popupshowing', this, false);
        this.editBookmarkPanel.addEventListener('popupshown', this, false);
        this.editBookmarkPanel.addEventListener('popuphiding', this, false);
      },
    
      uninit: function(){
        window.removeEventListener('unload', this, false);
        this.editBookmarkPanel.removeEventListener('popupshowing', this, false);
        this.editBookmarkPanel.removeEventListener('popupshown', this, false);
        this.editBookmarkPanel.removeEventListener('popuphiding', this, false);
      },
    
      handleEvent: function(event){
        switch(event.type){
          case 'unload':
            this.uninit();
            break;
          case 'popupshowing':
            this.popupshowing(event);
            break;
          case 'popupshown':
            this.popupshown(event);
            break;
          case 'popuphiding':
            this.popuphiding(event);
        }
      },
    
      popuphiding: function(event){
        if (this.editBookmarkPanel != event.originalTarget)
          return;
        var state = !gEditItemOverlay._element(this.folderTreeRow).hidden;
        Services.prefs.setBoolPref(this.PREFOPENTREE, state);
        var state = !gEditItemOverlay._element(this.tagsSelectorRow).hidden;
        Services.prefs.setBoolPref(this.PREFOPENTAG, state);
    
        gEditItemOverlay._element(this.folderTreeRow).hidden = true;
        gEditItemOverlay._element(this.tagsSelectorRow).hidden = true;
      },
    
      popupshowing: function(event){
        if (this.editBookmarkPanel != event.originalTarget)
          return;
    
        this.tree.height = this.getPrefTreeHeight;
        //this.tree.width = this.getPrefTreeWidth;
        //this.editBookmarkPanel.width = this.getPrefTreeWidth;
    
        if (!document.getElementById("openbookResizerbottomBox")) {
          var panel = StarUI.panel;
    
          var innerarrow = panel.openOrClosedShadowRoot.querySelector('.panel-arrowcontent');
          if (innerarrow)
            innerarrow.setAttribute('flex', 1);
    
          var box = document.createXULElement("hbox");
          box.setAttribute('id', 'openbookResizerbottomBox');
          box.setAttribute('align',"start");
    
          var resizer = document.createXULElement("image");
          resizer.setAttribute("class", "openbookResizerGripper");
          resizer.setAttribute('onmousedown', 'openbookResizer.mousedown(event)');
    
          box.appendChild(resizer);
          panel.appendChild(box);
    
          panel.setAttribute('onmousemove', 'openbookResizer.mousemove(event)');
          panel.setAttribute('onmouseup', 'openbookResizer.mouseup(event)');
        }
      },
    
      popupshown: function(event){
        if (this.editBookmarkPanel != event.originalTarget)
          return;
        setTimeout(function(self) {
          if (self.getPrefOpenTree &&
              gEditItemOverlay._element(self.folderTreeRow).hidden ) {
            gEditItemOverlay.toggleFolderTreeVisibility();
          }
          if (self.getPrefOpenTag &&
              gEditItemOverlay._element(self.tagsSelectorRow).hidden ) {
            gEditItemOverlay.toggleTagsSelector();
          }
          try {
            gEditItemOverlay._element(Services.prefs
              .getCharPref("browser.bookmarks.editDialog.firstEditField")).focus();
          } catch(e) {}
        }, 100, this);
      },
    
      mousedown: function(event){
        this.drag = true;
        this.height = parseInt(this.tree.boxObject.height);
        this.width = parseInt(this.editBookmarkPanel.boxObject.width);
        this.eventOffset = event;
      },
    
      mousemove: function(event) {
        if (this.timer)
          clearTimeout(this.timer);
        this.timer = setTimeout(function(event, self){
          if (self.drag) {
            // make sure height [150,screen-300] and width is [300,screen-50]
            var newValue;
            newValue = self.height + event.pageY - self.eventOffset.pageY;
            if (newValue <= screen.height - 300 && newValue >= 150) {
              self.tree.height = newValue;
            }
            newValue = self.width - event.pageX + self.eventOffset.pageX;
            if (newValue <= screen.width - 50 && newValue >= 300) {
              //self.tree.width = newValue;
              self.editBookmarkPanel.width = newValue;
            }
          }
        }, 10, event, this);
      },
      mouseup: function(event) {
        if (this.drag) {
          Services.prefs.setIntPref(this.PREFTREEHEIGHT, this.tree.height);
          Services.prefs.setIntPref(this.PREFTREEWIDTH, this.editBookmarkPanel.boxObject.width);
        }
        this.drag = false;
      }
    }
    //window.addEventListener("load", openbookResizer, false);
    openbookResizer.init();
    
    /* Fenster schließen nach 6 Sekunden */
    
    (function() {
      if (window.StarUI) {
        const delay = 6;
        StarUI._autoCloseTimeout = delay * 1000;
      }
    })();
    Alles anzeigen
  • extra_config_menu.uc.js > ohne security.allow_unsafe_dangerous_privileged_evil_eval auf false

    • bege
    • 30. August 2026 um 19:54

    Mira_Belle Danke für die viele Arbeit. Ich fände es toll, wenn wir hier wieder eine Version für alle hätten.

    Mit Verweis auf meinen Beitrag #90 möchte ich nochmal anregen, für alle Menüpunkte im Skript eine Steuerung im Konfigurationsabschnitt anzulegen, wie ich es in meiner Version ergänzt habe. Das macht einmalig mehr Arbeit, macht das Skript aber für jeden nutzbar und übersichtlich.

    Mir fehlt noch der Parameter für den Dateimanager (in meiner Version vFMParam)

    und die Einstellungen für die CSS-Ordner, in meiner Version so

    JavaScript
      // Einbindung CSS-Ordner (0: nein, 1: ja, Chrome-Unterordner, 2: ja, anderer Pfad):
    cssOrdner: 0,
      // Wenn cssOrdner = 1 oder 2, hier entweder Chrome-Unterordner (z.B. 'CSS') oder andere vollständige Pfade (z.B. 'C:\\Dropbox\\Chrome\\Thunderbird\\CSS-Ordner\\css-dateien') entragen, sonst '':
      cssLocation1: 'CSS',
      cssLocation2: '',
      cssLocation3: '',
      //Anzeigenamen für die CSS-Ordner
      cssLocation1Name: 'CSS-Ordner',
      cssLocation2Name: 'CSS-Ordner2',
      cssLocation3Name: 'CSS-Ordner3',

    Edit: Wer den UserCSSLoader nutzt, braucht davon vieles nicht.

    Der Ordner für die Symbole sollte auch konfigurierbar sein, statt

    JavaScript
    /*     Zu beachten ist, dass die Grafiken sich im richtigen Ordner befinden müssen     */
    /*            %appdata%\Mozilla\Firefox\Profiles\"Profilname"\chrome\icons             */

    Ich nutze z.B. einen Ordner außerhalb der Profile, um von allen Profilen - einschließlich Thunderbird - auf einen einzigen Symbolordner zugreifen zu können.

  • UserCSSLoader (2025)

    • bege
    • 30. August 2026 um 19:19
    Zitat von 2002Andreas
    Zitat von seipe

    etwa 3-4 Sekunden später erst angezeigt.

    Nach Änderung von diesem Wert wird es hier gleich angezeigt:

    Gut, dass du das herausgefunden hast. Es kann sein, dass ich das erhöht habe, weil bei mir beim Start einiges an Skripten lädt und verschoben wird, sodass es u.a. darauf ankommt, dass einzelne Skripte nicht zu früh geladen werden.

  • extra_config_menu.uc.js > ohne security.allow_unsafe_dangerous_privileged_evil_eval auf false

    • bege
    • 26. August 2026 um 19:08
    Zitat von Mira_Belle

    einen ellenlangen Text, der nun verloren geagangen ist,
    weil der Browser einfach neu startete

    OT: Ich nutze dieses Addon, das mich schon x Mal gerettet hat.

  • UserCSSLoader (2025)

    • bege
    • 26. August 2026 um 19:01

    Ich hatte das gleiche Problem und habe herausgefunden, dass FF 153 bei aktivierten Einträgen nur noch checked setzt, nicht mehr checked="true", wie in dem Skript. Bei deaktivierten Einträgen entfernt FF 153 das Attribut checked und setzt nicht checked="false". Das hat mir noch andere CSS-Änderungen zerschossen.

    Da die Einträge des Skripts also immer das Attribut checked enthalten, behält FF 153 die Haken bei, vorausgesetzt man hat keine anderen Änderungen vorgenommen. Es ist also ein reines Anzeigeproblem, die (De-)Aktivierung durch das Skript funktioniert weiter.

    Ich habe meine Version des Skripts mit Hilfe von KI so geändert, dass jetzt das Attribut entsprechend FF 153 gesetzt wird und damit die Haken wieder richtig angezeigt werden.

    JavaScript: userCSSLoader_2026-08-21.us.js
    /* UserCSSLoader 2026-08-21
     *
     * 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
     * 2026-08-21 angepasst an Firefox 153esr mit Hilfe von KI:
     *   Firefox setzt nicht mehr "checked=true" und "checked=false" wie dieses Skript,
     *    sondern nur noch "checked" oder keine Attribut. Dadurch bekamen auch Menüeinträge
     *    mit "checked=false" ein Checkmark, weil auch hier "checked" enthalten war.
     *    Jetzt setzt das Skript "checked=true" bzw. entfernt das Attribut.
     */
    
    /****** 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(){
    	setTimeout(async 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 (Achtung, nur mit fileManagerParam = "/select,"!):
     *    let fileManager = "C:\\Windows\\explorer.exe";
     * Bleibt Parameter leer, wird Standardmanager des Systems ohne Parameter
     * verwendet mit leicht eingeschränkter Funktionalität. */
    let fileManager = "C:\\Program Files\\FreeCommander XE\\FreeCommander.exe";
    /* eventuelle Parameter für den Dateimanager, Beispiele:
     *    let fileManagerParam = "/T";//FreeCommander oder Totalcommander
     *    let fileManagerParam = "/select,";//Windows Explorer, mit Komma korrekt!
     */
    let fileManagerParam = "/T";
    /* 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);
    		}
    		if (CSS.enabled) {
    		menuitem.setAttribute("checked", "true");
    		} else {
    		menuitem.removeAttribute("checked");
    	}
    	},
    	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 !== "" && fileManagerParam !== "/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 !== "" && fileManagerParam !== "/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.css.disabled = !this.css.disabled;
    		if (!this.css.disabled) {
    			this.setAttribute("checked", "true");
    		} else {
    			this.removeAttribute("checked");
    		}
    	}
    });
    			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); }
    	}, 3000); 
    })();
    Alles anzeigen
  • extra_config_menu.uc.js > ohne security.allow_unsafe_dangerous_privileged_evil_eval auf false

    • bege
    • 25. August 2026 um 20:44

    Mira_Belle Unten ist meine bisherige, unveränderte Version, die auch im FF 154 funktioniert. Die Symbole für Button und Menü habe ich jetzt nicht getestet, weil ich das Menü zusammen mit anderen Skripten und Menüs ins App-Menü verschiebe und dafür die Symbol mit einem eigenen CSS anpassen muss. Ansonsten ist es mir lieber, wenn die Symbole im Skript enthalten sind und nicht mit einem separaten CSS hinzugefügt werden müssen. Das wird für mich leicht unübersichtlich. (Ich habe ein anderes Symbol, weil ich das Skript hauptsächlich für das Untermenü mit den Skripten verwende, die meisten anderen Menüs sind bei mir ausgeblendet.)

    Alle Einstellungen, was angezeigt wird und was nicht, finden im Konfigurationsabschnitt am Anfang statt. Zusätzlich etwas per CSS auszublenden ist für mich unübersichtlich.
    In den Erläuterungen für die Konfiguration habe ich vermieden, Zeilennummern anzugeben (passt bei dir z.B. in Zeile 21 nicht), weil die sich mit jeder Änderung verschieben. Stattdessen so etwas wie "im Folgenden ...".

    Was hier, glaube ich, schon diskutiert wurde, ist, ob userChromeShadow.uc.js aufgelistet werden soll. Ich nutze das bisher nicht, es würde mich aber stören, wenn ich nicht alle Skripte angezeigt bekomme, die geladen werden. Deshalb würde ich das die Nutzer auch in der Konfiguration steuern lassen, anstatt es "hart zu verdrahten".

    Wesentliche Ergänzungen in meiner Version sind

    • Parameter für den Dateimanager (Zeile 23 - 25)
    • konfigurierbarer Skripte-Unterordner (Zeilen 26 - 28)
    • Einstellung, in welchem Menü, falls als Menü angezeigt (Zeilen 31 - 33)
    • umfangreichere Einstellungen für CSS-Ordner (war mal von einem Nutzer hier im Forum angefragt) (Zeilen 38 - 47)

    Beim Überfliegen deiner Version war ich mir nicht sicher, ob alle menuseparator in die if-Abfragen eingebunden sind, sodass sie jeweils nur angezeigt werden, wenn der jeweilige Menüpunkt auch angezeigt wird.

    Mit etwas mehr Muße schaue ich mir deine Version genauer an.

    JavaScript: extras_config_menu-Fx135.uc.js
    // ==UserScript==
    // @name           extras_config_menu.uc.js
    // @compatibility  Firefox 135*.*
    // @include        main
    // @version        1.0.20250112
    // @edit           @aborix 7/21 CSS Dateien als Untermenü eingefügt 
    // @edit           @2002Andreas 8/21 Shadow CSS Dateien als Untermenü + Ordner eingefügt
    // @edit 	   @BrokenHeart	1/25 Anpass. wg. Änderung der Sicherheitsrichtlinien bei 'inlineEvents'
    // @edit           @bege, eigene Änderungen
    // ==/UserScript==
    
    var uProfMenu = {
      // Beginn der Konfiguration -------------------------------------------------------------------
      
      // In der folgenden Zeile den Pfad zum Texteditor eintragen (unter Ubuntu 10.04 z.B.: '/usr/bin/gedit'). Bei Fehleintrag wird view_source.editor.path ausgelesen:
      //TextOpenExe: 'C:\\Program Files (x86)\\Notepad++\\notepad++.exe',
      TextOpenExe: 'C:\\Program Files\\Notepad++\\notepad++.exe',
      // Falls gewuenscht, in der Zeile nach den Beispielen einen Dateimanager eintragen (komplett leer lassen fuer Dateimanager des Systems) Beispiele:
      // vFileManager: 'E:\\Total Commander\\Totalcmd.exe',
      // vFileManager: 'C:\\Program Files (x86)\\FreeCommander\\FreeCommander.exe'
      vFileManager: 'C:\\Program Files\\FreeCommander XE\\FreeCommander.exe',
      // eventuelle Parameter für den alternativen Dateimanager, sonst vFilemanagerParam = "";
      //vFilemanagerParam = "/O /T";//Totalcommander, Freecommander
      vFMParam: "/T",
      // Falls die JavaScript-Scripte nicht im chrome-Verzeichnis, sondern einem Unterverzeichnis sind,
      // in der folgenden Zeile das Unterverzeichnis eintragen, sonst '':
      jsSubfolder: 'JS',
      // Im Folgenden bei "location" 'menu' eintragen, damit es in der Menueleiste erscheint, sonst '', damit es als Button erscheint:
      location: 'menu',
      // Für die Einstellung 'menu' wird hier der Ort festgelegt, wo das Menue angezeigt werden soll.
      // (0: in der Menueleiste, 1: im Extras-Menue)
      menuLocation: 0,  
      // Unter Linux sollte/kann versucht werden, die userChromeJS-Skripte zu sortieren, unter Windows ist das evtl. nicht noetig (die Sortierung wird Gross- und Kleinschreibung *nicht* beruecksichtigen - dazu wird die sort()-Funktion entsprechend mit einer Vergleichsfunktion aufgerufen)
      sortScripts: 0,   // 1 zum Erzwingen der Sortierung
      // Einbindung GM-Skripte-Ordner (0: nein, 1: Greasemonkey [Profil-Verzeichnis], 2: UserScriptLoader [Chrome-Verzeichnis], 3: Scriptish [Profil-Verzeichnis]):
      gmOrdner: 0,
      // Einbindung CSS-Ordner (0: nein, 1: ja, Chrome-Unterordner, 2: ja, anderer Pfad):
      cssOrdner: 0,
      // Wenn cssOrdner = 1 oder 2, hier entweder Chrome-Unterordner (z.B. 'CSS') oder andere vollständige Pfade (z.B. 'C:\\Dropbox\\Chrome\\Thunderbird\\CSS-Ordner\\css-dateien') entragen, sonst '':
      cssLocation1: 'CSS',
      cssLocation2: '',
      cssLocation3: '',
      //Anzeigenamen für die CSS-Ordner
      cssLocation1Name: 'CSS-Ordner',
      cssLocation2Name: 'CSS-Ordner2',
      cssLocation3Name: 'CSS-Ordner3',
      // In einer der folgenden Zeilen gueltige about:Adressen eintragen, die ebenfalls aufgerufen werden sollen.
      // - Zum Ausblenden: abouts: [],
      // - Damit die about:-Seiten nicht als Untermenue, sondern direkt als Menuepunkte aufgefuehrt werden, muss das erste Element '0' sein:
      // abouts: ['0','about:config','about:about','about:cache','about:certificate','about:checkerboard','about:crashes','about:debugging','about:devtools','about:memory','about:networking','about:performance','about:policies','about:profiles','about:serviceworkers','about:support','about:telemetry','about:url-classifier','about:webrtc'],
      // abouts: ['about:config','about:about','about:cache','about:certificate','about:checkerboard','about:crashes','about:debugging','about:devtools','about:memory','about:networking','about:performance','about:policies','about:profiles','about:serviceworkers','about:support','about:telemetry','about:url-classifier','about:webrtc'],
       abouts: [],
      // Einbindung config-Dateien wie user.js etc. (0: nein, 1: ja)
       configFiles: 0,
      // Die Firefox-Ordner anzeigen (0: nein, 1: ja):
       firefoxOrdner: 0,
      // Die normalen Firefox-Einstellungen auch zur Verfuegung stellen (0: nein, 1: ja):
      showNormalPrefs: 0,
      // Stellt "Skriptliste in Zwischenablage" zur Verfuegung (1: ja, 2: mit getrennter Nummerierung, 3: mit gemeinsamer Nummerierung) oder nicht (0):
      enableScriptsToClip: 3,
      // Den Eintrag "Neustart" anzeigen (0: nein, 1: ja):
      enableRestart: 0,
      
      // Ende der Konfiguration ---------------------------------------------------------------------------
    
      init: function() {
        if (this.location.toLowerCase() == 'menu') {
          // aufgrund des gewaehlten 'location' als Menue anlegen
          if (this.menuLocation) {
          var zielmenu = document.getElementById('menu_ToolsPopup');
          } else {
             var zielmenu = document.getElementById('main-menubar');
          }
        
          if (zielmenu==null) {
            userChrome.log("extras_config_menu.uc.js findet Zielmenue nicht, evtl. weil ein anderes Fenster als das Hauptfenster " +
                           "geoeffnet wurde. Falls dieser Fehler auch im Hauptfenster auftritt, bitte die vorgehende Definition " +
                           "von 'zielmenu' kontrollieren.");
           return
          }
          var menu = zielmenu.appendChild(this.createME("menu","Config-Menü",0,0,"ExtraConfigMenu"));
          //menu.setAttribute("class","menu-iconic");
          menu.setAttribute("tooltiptext","Mittelklick öffnet about:config");
          menu.setAttribute("accesskey", "M");
          menu.addEventListener('click',function(event) {
            if (event.button == 1 && !this.open) {
              openTrustedLinkIn('about:config', 'tab');
            }
          });
         } else {
    		 
    	 // als verschiebbaren Button anlegen
          if (window.__SSi == "window0") {
            CustomizableUI.createWidget({
              id: "ExtraConfigMenu-button",
              defaultArea: CustomizableUI.AREA_NAVBAR,
              label: "Extra Config Menü",
              tooltiptext: "Extra Config Menü\nRechtsklick \öffnet about:config"
            });
    		
          }
          var menu = document.getElementById("ExtraConfigMenu-button");
          menu.setAttribute("type", "menu");
    	  menu.addEventListener('click', function(event) {
    			if (event.button == 2 && !this.open) { 
    				openTrustedLinkIn("about:config", "tab");
    				event.preventDefault();
    			};
    	 },true);
         }
        var css = " \
          #ExtraConfigMenu-button { \
            list-style-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAC4gAAAuIAeWOKUkAAAEZSURBVDhP7ZMxLENRFIa/c2l5ESrFI+KpoUQTRoOYTJp0NBgsFpP5xSAxWNgkNlYJo72L3SIhMRiaaCxdRKIRkfQet+81FhUPsTnLvfnPzfefc3Ku6MW08oswrfPH8Q/4c8DohjKyFt+7AmVix5I/ULIlG4tfAfoXlb75eE+mDiGzIBgPctuG9HCkJ2tBOpTunPB4DrfrwvWS8lqTZioZQBvCQ9nirwqFU6Vn9n17kw+xEhqqu5a079o5MgwuR3NoD0j5sYO4tLbMmq61Y8NVUXipKAOlT1oINi0zZ8L4lsWbjB/3zlkKJ+KclSB0VYw5/S4if/yNKVdiECpeHp5vlOqe0HgSskXL0IrQmYH6JdzvO73eBvCtgDf14FTmcYgI3gAAAABJRU5ErkJggg==);  \
    		 margin-top: 0px !important; \);  \
    		 margin-top: 0px !important; \
    		 opacity: 1 !important;\
          } \
          #ExtraConfigMenu-button > dropmarker, #ExtraConfigMenu-button > hbox > .toolbarbutton-menu-dropmarker { \
            display: none !important; \
          } \
          #ExtraConfigMenu .menubar-text { \
            margin-inline-start: 0px !important;\
          }";
    
        //ab hier ist alles gleich, egal ob Button oder Menue
    
        var sss = Cc['@mozilla.org/content/style-sheet-service;1'].getService(Ci.nsIStyleSheetService);
        var uri = makeURI('data:text/css;charset=UTF=8,' + encodeURIComponent(css));
        sss.loadAndRegisterSheet(uri,sss.AGENT_SHEET);
    	menu.addEventListener('popupshowing', function(event) {
    			uProfMenu.getScripts(0);
    		//	uProfMenu.getCss(3);
    		//	uProfMenu.getCss(4);
    		//	uProfMenu.getCss(5);
    	 },true);
    	
        var menupopup = menu.appendChild(this.createME("menupopup",0,0,0,"ExtraConfigMenu-popup"));
        // Anlegen von Untermenues fuer userChromeJS-Skripte (befuellt werden sie spaeter)
        var submenu = menupopup.appendChild(this.createME("menu","uc.js",0,0,"submenu-ucjs"));
        var submenupopup = submenu.appendChild(this.createME("menupopup",0,0,0,"submenu-ucjs-items"));
        // var submenu = menupopup.appendChild(this.createME("menu","uc.xul",0,0,"submenu-ucxul"));
        // var submenupopup = submenu.appendChild(this.createME("menupopup",0,0,0,"submenu-ucxul-items"));
        menupopup.appendChild(this.createME("menuitem","uc.js-Datei erstellen","uProfMenu.createJSfile()","uProfMenu_createJSfile",0));
        if (this.enableScriptsToClip) menupopup.appendChild(this.createME("menuitem","Skriptliste in Zwischenablage","uProfMenu.getScripts(1)","uProfMenu_clipboard",0));
        // Ende Anlegen von Untermenues fuer die userChromeJS-Skripte
        if (this.configFiles)menupopup.appendChild(document.createXULElement('menuseparator'));
        // Einbindung von Konfigdateien
        if (this.configFiles) {
        menupopup.appendChild(this.createME("menuitem","userChrome.js","uProfMenu.edit(3,'userChrome.js');","uProfMenu_edit",0));
        menupopup.appendChild(this.createME("menuitem","userChrome.css","uProfMenu.edit(3,'userChrome.css');","uProfMenu_edit",0));
        menupopup.appendChild(this.createME("menuitem","userContent.css","uProfMenu.edit(3,'userContent.css');","uProfMenu_edit",0));
        menupopup.appendChild(this.createME("menuitem","prefs.js","uProfMenu.edit(1,'prefs.js');","uProfMenu_edit",0));
        menupopup.appendChild(this.createME("menuitem","user.js","uProfMenu.edit(1,'user.js');","uProfMenu_edit"),0);
        };
        // Ende Einbindung von Konfigdateien
        if (this.gmOrdner || this.cssOrdner) menupopup.appendChild(document.createXULElement('menuseparator'));
        // Einbindung von Ordnern
        switch (this.gmOrdner) {
          case 1:
            menupopup.appendChild(this.createME("menuitem","GM-Skripte","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfD')+uProfMenu.getDirSep()+'gm_scripts');","uProfMenu_folder"),0);
            break;
          case 2:
            menupopup.appendChild(this.createME("menuitem","USL-Skripte","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'UserScriptLoader');","uProfMenu_folder"),0);
            break;
          case 3:
            menupopup.appendChild(this.createME("menuitem","Scriptish-Skripte","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfD')+uProfMenu.getDirSep()+'scriptish_scripts');","uProfMenu_folder"),0);
            break;
        }
        
        if (this.cssOrdner) {
           if (this.cssOrdner == 1) {
          menupopup.appendChild(this.createME("menuitem",this.cssLocation1Name,"uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+uProfMenu.cssLocation1);","uProfMenu_folder"),0);
              if (this.cssLocation2.length>0) {
                 menupopup.appendChild(this.createME("menuitem",this.cssLocation2Name,"uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+uProfMenu.cssLocation2);","uProfMenu_folder"),0);
              };
              if (this.cssLocation3.length>0) {
                 menupopup.appendChild(this.createME("menuitem",this.cssLocation3Name,"uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+uProfMenu.cssLocation2);","uProfMenu_folder"),0);
              };
           } else {menupopup.appendChild(this.createME("menuitem",this.cssLocation1Name,"uProfMenu.dirOpen(uProfMenu.cssLocation1);","uProfMenu_folder"),0);
                if (this.cssLocation2.length>0) {
                menupopup.appendChild(this.createME("menuitem",this.cssLocation2Name,"uProfMenu.dirOpen(uProfMenu.cssLocation2);","uProfMenu_folder"),0);
                };
                if (this.cssLocation3.length>0) {
                menupopup.appendChild(this.createME("menuitem",this.cssLocation3Name,"uProfMenu.dirOpen(uProfMenu.cssLocation3);","uProfMenu_folder"),0);
                };
            }
        }
        
        if (this.firefoxOrdner) menupopup.appendChild(document.createXULElement('menuseparator'));
    
        if (this.firefoxOrdner) {
        menupopup.appendChild(this.createME("menuitem","Chromeordner","uProfMenu.prefDirOpen('UChrm');","uProfMenu_folder"),0);
        menupopup.appendChild(this.createME("menuitem","Profilordner","uProfMenu.prefDirOpen('ProfD');","uProfMenu_folder"),0);
     //   menupopup.appendChild(this.createME("menuitem","Icons-Ordner","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'Icons');","uProfMenu_folder"),0);
        menupopup.appendChild(this.createME("menuitem","Installationsordner","uProfMenu.prefDirOpen('CurProcD');","uProfMenu_folder"),0);
        menupopup.appendChild(this.createME("menuitem","Addonordner","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfD')+uProfMenu.getDirSep()+'extensions');","uProfMenu_folder"),0);
        menupopup.appendChild(this.createME("menuitem","Startup-Cacheordner","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfLD')+uProfMenu.getDirSep()+'startupCache');","uProfMenu_folder"),0);
      /*   menupopup.appendChild(this.createME("menuitem","Ordner about","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'about');","uProfMenu_folder"),0); */
        }
        // Ende Einbindung von Ordnern
        
        if (this.abouts.length>0 || this.showNormalPrefs) menupopup.appendChild(document.createXULElement('menuseparator'));
        
        // Einbindung von abouts
        if (this.abouts.length>0) {
          // falls der erste Eintrag des Arrays = '0' ist, dann kein Untermenue anlegen, sondern direkt als Menuepunkte einbinden
          if (this.abouts[0]=='0') {
            for (var i = 1; i < this.abouts.length; i++) {
            menupopup.appendChild(this.createME("menuitem",this.abouts[i],"openTrustedLinkIn('"+this.abouts[i]+"','tab')","uProfMenu_about"),0);
            }
           } else {
            // der erste Eintrag des arrays ist ungleich '0', deshalb als Untermenue einrichten
            var submenu = menupopup.appendChild(this.createME("menu","uc.js",0,0,"submenu-about"));
            var submenupopup = submenu.appendChild(this.createME("menupopup",0,0,0,"submenu-about-items"));
            this.fillMenu("submenu-about","submenu-about-items", "about:",this.abouts,"uProfMenu_about",1);
          }
        };
        // Ende Einbindung von abouts
        // Separator, falls dieser nicht schon durch abouts generiert wurde und weitere Menuepunkte folgen werden
       // if (this.abouts.length==0 && (this.showNormalPrefs || typeof(ToolRstartMod) != "undefined")) menupopup.appendChild(document.createXULElement('menuseparator'));
        // Falls gewuenscht (s. Konfigurationsabschnitt), Zugriff auf die normalen Einstellungen
        if (this.showNormalPrefs) menupopup.appendChild(this.createME("menuitem","Einstellungen","try{openOptionsDialog();}catch(e){openPreferences();}","uProfMenu_prefs"),0);
        
        if (this.enableRestart) menupopup.appendChild(document.createXULElement('menuseparator'));
    
        // Falls enableRestart = 1, Neustart-Menuepunkt zur Verfügung stellen
        if(this.enableRestart) menupopup.appendChild(this.createME("menuitem","Neustart",
        "Services.appinfo.invalidateCachesOnRestart(); Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit,0);"));
        },
    
      getDirSep:function() {
        // Betriebssystem nach https://developer.mozilla.org/en/Code_snippets/Miscellaneous ermitteln
        var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS;
        var dirsep = "/";
        switch(osString) {
          case "WINNT":
            dirsep = "\\";
            break;
          case "Linux":
            dirsep = "/";
            break;
          case "Darwin":
            dirsep = "/";
            break;
        }
        return dirsep;
      },
    
      edit:function(OpenMode,Filename){
        var Path = "";
        var dSep = this.getDirSep();  // die Trennzeichen zwischen Ordnern abhaengig vom Betriebssystem machen
        switch (OpenMode){
          //Current is Chrome Directory or Subfolder
          case 0:
            if (this.jsSubfolder.length != 0) {
            var Path = this.getPrefDirectoryPath("UChrm") + dSep + this.jsSubfolder + dSep + Filename;
            } else {
               var Path = this.getPrefDirectoryPath("UChrm") + dSep + Filename;
            }
            break;
          //Current is Profile Directory
          case 1:
            var Path = this.getPrefDirectoryPath("ProfD") + dSep + Filename;
            break;
          //Current is Root
          case 2:
            var Path = Filename;
            break;
          //Current is Chrome Directory
          case 3:
            var Path = this.getPrefDirectoryPath("UChrm") + dSep + Filename;
            break;
        }
        this.launch(this.TextOpenExe,Path);
      },
    
      dirOpen:function(Path){
        var dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
        if (this.vFileManager.length != 0) {
          var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
          var args = [this.vFMParam,Path];
          dir.initWithPath(this.vFileManager);
          process.init(dir);
          // Verzeichnis mit anderem Dateimanager oeffnen
          process.run(false, args, args.length);
         } else {
          // Verzeichnis mit Dateimanager des Systems oeffnen
          dir.initWithPath(Path);
          dir.launch();
        }
      },
    
      prefDirOpen:function(prefDir){
        Path = this.getPrefDirectoryPath(prefDir);
        this.dirOpen(Path);
      },
    
      getPrefDirectoryPath:function(str){
        // get profile directory
        var file = Components.classes["@mozilla.org/file/directory_service;1"]
          .getService(Components.interfaces.nsIProperties)
          .get(str, Components.interfaces.nsIFile);
       // folgende 3 Zeilen nur für Firefox, nicht für Thunderbird
        if (str == 'CurProcD') {
          file = file.parent;
        };
        return file.path;
      },
    
      launch:function(RanPath,OpenPath){
        var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIFile);
        var proc = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
        var args = [OpenPath];
        file.initWithPath(RanPath);
        // falls der im Konfigurationsabschnitt definierte Editor nicht gefunden wird, auf Einstellung in about:config ausweichen:
        if (!file.exists()) {
          var pref = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
          RanPath = pref.getCharPref("view_source.editor.path");
          file.initWithPath(RanPath);
        }
        proc.init(file);
        proc.run(false, args, args.length);
      },
    
      stringComparison:function(a, b){
        a = a.toLowerCase();
        a = a.replace(/ä/g,"a");
        a = a.replace(/ö/g,"o");
        a = a.replace(/ü/g,"u");
        a = a.replace(/ß/g,"s");
        b = b.toLowerCase();
        b = b.replace(/ä/g,"a");
        b = b.replace(/ö/g,"o");
        b = b.replace(/ü/g,"u");
        b = b.replace(/ß/g,"s");
        return(a==b)?0:(a>b)?1:-1;
      },
    
      getScripts:function(iType) {
        // Arrays (jeweils ein Array fuer uc.js und uc.xul) nehmen Namen der gefundenen Skripte auf
        let ucJsScripts = [];
        // let ucXulScripts = [];
        // Suchmuster, also die Dateierweiterungen uc.js und uc.xul
        let extjs = /\.uc\.js$/i;
        //let extxul = /\.uc\.xul$/i;
        let aFolder = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
        if (this.jsSubfolder.length != 0) {
           aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path+uProfMenu.getDirSep()+this.jsSubfolder);
        } else {
            aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path);
        };
        // files mit Eintraegen im Chrome-Ordner befuellen
        let files = aFolder.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
        // Ordner bzw. files durchlaufen und kontrollieren, ob gesuchte Dateien dabei sind
        while (files.hasMoreElements()) {
          let file = files.getNext().QueryInterface(Ci.nsIFile);
          // keine gewuenschte Datei, deshalb continue
          // if (!extjs.test(file.leafName) && !extxul.test(file.leafName)) continue;
          // uc.js gefunden -> im Array ablegen
          if (extjs.test(file.leafName)) ucJsScripts.push(file.leafName);
          // uc.xul gefunden -> im Array ablegen
          // if (extxul.test(file.leafName)) ucXulScripts.push(file.leafName);
        }
        if (this.sortScripts) {
          ucJsScripts.sort(this.stringComparison);
          // ucXulScripts.sort(this.stringComparison);
        }
        // Aufruf der naechsten Methoden um die beiden Untermenues oder die Zwischenablage zu befuellen
        if (iType==0) {
          this.fillMenu("submenu-ucjs","submenu-ucjs-items", "uc.js",ucJsScripts,"uProfMenu_ucjs",0);
          // this.fillMenu("submenu-ucxul","submenu-ucxul-items", "uc.xul",ucXulScripts,"uProfMenu_ucxul",0);
         } else {
          var result = this.fillClipboardValue(ucJsScripts/*,ucXulScripts*/);
          Components.classes["@mozilla.org/widget/clipboardhelper;1"].getService(Components.interfaces.nsIClipboardHelper).copyString(result);
        }
      },
    
    /*  getCss:function(iType) {
        // Array nimmt Namen der gefundenen css-Dateien auf
        let cssFiles = [];
        // Suchmuster, also die Dateierweiterung css
        let extcss = /\.css$/i;
        let aFolder = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
        if (iType==3) {
          aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path+this.getDirSep()+"CSS");
         } else if (iType==4) {
          aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path+this.getDirSep()+"CSSWeb");
        }  else if (iType==5) {
          aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path+this.getDirSep()+"CSSShadow");
        }
        // files mit Eintraegen im CSS- bzw. CSSWeb-Ordner befuellen
        let files = aFolder.directoryEntries.QueryInterface(Ci.nsISimpleEnumerator);
        // Ordner bzw. files durchlaufen und kontrollieren, ob gesuchte Dateien dabei sind
        while (files.hasMoreElements()) {
          let file = files.getNext().QueryInterface(Ci.nsIFile);
          // css gefunden -> im Array ablegen
          if (extcss.test(file.leafName)) cssFiles.push(file.leafName);
        }
        if (this.sortScripts) {
          cssFiles.sort(this.stringComparison);
        }
        // Untermenue befuellen
        if (iType==3) {
          this.fillMenu("submenu-css","submenu-css-items","Meine CSS-Dateien",cssFiles,"uProfMenu_css",3);
         } else if (iType==4) {
          this.fillMenu("submenu-cssweb","submenu-cssweb-items","Meine CSSWeb-Dateien",cssFiles,"uProfMenu_css",4);
        }  else if (iType==5) {
          this.fillMenu("submenu-CSSShadow","submenu-CSSShadow-items","Meine CSSShadow-Dateien",cssFiles,"uProfMenu_css",5);
        }
      },
    */
      fillMenu:function(whichsubmenu, whichsubmenuitems, strlabel, scriptArray,sClass,sTyp) {
        // Beschriftung des Untermenues mit Anzahl der gefundenen Dateien ergaenzen
        var e = document.getElementById(whichsubmenu);
        e.setAttribute('label',strlabel + ' (' + scriptArray.length + ')');
        var popup = document.getElementById(whichsubmenuitems);
        // zunaechst Untermenue zuruecksetzen
        while(popup.hasChildNodes()){
          popup.removeChild(popup.firstChild);
        }
        // Untermenue endlich befuellen
        for (var i = scriptArray.length-1; i > -1; i--) {
          // Typunterscheidung (userChromeJS-Skript oder about:)
          if (sTyp==0){
            var mitem = this.createME("menuitem",scriptArray[i],"uProfMenu.edit(0,'"+scriptArray[i]+"')",sClass,0);
    		mitem.addEventListener('click', function(event) {
    			uProfMenu.openAtGithub(event,'"+scriptArray[i]+"');
    			event.preventDefault();
    		},true);
    		
            mitem.setAttribute("tooltiptext"," Linksklick: Bearbeiten,\n Mittelklick: https://github.com/.../"+this.cleanFileName(scriptArray[i])+" oeffnen,\n Rechtsklick: Suche auf GitHub");
           } else if (sTyp==1){
            var mitem = this.createME("menuitem",scriptArray[i],"openTrustedLinkIn('"+scriptArray[i]+"','tab')",sClass,0);
           } /* else if (sTyp==3){
            var mitem = this.createME("menuitem",scriptArray[i],"uProfMenu.edit(3,'"+scriptArray[i]+"')",sClass,0);
           } else if (sTyp==4){
            var mitem = this.createME("menuitem",scriptArray[i],"uProfMenu.edit(4,'"+scriptArray[i]+"')",sClass,0);
          }
    	  else if (sTyp==5){
            var mitem = this.createME("menuitem",scriptArray[i],"uProfMenu.edit(5,'"+scriptArray[i]+"')",sClass,0);
          } */
          popup.insertBefore(mitem, popup.firstChild);
        }
      },
    
      fillClipboardValue:function(sArray/* ,xArray */) {
        var retValue;
        var s = 0;
        // var x = 0;
        s = sArray.length;
        // x = xArray.length;
        switch(this.enableScriptsToClip) {
          case 1:
            retValue = "userChromeJS/uc.js ("+s+"):\n------------------------\n"+sArray.join("\n"); // +
                       // "\n\nuserChromeJS/uc.xul ("+x+"):\n-------------------------\n"+xArray.join("\n");
            break;
          default:
            retValue = "userChromeJS/uc.js ("+s+"):\n------------------------";
            for (var i = 0; i < s ; i++) {
              j = i + 1;
              retValue = retValue + "\n" + j + ". " + sArray[i];
            }
     /*       retValue = retValue + "\n\nuserChromeJS/uc.xul ("+x+"):\n-------------------------";
            if (this.enableScriptsToClip==2) s = 0;
            for (var i = 0; i < x ; i++) {
              j = i + s + 1;
              retValue = retValue + "\n" + j + ". " + xArray[i];
            } */
            break;
        }
        return retValue;
      },
    
      createME:function(sTyp,sLabel,sCommand,sClass,sId) {
        // Anlegen von menuitem, menu oder menupop - fuer bestimmte Typen nicht eingesetzte Parameter werden als 0 uebergeben
        const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
        var m = document.createElementNS(XUL_NS, sTyp);
        switch (sTyp) {
          case "menuitem":
            // this.createME("menuitem","Label des Items","ZuzuweisenderCodeFueroncommand","GewuenschteKlasseDesItems",0)
            m.setAttribute('label', sLabel);
            m.setAttribute('class',sClass);
    		m.addEventListener('command', function(event) {
    			Function(sCommand)();
    		}, true);
    		
            break;
          case "menu":
            // this.createME("menu","Label des Menues",0,0,"GewuenschteIdDesMenues")
            m.setAttribute('label', sLabel);
            m.setAttribute('id', sId);
            break;
          case "menupopup":
            //this.createME("menupopup",0,0,0,"GewuenschteIdDesMenupopups");
            m.setAttribute('id', sId);
            break;
        }
        return m;
      },
    
      openAtGithub:function(e,sScript) {
        if (e.button==1){
          // Mittelklick - Seite auf GitHub oeffnen (funktioniert nur, wenn Ordner- und bereinigter Dateiname [ohne Erweiterung] uebereinstimmen):
          var sUrl = "https://github.com/Endor8/userChrome.js/tree/master/"+this.cleanFileName(sScript);
          openWebLinkIn(sUrl, 'tab');
        }
        if (e.button==2){
          // Rechtsklick - Suche auf GitHub starten (funktioniert nur, wenn der Dateiname im Code hinterlegt ist):
          e.preventDefault();
          var sUrl = "https://github.com/search?langOverride=&language=&q="+this.cleanFileName(sScript)+"&repo=&start_value=1&type=Code";
          openWebLinkIn(sUrl, 'tab');
        }
      },
    
    	createJSfile: function(Filename) {
    		if (!Filename) Filename = prompt("Name des Skripts", "skriptName");
    		if (Filename) Filename = Filename.replace(/\s+/g, " ").replace(/[\\/:*?\"<>|]/g, "");
    		if (!Filename || !/\S/.test(Filename)) return;
    		if (!/\.uc.js$/.test(Filename)) Filename += ".uc.js";
    		this.edit(0, Filename);
    	},
    
      cleanFileName:function(sName) {
        sName = sName.toLowerCase();
        /* Das folgende Array enthaelt regulaere Ausdruecke, um ungueltige Zeichenfolgen entfernen:
        /Datei-Erweiterungen am Ende/, /"ucjs_" am Anfang/, /"_"gefolgtVonZahlUndDanachBeliebigenZeichen/
        / "_fx"gefolgtVonZahl(en)/, /"-" oder "+" oder "."/, /"_v"gefolgtVonZahlen
        */
        var regs = [/\.uc\.js$/,/\.uc\.xul$/,/^ucjs_/,/_\d.+/,/_fx\d+/,/[-+\.]/g,/_v\d+/];
        for (var i = 0; i < regs.length; i++) {
          sName = sName.replace(regs[i],"");
        }
        return sName;
      }
    
    };
    
    uProfMenu.init();
    Alles anzeigen
  • extra_config_menu in Betterbird funktioniert nicht mehr

    • bege
    • 20. August 2026 um 22:08
    Seit Update auf Betterbird 153 funktioniert extra_config-menu nicht mehr - Thunderbird Mail DE
    Einzelne Einstellungen in extra_config_menu wie Einstellungen und das Icon für den Neustart (nicht sichtbar) im Datei-Orner nicht mehr.
    www.thunderbird-mail.de
  • extra_config_menu.uc.js > ohne security.allow_unsafe_dangerous_privileged_evil_eval auf false

    • bege
    • 17. August 2026 um 01:50
    Zitat von Endor

    Ist erledigt:

    https://github.com/Endor8/userChr…r/Firefox%20153

    In der Version fehlen viele Erläuterungen im Vergleich zur Version für FF 135, sowohl für die Konfiguration als auch innerhalb des Skripts zur Funktion einzelner Teile. (Einige sind aber zugefügt.) Ich wüsste nicht, wie ich die Konfiguration einstellen muss, noch, was die einzelnen Skriptteile tun, was künftige Änderungen erschwert. Ich habe allerdings inzwischen eine an einigen Stellen abweichende Version, die ich deshalb beibehalte.

    Es gibt einige Änderungen mit der Erklärung (ANGEPASST: sCommand als Funktion). Welchen Vorteil hat das gegenüber der vorherigen Version? In der wird das an nur einer Stelle in den Zeilen 429 - 430 gelöst.

    Der Wert helpMenu in Zeile 20 stammt wohl noch aus einer älteren Version, als es den verschiebbaren Button noch nicht gab. Das ist in der Erläuterung der Version für FF 135 falsch. Es gibt es nur noch den Wert menu als Menü im Extras Menü (menu_ToolsPopup in Zeile 35 fest eingestellt) und sonst z.B. leer für Button. Das Skript prüft nur noch auf menu. Wenn das dort nicht steht, egal ob leer oder irgend etwas anderes, wird ein Button erstellt.

  • userChrome.js Scripte für den Fuchs (Diskussion)

    • bege
    • 5. Juli 2026 um 18:49

    Endor Danke. Ich habe meine Version mal durchgetestet und da geht mit FF 152.0.4 noch alles.

  • userChrome.js Scripte für den Fuchs (Diskussion)

    • bege
    • 27. Juni 2026 um 22:45

    Endor Was machen die Zeilen 98 bis 120 in der neuen Version von ExtensionOptionsMenu.uc.js in deinem Repo?

    Ich habe bisher keine Probleme in meiner - in einigem abweichenden - Version mit dem FF 152 gefunden, allerdings nutze ich nicht alle Funktionen des Skripts. Gibt es für die neue Version einen Beitrag hier im Forum? Die Suche nach "ExtensionOptionsMenu" hat nichts neues ergeben.

  • Diverse Scripte funktionieren nicht mehr in Nightly

    • bege
    • 27. Juni 2026 um 22:05
    Zitat von 2002Andreas

    erledigt;)

    Die URL im namespace ist noch nicht aktualisiert.

  • Diverse Scripte funktionieren nicht mehr in Nightly

    • bege
    • 27. Juni 2026 um 21:53
    Zitat von 2002Andreas

    Ich habe das mal per KI anpassen lassen, funktioniert hier ;)

    Vielen Dank.

    Vielleicht magst du noch diese Zeilen ändern, damit es aktuell ist:

    // @name           downloadSoundPlay_Fx 152.uc.js

    // @namespace      https://github.com/alice0775/userChrome.js

    // @compatibility  Firefox 152

    Im Repo von alice gibt es noch keine Lösung, ich habe deine Version dort verlinkt.

    downloadSoundPlay_Fx26.uc.js doesn't work any more with Fx 152 · Issue #99 · alice0775/userChrome.js
    The sound is not played any more after a finished download. The error console shows this error: 07:45:04.027 TypeError: sound.play is not a function play…
    github.com
  • Thunderbird 102.11 userChromeJS, Services is not defined in config.js

    • bege
    • 17. Mai 2026 um 17:15
    Zitat von laxx

    Thunderbird 102.11

    Die Dateien, die dort zum Download zur Verfügung gestellt werden, wurden für neuere Firefox-Versionen verändert. (Ich hatte mir zu den letzten notiert, dass sie ab Firefox 115 funktionieren.) Sie funktionieren im Firefox 150 und in bei mir auch in Thunderbird 140esr.

    Für Firefox angebotene Skripte müssen so gut wie immer für Thunderbird angepasst werden. Bei Endor gibt es einen eigenen Ordner dafür und weitere Skripte - dort allerdings über verschiedene Themen verteilt - im Thunderbird-Forum.

  • Diverse Scripte funktionieren nicht mehr in Nightly

    • bege
    • 10. Mai 2026 um 18:44
    Zitat von milupo

    Statt ownerGlobal steht dann in Zukunft documentGlobal.

    Funktioniert das schon ab v151 oder erst ab v152? Im aktuellen release v150.0.2 funktioniert es noch nicht, wie ja schon festgestellt wurde.

  • Ich bin einzigartig! 😉

    • bege
    • 10. Mai 2026 um 18:25
    Zitat von Sören Hentzschel

    Ich möchte da in keine Grundsatzdiskussion darüber gehen, wieso das eigentlich auch zum Vorteil des Anwenders wäre. Es ist ja legitim, dass man das grundsätzlich nicht möchte oder ein Problem damit hat, wie die Daten generiert werden. Mir geht es an dieser Stelle alleine darum: Dass man einen angepassten Inhalt sieht, ist so ziemlich das „Schlimmste”, was einem tatsächlich passiert, wenn man getrackt wird. Das hat nichts mit „Spionage” oder dergleichen zu tun.

    Danke, Sören, meine Frage nach dem Trackingschutz des Firefox ist beantwortet.

    Ich werde auch keine weitere Diskussion hier darüber fortführen, möchte aber zum Abschluss dieses Themas meine in einem Punkt abweichende Sichtweise neben deine stellen, nämlich, dass die Grenze zwischen "angepassten Inhalten", Manipulation und staatlicher Überwachung fließend ist, wie u.a. der Datenschutzskandal um Cambridge Analytica gezeigt hat. Eine einzelne Website mag nicht allzu viel über mich erfahren, Konzerne, deren Geschäftsmodell der Verkauf und die Zur-Verfügung-Stellung von Nutzerprofilen ist, schon. Zum Glück greift da zumindest bei Website-übergreifendem Tracking der Schutz von Firefox.

  • Skript für den Toolbox-Button funktioniert im Nightly nicht mehr

    • bege
    • 4. Mai 2026 um 21:18
    Zitat von grisu2099

    Das folgende Skript zum Öffnen der Browser-Werkzeuge mag im Nightly nicht mehr.

    Würdest du das bitte bei aminomancer posten? Vielleicht ist das der bessere Weg das Skript anzupassen. (Ich nutze den Nightly nicht.)

  • Ich bin einzigartig! 😉

    • bege
    • 3. Mai 2026 um 18:17

    Danke Sören Hentzschel .

    Habe ich das so richtig verstanden?: Der Trackingschutz von Firefox bezieht sich auf Third-Party-Tracking-Skripte, sodass z.B. Google oder Facebook nicht über Skripte das Surfverhalten von Benutzern verfolgen können. Er bezieht sich aber nicht auf einzelne Websites, die weiterhin gar keine Cookies o.ä. benötigen, um Benutzerprofile anzulegen, weil sie den Browser auf anderen Wegen wiedererkennen können, wenn sie das mit entsprechendem Aufwand betreiben wollen.

    Mein Ziel ist nicht mehr und nicht weniger als nicht getrackt werden zu wollen, das, was ich unter dem Trackingschutz des Firefox verstanden habe.

  • Ich bin einzigartig! 😉

    • bege
    • 28. April 2026 um 19:04
    Zitat von Sören Hentzschel

    Anonymität gehört nicht zu Mozillas Versprechen.

    Danke für deine Antwort.

    Ich habe den Trackingschutz so verstanden, dass ein Website-Betreiber nicht feststellen kann, wenn ich zum wiederholten Mal auf die Website komme. Wenn aber jede Website anhand einiger Merkmale meinen Firefox-Browser genau erkennen kann, besteht doch keine Trackingschutz? Habe ich da etwas grundsätzlich falsch verstanden?

    Zitat von Sören Hentzschel

    Laut der von dir genannten Seite bin ich auch mit Google Chrome in seiner Standard-Konfiguration einzigartig. Und das ist der mit Abstand meist genutzte Browser auf der Welt.

    Bei mir ist es vor allem der "Canvas", und soweit ich das verstanden habe, ist der stark systemabhängig, also weniger vom Browser. Wenn das so stimmt, kann der Firefox nicht trotzdem diese Erkennung verschleiern?

Unterstütze uns!

Jährlich (2026)

71,6 %

71,6% (554,79 von 775 EUR)

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