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. FuchsFan

Beiträge von FuchsFan

  • Selektor für kleinen Pfeil in CSS-Code zum extra-config-menü.uc.js ab v139

    • FuchsFan
    • 2. Mai 2025 um 14:59
    Zitat von Horstmann

    Unglaublich ....

    Tief Luft holen bringt den Puls wieder in Ordnung. Nun hör bitte auf damit, seid ihr alle unfehlbar?


    Zitat von Horstmann

    Oder mal sowas wie #ExtraConfigMenu-popup > menu:hover menu::after testen, mit oder ohne > ... 8)

    Bringt es auch nicht.:/

  • Selektor für kleinen Pfeil in CSS-Code zum extra-config-menü.uc.js ab v139

    • FuchsFan
    • 2. Mai 2025 um 14:43
    Zitat von Mira_Belle

    Wurdest Du nicht aufgefordert ganze Skripte zu posten?

    Nun fangt doch nicht schon wieder damit an, das nervt ja langsam. Aber du hast ja nicht ganz Unrecht, bitteschön.

    CSS
    // ==UserScript==
    // @name           extras_config_menu.uc.js
    // @compatibility  Firefox 6*.*
    // @include        main
    // @version        1.0.20190504
    // @edit           @aborix - Erweiterung mit Submenüs / 02.12.2022 
    // @edit           @FuchsFan - Erweiterung mit Ordner JS und Submenü Scripte
    // @edit 		   @BrokenHeart	1/25 - Anpass. wg. Änderung der Sicherheitsrichtlinien bei 'inlineEvents'
    // ==/UserScript==
    
    var uProfMenu = {
      // Beginn der Konfiguration
      // In der folgenden Zeile (11) 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:\\notepad++\\notepad++.exe',
      // Falls gewuenscht, in Zeile 15 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: '',
      // Falls die JavaScript-Scripte nicht im chrome-Verzeichnis, sondern einem Unterverzeichnis sind,
      // in der folgenden Zeile das Unterverzeichnis eintragen, sonst '':
      jsSubfolder: 'Scripte',
      // In der folgenden Zeile (19) 'menu' eintragen, damit es unter "Extras" als Menue erscheint, sonst die id des gewuenschten
      // Elements *nach* dem der Button erscheinen soll (z.B. 'urlbar', 'searchbar', 'undoclosetab-button','abp-toolbarbutton')
      // Bitte nicht so etwas wie die Menue- oder Navigationsleiste (sondern einen Menuepunkt oder einen Button mit id auf diesen Leisten) eintragen:
      warpmenuto: 'searchbar',
     // Unter Linux sollte/kann versucht werden, die userChromeJS-Skripte zu sortieren, unter Windows ist das evtl. nicht noetig (die Sortierung wird Gross- und Kleinschreibung *nicht* beruecksichtigen - dazu wird die sort()-Funktion entsprechend mit einer Vergleichsfunktion aufgerufen)
      sortScripts: 0,   // 1 zum Erzwingen der Sortierung
      // Einbindung GM-Skripte-Ordner (0: nein, 1: Greasemonkey [Profil-Verzeichnis], 2: UserScriptLoader [Chrome-Verzeichnis], 3: Scriptish [Profil-Verzeichnis]):
      gmOrdner: 0,
      // Einbindung CSS-Ordner (0: nein, 1: UserCSSLoader-Ordner im Chrome-Verzeichnis):
      cssOrdner: 0,
      // In Zeile 30 gueltige about:Adressen eintragen, die ebenfalls aufgerufen werden sollen.
      // - Zum Ausblenden: abouts: [],
      // - Damit die about:-Seiten nicht als Untermenue, sondern direkt als Menuepunkte aufgefuehrt werden, muss das erste Element '0' sein:
      // abouts: ['0','about:about','about:addons','about:cache','about:config','about:support'],
      abouts: ['about:about','about:addons','about:buildconfig','about:cache','about:certificate','about:compat','about:config','about:crashes','about:debugging',
               'about:logging','about:logins','about:loginsimportreport','about:memory','about:networking','about:performance','about:plugins','about:policies','about:preferences','about:privatebrowsing','about:profiles','about:processes','about:profiling',
               'about:protections','about:serviceworkers','about:support','about:telemetry','about:third-party','about:unloads','about:url-classifier','about:webrtc','about:welcome','about:welcomeback','about:windows-messages'],
      // 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: 1,
      // Um den Eintrag "Neustart" zu erzwingen (falls z.B. das andere Skript zu spaet eingebunden und nicht erkannt wird), auf 1 setzen:
      enableRestart: 1,
      // Ende der Konfiguration
      
      init: function() {
    	  
    	  if (location != 'chrome://browser/content/browser.xhtml') return;
    	  
        if (this.warpmenuto.toLowerCase() == 'menu') {
          // aufgrund des gewaehlten warpmenuto als Untermenue von Extras anlegen
          var zielmenu = document.getElementById('menu_ToolsPopup');
          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\u00FC",0,0,"ExtraConfigMenu"));
          menu.setAttribute("class","menu-iconic");
          menu.setAttribute("ondblclick","openTrustedLinkIn('about:config', 'tab');");
         } else {
          // als Button nach dem per warpmenuto gewaehlten Element anlegen (s. Kommentar ueber warpmenuto im Konfigurationsabschnitt)
          /* var zielmenu = document.getElementById(this.warpmenuto);
          if (zielmenu==null) {
            userChrome.log("extras_config_menu.uc.js findet Zielpunkt '"+this.warpmenuto+"' nicht, evtl. weil ein anderes Fenster als das Hauptfenster " +
                           "geoeffnet wurde. Falls dieser Fehler auch im Hauptfenster auftritt, bitte die vorgehende Definition " +
                           "von 'warpmenuto' kontrollieren.");
            return;
          }
          var menu = zielmenu.parentNode.insertBefore(document.createXULElement('toolbarbutton'), zielmenu.nextSibling);
          menu.setAttribute("id", "ExtraConfigMenu-button");
          menu.setAttribute("class", "toolbarbutton-1");
          menu.setAttribute("type", "menu");
          menu.setAttribute("tooltiptext", "Extra Config Menü\nMittelklick \öffnet about:config");
          menu.setAttribute("onclick", "if (event.button===1 && event.target==this) openTrustedLinkIn('about:config','tab');");
        } */
    	
    	// 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);
    	  
        }
    	
    	//ab hier ist alles gleich, egal ob Button oder Menue
        var css = " \
          #ExtraConfigMenu, #ExtraConfigMenu-button { \
            list-style-image: url(file:///C:/FoxIcons/1206.png) !important; margin-right: 10px !important; margin-bottom: 2px !important; margin-top: 2px !important; \
          } \
          #ExtraConfigMenu-button > dropmarker, #ExtraConfigMenu-button > hbox > .toolbarbutton-menu-dropmarker { \
            display: none !important; \
          }";
        var sss = Cc['@mozilla.org/content/style-sheet-service;1'].getService(Ci.nsIStyleSheetService);
        var uri = makeURI('data:text/css;charset=UTF=8,' + encodeURIComponent(css));
        sss.loadAndRegisterSheet(uri,sss.AGENT_SHEET);
    	menu.addEventListener('popupshowing', function(event) {
    			uProfMenu.getScripts(0);
    			uProfMenu.getCss(3);
    			uProfMenu.getCss(4);
    			uProfMenu.getCss(5);
    			uProfMenu.getCss(6);
    	 },true);
    	
        var menupopup = menu.appendChild(this.createME("menupopup",0,0,0,"ExtraConfigMenu-popup"));
        // Anlegen von Untermenues fuer userChromeJS-Skripte und CSS-Dateien (befuellen spaeter)
        var submenu=menupopup.appendChild(this.createME("menu","Scripte",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"));
        var submenu = menupopup.appendChild(this.createME("menu","css",0,0,"submenu-css"));
        var submenupopup = submenu.appendChild(this.createME("menupopup",0,0,0,"submenu-css-items"));
        var submenu = menupopup.appendChild(this.createME("menu","cssweb",0,0,"submenu-cssweb"));
        var submenupopup = submenu.appendChild(this.createME("menupopup",0,0,0,"submenu-cssweb-items"));
        var submenu = menupopup.appendChild(this.createME("menu","cssabout",0,0,"submenu-cssabout"));
        var submenupopup = submenu.appendChild(this.createME("menupopup",0,0,0,"submenu-cssabout-items"));
    	var submenu = menupopup.appendChild(this.createME("menu","cssshadow",0,0,"submenu-cssshadow"));
        var submenupopup = submenu.appendChild(this.createME("menupopup",0,0,0,"submenu-cssshadow-items"));
        
    	if (this.enableScriptsToClip) menupopup.appendChild(this.createME("menuitem","Skriptliste in Zwischenablage","uProfMenu.getScripts(1)","uProfMenu_clipboard",0));
    	
        // Ende Anlegen von Untermenues
    	    
    	menupopup.appendChild(document.createXULElement('menuseparator'));
        
    	// Einbindung von Konfigdateien
        menupopup.appendChild(this.createME("menuitem","userChrome.css","uProfMenu.edit(7,'userChrome.css');","uProfMenu_edit",0));
        menupopup.appendChild(this.createME("menuitem","userContent.css","uProfMenu.edit(7,'userContent.css');","uProfMenu_edit",0));
        menupopup.appendChild(this.createME("menuitem","userChromeShadow.css","uProfMenu.edit(7,'userChromeShadow.css');","uProfMenu_edit",0));
        menupopup.appendChild(this.createME("menuitem","userChrome.js","uProfMenu.edit(7,'userChrome.js');","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);
        menupopup.appendChild(this.createME("menuitem","policies.json","uProfMenu.edit(9,'policies.json');","uProfMenu_edit"),0);
        // Ende Einbindung von Konfigdateien
    	
    	// Einbindung von abouts
        if (this.abouts.length>0) {
          menupopup.appendChild(document.createXULElement('menuseparator'));
          // falls der erste Eintrag des Arrays = '0' ist, dann kein Untermenue anlegen, sondern direkt als Menuepunkte einbinden
          if (this.abouts[0]=='0') {
            for (var i = 1; i < this.abouts.length; i++) {
            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 Funktionen",this.abouts,"uProfMenu_about",1);
          }
        }
        // Ende Einbindung von abouts
    	
    	// Einbindung von Menü Funktionen
        var submenu = menupopup.appendChild(this.createME("menu","Funktionen",0,0,"submenu-extra2"));
        var submenupopup = submenu.appendChild(this.createME("menupopup",0,0,0,"submenu-extra2-items"));
        this.fillMenu("submenu-extra2","submenu-extra2-items", "Funktionen",
          [
            {label:'Addon-Manager', command:"BrowserAddonUI.openAddonsMgr();"},
    		{label:'Einstellungen', command:"openPreferences();"},
    		{label:'about:config', command:"openTrustedLinkIn('about:config', gBrowser.selectedTab.isEmpty ? 'current' : 'tab');"},
    		{label:'about:support', command:"openTrustedLinkIn('about:support', gBrowser.selectedTab.isEmpty ? 'current' : 'tab');"},
    		{label:'Browser-Werkzeuge', command:"var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});\
                          var { BrowserToolboxLauncher } = require('resource://devtools/client/framework/browser-toolbox/Launcher.sys.mjs');\
                          BrowserToolboxLauncher.init();",
    		},			  
    		{label:'Browser-Konsole', command:"var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});\
                          var { BrowserConsoleManager } = require('resource://devtools/client/webconsole/browser-console-manager');\
                          BrowserConsoleManager.openBrowserConsoleOrFocus();",
            },
    		{label:'Entwickler-Werkzeuge', command:"var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});\
                    var { gDevToolsBrowser } = require('devtools/client/framework/devtools-browser');\
                    gDevToolsBrowser.toggleToolboxCommand(window.gBrowser, Cu.now());",
            },
            {label:'Neustart im abgesicherten Modus', command:"safeModeRestart();"},		
    	  ],
          "extra2-directory",7);
        // Ende Einbindung von Menü Funktionen	  
    
        // Einbindung von Menü Verzeichnisse
        var submenu = menupopup.appendChild(this.createME("menu","Verzeichnisse",0,0,"submenu-extra"));
        var submenupopup = submenu.appendChild(this.createME("menupopup",0,0,0,"submenu-extra-items"));
        this.fillMenu("submenu-extra","submenu-extra-items", "Verzeichnisse",
          [
            {label:'Installationsordner', command:"uProfMenu.prefDirOpen('CurProcD')"},
    		{label:'Profilordner', command:"uProfMenu.prefDirOpen('ProfD')"},
            {label:'Icons', command:"uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'Icons');"},
    		{label:'IconsMenü', command:"uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'IconsMenü');"},
    		{label:'IconsHamburger', command:"uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'IconsHamburger');"},
    		{label:'Bookmark-Backups', command:"uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfD')+uProfMenu.getDirSep()+'bookmarkbackups');"},
    		{label:'Addonordner', command:"uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfD')+uProfMenu.getDirSep()+'extensions');"},
    		{label:'Startup-Cacheordner', command:"uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfD')+uProfMenu.getDirSep()+'startupCache');"},
    		{label:'FoxIcons', command:"uProfMenu.dirOpen('C:\\FoxIcons');"}, 
    		{label:'FoxIcons2', command:"uProfMenu.dirOpen('C:\\FoxIcons2');"},
    		{label:'FoxBilder', command:"uProfMenu.dirOpen('C:\\FoxBilder');"},
    		{label:'Download Firefox', command:"uProfMenu.dirOpen('D:\\Download Firefox');"}
    	  ],
          "extra-directory",7);
    	// Ende Einbindung von Menü Verzeichnisse  
        
        menupopup.appendChild(document.createXULElement('menuseparator'));
    	
        // Einbindung von Ordnern
        switch (this.gmOrdner) {
          case 1:
            menupopup.appendChild(this.createME("menuitem","GM-skripty","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfD')+uProfMenu.getDirSep()+'gm_scripts');","uProfMenu_folder"),0);
            break;
          case 2:
            menupopup.appendChild(this.createME("menuitem","USL-skripty","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'UserScriptLoader');","uProfMenu_folder"),0);
            break;
          case 3:
            menupopup.appendChild(this.createME("menuitem","Skripty Scriptish","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('ProfD')+uProfMenu.getDirSep()+'scriptish_scripts');","uProfMenu_folder"),0);
            break;
        }
        if (this.cssOrdner) {
          menupopup.appendChild(this.createME("menuitem","CSS-Ordner","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'CSS');","uProfMenu_folder"),0);
        }
        menupopup.appendChild(this.createME("menuitem","Ordner chrome","uProfMenu.prefDirOpen('UChrm');","uProfMenu_folder"),0);
        menupopup.appendChild(this.createME("menuitem","Ordner CSSWeb","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'CSSWeb');","uProfMenu_folder"),0);
        menupopup.appendChild(this.createME("menuitem","Ordner CSS","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'css');","uProfMenu_folder"),0);
    	
        //menupopup.appendChild(this.createME("menuitem","Profilordner","uProfMenu.prefDirOpen('ProfD');","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 CSSAbout","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'CSSAbout');","uProfMenu_folder"),0);
    	menupopup.appendChild(this.createME("menuitem","Ordner Scripte","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'Scripte');","uProfMenu_folder"),0);
    	menupopup.appendChild(this.createME("menuitem","Ordner CSSShadow","uProfMenu.dirOpen(uProfMenu.getPrefDirectoryPath('UChrm')+uProfMenu.getDirSep()+'CSSShadow');","uProfMenu_folder"),0);
    	
    	// Ende Einbindung von Ordnern
    	
        
    	
        // 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);
        // Falls addRestartButton installiert ist, Neustart zur Verfuegung stellen (addRestartButton 1.0.20120105mod erforderlich)
        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
          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 CSS folder
          case 3:
            var Path = this.getPrefDirectoryPath("UChrm") + dSep + "CSS" + dSep + Filename;
            break;
          //Current is CSSWeb folder
          case 4:
            var Path = this.getPrefDirectoryPath("UChrm") + dSep + "CSSWeb" + dSep + Filename;
            break;
          //Current is Sonstige CSS-Dateien folder
          case 5:
            var Path = this.getPrefDirectoryPath("UChrm") + dSep + "CSSAbout" + dSep + Filename;
            break;
    	  //Current is CSSShadow folder
          case 6:
            var Path = this.getPrefDirectoryPath("UChrm") + dSep + "CSSShadow" + dSep + Filename;
            break;			
          //Current is Chrome Directory
          case 7:	  
    	    var Path = this.getPrefDirectoryPath("UChrm") + dSep + Filename;
            break;
    	  //Current is Scripte folder
          case 8:
            var Path = this.getPrefDirectoryPath("UChrm") + dSep + "Scripte" + dSep + Filename;
            break;	
    	  //Current is distribution folder
          case 9:
            var Path = this.getPrefDirectoryPath("CurProcD") + dSep + "distribution" + dSep + Filename;
            break;	
        }
        this.launch(this.TextOpenExe,Path);
      },
    
      dirOpen:function(Path){
        if (this.vFileManager.length != 0) {
          var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
          var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
          var args = [Path];
          file.initWithPath(this.vFileManager);
          process.init(file);
          // Verzeichnis mit anderem Dateimanager oeffnen
          process.run(false, args, args.length);
         } else {
          // Verzeichnis mit Dateimanager des Systems oeffnen
          var dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
          dir.initWithPath(Path);
          dir.launch();
        }
      },
    
      prefDirOpen:function(prefDir){
        Path = this.getPrefDirectoryPath(prefDir);
        this.dirOpen(Path);
      },
    
      getPrefDirectoryPath:function(str){
        // get profile directory
        var file = Components.classes["@mozilla.org/file/directory_service;1"]
          .getService(Components.interfaces.nsIProperties)
          .get(str, Components.interfaces.nsIFile);
        if (str == 'CurProcD') {
          file = file.parent;
        };
        return file.path;
      },
    
      launch:function(RanPath,OpenPath){
        var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsIFile);
        var proc = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess);
        var args = [OpenPath];
        file.initWithPath(RanPath);
        // falls der im Konfigurationsabschnitt definierte Editor nicht gefunden wird, auf Einstellung in about:config ausweichen:
        if (!file.exists()) {
          var pref = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
          RanPath = pref.getCharPref("view_source.editor.path");
          file.initWithPath(RanPath);
        }
        proc.init(file);
        proc.run(false, args, args.length);
      },
    
      stringComparison:function(a, b){
        a = a.toLowerCase();
        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);
        aFolder.initWithPath(Services.dirsvc.get("UChrm", Ci.nsIFile).path+uProfMenu.getDirSep()+this.jsSubfolder);
        // 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);
          // 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", "Scripte",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()+"CSSAbout");
    	 } else if (iType==6) {
          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","CSS-Dateien",cssFiles,"uProfMenu_css",3);
         } else if (iType==4) {
          this.fillMenu("submenu-cssweb","submenu-cssweb-items","CSSWeb-Dateien",cssFiles,"uProfMenu_css",4);
         } else if (iType==5) {
          this.fillMenu("submenu-cssabout","submenu-cssabout-items","CSSAbout-Dateien",cssFiles,"uProfMenu_css",5);
         } else if (iType==6) {
          this.fillMenu("submenu-cssshadow","submenu-cssshadow-items","CSSShadow-Dateien",cssFiles,"uProfMenu_css",6);
         }
      },
    
      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: oder css)
          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);
    	   }else if (sTyp==6){
            var mitem = this.createME("menuitem",scriptArray[i],"uProfMenu.edit(6,'"+scriptArray[i]+"')",sClass,0);		
           } else if (sTyp==7){
            var mitem = this.createME("menuitem",scriptArray[i].label,scriptArray[i].command,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/ardiman/userChrome.js/tree/master/"+this.cleanFileName(sScript);
          openWebLinkIn(sUrl, 'tab');
        }
        if (e.button==2){
          // Rechtsklick - Suche auf GitHub starten (funktioniert nur, wenn der Dateiname im Code hinterlegt ist):
          e.preventDefault();
          var sUrl = "https://github.com/search?langOverride=&language=&q="+sScript+"&repo=&start_value=1&type=Code";
          openWebLinkIn(sUrl, 'tab');
          document.getElementById("ExtraConfigMenu-popup").hidePopup();
        }
      },
    
      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

    Zitat von .DeJaVu

    wobei xyz123 das Element des entsprechenden Eintrags ist.

    Alles was ich dazu gefunden habe ist probiert worden, aber ohne Erfolg.:rolleyes:

  • Ganze Seite nach unten oder oben Scrollen

    • FuchsFan
    • 2. Mai 2025 um 14:39
    Zitat von Mira_Belle

    aber mir ist aufgefallen, dass in der Nightly nicht mehr "gehovert" wird!

    Den Button selbst schon, aber mir gelingt es auch nicht, den Pfeilen eine andere Farbe zu geben.

  • Selektor für kleinen Pfeil in CSS-Code zum extra-config-menü.uc.js ab v139

    • FuchsFan
    • 2. Mai 2025 um 14:28

    Ich bitte in der Sache nochmals um Hilfe. Im Beitrag #1 ist der zweite Codee für Hoover vorhanden, was bis zur Version 138 für jeden einzelnen Button den roten Pfeil bringt. Sieht dann so aus:

    In Version 139/140 will mir das nicht gelingen, es auch dort so einzurichten. Wenn ich z.B. diesen Code dafür einsetze, so werden alle Button gleichzeitig angesprochen.

    CSS
    /*rechts der kleine Pfeil bei hoover*/
    #ExtraConfigMenu-popup:hover > menu::after {
      content: "" !important;
      background-image: url("..//icons/down2.png") !important;
      margin-right: 12px !important; 
      display: block !important;
      background-repeat: no-repeat !important;
      background-position: 0px 3px !important;
      background-size: 14px 14px !important;
    }

    Was dann so aussieht:

    Bilder

    • 140.png
      • 8,45 kB
      • 310 × 140
  • Selektor für kleinen Pfeil in CSS-Code zum extra-config-menü.uc.js ab v139

    • FuchsFan
    • 1. Mai 2025 um 19:08
    Zitat von grisu2099

    Dann war meine Schuß ins Blaue ja wenigstens ein halber Treffer...

    Genau so ist es. :thumbup:

    Zitat von .DeJaVu

    einfach nur ärgerlich - und unhöflich gegenüber den Helfern.

    Ich bitte alle Helfer um Verzeihung, wusste nicht, dass es so wichtig ist.

  • Selektor für kleinen Pfeil in CSS-Code zum extra-config-menü.uc.js ab v139

    • FuchsFan
    • 1. Mai 2025 um 17:29
    Zitat von Sören Hentzschel

    oder es wurde nicht bedacht, dass wenn ::after genutzt wird, es zwingend die Eigenschaft content geben muss

    Das war natürlich der gröbste Fehler, ich bedanke mich für den Hinweis.

    Zitat von .DeJaVu

    Wäre noch hilfreich, das Script zu posten, mindestens zu verlinken.

    Es lag aber nicht zwingend an dem Script, denn darin hat sich nichts geändert. Gibt es hier im Forum an jeder Ecke.;)

    Zitat von Horstmann

    Wie ebenfalls erwähnt, ist .menu-right jetzt wohl menu::after, und hat einen anderen Pfad, irgendwie sowas.

    Danke, das hat mich jetzt auf die Lösung gebracht, denn content  fehlte, und es muss jetzt dazu background-image heißen.

    Damit funktioniert es dann wieder;

    CSS
    #ExtraConfigMenu-popup menu::after {
      content: "" !important;
      background-image: url("..//icons/rechts6.png") !important;
    }
  • Selektor für kleinen Pfeil in CSS-Code zum extra-config-menü.uc.js ab v139

    • FuchsFan
    • 1. Mai 2025 um 14:48
    Zitat von grisu2099

    Mal ein Schuß ins Blaue

    Das hatte ich auch gesehen, aber will mir trotzdem nicht gelingen.:rolleyes:

  • Selektor für kleinen Pfeil in CSS-Code zum extra-config-menü.uc.js ab v139

    • FuchsFan
    • 1. Mai 2025 um 14:12

    Bis zur Version 138 funktioniert dafür dieser Code:

    CSS
    /*rechts der kleine Pfeil*/
    #ExtraConfigMenu-popup menu > .menu-right {
    	list-style-image: url("..//icons/rechts6.png") !important;
    }
    
    #ExtraConfigMenu-popup menu:hover > .menu-right {
      list-style-image: url("..//icons/down2.png") !important;
      margin-right: 8px !important; 
      padding-right: 20px !important;
      display: block !important;
      width: 16px !important;
      height: 16px !important;
      background-repeat: no-repeat !important;
      background-position: 0px 0px !important;
      background-size: 17px 17px !important;
    }
    Alles anzeigen


    Ich finde den neuen Selektor dafür nicht, bitte helfen.

  • Firefox v136.0a1 - Skript „saveTo“ funktioniert nicht mehr

    • FuchsFan
    • 19. April 2025 um 22:06
    Zitat von 2002Andreas

    Kompl. Skript dann:

    2002Andreas

    Sorry, Andreas, konnte nicht mehr online sein.

    Mein Dank geht an dich, das funktioniert perfekt, wie immer bei dir. :thumbup::thumbup::thumbup::)

    Ich wünsche dir, und auch allen Mitlesern, schöne Osterfeiertage.<3

  • Firefox v136.0a1 - Skript „saveTo“ funktioniert nicht mehr

    • FuchsFan
    • 19. April 2025 um 16:38
    Zitat von 2002Andreas

    Zeile 25 im Skript:

    Habe es im Original übernommen, aber lässt sich nicht ändern.

    Ich stelle mal das geänderte Script hier ein, schaust du mal bitte, ob es bei dir funktioniert.

    CSS
    // ==UserScript==
    // @include       chrome://mozapps/content/downloads/unknownContentType.xhtml
    // @charset       UTF-8
    // @version       Fx114+
    
    // ==/UserScript==
    (function () {
    	
    	if (location.href !== 'chrome://mozapps/content/downloads/unknownContentType.xhtml') return;
    	
      const Cu = Components.utils;
      const { FileUtils } = ChromeUtils.importESModule( 'resource://gre/modules/FileUtils.sys.mjs');
        
      setTimeout(function () {
        saveTo();
      }, 200);
    
      function saveTo() {
        // Config
        const dirArray = [
    	        ['D:\\Download Firefox', 'Download Firefox'],
                ['D:\\Download Firefox\\Dokumente'],
                ['D:\\Download Firefox\\Bilder'],
                ['D:\\Download Firefox\\Software'], 
                ['D:\\Download Firefox\\Ablage'],
                ['D:\\Download Firefox\\Sonstiges'],
                ["C:\\", "C:"],
                ["E:\\", "E:"],
                ];
        const button = document.getElementById('unknownContentType').getButton('cancel');
        const saveTo = button.parentNode.insertBefore(document.createXULElement('button'), button);
        const saveToMenu = saveTo.appendChild(document.createXULElement('menupopup'));
    
        saveTo.classList.toggle('dialog-button');
        saveTo.label = 'Speichern in…';
        saveTo.type = 'menu';
    
    
        const css =`
          hbox.dialog-button-box button.dialog-button menupopup {
            background: gold !important;
            min-width: 220px !important;
            padding: 5px !important;
            margin: 15px 0 0 -62px !important;
            border: 3px solid dodgerblue !important;
        }
            hbox.dialog-button-box button.dialog-button menupopup menuitem{
            appearance: none !important;
            color: blue !important;
            background: #fefefc !important; 
            border: 1px solid silver !important;
            margin-top: 1px !important;
            padding-left: 12px !important;
        }
            hbox.dialog-button-box button.dialog-button menupopup menuitem:hover {
            background: greenyellow !important;
            border: 1px solid red !important;
        }    
            hbox.dialog-button-box button.dialog-button menupopup menuitem.menuitem-iconic label.menu-iconic-text{
            color: blue !important;    
            font-size: 15px !important;
            font-weight: 600 !important;
                padding: 3px !important;
    			padding-left: 85px !important;
    			padding-right: 12px !important;
    
        } 
    	/* [FF139+] -> */
    		hbox.dialog-button-box button.dialog-button menupopup menuitem:not([highlightable]) > .menu-highlightable-text, menuitem[highlightable] > .menu-text {
    			  display: none;
    		}
    		/* <- [FF139+] */
    
    	`;
    
        const sss = Cc['@mozilla.org/content/style-sheet-service;1'].getService(Ci.nsIStyleSheetService);
        const uri = Services.io.newURI('data:text/css,' + encodeURIComponent(css));
        sss.loadAndRegisterSheet(uri, sss.AGENT_SHEET);
    
        dirArray.forEach(function (directory) {
          const [name, dir] = [directory[1], directory[0]];
          const mi = document.createXULElement('menuitem');
          const item = saveToMenu.appendChild(mi);
          item.setAttribute('label', (name || (dir.match(/[^\\/]+$/) || [dir])[0]));
          item.setAttribute('image', 'moz-icon:file:///' + dir + '\\');
          item.setAttribute('class', 'menuitem-iconic');
          item.addEventListener('click', function () {
            const locationtext = document.getElementById('locationtext');
            const pathFile = dir + '\\' + (locationtext ? locationtext.value : document.getElementById('location').value);
            const file = new FileUtils.File(pathFile);
            dialog.mLauncher.saveDestinationAvailable(file);
            dialog.onCancel = function () {};
            close();
          });
        });
      }
    }());
    Alles anzeigen
  • Firefox v136.0a1 - Skript „saveTo“ funktioniert nicht mehr

    • FuchsFan
    • 19. April 2025 um 16:07
    Zitat von 2002Andreas
    Zitat von BrokenHeart

    Jetzt sollte es auch in der Nightly wieder so funktionieren

    :thumbup:

    2002Andreas

    Hilf mir mal bitte, ich bekomme den Text nicht nach rechts verlagert.:rolleyes:

  • Mehrzeilige Tableiste für aktuelle Firefox-Versionen

    • FuchsFan
    • 8. April 2025 um 16:38
    Zitat von BrokenHeart

    Ich glaube, jetzt ist ein guter Zeitpunkt gekommen, dieses Dinosaurier-Skript (aus-)sterben zu lassen.

    BrokenHeart

    Ich möchte es aber nicht versäumen mich für Deine Arbeit zu bedanken, es war echt ein tolles Script.

    In weiser Voraussicht (wegen der häufigen Anpassungen) habe ich rechtzeitig für mich eine neue Arbeitsweise mit den Tabs eingerichtet, und mich auch daran gewöhnt. Alles hat ein ......... ! Danke BrokenHeart! :thumbup::)

  • Mehrzeilige Tableiste für aktuelle Firefox-Versionen

    • FuchsFan
    • 7. April 2025 um 18:22
    Zitat von Endor

    Der Autor hat was neues:

    Ja, und damit funktioniert auch das Verschieben der Tabs wieder.

  • Tabs ganz unten

    • FuchsFan
    • 7. April 2025 um 11:58
    Zitat von yaqwa

    Seit der Version 137 ist die Tab leiste wieder oben. Bitte um hilfe

    Wenn du die aktuelle Version von hier Mehrzeilige Tableiste für aktuelle Firefox-Versionen hast, dann funktioniert es bis Version 139.

  • Mehrzeilige Tableiste eine leere Zeile (Fehler)

    • FuchsFan
    • 6. April 2025 um 18:27
    Zitat von 2002Andreas

    Es geht auch etwas schneller

    :thumbup:;)

  • Mehrzeilige Tableiste eine leere Zeile (Fehler)

    • FuchsFan
    • 6. April 2025 um 18:00
    Zitat von Platos

    Du weisst nicht zufällig, wie ich in diesem (neuen) Skript diesen Pfeil rechts bei der Tableiste wegmache

    Doch, eine Möglichkeit hat 2002Andreas dir im vorherigen Beitrag gezeigt.

    Für mich habe ich das so gemacht, ein Rechtsklick auf eine freie Stelle in der Tabbar, und dann Symbolleiste anpassen auswählen.

    In der Folge dann mit der linken Maus das Pfeil-Symbol anfassen und z.B. in das Fenster ziehen (kann auch in das große linke abgelegt werden),

  • Mehrzeilige Tableiste eine leere Zeile (Fehler)

    • FuchsFan
    • 6. April 2025 um 14:18
    Zitat von Platos

    Naja, manchmal hilft ein kleiner Input um festzustellen, dass irgendwas schief gelaufen ist

    Da bist du nicht allein, glaube es mir.;)

  • Mehrzeilige Tableiste eine leere Zeile (Fehler)

    • FuchsFan
    • 6. April 2025 um 13:53
    Zitat von Platos

    Hat jemand eine Ahnung, wie man das beheben kann?

    Kann ich nicht, aber diese Version 135+ habe ich zum Test in Nightly, da ist alles "normal". Darfst du probieren, eventuell hilft es weiter.

    CSS
    // ==UserScript==
    // @name           MultiRowTabLiteforFx.uc.js
    // @namespace      Based on Alice0775's zzzz-MultiRowTab_LiteforFx48.uc.js
    // @description    Mehrzeilige Tableiste - Experimentelle CSS Version
    // @include        main
    // @compatibility  Firefox 135+
    // @version        2025/01/06 12:00
    // ==/UserScript==
    "use strict";
    
    MultiRowTabLiteforFx();
    function MultiRowTabLiteforFx() {
    if (!window.gBrowser) { return; }
    
        // -- Config --
        														// Vergleichbarer CSS Code in userChrome.css Datei wird vorrangig behandelt!
    
        const                                   	    	    // Mehrzeilige Tableiste Ein/Aus Anzahl der Tabzeilen
        MultiRowTab_OnOff_and_TabBar_Rows =     		2     ,// [-1] = Mehrzeilige Tableiste aktiv unbegrenzte Anzahl von Zeilen.
                                                	    	 	//  0   = Mehrzeilige Tableiste aus.
                                                	    		//  1   = Mehrzeilige Tableiste aktiv. Standard = 1 Zeile. Bei Berührung
    															//        der Tableiste mit der der Maus, werden die zweite und die folgenden Zeilen
                                                             	//        bis zur angegebenen Anzahl von Zeilen angezeigt.
    	                                                        //  2   = Mehrzeilige Tableiste aktiv. Anzahl der Tabzeilen angeben.
    	    
        TabBar_Rows_on_MouseOver =              		3      ,// Standard = 1 Zeile. Anzahl der Zeilen angeben, die angezeigt werden sollen, 
    	                                                        // wenn der Mauszeiger über die Tableiste bewegt wird. Voraussetzung: 
    															// „MultiRowTab_OnOff_and_TabBar_Rows“ auf „1“ setzen.
    	    
        TabBar_DisplayTime_on_MouseOver =       		1      ,// Sie können die Anzeigezeit (Sekunden) festlegen, wann die zweite und die folgenden
    	                                                        // Zeilen beim Mouseover angezeigt werden. Das Display zeigt den eingestellten Wert 
    															// (Sekunden) an und kehrt dann zur ersten Zeile zurück.
    
    															// Position der Tab-Leiste.
        TabBar_Position =          	    	    		0      ,// [0] = Standard
    															// 1   = unter der Symbolleiste
    															// 2   = unter dem Fenster
    
    															// Positionen der Tab-Leiste und der Lesezeichen-Symbolleiste tauschen.
    															// sofern die Position der Tab-Leiste unterhalb der Symbolleiste festgelegt ist.
    															// Voraussetzung: Setze "TabBar_Position" auf "1".
        Bookmark_Toolbar_Position =             	    true   ,// [true] = Menüleiste, Navigationsleiste, Lesezeichenleiste, Tableiste
    															// false = Menüleiste, Navigationsleiste, Tableiste, Lesezeichensymbolleiste
    
    															// Tab-Höhe „UI-Dichte“
        UI_Density_Compact =               			    26	   ,// Standard = 29 Pixelbei Kompakt
        UI_Density_Normal =                			    26	   ,// Standard = 36 Pixel bei Normal
        UI_Density_Touch =                 			    26	   ,// Standard = 41 Pixel bei Touch
    
    															// Tab-Breite
        Tab_Min_Width =                    			270		   ,// Standard - Mindestwert = 76px
        Tab_Max_Width =                    			271		   ,// Standard - Maxwert = 225px
    															// Bei gleichen Werten bei Min und Max, wird die Tabbreite fixiert!
    
    															// „Tab schließen“ Schaltfläche
        Tab_Close_Button =                 			3		   ,// [0] = Standard
    															//  1  = Ausgeblendet
    															//  2  = Auf allen Tabs anzeigen
    															//  3  = Nur bei Mausberührung anzeigen
    															//  4  = Aktive Tabs werden immer angezeigt, inaktive Tabs
    															// werden beim Mouseover angezeigt. *Standard für vertikalen Tab-Modus.
    
    															// ProtonUI Erscheinungsbild der Tabs ändern
        Proton_Margins =                   			false       ,// [true] = Darstellung ProtonUI
    															// Die Höhe der Tab-Leiste entspricht der Höhe der UI-Dichte plus dem Leerraum darüber
    															// und darunter.                                                 
    															// false  = Darstellung wie bei browser.proton.enabled auf false, was man vor Firefox 90
    															// noch einstellen konnte.
    															// Wenn der Leerraum um die Tabs auf 0 und die Höhe auf die UI-Dichte eingestellt
    															// ist, ist sie 4 Pixel breiter und 8 Pixel niedriger als die Standardeinstellung.
    								 
    															// Ränder auf der linken und rechten Seite der Tabs
        Tab_Separators  =                  			false      ,// [false] = Nicht anzeigen
    															// true    = Anzeigen
    															// Rahmen CSS wurde extrahiert und angepasst, an Aussehen wie bei browser.proton.enabled
    															// auf false, was man vor Firefox 90 noch einstellen konnte.
    									
    															// Voraussetzung: „TabBar_Position“ auf „0“ setzen.
        TitleBar_Button_Autohide =         			false	   ,// [false] = Aktiviert
    															// true    = Deaktiviert
    	    
    															// Äußeren Rahmen der Titelleistenschaltfläche [-□×] reduzieren und transparent machen.
        TitleBar_Button_DisplayTime =       		0.6		   ,// Dauer der Anzeige in Sekunden, nach der Rückkehr zur Originalgröße und dem Aufheben
    															// der Transparenz per Mouseover angeben.
    
    															// Tab-Leiste von Anfang an auf die angegebene Höhe einstellen.
    															// Voraussetzung: „MultiRowTab_OnOff_and_TabBar_Rows“ auf „2“ oder höher setzen.
        Set_the_TabBar_to_the_Specified_Height =	false  	   ,// [false] = Die Tab-Leiste wird höher, wenn der nächsten Zeile weitere Tabs hinzugefügt werden.
                                                	    	 	//  true   = Verwendung: Die Tab-Leiste wird von Anfang an auf die angegebene Höhe eingestellt 
    
                                                	    	 	// „.tabDropIndicator“, der beim Ziehen und Ablegen eines Tabs angezeigt wird, ersetzen.
                                                	    	 	// Voraussetzung: „MultiRowTab_OnOff_and_TabBar_Rows“ auf einen anderen Wert als „0“ setzen.
        Tab_Drop_Indicator =                    	false  	   ,// [false] = Stecknadel Symbol 📍
    															// true    = Rote Linie (2px × 29px) als Symbol
    
                                                	    	 	// Position der angepinnten Tabs
                                                	    	 	// Voraussetzung: „MultiRowTab_OnOff_and_TabBar_Rows“ auf einen Wert ungleich „0“ setzen.
        Separate_Tabs_and_PinnedTabs =     			false  	   ,// [false] = Standard
    															// true    = Angeheftete Tabs von der Tab-Leiste lösen und in die darüber liegende 
    															// Zeile verschieben. Breite der angehefteten Tabs für die Position der 
    															// angehefteten Tabs „true“ anpassen.
    
        PinnedTab_Width =                   		false	   ,// [false] = Kein Standard
    															//  true   = Breite angehefteter Tabs anpassen, z. B. „Tab-Breite“.
    
        PinnedTab_Min_Width =               		76   	   ,// Standard Mindestbreite =  76 Pixel
        PinnedTab_Max_Width =               		225   	   ,// Standard Maximalbreite = 225 Pixel
    															// Bei gleichen Werten ist die Breite fixiert.
    
                                                	    	 	// Angeheftete Tab, Schließen Schaltfläche
                                                	    	 	// Voraussetzung: „Separate_Tabs_and_PinnedTabs“ auf „true“ setzen.
        PinnedTab_Close_Button =                	0   	   ,// [0] = Standard
                                                	    	 	//  1  = auf allen Tabs sichtbar
                                                	    		//  2  = auf Tab bei Mouseover anzeigen
                                                	    	 	//  3  = Aktiver Tab immer sichtbar, inaktiver Tab bei Mouseover sichtbar 
    															// *Standard für vertikalen Tab-Modus.
    
    															// Tab-Leisten-Ziehbereich
        Left_Drag_Area =                   			0		   ,// Linker Ziehbereich Breite: Standard 40 Pixel
        Right_Drag_Area =                  			0		   ,// Rechter Ziehbereich Breite: Standard 40 Pixel
        Maximize_Left_Drag_Area =   	    		false      ,// true = Linken Ziehbereich bei maximiertem Fenster anzeigen. Standard ausgeblendet.
        Fullscreen_Drag_Area =             			false	   ,// true = Linken und rechten Ziehbereich bei Vollbild anzeigen. Standard ausgeblendet.
    															// Wenn die Titelleiste angezeigt wird, funktioniert sie nicht als Drag-Bereich, selbst
    															// wenn „.titlebar-spacer“ angezeigt wird. Daher habe ich dafür gesorgt, dass sie nichts bewirkt.
        // -- Config Ende --
    
        css = `
    
        #TabsToolbar:not([collapsed="true"]) {
    
          :root[uidensity="compact"] & {
            --tab-min-height: ${UI_Density_Compact}px;
          }
          :root:not([uidensity]) & {
            --tab-min-height: ${UI_Density_Normal}px;
          }
          :root[uidensity="touch"] & {
            --tab-min-height: ${UI_Density_Touch}px;
          }
    
          #tabbrowser-tabs {
            min-height: calc(var(--tab-min-height) + ${Proton_Margins ? 8 : 0}px);
    
            ${MultiRowTab_OnOff_and_TabBar_Rows != 0 ? `
              &[overflow] {
                padding-inline: 0 !important;
                & > #tabbrowser-arrowscrollbox {
                  & > .tabbrowser-tab[pinned] {
                    display: flex;
                    margin-inline-start: 0 !important;
                    position: static !important;
                  }
                  &::part(scrollbox) {
                    padding-inline: 0;
                  }
                }
                & + #new-tab-button {
                  display: none;
                }
              }
    
              ${Tab_Drop_Indicator ? `
                & > .tab-drop-indicator {
                  background: url(
                    data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAAdCAIAAAAPVCo9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASSURBVBhXY3growJEQ5+SUQEAOb1EM8kwskcAAAAASUVORK5CYII=
                  ) no-repeat center;
                }
              ` : ``}
    
              #tabbrowser-arrowscrollbox {
                &::part(scrollbox) {
                  & > slot {
                    flex-wrap: wrap;
                  }
    
                  ${MultiRowTab_OnOff_and_TabBar_Rows != -1 ? `
                    ${MultiRowTab_OnOff_and_TabBar_Rows == 1 ? `
                      ${TabBar_Rows_on_MouseOver == 0 || TabBar_Rows_on_MouseOver == 1 ? `
                        max-height: calc((var(--tab-min-height) + ${Proton_Margins ? 8 : 0}px) * 2);
                      ` : `
                        max-height: calc((var(--tab-min-height) + ${Proton_Margins ? 8 : 0}px) * ${TabBar_Rows_on_MouseOver});
                      `}
                      &:not(:hover) {
                        max-height: calc(var(--tab-min-height) + ${Proton_Margins ? 8 : 0}px) !important;
                        ${Proton_Margins ? `scrollbar-width: none;` : ``}
                        transition: all 0s ease-in-out ${TabBar_DisplayTime_on_MouseOver}s;
                      }
                    ` : `
                      ${Set_the_TabBar_to_the_Specified_Height ? `
                        min-height: calc((var(--tab-min-height) + ${Proton_Margins ? 8 : 0}px) * ${MultiRowTab_OnOff_and_TabBar_Rows});
                        & > slot {
                          max-height: calc(var(--tab-min-height) + ${Proton_Margins ? 8 : 0}px);
                        }
                      ` : `
                        max-height: calc((var(--tab-min-height) + ${Proton_Margins ? 8 : 0}px) * ${MultiRowTab_OnOff_and_TabBar_Rows});
                      `}
                    `}
    
                    overflow: hidden auto;
                    & scrollbar {
                      -moz-window-dragging: no-drag;
                    }
                  ` : ``}
    
                }
                &::part(overflow-start-indicator),
                &::part(overflow-end-indicator),
                &::part(scrollbutton-up),
                &::part(scrollbutton-down) {
                  display: none;
                }
    
                ${Separate_Tabs_and_PinnedTabs ? `
                  &:has(> .tabbrowser-tab[fadein][pinned]) {
                    &::part(scrollbox) {
                      & > slot::after {
                        display: flow-root list-item;
                        content: "";
                        flex-basis: -moz-available;
                        height: 0;
                        overflow: hidden;
                      }
                    }
                  }
                  .tabbrowser-tab[fadein] {
                    &:not([pinned]) {
                      #tabbrowser-tabs[haspinnedtabs] & {
                        &, & + :not(#tabs-newtab-button) {
                          order: 1;
                        }
                      }
                    }
                    &[pinned] {
                      .tab-background:after {
                        content: "📌";
                        font-size: 11px;
                        right: -2px;
                        position: absolute;
                        top: -2px;
                      }
    
                      ${PinnedTab_Width ? `
                        flex: 100 100;
                        max-width: ${PinnedTab_Max_Width}px;
                        min-width: ${PinnedTab_Min_Width}px;
                        .tab-throbber, .tab-icon-pending, .tab-icon-image, .tab-sharing-icon-overlay, .tab-icon-overlay {
                          margin-inline-end: 5.5px !important;
                        }
    
                        ${PinnedTab_Close_Button == 1 ? `
                          .tab-close-button {
                            display: flex;
                          }
                        ` : PinnedTab_Close_Button == 2 ? `
                          .tab-close-button {
                            display: none;
                          }
                          &:hover .tab-close-button {
                            display: flex;
                          }
                        ` : PinnedTab_Close_Button == 3 ? `
                          &:not([selected]):hover,
                          &[selected] {
                            .tab-close-button {
                              display: flex;
                            }
                          }
                        ` : ``}
    
                      ` : ``}
    
                    }
                  }
                ` : ``}
    
                #tabbrowser-tabs[haspinnedtabs]:not([positionpinnedtabs]):not([orient="vertical"]) > & {
                  &  > .tabbrowser-tab:nth-child(1 of :not([pinned], [hidden])) {
                    margin-inline-start: 0 !important;
                  }
                }
    
              }
            ` : ``}
          }
    
          .tabbrowser-tab[fadein]:not([pinned]) {
            max-width: ${Tab_Max_Width}px;
            min-width: ${Tab_Min_Width}px;
    
            ${Tab_Close_Button == 1 ? `
              .tab-close-button {
                display: none;
              }
            ` : Tab_Close_Button == 2 ? `
              .tab-close-button {
                display: flex;
              }
            ` : Tab_Close_Button == 3 ? `
              .tab-close-button {
                display: none;
    			background: none !important;
    			fill: white !important;
    			scale: 1.3 !important;
              }
              &:hover .tab-close-button {
                display: flex;
              }
    		  .tab-close-button.close-icon:hover {
    			fill: red !important;
              }	
            ` : Tab_Close_Button == 4 ? `
              &:not([selected]):hover {
                .tab-close-button {
                  display: flex;
                }
              }
            ` : ``}
    
          }
    
          ${Tab_Separators ? `
            .titlebar-spacer[type="pre-tabs"] {
              border-inline-end: 1px solid color-mix(in srgb, currentColor 20%, transparent);
            }
            .tabbrowser-tab {
              &::after,
              &::before {
                border-left: 1px solid color-mix(in srgb, currentColor 50%, transparent);
                height: calc(var(--tab-min-height) - 15%);
                margin-block: auto;
              }
              &:hover::after,
              &[multiselected]::after,
              #tabbrowser-tabs:not([movingtab]) &:has(+ .tabbrowser-tab:hover)::after,
              #tabbrowser-tabs:not([movingtab]) &:has(+ [multiselected])::after {
                height: 100%;
              }
              &::after,
              #tabbrowser-tabs[movingtab] &[visuallyselected]::before {
                display: flex;
                content: "";
              }
            }
          ` : ``}
    
          ${Proton_Margins ? `` : `
            .tabbrowser-tab,
            .toolbarbutton-1 {
              padding: 0;
            }
            .tabbrowser-tab,
            #tabs-newtab-button {
              height: var(--tab-min-height);
            }
            .tabbrowser-tab {
              .tab-background {
                box-shadow: none;
                margin-block: 0;
              }
              .tab-label-container,
              .tab-close-button {
                height: var(--tab-min-height);
                max-height: 24px;
              }
              .tab-close-button {
                padding-block: 0;
              }
              &[usercontextid] > .tab-stack > .tab-background > .tab-context-line {
                margin-block-start: 1px !important;
              }
            }
          `}
    
        ${TabBar_Position == 0 ? `
          .titlebar-buttonbox-container {
            height: calc(var(--tab-min-height) + ${Proton_Margins ? 8 : 0}px);
          }
    
          ${TitleBar_Button_Autohide ? `
            & > .titlebar-buttonbox-container {
              background-color: color-mix(in srgb, currentColor 20%, transparent);
              position: fixed;
              right: 0;
              &:not(:hover) {
                height: 6px;
                .titlebar-button {
                  padding: 0;
                }
                &,& .titlebar-button {
                  opacity: 0;
                  transition: all 0s ease-in-out ${TitleBar_Button_DisplayTime}s;
                }
              }
            }
          ` : ``}
    
        }` : `
    
          ${TabBar_Position == 1 || TabBar_Position == 2 ? `
            & > .titlebar-buttonbox-container {
                display: none;
            }}
            #nav-bar {
              &:not(.browser-titlebar) {
                :root[customtitlebar] #toolbar-menubar[autohide="true"] ~ &,
                :root[inFullscreen] #toolbar-menubar ~ & {
                  & > .titlebar-buttonbox-container {
                    display: flex;
                  }
                }
              }
              .titlebar-button {
                padding-block: 0;
              }
            }
          ` : ``}
    
          body:has(> #navigator-toolbox:not([tabs-hidden])) {
            ${TabBar_Position == 1 ? `
              script, toolbar:not(#TabsToolbar ${Bookmark_Toolbar_Position ? `` : `, #PersonalToolbar`}) {
                order: -1;
              }
            ` : TabBar_Position == 2 ? `
              & > #fullscr-toggler[hidden] + tabbox,
              :root[inFullscreen] & > tabbox:hover {
                border-top: 0.01px solid var(--chrome-content-separator-color);
              }
              & > tabbox > #navigator-toolbox {
                border-block: none !important;
              }
              :root[inFullscreen] & {
                & > #navigator-toolbox {
                  transition: none;
                  &:has(~ tabbox:hover) {
                    margin-top: 0 !important;
                  }
                  &:hover ~ tabbox > #navigator-toolbox {
                    display: flex;
                  }
                }
                & > tabbox:not(:hover) {
                  border-top: 0.01px solid transparent;
                  & > #navigator-toolbox {
                    display: none;
                  }
                }
              }
            ` : ``}
          }
    
        `}
    
        toolbar[id$="bar"].browser-titlebar {
          .titlebar-spacer {
            &[type="pre-tabs"] {
              width: ${Left_Drag_Area}px;
            }
            &[type="post-tabs"] {
              width: ${Right_Drag_Area}px;
            }
            ${Maximize_Left_Drag_Area ? `
              :root[customtitlebar]:not([sizemode="normal"], [inFullscreen]) &[type="pre-tabs"] {
                display: flex;
              }
            ` : ``}
            ${Fullscreen_Drag_Area ? `
              :root[customtitlebar][inFullscreen] & {
                display: flex;
              }
            ` : ``}
          }
          #navigator-toolbox[tabs-hidden] & {
            #new-tab-button {
              display: none;
            }
          }
        }
    
        `,
        sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService),
        uri = Services.io.newURI("data:text/css;charset=UTF=8," + encodeURIComponent(css));
        ["0", "2", "dragend", "SSTabRestored", "TabAttrModified"].find(eventType => {
          if(!sss.sheetRegistered(uri, eventType)) sss.loadAndRegisterSheet(uri, eventType);
          if (MultiRowTab_OnOff_and_TabBar_Rows > 0) {
            gBrowser.tabContainer.addEventListener(eventType, (e) => {
              e.target.scrollIntoView({ behavior: "instant", block: "nearest" })
            })
          }
        })
    
        if (TabBar_Position == 2) {
          document.body.appendChild(
            document.createXULElement("tabbox")
          ).appendChild(
            document.importNode(document.getElementById("navigator-toolbox"))
          ).appendChild(
            document.adoptNode(document.getElementById("TabsToolbar"))
          )
        }
    
        gBrowser.tabContainer.addEventListener("dragover", function(event) { this._on_dragover(event); }, false)
        gBrowser.tabContainer.addEventListener("drop", function(event) { this._on_drop(event); }, false)
        gBrowser.tabContainer.on_dragover = function(event) { return false; }
        gBrowser.tabContainer.on_drop = function(event) { return false; }
    
        gBrowser.tabContainer._on_dragover = function(event) {
          var effects = this.getDropEffectForTabDrag(event);
    
          var ind = this._tabDropIndicator;
          if (effects == "" || effects == "none") {
            ind.hidden = true;
            return;
          }
          event.preventDefault();
          event.stopPropagation();
    
          var arrowScrollbox = this.arrowScrollbox;
    
          if (this.verticalMode || MultiRowTab_OnOff_and_TabBar_Rows == 0) {
    
          // autoscroll the tab strip if we drag over the scroll
          // buttons, even if we aren't dragging a tab, but then
          // return to avoid drawing the drop indicator
          var pixelsToScroll = 0;
          if (this.overflowing) {
            switch (event.originalTarget) {
              case arrowScrollbox._scrollButtonUp:
                pixelsToScroll = arrowScrollbox.scrollIncrement * -1;
                break;
              case arrowScrollbox._scrollButtonDown:
                pixelsToScroll = arrowScrollbox.scrollIncrement;
                break;
            }
            if (pixelsToScroll) {
              arrowScrollbox.scrollByPixels(
                (RTL_UI ? -1 : 1) * pixelsToScroll,
                true
              );
            }
          }
    
          let draggedTab = event.dataTransfer.mozGetDataAt(TAB_DROP_TYPE, 0);
          if (
            (effects == "move" || effects == "copy") &&
            this == draggedTab.container &&
            !draggedTab._dragData.fromTabList
          ) {
            ind.hidden = true;
    
         // if (this.#isAnimatingMoveTogetherSelectedTabs()) {
         //   // Wait for moving selected tabs together animation to finish.
         //   return;
         // }
            this._finishMoveTogetherSelectedTabs(draggedTab);
    
            if (effects == "move") {
              // Pinned tabs in expanded vertical mode are on a grid format and require
              // different logic to drag and drop.
           // if (this.#isContainerVerticalPinnedExpanded(draggedTab)) {
           //   this.#animateExpandedPinnedTabMove(event);
           //   return;
           // }
              this._animateTabMove(event);
              return;
            }
          }
    
          this._finishAnimateTabMove();
    
          }
    
          if (effects == "link") {
            let tab = this._getDragTargetTab(event, { ignoreTabSides: true });
            if (tab) {
              if (!this._dragTime) {
                this._dragTime = Date.now();
              }
              if (Date.now() >= this._dragTime + this._dragOverDelay) {
                this.selectedItem = tab;
              }
              ind.hidden = true;
              return;
            }
          }
    
          var tabRect, rect = arrowScrollbox.getBoundingClientRect();
          var newMargin, newMarginY;
          if (pixelsToScroll) {
            // if we are scrolling, put the drop indicator at the edge
            // so that it doesn't jump while scrolling
            let scrollRect = arrowScrollbox.scrollClientRect;
            let minMargin = this.verticalMode
              ? scrollRect.top - rect.top
              : scrollRect.left - rect.left;
            let maxMargin = this.verticalMode
              ? Math.min(minMargin + scrollRect.height, scrollRect.bottom)
              : Math.min(minMargin + scrollRect.width, scrollRect.right);
            if (RTL_UI) {
              [minMargin, maxMargin] = [
                this.clientWidth - maxMargin,
                this.clientWidth - minMargin,
              ];
            }
            newMargin = pixelsToScroll > 0 ? maxMargin : minMargin;
          } else {
            let newIndex = this._getDropIndex(event);
            let children = this.allTabs;
            if (newIndex === children.length) {
              tabRect = this.visibleTabs.at(-1).getBoundingClientRect();
              if (this.verticalMode) {
                newMargin = tabRect.bottom - rect.top;
              } else if (RTL_UI) {
                newMargin = rect.right - tabRect.left;
              } else {
                newMargin = tabRect.right - rect.left;
              }
            } else {
              tabRect = children[newIndex].getBoundingClientRect();
              if (this.verticalMode) {
                newMargin = rect.top - tabRect.bottom;
              } else if (RTL_UI) {
                newMargin = rect.right - tabRect.right;
              } else {
                newMargin = tabRect.left - rect.left;
              }
            }
            newMarginY = tabRect.top - rect.top + tabRect.height / 2 - rect.height / 2;
          }
    
          ind.hidden = false;
          newMargin += this.verticalMode ? ind.clientHeight : ind.clientWidth / 2;
          if (RTL_UI) {
            newMargin *= -1;
          }
          ind.style.transform = this.verticalMode
            ? "translateY(" + Math.round(newMargin) + "px)"
            : MultiRowTab_OnOff_and_TabBar_Rows == 0
            ? "translateX(" + Math.round(newMargin) + "px)"
            : "translate(" + Math.round(newMargin) + "px, " + Math.round(newMarginY) + "px)";
        }
    
        gBrowser.tabContainer._on_drop = function(event) {
          var dt = event.dataTransfer;
          var dropEffect = dt.dropEffect;
          var draggedTab;
          let movingTabs;
          if (dt.mozTypesAt(0)[0] == TAB_DROP_TYPE) {
            // tab copy or move
            draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
            // not our drop then
            if (!draggedTab) {
              return;
            }
            movingTabs = draggedTab._dragData.movingTabs;
            draggedTab.container._finishMoveTogetherSelectedTabs(draggedTab);
          }
    
          this._tabDropIndicator.hidden = true;
          event.stopPropagation();
          if (draggedTab && dropEffect == "copy") {
            // copy the dropped tab (wherever it's from)
            let newIndex = this._getDropIndex(event);
            let draggedTabCopy;
            for (let tab of movingTabs) {
              let newTab = gBrowser.duplicateTab(tab);
              gBrowser.moveTabTo(newTab, newIndex++);
              if (tab == draggedTab) {
                draggedTabCopy = newTab;
              }
            }
            if (draggedTab.container != this || event.shiftKey) {
              this.selectedItem = draggedTabCopy;
            }
          } else if (draggedTab && draggedTab.container == this) {
            let oldTranslateX = Math.round(draggedTab._dragData.translateX);
            let oldTranslateY = Math.round(draggedTab._dragData.translateY);
            let tabWidth = Math.round(draggedTab._dragData.tabWidth);
            let tabHeight = Math.round(draggedTab._dragData.tabHeight);
            let translateOffsetX = oldTranslateX % tabWidth;
            let translateOffsetY = oldTranslateY % tabHeight;
            let newTranslateX = oldTranslateX - translateOffsetX;
            let newTranslateY = oldTranslateY - translateOffsetY;
    
            // Update both translate axis for pinned vertical expanded tabs
            if (oldTranslateX > 0 && translateOffsetX > tabWidth / 2) {
              newTranslateX += tabWidth;
            } else if (oldTranslateX < 0 && -translateOffsetX > tabWidth / 2) {
              newTranslateX -= tabWidth;
            }
            if (oldTranslateY > 0 && translateOffsetY > tabHeight / 2) {
              newTranslateY += tabHeight;
            } else if (oldTranslateY < 0 && -translateOffsetY > tabHeight / 2) {
              newTranslateY -= tabHeight;
            }
    
            let dropIndex;
            if (draggedTab._dragData.fromTabList) {
              dropIndex = this._getDropIndex(event);
            } else {
              dropIndex = this.verticalMode || MultiRowTab_OnOff_and_TabBar_Rows == 0
                ? "animDropIndex" in draggedTab._dragData && draggedTab._dragData.animDropIndex
                : this._getDropIndex(event);
            }
            let incrementDropIndex = true;
            if (dropIndex && dropIndex > movingTabs[0]._tPos) {
              dropIndex--;
              incrementDropIndex = false;
            }
    
            let shouldTranslate =
              !gReduceMotion && !("groupDropIndex" in draggedTab._dragData);
         // if (this.#isContainerVerticalPinnedExpanded(draggedTab)) {
         //   shouldTranslate &&=
         //     (oldTranslateX && oldTranslateX != newTranslateX) ||
         //     (oldTranslateY && oldTranslateY != newTranslateY);
         // } else
            if (this.verticalMode) {
              shouldTranslate &&= oldTranslateY && oldTranslateY != newTranslateY;
            } else {
              shouldTranslate &&= oldTranslateX && oldTranslateX != newTranslateX;
            }
    
            if (shouldTranslate) {
              for (let tab of movingTabs) {
                tab.toggleAttribute("tabdrop-samewindow", true);
                tab.style.transform = `translate(${newTranslateX}px, ${newTranslateY}px)`;
                let postTransitionCleanup = () => {
                  tab.removeAttribute("tabdrop-samewindow");
    
                  this._finishAnimateTabMove();
                  if (dropIndex !== false) {
                    gBrowser.moveTabTo(tab, dropIndex);
                    if (incrementDropIndex) {
                      dropIndex++;
                    }
                  }
    
                  gBrowser.syncThrobberAnimations(tab);
                };
                if (gReduceMotion) {
                  postTransitionCleanup();
                } else {
                  let onTransitionEnd = transitionendEvent => {
                    if (
                      transitionendEvent.propertyName != "transform" ||
                      transitionendEvent.originalTarget != tab
                    ) {
                      return;
                    }
                    tab.removeEventListener("transitionend", onTransitionEnd);
    
                    postTransitionCleanup();
                  };
                  tab.addEventListener("transitionend", onTransitionEnd);
                }
              }
            } else {
              let groupTab =
                "groupDropIndex" in draggedTab._dragData
                  ? this.allTabs[draggedTab._dragData.groupDropIndex]
                  : null;
              this._finishAnimateTabMove();
              if (dropIndex !== false) {
                for (let tab of movingTabs) {
                  gBrowser.moveTabTo(tab, dropIndex);
                  if (incrementDropIndex) {
                    dropIndex++;
                  }
                }
              }
              if (groupTab) {
                gBrowser.addTabGroup([groupTab, ...movingTabs], {
                  insertBefore: draggedTab,
                });
              }
            }
          } else if (draggedTab) {
            // Move the tabs. To avoid multiple tab-switches in the original window,
            // the selected tab should be adopted last.
            const dropIndex = this._getDropIndex(event);
            let newIndex = dropIndex;
            let selectedTab;
            let indexForSelectedTab;
            for (let i = 0; i < movingTabs.length; ++i) {
              const tab = movingTabs[i];
              if (tab.selected) {
                selectedTab = tab;
                indexForSelectedTab = newIndex;
              } else {
                const newTab = gBrowser.adoptTab(tab, newIndex, tab == draggedTab);
                if (newTab) {
                  ++newIndex;
                }
              }
            }
            if (selectedTab) {
              const newTab = gBrowser.adoptTab(
                selectedTab,
                indexForSelectedTab,
                selectedTab == draggedTab
              );
              if (newTab) {
                ++newIndex;
              }
            }
    
            // Restore tab selection
            gBrowser.addRangeToMultiSelectedTabs(
              gBrowser.tabs[dropIndex],
              gBrowser.tabs[newIndex - 1]
            );
          } else {
            // Pass true to disallow dropping javascript: or data: urls
            let links;
            try {
              links = browserDragAndDrop.dropLinks(event, true);
            } catch (ex) {}
    
            if (!links || links.length === 0) {
              return;
            }
    
            let inBackground = Services.prefs.getBoolPref(
              "browser.tabs.loadInBackground"
            );
            if (event.shiftKey) {
              inBackground = !inBackground;
            }
    
            let targetTab = this._getDragTargetTab(event, { ignoreTabSides: true });
            let userContextId = this.selectedItem.getAttribute("usercontextid");
            let replace = !!targetTab;
            let newIndex = this._getDropIndex(event);
            let urls = links.map(link => link.url);
            let csp = browserDragAndDrop.getCsp(event);
            let triggeringPrincipal =
              browserDragAndDrop.getTriggeringPrincipal(event);
    
            (async () => {
              if (
                urls.length >=
                Services.prefs.getIntPref("browser.tabs.maxOpenBeforeWarn")
              ) {
                // Sync dialog cannot be used inside drop event handler.
                let answer = await OpenInTabsUtils.promiseConfirmOpenInTabs(
                  urls.length,
                  window
                );
                if (!answer) {
                  return;
                }
              }
    
              gBrowser.loadTabs(urls, {
                inBackground,
                replace,
                allowThirdPartyFixup: true,
                targetTab,
                newIndex,
                userContextId,
                triggeringPrincipal,
                csp,
              });
            })();
          }
    
          if (draggedTab) {
            delete draggedTab._dragData;
          }
        }
    
    }
    Alles anzeigen
  • Toolbox Button.uc.js funktioniert nur teilweise in Fx 139

    • FuchsFan
    • 4. April 2025 um 11:02
    Zitat von Sören Hentzschel

    Das ist 1:1 das Script aus Beitrag #14.

    Gern möglich, habe ich nicht kontrolliert. Es funktioniert aber, und das ist gut.

    Und wie erwähnt, ich hatte es zum Test schon vor einer ganzen Weile installiert.

    Sorry, jetzt fällt mir ein, ich hatte das Script aus #14 rüber kopiert, deshalb.

  • Toolbox Button.uc.js funktioniert nur teilweise in Fx 139

    • FuchsFan
    • 4. April 2025 um 10:44

    2002Andreas

    Das Script hatte ich zum Test in Nightly mal installiert, es funktioniert auch unter den "verschärften" Bedingungen, und auch ohne Fehler in der Konsole. Kannst du das bitte mal bei dir testen.

    JavaScript
    // ==UserScript==
    // @name           Toolbox Button
    // @version        1.4.0
    // @author         aminomancer
    // @homepageURL    https://github.com/aminomancer/uc.css.js
    // @long-description
    // @description
    /*
    Adds a new toolbar button that 1) opens the content toolbox on left click; 2) opens the browser toolbox on right click; 3) toggles "Popup Auto-Hide" on middle click. Left click will open the toolbox for the active tab, or close it if it's already open. Right click will open the elevated browser toolbox if it's not already open. If it is already open, then instead of trying to start a new process and spawning an irritating dialog, it'll just show a brief notification saying the toolbox is already open. The button also shows a badge while a toolbox window is open. Middle click will toggle the preference for popup auto-hide: `ui.popup.disable_autohide`. This does the same thing as the "Disable Popup Auto-Hide" option in the menu at the top right of the browser toolbox, prevents popups from closing so you can debug them.
    
    If you want to change which mouse buttons execute which functions, search for `userChrome.toolboxButton.mouseConfig` in <about:config>. Change the 0, 1, and 2 values. 0 = left click, 1 = middle, and 2 = right. By default, when you open a browser toolbox window, the script will disable popup auto-hide, and then re-enable it when you close the toolbox. I find that I usually want popup auto-hide disabled when I'm using the toolbox, and never want it disabled when I'm not using the toolbox, so I made it automatic, instead of having to right click and then immediately middle click every time. If you don't like this automatic feature, you can turn it off by setting `userChrome.toolboxButton.popupAutohide.toggle-on-toolbox-launch` to false in about:config.
    
    You can force the browser toolbox to open in multiprocess mode by holding Shift and Accel (Ctrl/Cmd) when you right click (or whatever mouse button you set `browserToolbox` to for `userChrome.toolboxButton.mouseConfig`) the button.
    
    When you middle click, the button will show a notification telling you the current status of popup auto-hide, e.g. "Holding popups open." This is just so that people who use the feature a lot won't lose track of whether it's on or off, and won't need to open a popup and try to close it to test it. The toolbar button also changes appearance while popup auto-hide is disabled. It becomes blue like the downloads button and the icon changes into a popup icon. This change is animated, as long as the user doesn't have reduced motion enabled. All of these notifications use the native confirmation hint custom element, since it looks nice. That's the one that appears when you save a bookmark, `#confirmation-hint`. So you can customize them with that selector.
    */
    // @downloadURL    https://cdn.jsdelivr.net/gh/aminomancer/uc.css.js@master/JS/atoolboxButton.uc.js
    // @updateURL      https://cdn.jsdelivr.net/gh/aminomancer/uc.css.js@master/JS/atoolboxButton.uc.js
    // @license        This Source Code Form is subject to the terms of the Creative Commons Attribution-NonCommercial-ShareAlike International License, v. 4.0. If a copy of the CC BY-NC-SA 4.0 was not distributed with this file, You can obtain one at http://creativecommons.org/licenses/by-nc-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
    // ==/UserScript==
    
    
    (() => {
      // Modify these strings for easy localization. I tried to use built-in strings
      // for this so it would automatically localize itself, but I found that every
      // reference to the "Browser Toolbox" throughout the entire firefox UI is
      // derived from a single message in a single localization file, which doesn't
      // follow the standard format. It can only be parsed by the devtools' own
      // special l10n module, which itself can only be imported by a CJS module.
      // Requiring CJS just for a button seems ridiculous, plus there really aren't
      // any localized strings that work for these confirmation messages anyway, or
      // even the tooltip. So if your UI language isn't English you can modify all the
      // strings created by this script in the following object:
      const l10n = {
        // Confirmation hint. You receive this message when you right click the
        // toolbox button, but a toolbox process for the window is already open. You
        // can only have one toolbox open per-window. So if I have 3 windows open, and
        // I right-click the toolbox button in window 1, then it'll launch a browser
        // toolbox for window 1. If I then right-click the toolbox button in window 2,
        // it'll launch a browser toolbox for window 2. But if I go back to window 1
        // and right-click the toolbox button a second time, it will do nothing except
        // show a brief confirmation hint to explain the lack of action.
        alreadyOpenMsg: "Browser Werkzeuge sind bereits geöffnet.",
        // Confirmation hint. This appears when you first middle-click the toolbox
        // button. It signifies that popups are being kept open. That is, "popup
        // auto-hide" has been temporarily disabled.
        holdingOpenMsg: "Popups werden offen gehalten.",
        // Confirmation hint. This appears when you middle-click the toolbox button a
        // second time, toggling "popup auto-hide" back on, thereby allowing popups to
        // close on their own.
        lettingCloseMsg: "Popups werden automatisch geschlossen.",
    
    
        bundles: {},
        strings: new Map(),
        getString(name, where) {
          let string = this.strings.get(name);
          if (string) return string;
          string = this.bundles[where].GetStringFromName(name);
          this.strings.set(name, string);
          return string;
        },
        getFluentValue(id, args) {
          return this.fluentStrings.formatValueSync(id, args);
        },
        get defaultLabel() {
          return this.getString("toolbox.label", "toolbox");
        },
        get defaultTooltip() {
          return this.defaultLabel;
        },
      };
      ChromeUtils.defineLazyGetter(l10n.bundles, "menu", () =>
        Services.strings.createBundle("chrome://devtools/locale/menus.properties")
      );
      ChromeUtils.defineLazyGetter(l10n.bundles, "toolbox", () =>
        Services.strings.createBundle("chrome://devtools/locale/toolbox.properties")
      );
      ChromeUtils.defineLazyGetter(
        l10n,
        "fluentStrings",
        () => new Localization(["devtools/client/toolbox.ftl"], true)
      );
    
      if (
        /^chrome:\/\/browser\/content\/browser.(xul||xhtml)$/i.test(location) &&
        !CustomizableUI.getPlacementOfWidget("toolbox-button", true)
      ) {
        const { loader } = ChromeUtils.importESModule(
          "resource://devtools/shared/loader/Loader.sys.mjs"
        );
        const lazy = {};
        ChromeUtils.defineESModuleGetters(lazy, {
          BrowserToolboxLauncher:
            "resource://devtools/client/framework/browser-toolbox/Launcher.sys.mjs",
        });
        for (const [key, val] of Object.entries({
          gDevToolsBrowser:
            "resource://devtools/client/framework/devtools-browser.js",
          Actor: "resource://devtools/shared/protocol/Actor.js",
          dumpn: "resource://devtools/shared/DevToolsUtils.js",
        })) {
          loader.lazyRequireGetter(lazy, key, val, true);
        }
    
        if (location.href !== 'chrome://browser/content/browser.xhtml') return;
    
    
        CustomizableUI.createWidget({
          id: "toolbox-button",
          type: "custom",
          defaultArea: CustomizableUI.AREA_NAVBAR,
          label: l10n.defaultLabel,
          removable: true,
          overflows: true,
          tooltiptext: l10n.defaultTooltip,
          onBuild(aDoc) {
            let CustomHint = {
              ...aDoc.ownerGlobal.ConfirmationHint,
    
              /**
               * Shows a transient, non-interactive confirmation hint anchored to an
               * element, usually used in response to a user action to reaffirm that
               * it was successful and potentially provide extra context.
               *
               * @param  anchor (DOM node, required)
               *         The anchor for the panel. A value of null will anchor to the
               *         viewpoint (see options.x below)
               * @param  message (string, required)
               *         The message to be shown.
               * @param  options (object, optional)
               *         An object with any number of the following optional properties:
               *         - event (DOM event): The event that triggered the feedback.
               *         - hideArrow (boolean): Optionally hide the arrow.
               *         - hideCheck (boolean): Optionally hide the checkmark.
               *         - description (string): If provided, show a more detailed
               *                                 description/subtitle with the passed text.
               *         - duration (numeric): How long the hint should stick around, in
               *                               milliseconds. Default is 1500 — 1.5 seconds.
               *         - position (string): One of a number of strings representing how the anchor point of the popup
               *                              is aligned relative to the anchor point of the anchor node.
               *                              Possible values for position are:
               *                                  before_start, before_end, after_start, after_end,
               *                                  start_before, start_after, end_before, end_after,
               *                                  overlap, after_pointer
               *                              For example, after_start means the anchor node's bottom left corner will
               *                              be aligned with the popup node's top left corner. overlap means their
               *                              top left corners will be lined up exactly, so they will overlap.
               *         - x (number): Horizontal offset in pixels, relative to the anchor.
               *                       If no anchor is provided, relative to the viewport.
               *         - y (number): Vertical offset in pixels, relative to the anchor. Negative
               *                       values may also be used to move to the left and upwards respectively.
               *                       Unanchored popups may be created by supplying null as the
               *                       anchor node. An unanchored popup appears at the position
               *                       specified by x and y, relative to the viewport of the document
               *                       containing the popup node. (ignoring the anchor parameter)
               *
               */
              show(anchor, message, options = {}) {
                this._reset();
    
                this._message.removeAttribute("data-l10n-id");
                this._message.textContent = message;
    
                if (options.description) {
                  this._description.removeAttribute("data-l10n-id");
                  this._description.textContent = options.description;
                  this._description.hidden = false;
                  this._panel.classList.add("with-description");
                } else {
                  this._description.hidden = true;
                  this._panel.classList.remove("with-description");
                }
    
                if (options.hideArrow) {
                  this._panel.setAttribute("hidearrow", "true");
                }
    
                if (options.hideCheck) {
                  this._animationBox.setAttribute("hidden", "true");
                  this._panel.setAttribute("data-message-id", "hideCheckHint");
                } else {
                  this._animationBox.removeAttribute("hidden");
                  this._panel.setAttribute("data-message-id", "checkmarkHint");
                }
    
                const DURATION = options.duration || 1500;
                this._panel.addEventListener(
                  "popupshown",
                  () => {
                    this._animationBox.setAttribute("animate", "true");
                    this._timerID = setTimeout(
                      () => this._panel.hidePopup(true),
                      DURATION + 120
                    );
                  },
                  { once: true }
                );
    
                this._panel.addEventListener("popuphidden", () => this._reset(), {
                  once: true,
                });
    
                let { position, x, y } = options;
                this._panel.openPopup(null, {
                  position,
                  triggerEvent: options.event,
                });
                this._panel.moveToAnchor(anchor, position, x, y);
              },
    
              _reset() {
                if (this._timerID) {
                  clearTimeout(this._timerID);
                  this._timerID = null;
                  this._animationBox.removeAttribute("hidden");
                }
                if (this.__panel) {
                  this._panel.removeAttribute("hidearrow");
                  this._animationBox.removeAttribute("animate");
                  this._panel.removeAttribute("data-message-id");
                  this._panel.hidePopup();
                }
              },
    
              _ensurePanel() {
                if (!this.__panel) {
                  // hook into the built-in confirmation hint element
                  let wrapper = document.getElementById(
                    "confirmation-hint-wrapper"
                  );
                  wrapper?.replaceWith(wrapper.content);
                  this.__panel = ConfirmationHint.__panel =
                    document.getElementById("confirmation-hint");
                }
              },
            };
    
            let toolbarbutton = aDoc.createXULElement("toolbarbutton");
            let badgeStack = aDoc.createXULElement("stack");
            let icon = aDoc.createXULElement("image");
            let label = aDoc.createXULElement("label");
            let badgeLabel = aDoc.createElement("label");
            for (const [key, val] of Object.entries({
              class: "toolbarbutton-1 chromeclass-toolbar-additional",
              badged: true,
              label: l10n.defaultLabel,
              id: "toolbox-button",
              role: "button",
              icon: "toolbox",
              removable: true,
              overflows: true,
              tooltiptext: l10n.defaultTooltip,
            })) {
              toolbarbutton.setAttribute(key, val);
            }
    
            toolbarbutton.appendChild(badgeStack);
            badgeStack.after(label);
            badgeStack.appendChild(icon);
            icon.after(badgeLabel);
            badgeStack.setAttribute("class", "toolbarbutton-badge-stack");
            icon.setAttribute("class", "toolbarbutton-icon");
            badgeLabel.setAttribute("class", "toolbarbutton-badge");
            for (const [key, val] of Object.entries({
              class: "toolbarbutton-text",
              crop: "right",
              flex: "1",
              value: l10n.defaultLabel,
            })) {
              label.setAttribute(key, val);
            }
    
            let prefSvc = Services.prefs;
            let defaultPrefs = prefSvc.getDefaultBranch("");
            let obSvc = Services.obs;
            let toolboxBranch = "userChrome.toolboxButton";
            let autoHide = "ui.popup.disable_autohide";
            let autoTogglePopups =
              "userChrome.toolboxButton.popupAutohide.toggle-on-toolbox-launch";
            let mouseConfig = "userChrome.toolboxButton.mouseConfig";
    
            let onClick = function (e) {
              let { button } = e;
              let accel = e.getModifierState("Accel");
              let shift = e.getModifierState("Shift");
              if (accel) {
                if (button == 2 && !shift) {
                  return;
                }
                if (button == 0 && AppConstants.platform == "macosx") {
                  button = 2;
                  accel = false;
                }
              }
              switch (button) {
                case this.mouseConfig.contentToolbox:
                  // toggle the content toolbox
                  lazy.gDevToolsBrowser.toggleToolboxCommand(
                    aDoc.ownerGlobal.gBrowser
                  );
                  break;
                case this.mouseConfig.browserToolbox:
                  if (lazy.BrowserToolboxLauncher.getBrowserToolboxSessionState()) {
                    // check if a browser toolbox window is already open. if so,
                    // just show a hint that it's already open.
                    CustomHint.show(toolbarbutton, l10n.alreadyOpenMsg, {
                      event: e,
                      hideCheck: true,
                    });
                  } else {
                    // if not, launch a new one.
                    lazy.BrowserToolboxLauncher.init({
                      forceMultiprocess: accel && shift,
                    });
                  }
                  break;
                case this.mouseConfig.popupHide:
                  CustomHint.show(
                    toolbarbutton,
                    l10n[this.popupAutoHide ? "lettingCloseMsg" : "holdingOpenMsg"],
                    { event: e, hideCheck: this.popupAutoHide }
                  );
                  // toggle the pref
                  prefSvc.setBoolPref(autoHide, !this.popupAutoHide);
                  // animate the icon transformation
                  this.triggerAnimation();
                  break;
                default:
                  return;
              }
              e.preventDefault();
            };
    
            if (AppConstants.platform === "macosx") {
              toolbarbutton.onmousedown = onClick;
              toolbarbutton.onclick = e => {
                if (e.getModifierState("Accel")) return;
                e.preventDefault();
              };
            } else {
              toolbarbutton.onclick = onClick;
            }
    
            toolbarbutton.triggerAnimation = function () {
              this.addEventListener(
                "animationend",
                () => this.removeAttribute("animate"),
                { once: true }
              );
              this.setAttribute("animate", "true");
            };
    
            function getPref(root, pref) {
              switch (root.getPrefType(pref)) {
                case root.PREF_BOOL:
                  return root.getBoolPref(pref);
                case root.PREF_INT:
                  return root.getIntPref(pref);
                case root.PREF_STRING:
                  return root.getStringPref(pref);
                default:
                  return null;
              }
            }
    
            function prefObserver(sub, _top, pref) {
              let value = getPref(sub, pref);
              switch (pref) {
                case autoHide:
                  if (value === null) value = false;
                  toolbarbutton.popupAutoHide = value;
                  if (value) {
                    // change icon src to popup icon
                    toolbarbutton.setAttribute("icon", "autohide");
                    // highlight color
                    icon.style.fill = "var(--toolbarbutton-icon-fill-attention)";
                  } else {
                    // change icon src to toolbox icon
                    toolbarbutton.setAttribute("icon", "toolbox");
                    // un-highlight color
                    icon.style.removeProperty("fill");
                  }
                  break;
                case autoTogglePopups:
                  if (value === null) value = true;
                  toolbarbutton.autoTogglePopups = value;
                  break;
                case mouseConfig:
                  if (value === null) {
                    value = {
                      contentToolbox: 0,
                      browserToolbox: 2,
                      popupHide: 1,
                    };
                  }
                  toolbarbutton.mouseConfig = JSON.parse(value);
                  toolbarbutton.setStrings();
                  break;
              }
            }
    
            // listen for toolboxes opening and closing
            function toolboxObserver(sub, top, _data) {
              // whether a toolbox is open
              let state =
                lazy.BrowserToolboxLauncher.getBrowserToolboxSessionState();
              // set toolbar button's badge content
              badgeLabel.textContent = state ? 1 : "";
              // if toolbox is open and autohide is not already enabled, enable it
              switch (top) {
                case "initial-load":
                  return;
                // when a thread is created, set up its destroy method so it will
                // call the observer when it's destroyed. this ensures that if a
                // toolbox is closed while a content toolbox is inspecting the
                // system principal (such as on about:preferences), we will still
                // get notified that the toolbox has closed. otherwise, we wouldn't
                // get notified until the content toolbox also closes.
                case "devtools-thread-ready": {
                  let threadActor = sub?.wrappedJSObject;
                  if (threadActor) {
                    if (threadActor.destroy.name !== "destroyThreadActor") {
                      const STATES = {
                        DETACHED: "detached",
                        EXITED: "exited",
                        RUNNING: "running",
                        PAUSED: "paused",
                      };
    
                      threadActor.destroy = function destroyThreadActor() {
                        lazy.dumpn("in ThreadActor.prototype.destroy");
                        if (this._state == STATES.PAUSED) {
                          this.doResume();
                        }
    
                        this.removeAllWatchpoints();
                        this._xhrBreakpoints = [];
                        this._updateNetworkObserver();
    
                        this._activeEventBreakpoints = new Set();
                        this._debuggerNotificationObserver.removeListener(
                          this._eventBreakpointListener
                        );
    
                        for (const global of this.dbg.getDebuggees()) {
                          try {
                            this._debuggerNotificationObserver.disconnect(
                              global.unsafeDereference()
                            );
                          } catch (e) {
                          }
                        }
    
                        this.targetActor.off("window-ready", this._onWindowReady);
                        this.targetActor.off("will-navigate", this._onWillNavigate);
                        this.targetActor.off("navigate", this._onNavigate);
    
                        this.sourcesManager.off("newSource", this.onNewSourceEvent);
                        this.clearDebuggees();
                        this._threadLifetimePool.destroy();
                        this._threadLifetimePool = null;
                        this._dbg = null;
                        this._state = STATES.EXITED;
    
                        lazy.Actor.prototype.destroy.call(this);
                        // this leads back to toolboxObserver in 200ms
                        setTimeout(() => Services.obs.notifyObservers(null, "devtools-thread-destroyed"), 200);
                      }
                    }
                  }
                  break;
                }
                default:
                  break;
              }
              if (!toolbarbutton.autoTogglePopups) return;
              if (state && !toolbarbutton.popupAutoHide) {
                prefSvc.setBoolPref(autoHide, true);
              }
              // if toolbox just closed and autohide is not already disabled, disable it
              else if (!state && toolbarbutton.popupAutoHide) {
                prefSvc.setBoolPref(autoHide, false);
              }
            }
    
            toolbarbutton.setStrings = function () {
              let hotkey, labelString;
              for (const [key, val] of Object.entries(toolbarbutton.mouseConfig)) {
                if (val === 0) {
                  switch (key) {
                    case "contentToolbox":
                      labelString = l10n.getString("toolbox.label", "toolbox");
                      hotkey = aDoc.getElementById("key_toggleToolbox");
                      break;
                    case "browserToolbox":
                      labelString = l10n.getString(
                        "browserToolboxMenu.label",
                        "menu"
                      );
                      hotkey = aDoc.getElementById("key_browserToolbox");
                      break;
                    case "popupHide":
                      labelString = l10n.getFluentValue(
                        "toolbox-meatball-menu-noautohide-label"
                      );
                      break;
                  }
                }
              }
              let shortcut = hotkey
                ? ` (${ShortcutUtils.prettifyShortcut(hotkey)})`
                : "";
              toolbarbutton.label = labelString;
              label.value = labelString;
              toolbarbutton.tooltipText = labelString + shortcut;
            };
    
            // remove this window's observers when the window closes, since observers are global
            function uninit() {
              prefSvc.removeObserver(autoHide, prefObserver);
              prefSvc.removeObserver(toolboxBranch, prefObserver);
              for (const topic of [
                "devtools-thread-ready",
                "devtools-thread-destroyed",
                "devtools:loader:destroy",
              ]) {
                obSvc.removeObserver(toolboxObserver, topic);
              }
              window.removeEventListener("unload", uninit);
            }
    
            function toolboxInit() {
              prefObserver(prefSvc, null, autoHide);
              prefObserver(prefSvc, null, autoTogglePopups);
              prefObserver(prefSvc, null, mouseConfig);
              toolboxObserver(null, "initial-load");
            }
    
            defaultPrefs.setBoolPref(autoTogglePopups, true);
            defaultPrefs.setStringPref(
              mouseConfig,
              `{"contentToolbox": 0, "browserToolbox": 2, "popupHide": 1}`
            );
            window.addEventListener("unload", uninit);
            prefSvc.addObserver(autoHide, prefObserver);
            prefSvc.addObserver(toolboxBranch, prefObserver);
            for (const topic of [
              "devtools-thread-ready",
              "devtools-thread-destroyed",
              "devtools:loader:destroy",
            ]) {
              obSvc.addObserver(toolboxObserver, topic);
            }
            if (gBrowserInit.delayedStartupFinished) {
              toolboxInit();
            } else {
              let delayedListener2 = (subject, topic) => {
                if (
                  topic == "browser-delayed-startup-finished" &&
                  subject == window
                ) {
                  obSvc.removeObserver(delayedListener2, topic);
                  toolboxInit();
                }
              };
              obSvc.addObserver(
                delayedListener2,
                "browser-delayed-startup-finished"
              );
            }
            return toolbarbutton;
          },
        });
      }
    
      let styleSvc = Cc["@mozilla.org/content/style-sheet-service;1"].getService(
        Ci.nsIStyleSheetService
      );
      let toolboxCSS = /* css */ `
      .toolbarbutton-1#toolbox-button {
        --uc-toolbox-button: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAdUlEQVQokZVSwRHAIAgLPYfoXs7RCTpG53Avt7APrhaFU8gLMEEJAkEQgFbc7IxkVjt0r6Sp7VIVITumBpKt00FA2ThmjXzkfMMWO8EZFSj8LrUyjsG9b9DaJXq+qAIVxEUxtLHpaXE95dj1NcK2rmbwaGJ4Af0tIg00j/6iAAAAAElFTkSuQmCC');
        --uc-autohide-button: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABkAAAATCAYAAABlcqYFAAABeUlEQVQ4ja3UMSiEcRjH8Z8jKWU8q03JYEAhZ7PcZDFYrMpOWaTEgsEom4RFBmEjcSaEU0onFN0Rd9dFzr3er+Ut7vV/eS/vU7/l3/s8n/f/PvVKrkKKIm0hJZEoIUmkTaQO90w3MFniYK8MewHRgACQLKRmE7IRIALSkglJBYzcmhDPhrtwGJ6fIZeDTOYrwF5ri2dfSchBZxumOpoY5+mXvpKQ7NzID+Dl4Z6TitCvn8w3kpbIJS5dxBv7TbV/7sU3chOuAssqIqzMOfGZUV5W1yAWIzE4+D9kp6vLGf0KWLjrIx9nO9L4T6SmhrWePs7GI2A/FgHvJ/PEqwNaPBLHPZEi4HB6ipugdoJEQeJqZRYAO59kt7+B1B+AF+L5101UCgppwOYwWmceWubk6+zChKx7IamVXk6XxzgtD/Hh4wZOFkxIO5LtfjgrsdVdRjzkPdAA55HqfyAONIRU8Pmm2ObzPNKAEfgGNSMtIl37xZxcIy2YbvAJBGtcN/WRF/UAAAAASUVORK5CYII');
        list-style-image: var(--uc-toolbox-button);
        align-items: center;
      }
      .toolbarbutton-1#toolbox-button[icon="autohide"] {
        list-style-image: var(--uc-autohide-button);
      }
      .toolbarbutton-1#toolbox-button .toolbarbutton-badge-stack {
        justify-items: center;
      }
      .toolbarbutton-1#toolbox-button .toolbarbutton-icon {
        height: 16px;
        width: 16px;
        transition: fill 50ms ease-in-out 0s;
        background-image: var(--uc-toolbox-button), var(--uc-autohide-button);
        background-size: 0, 0;
      }
      @media (prefers-reduced-motion: no-preference) {
        .toolbarbutton-1#toolbox-button[animate] .toolbarbutton-icon {
          animation-name: toolboxButtonPulse;
          animation-duration: 200ms;
          animation-iteration-count: 1;
          animation-timing-function: ease-in-out;
        }
      }
      @keyframes toolboxButtonPulse {
        from {
          transform: scale(1);
        }
        40% {
          transform: scale(0.7);
        }
        to {
          transform: scale(1);
        }
      }
      #confirmation-hint[data-message-id="hideCheckHint"] #confirmation-hint-message {
        margin-inline: 0;
      }`;
    
      if (location.href !== 'chrome://browser/content/browser.xhtml') return;
    
      let styleURI = makeURI(
        `data:text/css;charset=UTF=8,${encodeURIComponent(toolboxCSS)}`
      );
      if (!styleSvc.sheetRegistered(styleURI, styleSvc.AUTHOR_SHEET)) {
        styleSvc.loadAndRegisterSheet(styleURI, styleSvc.AUTHOR_SHEET);
      }
    
      let observer = new MutationObserver(() => {
        if (document.getElementById("key_toggleToolbox")) {
          CustomizableUI.getWidget("toolbox-button")
            .forWindow(window)
            .node.setStrings();
          observer.disconnect();
          observer = null;
        }
      });
      observer.observe(document.body, { childList: true });
    })();
    Alles anzeigen

Unterstütze uns!

Jährlich (2025)

74,7 %

74,7% (485,86 von 650 EUR)

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