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

Beiträge von Mira_Belle

  • TABs lassen sich nicht mehr nach rechts verschieben

    • Mira_Belle
    • 4. August 2025 um 22:20

    GermanFreme82 Nimm diese Version.

    JavaScript
    // ==UserScript==
    // @name           MultiRowTabLiteforFx.uc.js
    // @namespace      Based on Alice0775's zzzz-MultiRowTab_LiteforFx48.uc.js
    // @description    Mehrzeilige Tableiste - Experimentelle CSS Version
    // @include        main
    // @compatibility  Firefox141+
    // @version        2025/06/30 16:58
    // @note           Wenn Sie das Gefühl haben, dass Tab-Gruppen beim Reinziehen zu schnell 
    //                 geöffnet und geschlossen werden, oder dass Tabs beim Reinziehen von Links 
    //                 zu schnell ausgewählt werden, versuchen Sie, diese Werte in about:config 
    //                 zu erhöhen, z. B. 
    //                 browser.tabs.dragDrop.selectTab.delayMS:800, 
    //                 browser.tabs.dragDrop.expandGroup.delayMS:1000.
    // ==/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 =       -1         ,// [-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 =                         1          ,// [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: "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 =                    32           ,// Standard = 29 Pixelbei Kompakt
       UI_Density_Normal =                     32           ,// Standard = 36 Pixel bei Normal
       UI_Density_Touch =                      41           ,// Standard = 41 Pixel bei Touch
                                                             // Tab-Breite
       Tab_Min_Width =                        165           ,// Standard - Mindestwert = 76px
       Tab_Max_Width =                        165           ,// Standard - Maxwert = 225px
                                                             // Bei gleichen Werten bei Min und Max, wird die Tabbreite fixiert!
                                                             // „Tab schließen“ Schaltfläche
       Tab_Close_Button =                       2           ,// [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 =                      true           ,// [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;
          }
          
    &[dragtarget] {
        z-index: unset !important;
        position: unset !important;
        pointer-events: unset !important; /* avoid blocking dragover events on scroll buttons */
    }
    #tabbrowser-tabs[movingtab] & {
       position: unset !important;
    }
    #tabbrowser-tabs[movingtab] &:is(:active, [multiselected]) {
        position: relative;
        z-index: 2;
        pointer-events: none; /* avoid blocking dragover events on scroll buttons */
    }
    
          #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;
              }
              &:hover .tab-close-button {
                display: flex;
              }
            ` : 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 {
                height: var(--tab-min-height);
                max-height: 24px;
              }
              .tab-close-button {
                height: 20px !important;
                padding-block: 3px !important;
              }
              &[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._getDropIndex = function(event) {
            let tabToDropAt = getTabFromEventTarget(event, false);
            if (tabToDropAt?.localName == "tab-group") {
              tabToDropAt = tabToDropAt.previousSibling;
              if (!tabToDropAt) {
                tabToDropAt = gBrowser.visibleTabs[0];
              }
            }
            if (!tabToDropAt) {
              tabToDropAt = gBrowser.visibleTabs[gBrowser.visibleTabs.length - 1];
            }
            const tabPos = gBrowser.tabContainer.getIndexOfItem(tabToDropAt);
    
            if (window.getComputedStyle(this).direction == "ltr") {
                let rect = tabToDropAt.getBoundingClientRect();
                if (event.clientX < rect.x + rect.width / 2)
                    return tabPos;
                else 
                    return tabPos + 1;
                
            } else {
                let rect = tabToDropAt.getBoundingClientRect();
                if (event.clientX > rect.x + rect.width / 2)
                    return tabPos;
                else
                    return tabPos + 1;
            }
        };
    
        // We set this to check if the listeners were added before
        let listenersActive = false;
    
    gBrowser.tabContainer.startTabDrag = function    startTabDrag(event, tab, { fromTabList = false } = {}) {
      const isTab = element => gBrowser.isTab(element);
      const isTabGroup = element => gBrowser.isTabGroup(element);
      const isTabGroupLabel = element => gBrowser.isTabGroupLabel(element);
          if (tab.multiselected) {
            for (let multiselectedTab of gBrowser.selectedTabs.filter(
              t => t.pinned != tab.pinned
            )) {
              gBrowser.removeFromMultiSelectedTabs(multiselectedTab);
            }
          }
    
          let dataTransferOrderedTabs;
          if (fromTabList || isTabGroupLabel(tab)) {
            // Dragging a group label or an item in the all tabs menu doesn't
            // change the currently selected tabs, and it's not possible to select
            // multiple tabs from the list, thus handle only the dragged tab in
            // this case.
            dataTransferOrderedTabs = [tab];
          } else {
            this.selectedItem = tab;
            let selectedTabs = gBrowser.selectedTabs;
            let otherSelectedTabs = selectedTabs.filter(
              selectedTab => selectedTab != tab
            );
            dataTransferOrderedTabs = [tab].concat(otherSelectedTabs);
          }
    
          let dt = event.dataTransfer;
          for (let i = 0; i < dataTransferOrderedTabs.length; i++) {
            let dtTab = dataTransferOrderedTabs[i];
            dt.mozSetDataAt(TAB_DROP_TYPE, dtTab, i);
            if (isTab(dtTab)) {
              let dtBrowser = dtTab.linkedBrowser;
    
              // We must not set text/x-moz-url or text/plain data here,
              // otherwise trying to detach the tab by dropping it on the desktop
              // may result in an "internet shortcut"
              dt.mozSetDataAt(
                "text/x-moz-text-internal",
                dtBrowser.currentURI.spec,
                i
              );
            }
          }
    
          // Set the cursor to an arrow during tab drags.
          dt.mozCursor = "default";
    
          // Set the tab as the source of the drag, which ensures we have a stable
          // node to deliver the `dragend` event.  See bug 1345473.
          dt.addElement(tab);
    
          // Create a canvas to which we capture the current tab.
          // Until canvas is HiDPI-aware (bug 780362), we need to scale the desired
          // canvas size (in CSS pixels) to the window's backing resolution in order
          // to get a full-resolution drag image for use on HiDPI displays.
          let scale = window.devicePixelRatio;
          let canvas = this._dndCanvas;
          if (!canvas) {
            this._dndCanvas = canvas = document.createElementNS(
              "http://www.w3.org/1999/xhtml",
              "canvas"
            );
            canvas.style.width = "100%";
            canvas.style.height = "100%";
            canvas.mozOpaque = true;
          }
    
          canvas.width = 160 * scale;
          canvas.height = 90 * scale;
          let toDrag = canvas;
          let dragImageOffset = -16;
          let browser = isTab(tab) && tab.linkedBrowser;
          if (isTabGroupLabel(tab)) {
            toDrag = tab;
          } else if (gMultiProcessBrowser) {
            var context = canvas.getContext("2d");
            context.fillStyle = "white";
            context.fillRect(0, 0, canvas.width, canvas.height);
    
            let captureListener;
            let platform = AppConstants.platform;
            // On Windows and Mac we can update the drag image during a drag
            // using updateDragImage. On Linux, we can use a panel.
            if (platform == "win" || platform == "macosx") {
              captureListener = function () {
                dt.updateDragImage(canvas, dragImageOffset, dragImageOffset);
              };
            } else {
              // Create a panel to use it in setDragImage
              // which will tell xul to render a panel that follows
              // the pointer while a dnd session is on.
              if (!this._dndPanel) {
                this._dndCanvas = canvas;
                this._dndPanel = document.createXULElement("panel");
                this._dndPanel.className = "dragfeedback-tab";
                this._dndPanel.setAttribute("type", "drag");
                let wrapper = document.createElementNS(
                  "http://www.w3.org/1999/xhtml",
                  "div"
                );
                wrapper.style.width = "160px";
                wrapper.style.height = "90px";
                wrapper.appendChild(canvas);
                this._dndPanel.appendChild(wrapper);
                document.documentElement.appendChild(this._dndPanel);
              }
              toDrag = this._dndPanel;
            }
            // PageThumb is async with e10s but that's fine
            // since we can update the image during the dnd.
            PageThumbs.captureToCanvas(browser, canvas)
              .then(captureListener)
              .catch(e => console.error(e));
          } else {
            // For the non e10s case we can just use PageThumbs
            // sync, so let's use the canvas for setDragImage.
            PageThumbs.captureToCanvas(browser, canvas).catch(e =>
              console.error(e)
            );
            dragImageOffset = dragImageOffset * scale;
          }
          dt.setDragImage(toDrag, dragImageOffset, dragImageOffset);
    
          // _dragData.offsetX/Y give the coordinates that the mouse should be
          // positioned relative to the corner of the new window created upon
          // dragend such that the mouse appears to have the same position
          // relative to the corner of the dragged tab.
          let clientPos = ele => {
            const rect = ele.getBoundingClientRect();
            return this.verticalMode ? rect.top : rect.left;
          };
    
          let tabOffset = clientPos(tab) - clientPos(this);
    
          let movingTabs = tab.multiselected ? gBrowser.selectedTabs : [tab];
          let movingTabsSet = new Set(movingTabs);
    
          tab._dragData = {
            offsetX: this.verticalMode
              ? event.screenX - window.screenX
              : event.screenX - window.screenX - tabOffset,
            offsetY: this.verticalMode
              ? event.screenY - window.screenY - tabOffset
              : event.screenY - window.screenY,
            scrollPos:
              this.verticalMode && tab.pinned
                ? this.verticalPinnedTabsContainer.scrollPosition
                : this.arrowScrollbox.scrollPosition,
            screenX: event.screenX,
            screenY: event.screenY,
            movingTabs,
            movingTabsSet,
            fromTabList,
            tabGroupCreationColor: gBrowser.tabGroupMenu.nextUnusedColor,
            expandGroupOnDrop: false,
          };
    
          event.stopPropagation();
    
        }
        // This sets when to apply the fix (by default a new row starts after the 23th open tab, unless you changed the min-size of tabs)
        gBrowser.tabContainer.addEventListener("dragstart", () => {
            // Multiple tab select fix
            gBrowser.visibleTabs.forEach(t => t.style.transform = "");
    
            // Event handling
            if (!listenersActive) {
                gBrowser.tabContainer.getDropEffectForTabDrag = function(){};
                gBrowser.tabContainer._getDropEffectForTabDrag = function(){};
                gBrowser.tabContainer.on_dragover = (dragoverEvent) => performTabDragOver(dragoverEvent);
                gBrowser.tabContainer._onDragOver = (dragoverEvent) => performTabDragOver(dragoverEvent);
                gBrowser.tabContainer.ondrop = (dropEvent) => performTabDropEvent(dropEvent);
                gBrowser.tabContainer.ondragleave = (ondragleave) => {gBrowser.tabContainer._dragTime = 0};
                gBrowser.tabContainer.ondragend = (ondragend) => clearTimeout(dragovertimer);
                listenersActive = true;
            }
        });
    }
    
    var lastKnownIndex = null;
    var lastGroupStart = null;
    var lastGroupEnd = null;
    let dragovertimer = null;
    let lasttabgroup = null;
    
    /**
     * Gets the tab from the event target.
     * @param {*} event The event.
     * @returns The tab if it was part of the target or its parents, otherwise null
     */
    function getTabFromEventTarget(event, { ignoreTabSides = false } = {}) {
        let { target } = event;
        if (target.nodeType != Node.ELEMENT_NODE) {
            target = target.parentElement;
        }
        let tab = target?.closest("tab") || target?.closest("tab-group");
        const selectedTab = gBrowser.selectedTab;
        if (tab && ignoreTabSides) {
            let { width, height } = tab.getBoundingClientRect();
            if (
                event.screenX < tab.screenX + width * 0.25 ||
                event.screenX > tab.screenX + width * 0.75 ||
                ((event.screenY < tab.screenY + height * 0.25 ||
                    event.screenY > tab.screenY + height * 0.75) &&
                    gBrowser.tabContainer.verticalMode)
            ) {
                return selectedTab;
            }
        }
        return tab;
    }
    
    /**
     * Performs the tab drag over event.
     * @param {*} event The drag over event.
     */
    function performTabDragOver(event) {
        event.preventDefault();
        event.stopPropagation();
    
        let ind = gBrowser.tabContainer._tabDropIndicator;
    
        let effects = orig_getDropEffectForTabDrag(event);
        let tab;
        if (effects == "link") {
          tab = getTabFromEventTarget(event, true);
          if (tab) {
            if (!gBrowser.tabContainer._dragTime)
              gBrowser.tabContainer._dragTime = Date.now();
            if (!tab.hasAttribute("pendingicon") && // annoying fix
                Date.now() >= gBrowser.tabContainer._dragTime + Services.prefs.getIntPref("browser.tabs.dragDrop.selectTab.delayMS")) {
                gBrowser.selectedTab = tab;
                ind.hidden = true;
                return;
            }
          }
        }
    
        if (!tab) {
            tab = getTabFromEventTarget(event, false);
        }
        if (tab?.nodeName == "tab-group") {
          if(lasttabgroup !== tab) {
            lasttabgroup = tab
            clearTimeout(dragovertimer);
            dragovertimer = setTimeout((tabgroup) => {
              tabgroup.collapsed = !tabgroup.collapsed
            }, Services.prefs.getIntPref("browser.tabs.dragDrop.expandGroup.delayMS"), tab);
          }
        } else {
          clearTimeout(dragovertimer);
          lasttabgroup = null;
        }
    
    
    
        let newIndex = gBrowser.tabContainer._getDropIndex(event);
        if (newIndex == null)
            return;
    
        // Update the last known index and group position
        lastKnownIndex = newIndex;
        
        if (tab?.nodeName == "tab-group" && !lastGroupStart) {
            lastGroupStart = tab.querySelector("tab:first-of-type")._tPos;
            lastGroupEnd = tab.querySelector("tab:last-of-type")._tPos;
        }
    
        let tabs = gBrowser.tabs;
        let ltr = (window.getComputedStyle(gBrowser.tabContainer).direction == "ltr");
        let rect = gBrowser.tabContainer.arrowScrollbox.getBoundingClientRect();
        let newMarginX, newMarginY;
    
       if (newIndex == tabs.length) {
            let tabRect = tabs[newIndex - 1].getBoundingClientRect();
            if (ltr)
                newMarginX = tabRect.right - rect.left;
            else
                newMarginX = rect.right - tabRect.left;
            newMarginY = tabRect.top + tabRect.height - rect.top - rect.height; // multirow fix
    
            if (CSS.supports("offset-anchor", "left bottom")) // Compatibility fix for FF72+
                newMarginY += rect.height / 2 - tabRect.height / 2;
            
        } else if (newIndex != null || newIndex != 0) {
            let tabRect = tabs[newIndex].getBoundingClientRect();
            if (ltr)
                newMarginX = tabRect.left - rect.left;
            else
                newMarginX = rect.right - tabRect.right;
            newMarginY = tabRect.top + tabRect.height - rect.top - rect.height; // multirow fix
    
            if (CSS.supports("offset-anchor", "left bottom")) // Compatibility fix for FF72+
                newMarginY += rect.height / 2 - tabRect.height / 2;
        }
    
        newMarginX += ind.clientWidth / 2;
        if (!ltr)
            newMarginX *= -1;
    
        ind.hidden = false;
    
        ind.style.transform = "translate(" + Math.round(newMarginX) + "px," + Math.round(newMarginY) + "px)"; // multirow fix
        ind.style.marginInlineStart = (-ind.clientWidth) + "px";
    }
    
    /**
     * Performs the tab drop event.
     * @param {*} event The drop event.
     */
    function performTabDropEvent(event) {
        clearTimeout(dragovertimer);
        let newIndex;
        let dt = event.dataTransfer;
        let dropEffect = dt.dropEffect;
        let draggedTab;
        if (dt.mozTypesAt(0)[0] == TAB_DROP_TYPE) {
            draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
            if (!draggedTab) {
                return;
            }
        }
    
        if (draggedTab && dropEffect != "copy" && draggedTab.container == gBrowser.tabContainer) {
            newIndex = gBrowser.tabContainer._getDropIndex(event);
    
            let selectedTabs = gBrowser.selectedTabs.length > 1 ? gBrowser.selectedTabs : [draggedTab];
            let tabToMoveAt = gBrowser.tabContainer.getItemAtIndex(newIndex);
            let tab = getTabFromEventTarget(event, false);
            let tabgroup = tab?.closest("tab-group");
            if (!tab) {
              newIndex = gBrowser.tabs.length;
              tabToMoveAt = null;
            }
            if (tab?.pinned && !selectedTabs[0].pinned) {
              selectedTabs.forEach(t => gBrowser.pinTab(t));
              if (tabToMoveAt == tab) {
                selectedTabs.forEach(t => {gBrowser.moveTabBefore(t, tab)});
              } else {
                selectedTabs.forEach(t => {gBrowser.moveTabBefore(t, tabToMoveAt)});
              }
              return;
            } else if(!tab?.pinned && selectedTabs[0].pinned) {
              selectedTabs.forEach(t => gBrowser.unpinTab(t));
            }
    
            if (tabgroup && !tabgroup.previousSibling) {
              newIndex = 0; 
              selectedTabs.forEach(t => {gBrowser.moveTabTo(t, { tabIndex: newIndex++,forceUngrouped:true});});
            } else if (!tab || 
                !tabgroup && !tabToMoveAt?.group || 
                tabgroup && tabToMoveAt?.group) {
              if (tab !== tabToMoveAt) {
                tabToMoveAt = gBrowser.tabContainer.getItemAtIndex(newIndex -1);
                selectedTabs.forEach(t => {gBrowser.moveTabAfter(t, tabToMoveAt); tabToMoveAt = t});
              } else {
                selectedTabs.forEach(t => {gBrowser.moveTabBefore(t, tabToMoveAt)});
              }
            } else  {
              tabToMoveAt = gBrowser.tabContainer.getItemAtIndex(newIndex -1);
              selectedTabs.forEach(t => {gBrowser.moveTabAfter(t, tabToMoveAt); tabToMoveAt = t});
            }
    
            // Restart global vars
            lastKnownIndex = null;
            lastGroupStart = null;
            lastGroupEnd = null;
        }
    }
    
    // copy of the original and overrided _getDropEffectForTabDrag method
    function orig_getDropEffectForTabDrag(event) {
        let dt = event.dataTransfer;
    
        let isMovingTabs = dt.mozItemCount > 0;
        for (let i = 0; i < dt.mozItemCount; i++) {
            // tabs are always added as the first type
            let types = dt.mozTypesAt(0);
            if (types[0] != TAB_DROP_TYPE) {
                isMovingTabs = false;
                break;
            }
        }
    
        if (isMovingTabs) {
            let sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
            if (XULElement.isInstance(sourceNode) &&
                sourceNode.localName == "tab" &&
                sourceNode.ownerGlobal.isChromeWindow &&
                sourceNode.ownerDocument.documentElement.getAttribute("windowtype") ==
                "navigator:browser" &&
                sourceNode.ownerGlobal.gBrowser.tabContainer == sourceNode.container) {
                // Do not allow transfering a private tab to a non-private window
                // and vice versa.
                if (PrivateBrowsingUtils.isWindowPrivate(window) !=
                    PrivateBrowsingUtils.isWindowPrivate(sourceNode.ownerGlobal))
                    return "none";
            
    
                if (window.gMultiProcessBrowser !=
                    sourceNode.ownerGlobal.gMultiProcessBrowser)
                    return "none";
            
    
                if (window.gFissionBrowser != sourceNode.ownerGlobal.gFissionBrowser)
                    return "none";
            
    
                return dt.dropEffect == "copy" ? "copy" : "move";
            }
        }
    
        if (Services.droppedLinkHandler.canDropLink(event, true)) 
            return "link";
    
        return "none";
    }
    Alles anzeigen

    Oh, zwei Doofe, ein Gedanke.
    Meine ist direkt vom Autor, mir German's Einstellungen und Endor's Übersetzungen.

    Such Dir was aus!

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

    • Mira_Belle
    • 3. August 2025 um 23:27

    Muss noch einen Nachtragen, was irgendwie immer vergessen geht.
    Ich nutze nicht immer KI!
    Ich habe auf meiner Platte genug Beispielcode, den ich als Referenz nutze, manches weiß ich halt einfach,
    da brauch ich nicht mehr nach zu guggn. Aber jetzt, wo es am Code von FF solche Änderungen gibt,
    nutze ich eben auch KI, nicht eine, sondern gleich mehrere und veranstalte auch schon mal ein Battle.
    Auch muss so ein korrigiertes und angepasstes Skript getestet werden und hie oder da fällt mir auch selber auf,
    dass da was am Code nicht stimmen kann.

    Was ich ganz gerne mache, ich lass mir von "LeChat" UND ChatGPT und 'Duck.ai' den Code von JS Zeile für Zeile erklären.
    Apropos 'Duck.ai', das ist nicht nur eine KI! Es können aus mehrere ausgewählt werden.
    Und dann gibt es ja noch "https://lmarena.ai/", sehr interessant.

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

    • Mira_Belle
    • 3. August 2025 um 23:05
    Zitat von milupo

    Da sind wir uns doch wieder alle einig. :)

    Mir ist da gerade der Browser abgeschmiert, falsche Taste betätigt!

    Mh, weiß aber gerade nicht mehr, was ich noch so alles geschrieben hatte.
    Egal.
    Die Frage, die sich mir stellt, mach' ich weiter wie bisher, oder soll, muss ich aufhören?

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

    • Mira_Belle
    • 3. August 2025 um 22:51

    Ich wusste, dass diese Diskussion in diese Richtung laufen würde.

    Es geht um einzelne Codezeilen, die angepasst werden müssen.
    Um Zeilen, die, wie Du es beschreibst, die Kenntnisse über den Firefox-Code benötigen!
    Wer hat diese? DU! Und wer noch?

    Ich prüfe nach meinen Möglichkeiten die korrigierten Skripte.

  • Fenster "Lesezeichen verwalten" in bestimmten Ordner öffnen - Wie?

    • Mira_Belle
    • 3. August 2025 um 22:38
    Zitat von katzi

    Dieser Eintrag "Lesezeichen verwalten" ist via Rechtsklick über der Lesezeichen-Symbolleiste in dem dann aufgerufenen Kontextmenü, (nenne ich mal so), ganz unten sichtbar und auswählbar.

    Und dann ist "Weitere Lesezeichen" ausgewählt!
    Ist immer so, egal wie und wo ich "Lesezeichen verwalten" anklicke.

    Wenn ich den Themenstarter richtig verstanden habe, möchte er aber, dass sich das Programm merkt,
    welcher Ordner zuletzt genutzt wurde,
    oder dass wenigstens "Lesezeichen-Menü" ausgewählt ist.

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

    • Mira_Belle
    • 3. August 2025 um 22:10
    Zitat von milupo

    Nur so zum Vergleich: Das erinnert mich als Sprachfreund an die Sprachführer für Leute, die in ein Land fahren, deren Sprache sie nicht kennen. Sie sind letztendlich mit diesem Sprachführer genauso hilflos wie ohne. Ein paar Grundkenntnisse in der jeweiligen Sprache wären besser.

    Da gebe ich Dir grundsätzlich recht, aber ohne Sprachführer findest Du nicht einmal ein Klo!
    Ergo nutze ich in einem Land, dessen Sprache ich so gar nicht beherrsche, zur Not eben auch mal einen "Übersetzer"!
    Und ich kann berichten, dass mich das vor einer sehr peinlichen Lage gerettet hat!

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

    • Mira_Belle
    • 3. August 2025 um 22:05

    Seien wir doch mal ehrlich, die alten Hasen, die JS aus dem Effeff beherrschten sind nicht mehr da!
    Wenn KI zum Korrigieren und anpassen von bestehendem Code nicht genutzt werden darf,
    ist JS zum Erweitern der Funktionen hier "on Board" tot!
    Dann kann man nur noch auf den GitHub-Seiten von z.B. alice0775, MrOtherGuy, benzBrake oder Aris-t2
    darum bitten, dass sie ihre Skripte anpassen und erneuern.
    Andere Skripte dürfen dann gar nicht mehr genutzt werden, bzw, wenn sie nicht mehr funktionieren,
    sind sie dann "End of Life" und können eben nicht mehr genutzt werden.

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

    • Mira_Belle
    • 3. August 2025 um 21:50
    Zitat von Horstmann

    Bei nur sehr begrenzten Erfahrung mit AI: niemals Code direkt übernehmen, nicht eine Zeile, ohne gegen zu recherchieren.

    Ist es legitim, einfach zuschauen, was der Code macht?
    Ob es funktioniert?
    Eine zweite, andere KI zu befragen?

    Wir sind dann gerade in eine Grundsatzdiskussion geraten!

    Wann darf KI genutzt werden?
    Darf überhaupt KI genutzt werden?

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

    • Mira_Belle
    • 3. August 2025 um 20:57

    .DeJaVu Es geht ja auch nicht um das Generieren!
    In erster Linie geht es um Anpassungen und Fehlerkorrekturen, das geht, vorausgesetzt man stellt die richtigen Fragen
    oder gibt die richtigen Kommandos, dann doch recht gut.
    Ganz neue Skripte oder neue Funktionen, das wird extrem schwierig und bedarf viel Zeit und Geduld
    und ob es überhaupt klappt, steht auch überhaupt nicht fest.

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

    • Mira_Belle
    • 3. August 2025 um 20:35
    Zitat von FuchsFan

    Gewagt habe ich es schon mehrmals, mit Vorlagen aus anderen Scripten, aber es will nicht gelingen.

    Verstehe, ist auch nicht ganz einfach, gebe ich zu. Vielleicht habe ich doch ein Händchen dafür, mit diesen
    widerspenstigen Programmen, KI's sind nichts anderes, umzugehen.

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

    • Mira_Belle
    • 3. August 2025 um 19:19
    Zitat von FuchsFan

    ... ist es möglich hier auch Submenüs (wenigsten eines) einzuarbeiten, ...

    Bestimmt, ganz sicher sogar, aber Du vergisst, ich kann kein JavaScript!
    Wenn ich bestehende Skript "repariere", dann ganz oft mittels mistral.ai oder ChatGPT, manchmal auch mittels arena.ai.
    Und selbst da muss ich schon recht oft mehrere Anläufe machen, nicht immer verstehen diese KI's, was ich von denen will.
    Sicher, kleinere Anpassungen kann ich auch so machen, wenn nicht allzu komplex, habe ja so einige Vorlagen.
    Aber das, was Du gerne möchtest, das ist dann doch schon eine Hausnummer.
    Eventuell kann einer der ganz wenigen Profis hier Dir weiter helfen, oder Du wagst es selbst einmal.

  • Symbolabstände in einigen Menüs und Kontextmenüs zu groß

    • Mira_Belle
    • 3. August 2025 um 18:35

    1. Deine userChrome.css
    2. Screenshot, damit ich sehen kann, um welches Symbol es geht.

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

    • Mira_Belle
    • 3. August 2025 um 18:32
    Zitat von FuchsFan

    Ich habe nur in Zeile 14 "Button" eingetragen.

    Oh sorry, mein Fehler!
    Das Versuchsskript war ein anderes und ich habe aus dem Original den oberen Teil einfach hier reinkopiert!
    Im Versuchsskript steht da tatsächlich:

    JavaScript
    var gExternalApplications = {
      type: 'button', // 'menu' or 'button'
      insertafter: 'PanelUI-menu-button',
  • userChrome.js Scripte für den Fuchs (Diskussion)

    • Mira_Belle
    • 3. August 2025 um 17:04

    FuchsFan Soooo, verschiebbar und mit Symbol.

    JavaScript
    // ==UserScript==
    // @name           XP - Spider.uc.js
    // @namespace      ithinc#mozine.cn
    // @description    External Applications
    // @include        main
    // @compatibility  Firefox 143.x
    // @author         ithinc
    // @version        20250803 Edited by: Mira
    // ==/UserScript==
    
    /* :::: External Applications :::: */
    
    var gExternalApplications = {
      type: 'menu', //'menu' or 'button'
      insertafter: '',
    
      apps: [
        
    	{name: 'Download Firefox', path: 'D:\\Download Firefox'},
    	{name: 'Ordner Screenshots', path: 'C:\\Users\\Old Man\\Pictures\\Screenshots'},
    	{name: 'Windows Explorer', path: 'C:\\Windows\\explorer.exe'},
    	{name: 'Editor', path: 'C:\\Windows\\System32\\notepad.exe'},
    	{name: 'Ordner Dokumente', path: 'C:\\Users\\Old Man\\Documents'},
    	{name: 'notepad++', path: 'C:\\notepad++\\notepad++.exe'},
    	{name: 'Rechner', path: 'C:\\WINDOWS\\system32\\calc.exe'},
    	{name: 'Ordner Backup ArbeitsFox', path: 'E:\\BackupFirefox\\ArbeitsFox '},
    	{name: 'Ordner BackupFirefox', path: 'E:\\BackupFirefox'},
    	{name: 'Ordner ArchiveFirefox', path: 'G:\\ArchiveFirefox'},
    	{name: 'Firefox Beta 3', path: 'G:\\Portable.Firefox.Updater.3\\Firefox Beta x64 Launcher.exe'},
    	{name: 'Firefox Nightly 3', path: 'G:\\Portable.Firefox.Updater.3\\Firefox Nightly x64 Launcher.exe'},
    	{name: 'Firefox Stable 3', path: 'G:\\Portable.Firefox.Updater.3\\Firefox Stable x64 Launcher.exe'},
    	{name: 'Ordner Portable.Firefox.Updater.1', path: 'G:\\Portable.Firefox.Updater.1'},
    	{name: 'Ordner Portable.Firefox.Updater.2', path: 'G:\\Portable.Firefox.Updater.2'},
    	{name: 'Ordner Portable.Firefox.Updater.3', path: 'G:\\Portable.Firefox.Updater.3'},
    	{name: 'Ordner Portable.Firefox.Updater.4', path: 'G:\\Portable.Firefox.Updater.4'},
    	{name: 'Portable Start', path: 'G:\\Starter'},
    	{name: 'Ordner FoxIcons', path: 'C:\\FoxIcons'},
    	{name: 'Ordner FoxIcons2', path: 'C:\\FoxIcons2'},
    	{name: 'Installationsordner', path: 'C:\\Program Files\\Mozilla Firefox'},
    	
      ],
    
      init: function() {
        for (var i = 0; i < this.apps.length; i++) {
          if (!this.apps[i].path) continue;
          if (!this.apps[i].args) this.apps[i].args = [];
    
          this.apps[i].path = this.apps[i].path.replace(/\//g, '\\');
    
          var ffdir = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties).get('CurProcD', Ci.nsIFile).path;
          if (/^(\\)/.test(this.apps[i].path)) {
            this.apps[i].path = ffdir.substr(0, 2) + this.apps[i].path;
          } else if (/^(\.)/.test(this.apps[i].path)) {
            this.apps[i].path = ffdir + '\\' + this.apps[i].path;
          }
        }
    
        if (location.href !== 'chrome://browser/content/browser.xhtml') return;
    
        if (this.type == 'menu') {
          var mainmenu = document.getElementById('nav-bar');
          var menu = mainmenu.appendChild(document.createXULElement('menu'));
          menu.setAttribute('label', 'Start');
          menu.setAttribute('accesskey', 'a');
    
          var menupopup = menu.appendChild(document.createXULElement('menupopup'));
          for (var i = 0; i < this.apps.length; i++) {
            menupopup.appendChild(this.createMenuitem(this.apps[i]));
          }
        } else {
          if (!CustomizableUI.getPlacementOfWidget('ExtAppButton')) {
            try {
              CustomizableUI.createWidget({
                id: 'ExtAppButton',
                type: 'custom',
                defaultArea: CustomizableUI.AREA_NAVBAR,
                onBuild: function(aDocument) {
                  let toolbarbutton = aDocument.createElementNS('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul', 'toolbarbutton');
                  toolbarbutton.id = 'ExtAppButton';
                  toolbarbutton.setAttribute('label', 'Start');
                  toolbarbutton.setAttribute('class', 'toolbarbutton-1 chromeclass-toolbar-additional');
                  toolbarbutton.setAttribute('type', 'menu');
                  let menupopup = toolbarbutton.appendChild(aDocument.createElementNS('http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul', 'menupopup'));
                  for (var i = 0; i < gExternalApplications.apps.length; i++) {
                    menupopup.appendChild(gExternalApplications.createMenuitem(gExternalApplications.apps[i]));
                  }
                  return toolbarbutton;
                }
              });
            } catch(e) {
              console.error(e);
              return;
            };
    
            let ProfilePath = PathUtils.toFileURI(PathUtils.join(PathUtils.profileDir, 'chrome', 'icons')); // Pfad zum Profilordner und gleich in den entsprechenden Unterordner
            let ButtonIcon = "default-browser-red.svg"; // Name & Dateiendung des anzuzeigenden Symbols!
            let sss = Components.classes["@mozilla.org/content/style-sheet-service;1"].getService(Components.interfaces.nsIStyleSheetService);       
            let uri = Services.io.newURI("data:text/css;charset=utf-8," + encodeURIComponent(`
        
                #ExtAppButton { list-style-image: url("${ProfilePath}/${ButtonIcon}") }
                #ExtAppButton.toolbarbutton-1.chromeclass-toolbar-additional image.toolbarbutton-icon {
                  width: 28px !important;
                  height: 28px !important;
                  fill: #83ee1a !important;
                  fill-opacity: 1 !important;
                  }
        
              `), null, null);
        
            sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);   
          }
        }
      },
    
      exec: function(path, args) {
        for (var i = 0; i < args.length; i++) {
          args[i] = args[i].replace(/%u/g, gBrowser.currentURI.spec);
        }
    
        var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
        file.initWithPath(path);
        if (!file.exists()) {
          throw 'File Not Found: ' + path;
        }
    
        if (!file.isExecutable() || args.length == 0) {
          file.launch();
        } else {
          var process = Cc['@mozilla.org/process/util;1'].getService(Ci.nsIProcess);
          process.init(file);
          process.run(false, args, args.length);
        }
      },
    
      createMenuitem: function(app) {
        if (app.name == 'separator')
          return document.createXULElement('menuseparator');
    
        var item = document.createXULElement('menuitem');
        item.setAttribute('class', 'menuitem-iconic');
        item.setAttribute('label', app.name);
        item.setAttribute('image', 'moz-icon:file:///' + encodeURIComponent(app.path) + '?size=16');
    
        item.addEventListener('command', function(event) {
          if (event.button == 0) {
            gExternalApplications.exec(this.path, this.args);
          }
        });
    
        item.path = app.path;
        item.args = app.args;
        return item;
      }
    };
    
    gExternalApplications.init();
    Alles anzeigen

    Symbol kann ausgetauscht werden und der Pfad dahin sollte auch angepasst werden.

    Und putzen müsste man auch mal!

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

    • Mira_Belle
    • 3. August 2025 um 16:09

    FuchsFan
    Bitte testen.


    JavaScript
    // ==UserScript==
    // @name           XP - Spider.uc.js
    // @namespace      ithinc#mozine.cn
    // @description    External Applications
    // @include        main
    // @compatibility  Firefox 143.x
    // @author         ithinc
    // @version        20250803
    // ==/UserScript==
    
    /* :::: External Applications :::: */
    
    
    
    var gExternalApplications = {
      type: 'menu', //'menu' or 'button'
      insertafter: '',
    
      apps: [
        
    	{name: 'Download Firefox', path: 'D:\\Download Firefox'},
    	{name: 'Ordner Screenshots', path: 'C:\\Users\\Old Man\\Pictures\\Screenshots'},
    	{name: 'Windows Explorer', path: 'C:\\Windows\\explorer.exe'},
    	{name: 'Editor', path: 'C:\\Windows\\System32\\notepad.exe'},
    	{name: 'Ordner Dokumente', path: 'C:\\Users\\Old Man\\Documents'},
    	{name: 'notepad++', path: 'C:\\notepad++\\notepad++.exe'},
    	{name: 'Rechner', path: 'C:\\WINDOWS\\system32\\calc.exe'},
    	{name: 'Ordner Backup ArbeitsFox', path: 'E:\\BackupFirefox\\ArbeitsFox '},
    	{name: 'Ordner BackupFirefox', path: 'E:\\BackupFirefox'},
    	{name: 'Ordner ArchiveFirefox', path: 'G:\\ArchiveFirefox'},
    	{name: 'Firefox Beta 3', path: 'G:\\Portable.Firefox.Updater.3\\Firefox Beta x64 Launcher.exe'},
    	{name: 'Firefox Nightly 3', path: 'G:\\Portable.Firefox.Updater.3\\Firefox Nightly x64 Launcher.exe'},
    	{name: 'Firefox Stable 3', path: 'G:\\Portable.Firefox.Updater.3\\Firefox Stable x64 Launcher.exe'},
    	{name: 'Ordner Portable.Firefox.Updater.1', path: 'G:\\Portable.Firefox.Updater.1'},
    	{name: 'Ordner Portable.Firefox.Updater.2', path: 'G:\\Portable.Firefox.Updater.2'},
    	{name: 'Ordner Portable.Firefox.Updater.3', path: 'G:\\Portable.Firefox.Updater.3'},
    	{name: 'Ordner Portable.Firefox.Updater.4', path: 'G:\\Portable.Firefox.Updater.4'},
    	{name: 'Portable Start', path: 'G:\\Starter'},
    	{name: 'Ordner FoxIcons', path: 'C:\\FoxIcons'},
    	{name: 'Ordner FoxIcons2', path: 'C:\\FoxIcons2'},
    	{name: 'Installationsordner', path: 'C:\\Program Files\\Mozilla Firefox'},
    	
      ],
    
      init: function() {
        for (var i = 0; i < this.apps.length; i++) {
          if (!this.apps[i].path) continue;
          if (!this.apps[i].args) this.apps[i].args = [];
    
          this.apps[i].path = this.apps[i].path.replace(/\//g, '\\');
    
          var ffdir = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties).get('CurProcD', Ci.nsIFile).path;
          if (/^(\\)/.test(this.apps[i].path)) {
            this.apps[i].path = ffdir.substr(0, 2) + this.apps[i].path;
          } else if (/^(\.)/.test(this.apps[i].path)) {
            this.apps[i].path = ffdir + '\\' + this.apps[i].path;
          }
        }
    	
        if (location.href !== 'chrome://browser/content/browser.xhtml') return;
    
        if (this.type == 'menu') {
          var mainmenu = document.getElementById('nav-bar');
          var menu = mainmenu.appendChild(document.createXULElement('menu'));
          menu.setAttribute('label', 'Start');
          menu.setAttribute('accesskey', 'a');
    
          var menupopup = menu.appendChild(document.createXULElement('menupopup'));
          for (var i = 0; i < this.apps.length; i++) {
            menupopup.appendChild(this.createMenuitem(this.apps[i]));
          }
        } else {
          var menubarItems = document.getElementById(this.insertafter);
          var toolbaritem = menubarItems.parentNode.insertBefore(document.createXULElement('toolbaritem'), menubarItems.nextSibling);
          toolbaritem.id = 'ExtAppButtons';
          toolbaritem.setAttribute("class", "chromeclass-toolbar-additional");
          toolbaritem.setAttribute("orient", "horizontal");
          for (var i = 0; i < this.apps.length; i++) {
            toolbaritem.appendChild(this.createButton(this.apps[i]));
          }
        }
      },
    
      exec: function(path, args) {
        for (var i=0; i<args.length; i++) {
          args[i] = args[i].replace(/%u/g, gBrowser.currentURI.spec);
        }
    
        var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
        file.initWithPath(path);
        if (!file.exists()) {
          throw 'File Not Found: ' + path;
        }
    
        if (!file.isExecutable() || args.length==0) {
          file.launch();
        }
        else {
          var process = Cc['@mozilla.org/process/util;1'].getService(Ci.nsIProcess);
          process.init(file);
          process.run(false, args, args.length);
        }
      },
    
      createButton: function(app) {
        if (app.name == 'separator')
          return document.createXULElement('toolbarseparator');
    
        if (location.href !== 'chrome://browser/content/browser.xhtml') return;
    
        var item = document.createXULElement('toolbarbutton');
        item.setAttribute('class', 'toolbarbutton-1 chromeclass-toolbar-additional');
        item.setAttribute('label', app.name);
        item.setAttribute('image', 'moz-icon:file:///' + encodeURIComponent(app.path) + '?size=16');
    
        item.addEventListener('command', function(event) {
          if (event.button == 0) {
            gExternalApplications.exec(this.path, this.args);
          }
        });
    
        item.path = app.path;
        item.args = app.args;
        return item;
      },
    
      createMenuitem: function(app) {
        if (app.name == 'separator')
          return document.createXULElement('menuseparator');
    
        var item = document.createXULElement('menuitem');
        item.setAttribute('class', 'menuitem-iconic');
        item.setAttribute('label', app.name);
        item.setAttribute('image', 'moz-icon:file:///' + encodeURIComponent(app.path) + '?size=16');
    
        item.addEventListener('command', function(event) {
          if (event.button == 0) {
            gExternalApplications.exec(this.path, this.args);
          }
        });
    
        item.path = app.path;
        item.args = app.args;
        return item;
      }
    };
    
    gExternalApplications.init();
    Alles anzeigen

    Wie man den "Button" jetzt noch verschiebbar bekommt, weiß ich noch nicht.

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

    • Mira_Belle
    • 3. August 2025 um 11:45
    Zitat von 2002Andreas

    Sorry der Nachfrage, aber wo finde ich das :/

    Habe ich mich auch gefragt! Wollte es erst einmal in FF 141 testen,
    aber worauf muss ich klicken, damit das Menü erscheint?

    Nachtrag.
    Ah, danke für die Erklärung.
    Das ist mir dann aber doch etwas zu viel. Wäre es einfach nur ein Button oder so, aber ...

  • Öffnen aktuell aktive Tab in einem privaten Fenster (Skript)

    • Mira_Belle
    • 2. August 2025 um 12:11

    Ich vermute, ich verstehe das falsch, aber im Kontextmenü gibt es doch einen Eintrag "Link in neuem privaten Fenster öffnen".

    Ich vermute, dass Skript soll wohl einen "privaten" Tab öffnen, richtig?

  • Symbolabstände in einigen Menüs und Kontextmenüs zu groß

    • Mira_Belle
    • 2. August 2025 um 12:06
    Zitat von bananovic

    Natürlich kann mein FF JS. Ich verwende auch andere Scripts, wie z.B. RestartFirefox_plus.uc.js. Was fehlt denn, wenn FF kein JS kann?

    Dann weiß ich auch nicht! Kontrolliere noch einmal ganz genau den Pfad!
    Oder nutze zum Testen einfach mal "interne" Symbole.

  • ScrollTopAndBottom.uc.js und Open with.uc.js zeigen keine Icons mehr an im Nightly

    • Mira_Belle
    • 1. August 2025 um 22:40
    Zitat von 2002Andreas

    Wo soll etwas unsichtbar werden?

    Meinst du hier das badge?

    Na dann schau Dir noch einmal Dein Sceenshot an.

    Beitrag

    RE: ScrollTopAndBottom.uc.js und Open with.uc.js zeigen keine Icons mehr an im Nightly

    […]



    und im rechten Teil fehlen die Haken.

    So sieht das in Fx 141 aus:

    2002Andreas
    1. August 2025 um 16:42


    FuchsFan

    JavaScript
    // ==UserScript==
    // @name           Appmenu.uc.js
    // @namespace      Appmenu@gmail.com
    // @description    Basiert auf dem Script externalFuncButtonM.uc.js, Wiederherstellung der Orangenen FF-Menü Schaltfläche
    // @include        main
    // @version        update for Firefox 68+ by aborix
    // @author         defpt
    // @charset        UTF-8
    // @version        2019.08.04
    // @version        2020.05.27
    // @version        2020.07.13 Weitere Menüs und Funktionen ergänzt by bege
    // @version        2024.08.10 alle Einstellungen im Abschnitt Konfiguration vornehmen
    // @version        2024.08.18 einige Veränderungen am Skript, Symbole, Funktionen & Menüs by Mira Bellenbaum
    // @version        2025.01.15 EventListener korrigiert und angepasst, by Mira Bellenbaum
    // @version        2025.04.03 Zeile 340 "eval()" ersetzt. Nachfolgend Zeilen 381-416 ergänzt und Parameter (command:) angepasst
    // ==/UserScript==
    
        // Definiere den Profilpfad für die Symbole
        let ProfilePath = PathUtils.toFileURI(
          PathUtils.join(PathUtils.profileDir, 'chrome', 'icons')
        );
    
        // Standard-Symbol-Dateiname
        let ButtonIcon01 = 'restart.svg';
        let ButtonIcon02 = 'quit.svg';
      
        let Icon01 = 'profile.svg';
        let Icon02 = 'chrome.svg';
        let Icon03 = 'css4.svg';
        let Icon04 = 'js.svg';
        let Icon05 = 'addons.svg';
        let Icon06 = 'folder.svg';
        let Icon07 = 'folder-1.svg';
      
        let Icon11 = 'Themes.svg';
        let Icon12 = 'debugging-workers.svg';
        let Icon13 = 'command-console.svg';
        let Icon14 = 'window-dev-tools.svg';
        let Icon15 = 'developer.svg';
        let Icon16 = 'sync.svg';
        let Icon17 = 'passwords.svg';
        let Icon18 = 'performance.svg';
        let Icon19 = 'plug-disconnected.svg';
    
      
      var Appmenu = {
        // ■■ START UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
      
        // Editor mit angegebenem Pfad verwenden
        // editor: 'C:\\Program Files\\Notepad++\\notepad++.exe',
        editor: "C:\\Program Files\\Microsoft VS Code\\Code.exe",
        // oder
        // in 'view_source.editor.path' eingetragenen Editor verwenden
        editor: Services.prefs.getCharPref('view_source.editor.path'),
        // Dateimanager mit angegebenem Pfad verwenden oder leer ('') wenn System-Dateimanager verwenden
        //fileManager: 'C:\\Program files\\FreeCommander XE\\FreeCommander.exe',
        fileManager: "",
        // Parameter für Dateimanager oder leer ('')
        //FMParameter: '/T',
        FMParameter: "",
        // Submenüs ohne Inhalt im Hauptmenü automatisch ausblenden
        autohideEmptySubDirs: true,
        // Submenüs im Hauptmenü nach unten verschieben
        moveSubDirstoBottom: false,
        // Ort und Aussehen des Menü-Buttons einstellen
        //   isUrlbar: 1,  // 0: TabsToolbar; 1: navbar,
        isUrlbar: 2, // 0: TabsToolbar; 1: navbar; 2: toolbar-menubar
        isButton: 0, // 0: Hamburger,klein; 1: Firefox,groß,
        // Hotkey zum Öffnen des Appmenüs oder leer ('')
        hotkey: "f",
        hotkeyModifier: "alt",
      
        // ■■ END UserConfiguration ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
      
        // Submenüs im Hauptmenü nach unten verschieben
        subdirPopupHash: [],
        subdirMenuHash: [],
      
        toolbar: {
          // Submenüs des Hauptmenüs definieren; Separator einfügen mit {name: 'separator'}
          subdirs: [
            {
              name: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/folder_currentColor.svg`, // Der Pfad wird direkt verwendet, ohne `url()`
            },
            {
              name: 'Firefox Funktionen',
              image: `${ProfilePath}/settings_currentColor.svg`, // Der Pfad wird direkt verwendet, ohne 'url()'
            },
            {
              name: 'separator',
            },
          ],
          
          apps: [
    
            // Untermenü Firefox Verzeichnisse
            {
              name: 'Profil-Verzeichniss',
              id: 'AMProfil',
              root: 'ProfD',
              path: '\\',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon01}`,
            },
            {
              name: 'Chrome-Ordner',
              id: 'AMchrome',
              root: 'ProfD',
              path: '\\chrome',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon02}`,
            },
            {
              name: 'CSS-Ordner',
              id: 'AMCSS',
              root: 'ProfD',
              path: '\\chrome\\css',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon03}`,          
            },
            {
              name: 'JS-Ordner',
              id: 'AMJS',
              root: 'ProfD',
              path: '\\chrome\\scripts',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon04}`,
            },
            {
              name: 'Addon-Verzeichniss',
              id: 'AMAddons',
              root: 'ProfD',
              path: '\\extensions',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon05}`,
             },
             {
              name: 'Programm-Verzeichniss',
              id: 'AMProgramm',
              root: 'CurProcD',
              path: '\\',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon06}`,
             },
             {
              name: 'Startup-Cache',
              id: 'AMCache',
              root: 'ProfLD',
              path: '\\startupCache',
              subdir: 'Firefox Verzeichnisse',
              image: `${ProfilePath}/${Icon07}`,
            },
          ],
          
           configs: [
            // Untermenü Firefox Funktionen
            {
              name: 'Anpassen',
              id: 'AMAnpassen',
              command: 'gCustomizeMode.enter()',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon11}`,
            },
            {
              name: 'Neustart im abgesicherten Modus',
              id: 'AMModus',
              command: 'safeModeRestart();',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon12}`,
            },
            {
              name: 'Browser-Konsole',
              id: 'AMKonsole',
              command: 'goKonsole',
    //            "var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});\
    //              var { BrowserConsoleManager } = require('resource://devtools/client/webconsole/browser-console-manager');\
    //              BrowserConsoleManager.openBrowserConsoleOrFocus();",
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon13}`,
            },
            {
              name: 'Browser-Werkzeuge',
              id: 'AMWerkzeuge',
              command: 'goWerkzeuge',
    //            "var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});\
    //              var { BrowserToolboxLauncher } = require('resource://devtools/client/framework/browser-toolbox/Launcher.sys.mjs');\
    //              BrowserToolboxLauncher.init();",
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon14}`,
            },
            {
              name: 'Web-Entwickler',
              id: 'AMEntwickler',
              command: 'goEntwickler',
    //            "var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});\
    //              var { gDevToolsBrowser } = require('resource://devtools/client/framework/devtools-browser');\
    //              gDevToolsBrowser.toggleToolboxCommand(window.gBrowser, Cu.now());",
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon15}`,
            },
            {
              name: 'Firefox synchronisieren',
              id: 'AMsynchron',
              command: 'gSync',
    //          command: "gSync.openPrefs('menubar');",
              subdir: 'Firefox Funktione',
              image: `${ProfilePath}/${Icon16}`,
            },
            {
            name: 'Zugangsdaten und Passwörter',
            id: 'AMdaten',
            command:
              'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })',
            tooltiptext: 'about:logins',
            subdir: 'Firefox Funktionen',
            image: `${ProfilePath}/${Icon17}`,
            },
            {
              name: 'Task Manager',
              id: 'AMManager',
              command: 'switchToTabHavingURI("about:processes", true)',
              tooltiptext: 'about:processes',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon18}`,
            },
            {
              name: 'Offline arbeiten',
              id: 'AMOffline',
              command: 'BrowserOffline.toggleOfflineStatus();',
              subdir: 'Firefox Funktionen',
              image: `${ProfilePath}/${Icon19}`,
            },
              /*
                {
                name: 'separator',
                },
                */
            {
              name: 'Neustart',
              id: 'AMreboot',
              tooltiptext: 'userChrome.js-Cache wird geleert',
              command: 'goReeboot',
    //          "Services.appinfo.invalidateCachesOnRestart(); \
    //                Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit);",
              image: `${ProfilePath}/${ButtonIcon01}`,
            },
            {
              name: 'Beenden',
              id: 'AMquit',
              command: 'goQuitApplication(event);',
              image: `${ProfilePath}/${ButtonIcon02}`,
            },
        ]
      },
    
      _externalAppPopup: null,
      _isready: false,
    
      init: function() {
        this.handleRelativePath(this.toolbar.apps);
        const XULNS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
    
        var ExternalAppBtn = document.createElementNS(XULNS, 'toolbarbutton');
        ExternalAppBtn.id = 'AppMenuButton';
        ExternalAppBtn.setAttribute('label', 'AppButton');
        //ExternalAppBtn.setAttribute("onclick", "event.preventDefault();event.stopPropagation();");
        ExternalAppBtn.addEventListener('click', event => {
          event.preventDefault();
          event.stopPropagation();
        });
        ExternalAppBtn.setAttribute('tooltiptext', 'Firefox Menü');
        ExternalAppBtn.setAttribute('type', 'menu');
        ExternalAppBtn.setAttribute('removable', 'true');
          
        // Definiere den Profilpfad
        let ProfilePath = PathUtils.toFileURI(
          PathUtils.join(PathUtils.profileDir, 'chrome', 'image')
        );
      
        // Symbole
        let DefaultIcon = 'Button_groß.png';
        let AlternateIcon = 'Button_klein-5.png';
    
    
        if (Appmenu.isButton) {
          ExternalAppBtn.style.listStyleImage = `url('${ProfilePath}/${DefaultIcon}')`; // Großes Symbol
          ExternalAppBtn.style.width = '94px'; // Feste Breite für großes Symbol
          ExternalAppBtn.style.height = '24px'; // Feste Höhe für großes Symbol
        } else {
          ExternalAppBtn.style.listStyleImage = `url('${ProfilePath}/${AlternateIcon}')`; // Kleines Symbol
          //ExternalAppBtn.style.width = "16px"; // Feste Breite für kleines Symbol
          ExternalAppBtn.style.width = '48px';
          ExternalAppBtn.style.height = '21px'; // Feste Höhe für kleines Symbol
        }
          
        if (Appmenu.isUrlbar === 1) {
          var navBar = document.getElementById('nav-bar-customization-target');
          navBar.insertBefore(ExternalAppBtn, navBar.firstChild);
        } else if (Appmenu.isUrlbar === 2) {
          var menubar = document.getElementById('toolbar-menubar');
          menubar.insertBefore(ExternalAppBtn, menubar.firstChild);
        } else {
          var TabsToolbar = document.getElementById('TabsToolbar');
          TabsToolbar.insertBefore(ExternalAppBtn, TabsToolbar.firstChild);
        }
    
        var ExternalAppPopup = document.createElementNS(XULNS, 'menupopup');
        //ExternalAppPopup.setAttribute('onpopupshowing', 'event.stopPropagation(); Appmenu.onpopupshowing();');
        ExternalAppPopup.addEventListener('click', event => {
          event.stopPropagation();
        });
        ExternalAppPopup.setAttribute('id', 'AMpopup');
        this._externalAppPopup = ExternalAppPopup;
        ExternalAppBtn.appendChild(ExternalAppPopup);
        Appmenu.onpopupshowing();
          
        // Menü mit Tastaturkürzel öffnen
        if (Appmenu.hotkey) {
        let key = document.createXULElement('key');
          key.id = 'key_AppMenuPopup';
          key.setAttribute('key', Appmenu.hotkey);
          if (Appmenu.hotkeyModifier)
          key.setAttribute('modifiers', Appmenu.hotkeyModifier);
        //  key.setAttribute('oncommand', 'document.getElementById("AMpopup").openPopup();');
    
          key.addEventListener('command', function () {
            document.getElementById('AMpopup').openPopup();
            });
          document.getElementById('mainKeyset').appendChild(key);
        }
      },
    
      onpopupshowing: function() {
        if (this._isready) return;
        if (this._externalAppPopup === null) return;
        var ExternalAppPopup = this._externalAppPopup;
    
        for (let subdir of this.toolbar.subdirs) {
          if (subdir.name == 'separator') {
            ExternalAppPopup.appendChild(document.createXULElement('menuseparator'));
          } else {
            var subdirItem = ExternalAppPopup.appendChild(document.createXULElement('menu'));
            var subdirItemPopup = subdirItem.appendChild(document.createXULElement('menupopup'));
            subdirItem.setAttribute('class', 'menu-iconic');
            subdirItem.setAttribute('label', subdir.name);
            subdirItem.setAttribute('image', subdir.image);
            Appmenu.subdirPopupHash[subdir.name] = subdirItemPopup;
            Appmenu.subdirMenuHash[subdir.name] = subdirItem;
          }
        }
    
        for (let app of this.toolbar.apps) {
          var appItem;
          if (app.name == 'separator') {
            appItem = document.createXULElement('menuseparator');
          } else {
            appItem = document.createXULElement('menuitem');
            appItem.setAttribute('class', 'menuitem-iconic');
            appItem.setAttribute('label', app.name);
            appItem.setAttribute('image', app.image);
            //appItem.setAttribute('oncommand', "Appmenu.exec(this.path, this.args);");
            appItem.addEventListener('command', function () {
              Appmenu.exec(this.path, this.args);
              });
            appItem.setAttribute('tooltiptext', app.name);
            appItem.path = app.path;
            appItem.args = app.args;
          }
          if (app.subdir && Appmenu.subdirPopupHash[app.subdir])
            Appmenu.subdirPopupHash[app.subdir].appendChild(appItem);
          else ExternalAppPopup.appendChild(appItem);
        }
    
        for (let config of this.toolbar.configs) {
          var configItem;
          if (config.name == 'separator') {
            configItem = document.createXULElement('menuseparator');
          } else {
            configItem = ExternalAppPopup.appendChild(document.createXULElement('menuitem'));
            configItem.setAttribute('class', 'menuitem-iconic');
            configItem.setAttribute('label', config.name);
            configItem.setAttribute('image', config.image);
            //configItem.setAttribute('oncommand', config.command);
    //        configItem.addEventListener('command', () => {
    //          eval(config.command);
    //        });
    
            configItem.addEventListener('command', () => {
              Appmenu.executeCommand(config.command);
            });
    
            if (config.tooltiptext) {
              configItem.setAttribute('tooltiptext', config.tooltiptext);
            } else {
              configItem.setAttribute('tooltiptext', config.name);
            }
            configItem.setAttribute('id', config.id);
          }
              
          if (config.subdir && Appmenu.subdirPopupHash[config.subdir]) {
            Appmenu.subdirPopupHash[config.subdir].appendChild(configItem);
          } else {
            ExternalAppPopup.appendChild(configItem);
          }
        }
    
        if (this.autohideEmptySubDirs) {
          for (let i = 0; i < Appmenu.subdirPopupHash.length; i++) {
            if (Appmenu.subdirPopupHash[i].hasChildNodes()) {
              continue;
            } else {
              Appmenu.subdirMenuHash[i].setAttribute('hidden', 'true');
            }
          }
        }
    
        if (this.moveSubDirstoBottom) {
          let i = ExternalAppPopup.childNodes.length;
          while (ExternalAppPopup.firstChild.getAttribute('class') != 'menuitem-iconic' && i-- != 0) {
            ExternalAppPopup.appendChild(ExternalAppPopup.firstChild);
          }
        }
        this._isready = true;
      },
    
      executeCommand: function(command) {
        const commandMap = { 
          'gCustomizeMode.enter()': () => gCustomizeMode.enter(),
          'safeModeRestart();': () => safeModeRestart(),
          'goKonsole': () => {
                  var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                  var { BrowserConsoleManager } = require('resource://devtools/client/webconsole/browser-console-manager');
                  BrowserConsoleManager.openBrowserConsoleOrFocus();
                },
          'goWerkzeuge': () => {
                  var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                  var { BrowserToolboxLauncher } = require('resource://devtools/client/framework/browser-toolbox/Launcher.sys.mjs');
                  BrowserToolboxLauncher.init();
                },
          'goEntwickler': () => {
                  var { require } = ChromeUtils.importESModule('resource://devtools/shared/loader/Loader.sys.mjs', {});
                  var { gDevToolsBrowser } = require('resource://devtools/client/framework/devtools-browser');
                  gDevToolsBrowser.toggleToolboxCommand(window.gBrowser, Cu.now());
                },
          'gSync': () => gSync.openPrefs('menubar'),
          'LoginHelper.openPasswordManager(window, { entryPoint: "mainmenu" })': () => LoginHelper.openPasswordManager(window, { entryPoint: 'mainmenu' }),
          'switchToTabHavingURI("about:processes", true)': () => switchToTabHavingURI('about:processes', true),
          'BrowserOffline.toggleOfflineStatus();': () => BrowserOffline.toggleOfflineStatus(),      
          'goReeboot': () => {
                    Services.appinfo.invalidateCachesOnRestart();
                    Services.startup.quit(Ci.nsIAppStartup.eRestart | Ci.nsIAppStartup.eAttemptQuit);
                  },
          'goQuitApplication(event);': () => goQuitApplication(event),
        };
        
        if (commandMap[command]) {
          commandMap[command]();
        } else {
          console.warn('Unbekannter Befehl: ', command);
        }
      },
    
      handleRelativePath: function(apps) {
        for (let app of apps) {
          if (app.path) {
            app.path = app.path.replace(/\//g, '\\');
            var ffdir = Cc['@mozilla.org/file/directory_service;1'].getService(Ci.nsIProperties).get(app.root, Ci.nsIFile).path;
            if (/^(\\)/.test(app.path)) {
              app.path = ffdir + app.path;
            }
          }
        }
      },
    
      exec: function(path, args) {
        args = args || [];
        var args_t = args.slice(0);
        for (let arg of args_t) {
          arg = arg.replace(/%u/g, gBrowser.currentURI.spec);
        }
        var file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
        file.initWithPath(path);
        if (!file.exists()) {
          //Cu.reportError('Datei nicht gefunden: ' + path);
          alert('Datei nicht gefunden: ' + path);
          return;
        }
        if (file.isExecutable() && !path.endsWith('.js')) {
          var process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
          process.init(file);
          process.run(false, args_t, args_t.length);
        } else if (file.isFile()) {
          if (this.editor) {
            let UI = Cc['@mozilla.org/intl/scriptableunicodeconverter'].createInstance(Ci.nsIScriptableUnicodeConverter);
            UI.charset = window.navigator.platform.toLowerCase().includes('win') ? 'Shift_JIS' : 'UTF-8';
            let path = UI.ConvertFromUnicode(file.path);
            let app = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
            app.initWithPath(this.editor);
            let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
            process.init(app);
            process.run(false, [path], 1);
          } else {
            file.launch();
          }
        } else if (file.isDirectory()) {
          if (this.fileManager) {
            let args=[this.FMParameter,path];
            let app = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
            app.initWithPath(this.fileManager);
            let process = Cc['@mozilla.org/process/util;1'].createInstance(Ci.nsIProcess);
            process.init(app);
            process.run(false, args, args.length);
          } else {
            file.launch();
          }
        }
      },
    };
    
    (function () {
      
        // StyleSheetService zum Hinzufügen der CSS-Regeln
        let sss = Components.classes['@mozilla.org/content/style-sheet-service;1'].getService(Components.interfaces.nsIStyleSheetService);
        let uri = Services.io.newURI(
          'data:text/css;charset=utf-8,' +
            encodeURIComponent(`
      
              menuitem[label='Profil-Verzeichniss'] { -moz-context-properties: fill, fill-opacity;
                            fill: currentColor;
                            }
              menuitem[label='Chrome-Ordner'] { -moz-context-properties: fill, fill-opacity;
                            fill: currentColor; 
                            }
              menuitem[label='CSS-Ordner'] { -moz-context-properties: fill, fill-opacity;
                            fill: currentColor;                       
                            }
              menuitem[label='JS-Ordner'] { -moz-context-properties: fill, fill-opacity;
                            fill: currentColor;                       
                            }
              menuitem[label='Addon-Verzeichniss'] { -moz-context-properties: fill, fill-opacity;
                            fill: currentColor;                       
                            }
              menuitem[label='Programm-Verzeichniss'] { -moz-context-properties: fill, fill-opacity;
                            fill: currentColor;                       
                            }
              menuitem[label='Startup-Cache'] { -moz-context-properties: fill, fill-opacity;
                            fill: currentColor;                       
                            }
      
              #AMAnpassen     { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;                          
                              }
              #AMModus        { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              }
              #AMKonsole      { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              }
              #AMWerkzeuge    { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              }
              #AMEntwickler   { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              }
              #AMsynchron     { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              }
              #AMdaten        { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              }        
              #AMManager      { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              }
              #AMOffline      { -moz-context-properties: fill, fill-opacity;
                                fill: currentColor;
                              } 
      
              /* Neustart-Button */
              #AMreboot { -moz-context-properties: fill, fill-opacity !important;
                  fill: #fbc96e !important;
                  padding-left: 10px !important;
              }
              #AMreboot > img:nth-child(1) {
                  width: 20px !important;
                  height: 20px !important;
              }
              /* Beenden-Button */
              #AMquit { -moz-context-properties: fill, fill-opacity !important;
                  fill: red !important;
              }
      
          `),
          null,
          null
        );
      
        // CSS-Regeln registrieren
        sss.loadAndRegisterSheet(uri, sss.AUTHOR_SHEET);
      })();
    
      
      if (window.gBrowser) Appmenu.init();
    Alles anzeigen

    für Tests setze ganz einfach "interne" Symbole
    oder schaue hier:

    Beitrag

    RE: Symbole in den Kontextmenüs [ Update ]

    Neu ab Version 141!

    (Quelltext, 881 Zeilen)

    icons_4.zip
    Mira_Belle
    22. Juli 2025 um 21:30
  • ScrollTopAndBottom.uc.js und Open with.uc.js zeigen keine Icons mehr an im Nightly

    • Mira_Belle
    • 1. August 2025 um 20:51

    UND visibility: hidden; getestet, funzt nicht!

Unterstütze uns!

Jährlich (2025)

104,5 %

104,5% (679,10 von 650 EUR)

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