Hallo Herzmann.
Der Autor hat seine Version aktualisiert:
CSS
// ==UserScript==
// @name zzzz-MultiRowTab_LiteforFx48.uc.js
// @namespace http://space.geocities.yahoo.co.jp/gl/alice0775
// @description Experimentelle CSS Version für Mehrzeilige Tableiste
// @include main
// @compatibility Firefox 128esr Firefox 131+
// @author Alice0775
// @version 2016/08/05 00:00 Firefox 48
// @version 2016/05/01 00:01 hide favicon if busy
// @version 2016/03/09 00:01 Bug 1222490 - Actually remove panorama for Fx45+
// @version 2016/02/09 00:01 workaround css for lwt
// @version 2016/02/09 00:00
// ==/UserScript==
"use strict";
MultiRowTabLiteforFx();
function MultiRowTabLiteforFx() {
if (!window.gBrowser) { return; }
// -- Config --
const // Anzahl der Tab-Leistenzeilen angeben oder eine unbegrenzte Anzahl von Zeilen wählen.
TabBar_Rows = false ,// [false] = unbegrenzt
// true = Begrenzte Tabzeilen - Anzahl der Zeilen angeben
Maximum_Rows = 3 ,// Tabzeilen angeben (Standard: 3 Zeilen)
// ProtonUI Erscheinungsbild der Tabs ändern
ProtonUI = 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.
// Leerraum um die Tabs auf 0 anpassen, um der Höhe der UI-Dichte zu entsprechen.
// Position der Tab-Leiste.
TabBar_Position = 0 ,// [0] = Standard
// 1 = unter der Symbolleiste
// 2 = unter dem Fenster
// Standardposition der Tableiste Blenden Sie die Titelleistenschaltfläche [-□×] aus und verwenden Sie die Breite der Tableiste entsprechend
TitleBar_Button_Autohide = false ,// [false] = Aktiviert
// true = Deaktiviert
// Außeren Rahmen der Titelleistenschaltfläche [-□×] redduzieren und transparent machen, obere rechte Ecke der Tab-Leiste auf ihre ursprüngliche Größe zurücksetzen und Transparenz aufheben.
// Tab-Höhe „UI-Dichte“
UI_Density_Compact = 29 ,// Standard = 29 Pixel bei Kompakt
UI_Density_Normal = 36 ,// Standard = 36 Pixel bei Normal
UI_Density_Touch = 41 ,// Standard = 41 Pixel bei Touch
// Entsprechender CSS Code in UserChrome.css wird vorrangig behandelt!
// Tab-Breite
// Bei gleichen Werten bei Min und Max, wird Tabbreite fixiert!
Tab_Min_Width = 76 ,// Standard - Mindestwert = 76px
Tab_Max_Width = 225 ,// Standard - Maxwert = 225px
// Entsprechender CSS Code in UserChrome.css wird vorrangig behandelt!
// .Tab-Drop-Indikator-Icon-Ersetzung.
Tab_Drop_Indicator = false ,// [false] = Stecknadel Symbol 📍
// true = Rote Linie (2px × 29px) als Symbol
// 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.
// Tab-Leisten-Ziehbereich
Left_Drag_Area = 0 ,// Linker Ziehbereich Breite: Standard 40 Pixel
Right_Drag_Area = 0 ,// Rechter Ziehbereich Breite: Standard 40 Pixel
Window_Maximize_Left_Drag_Area = false ,// true = Linken Ziehbereich bei maximiertem Fenster anzeigen. Standardmäßig ausgeblendet.
Fullscreen_Drag_Area = false ,// true = Linken und rechten Ziehbereich bei Vollbild anzeigen. Standardmäßig ausgeblendet.
// Angeheftete Tabs neu positionieren
Separate_Tabs_and_PinnedTabs = false ,// [false] = Standard
// true = Angeheftete Tabs von der Tab-Leiste lösen und in die darüber liegende Zeile verschieben.
// „Tab schließen“ Schaltfläche .
Tab_Close_Button = 0 ,// [0] = Standard
// 1 = Auf allen Tabs anzeigen
// 2 = Nur bei Mausberührung anzeigen
// Alle Tabs Schaltfläche
All_Tabs_Button = false ,// [false] = ausblenden
// true = anzeigen
// -- Config End --
css = `
#TabsToolbar {
: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; }
${Tab_Drop_Indicator ? `
#tabbrowser-tabs > .tab-drop-indicator {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAAdCAIAAAAPVCo9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAASSURBVBhXY3growJEQ5+SUQEAOb1EM8kwskcAAAAASUVORK5CYII=) no-repeat center !important;
}
` : ``}
.titlebar-spacer[type="pre-tabs"] {
width: ${Left_Drag_Area}px !important;
}
.titlebar-spacer[type="post-tabs"] {
width: ${Right_Drag_Area}px !important;
}
${Window_Maximize_Left_Drag_Area ? `
.titlebar-spacer {
:root:not([sizemode="normal"], [inFullscreen]) &[type="pre-tabs"] {
display: block !important;
}
}
` : ``}
${Fullscreen_Drag_Area ? `
.titlebar-spacer {
:root[inFullscreen] &, :root:not([tabsintitlebar]) & {
display: block !important;
}
}
` : ``}
#tabbrowser-arrowscrollbox {
&::part(scrollbox) {
&:has(+ spacer) > slot,
.scrollbox-clip > & {
flex-wrap: wrap;
}
${TabBar_Rows ? `
max-height: calc((var(--tab-min-height) + ${ProtonUI ? 8 : 0}px) * ${Maximum_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 ? `
&::part(scrollbox) {
&:has(+ spacer) > slot::after,
.scrollbox-clip > &::after {
display: flow-root list-item;
content: "";
flex-basis: -moz-available;
height: 0;
overflow: hidden;
}
}
.tabbrowser-tab:not([pinned]) {
#tabbrowser-tabs[haspinnedtabs] & {
&, & + :not(#tabs-newtab-button) {
order: 1;
}
}
}
` : ``}
.tabbrowser-tab[fadein]:not([pinned]) {
--tab-min-width: ${Tab_Min_Width}px;
--tab-max-width: ${Tab_Max_Width}px;
max-width: var(--tab-max-width);
${Tab_Close_Button !== 0 ? `
${Tab_Close_Button === 1 ? `
.tab-close-button {
display : block !important;
}
` : Tab_Close_Button === 2 ? `
.tab-close-button {
opacity: 0;
}
&:hover .tab-close-button {
opacity: 1;
display : block !important;
}
` : ``}
` : ``}
}
#tabbrowser-tabs[haspinnedtabs]:not([positionpinnedtabs]):not([orient="vertical"]) > & > .tabbrowser-tab:nth-child(1 of :not([pinned], [hidden])) {
margin-inline-start: 0 !important;
}
}
${ProtonUI ? `` : `
.toolbarbutton-1 {
margin: 0 !important;
padding: 0 !important;
}
.tabbrowser-tab,
#tabs-newtab-button {
height: var(--tab-min-height);
padding: 0 !important;
}
.tab-background {
box-shadow: none !important;
margin-block: 0 !important;
}
.tabbrowser-tab[usercontextid] > .tab-stack > .tab-background > .tab-context-line {
margin: 1px 2px 0 !important;
}
`}
${Tab_Separators ? `
.titlebar-spacer[type="pre-tabs"] {
border-inline-end: 1px solid color-mix(in srgb, currentColor 20%, transparent);
}
.tabbrowser-tab::after,
.tabbrowser-tab::before {
border-left: 1px solid color-mix(in srgb, currentColor 50%, transparent);
height: calc(var(--tab-min-height) - 15%);
margin-block: auto;
}
.tabbrowser-tab:hover::after,
.tabbrowser-tab[multiselected]::after,
#tabbrowser-tabs:not([movingtab]) .tabbrowser-tab:has(+ .tabbrowser-tab:hover)::after,
#tabbrowser-tabs:not([movingtab]) .tabbrowser-tab:has(+ [multiselected])::after {
height: 100%;
}
.tabbrowser-tab::after,
#tabbrowser-tabs[movingtab] .tabbrowser-tab[visuallyselected]::before {
content: "";
display: block;
}
` : ``}
${All_Tabs_Button ? `` : `
#alltabs-button {
display: none;
}
`}
}
${TabBar_Position === 0 ? `
#TabsToolbar {
.titlebar-buttonbox-container {
height: calc(var(--tab-min-height) + ${ProtonUI ? 8 : 0}px);
margin-bottom: 0 !important;
${TitleBar_Button_Autohide ? `
background-color: color-mix(in srgb, currentColor 20%, transparent);
height: 6px;
opacity: 0;
position: fixed;
right: 0;
z-index: 2147483647;
.titlebar-button {
opacity: 0;
padding: 0;
}
&:hover {
height: calc(var(--tab-min-height) + ${ProtonUI ? 8 : 0}px);
opacity: 1;
.titlebar-button {
opacity: 1;
padding: 8px 17px;
}
}
` : ``}
}
}
` : `
#nav-bar {
:root:not([inFullscreen]) #toolbar-menubar:not([inactive]) + & > .titlebar-buttonbox-container {
display: none;
}
.titlebar-button {
padding-block: 0 !important;
}
}
`}
${TabBar_Position !== 2 ? `` : `
body {
& > #fullscr-toggler[hidden] + tabbox,
:root[inFullscreen] & > tabbox:hover {
border-top: 0.5px solid var(--toolbar-bgcolor);
}
& > tabbox > #navigator-toolbox {
border-block: none !important;
}
:root[inFullscreen] & {
& > #navigator-toolbox {
transition: none;
&:has(~ tabbox:hover) {
margin-top: 0 !important;
}
&:hover ~ tabbox > #navigator-toolbox {
max-height: 100%;
}}
& > tabbox:not(:hover) {
border-top: .5px solid transparent;
& > #navigator-toolbox {
max-height: 0;
}
}
}
}
`}
`,
sss = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Ci.nsIStyleSheetService),
uri = Services.io.newURI("data:text/css;charset=UTF=8," + encodeURIComponent(css));
if (TabBar_Rows == false) {
["0", "2"].find(type => {
if(sss.sheetRegistered(uri, type)) sss.unregisterSheet(uri, type); sss.loadAndRegisterSheet(uri, type);
});
} else {
["0", "2", "SSTabRestored", "TabMove", "TabOpen", "TabSelect"].find(type => {
if(sss.sheetRegistered(uri, type)) sss.unregisterSheet(uri, type); sss.loadAndRegisterSheet(uri, type);
gBrowser.tabContainer.addEventListener(type, (e) => { e.target.scrollIntoView({ block: "nearest" }); });
});
}
if (TabBar_Position !== 0) {
if (TabBar_Position === 1) {
document.getElementById("navigator-toolbox").prepend(
document.getElementById("toolbar-menubar"),
document.getElementById("nav-bar"),
document.getElementById("PersonalToolbar"),
document.getElementById("titlebar"),
);
} else {
document.getElementById("navigator-toolbox").prepend(
document.getElementById("toolbar-menubar"),
document.getElementById("nav-bar"),
document.getElementById("PersonalToolbar"),
);
}
document.getElementById("nav-bar").appendChild(
document.querySelector("#TabsToolbar > .titlebar-buttonbox-container")
);
}
if (TabBar_Position === 2) {
document.body.appendChild(
document.createXULElement("tabbox")
).appendChild(
document.importNode(document.getElementById("navigator-toolbox"))
).appendChild(
document.getElementById("titlebar")
);
}
gBrowser.tabContainer.addEventListener("dragover", function(event) { this._on_dragover(event); }, false)
gBrowser.tabContainer.addEventListener("drop", function(event) { this._on_drop(event); }, false)
gBrowser.tabContainer.on_dragover = function(event) { return false; }
gBrowser.tabContainer.on_drop = function(event) { return false; }
gBrowser.tabContainer._on_dragover = function(event) {
var effects = this.getDropEffectForTabDrag(event);
var ind = this._tabDropIndicator;
if (effects == "" || effects == "none") {
ind.hidden = true;
return;
}
event.preventDefault();
event.stopPropagation();
var arrowScrollbox = this.arrowScrollbox;
if (effects == "link") {
let tab = this._getDragTargetTab(event, { ignoreTabSides: true });
if (tab) {
if (!this._dragTime) {
this._dragTime = Date.now();
}
if (Date.now() >= this._dragTime + this._dragOverDelay) {
this.selectedItem = tab;
}
ind.hidden = true;
return;
}
}
var tabRect, rect = arrowScrollbox.getBoundingClientRect();
var newMarginX, newMarginY;
let newIndex = this._getDropIndex(event);
let children = this.allTabs;
if (newIndex == children.length) {
tabRect = this._getVisibleTabs().at(-1).getBoundingClientRect();
newMarginX = tabRect.right - rect.left;
} else {
tabRect = children[newIndex].getBoundingClientRect();
newMarginX = tabRect.left - rect.left;
}
newMarginY = tabRect.top - rect.top + tabRect.height / 2 - rect.height / 2;
ind.hidden = false;
newMarginX += ind.clientWidth / 2;
ind.style.transform = "translate(" + Math.round(newMarginX) + "px," + Math.round(newMarginY) + "px)";
}
gBrowser.tabContainer._on_drop = function(event) {
var dt = event.dataTransfer;
var dropEffect = dt.dropEffect;
var draggedTab;
let movingTabs;
if (dt.mozTypesAt(0)[0] == TAB_DROP_TYPE) {
// tab copy or move
draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
// not our drop then
if (!draggedTab) {
return;
}
movingTabs = draggedTab._dragData.movingTabs;
draggedTab.container._finishGroupSelectedTabs(draggedTab);
}
this._tabDropIndicator.hidden = true;
event.stopPropagation();
if (draggedTab && dropEffect == "copy") {
// copy the dropped tab (wherever it's from)
let newIndex = this._getDropIndex(event);
let draggedTabCopy;
for (let tab of movingTabs) {
let newTab = gBrowser.duplicateTab(tab);
gBrowser.moveTabTo(newTab, newIndex++);
if (tab == draggedTab) {
draggedTabCopy = newTab;
}
}
if (draggedTab.container != this || event.shiftKey) {
this.selectedItem = draggedTabCopy;
}
} else if (draggedTab && draggedTab.container == this) {
let oldTranslate = Math.round(draggedTab._dragData.translatePos);
let tabSize = Math.round(draggedTab._dragData.tabSize);
let translateOffset = oldTranslate % tabSize;
let newTranslate = oldTranslate - translateOffset;
if (oldTranslate > 0 && translateOffset > tabSize / 2) {
newTranslate += tabSize;
} else if (oldTranslate < 0 && -translateOffset > tabSize / 2) {
newTranslate -= tabSize;
}
let dropIndex;
if (draggedTab._dragData.fromTabList) {
dropIndex = this._getDropIndex(event);
} else {
dropIndex = this._getDropIndex(event);
// "animDropIndex" in draggedTab._dragData &&
// draggedTab._dragData.animDropIndex;
}
let incrementDropIndex = true;
if (dropIndex && dropIndex > movingTabs[0]._tPos) {
dropIndex--;
incrementDropIndex = false;
}
if (oldTranslate && oldTranslate != newTranslate && !gReduceMotion) {
for (let tab of movingTabs) {
tab.toggleAttribute("tabdrop-samewindow", true);
tab.style.transform = this.verticalMode
? "translateY(" + newTranslate + "px)"
: "translateX(" + newTranslate + "px)";
let postTransitionCleanup = () => {
tab.removeAttribute("tabdrop-samewindow");
this._finishAnimateTabMove();
if (dropIndex !== false) {
gBrowser.moveTabTo(tab, dropIndex);
if (incrementDropIndex) {
dropIndex++;
}
}
gBrowser.syncThrobberAnimations(tab);
};
if (gReduceMotion) {
postTransitionCleanup();
} else {
let onTransitionEnd = transitionendEvent => {
if (
transitionendEvent.propertyName != "transform" ||
transitionendEvent.originalTarget != tab
) {
return;
}
tab.removeEventListener("transitionend", onTransitionEnd);
postTransitionCleanup();
};
tab.addEventListener("transitionend", onTransitionEnd);
}
}
} else {
this._finishAnimateTabMove();
if (dropIndex !== false) {
for (let tab of movingTabs) {
gBrowser.moveTabTo(tab, dropIndex);
if (incrementDropIndex) {
dropIndex++;
}
}
}
}
} else if (draggedTab) {
// Move the tabs. To avoid multiple tab-switches in the original window,
// the selected tab should be adopted last.
const dropIndex = this._getDropIndex(event);
let newIndex = dropIndex;
let selectedTab;
let indexForSelectedTab;
for (let i = 0; i < movingTabs.length; ++i) {
const tab = movingTabs[i];
if (tab.selected) {
selectedTab = tab;
indexForSelectedTab = newIndex;
} else {
const newTab = gBrowser.adoptTab(tab, newIndex, tab == draggedTab);
if (newTab) {
++newIndex;
}
}
}
if (selectedTab) {
const newTab = gBrowser.adoptTab(
selectedTab,
indexForSelectedTab,
selectedTab == draggedTab
);
if (newTab) {
++newIndex;
}
}
// Restore tab selection
gBrowser.addRangeToMultiSelectedTabs(
gBrowser.tabs[dropIndex],
gBrowser.tabs[newIndex - 1]
);
} else {
// Pass true to disallow dropping javascript: or data: urls
let links;
try {
links = browserDragAndDrop.dropLinks(event, true);
} catch (ex) {}
if (!links || links.length === 0) {
return;
}
let inBackground = Services.prefs.getBoolPref(
"browser.tabs.loadInBackground"
);
if (event.shiftKey) {
inBackground = !inBackground;
}
let targetTab = this._getDragTargetTab(event, { ignoreTabSides: true });
let userContextId = this.selectedItem.getAttribute("usercontextid");
let replace = !!targetTab;
let newIndex = this._getDropIndex(event);
let urls = links.map(link => link.url);
let csp = browserDragAndDrop.getCsp(event);
let triggeringPrincipal =
browserDragAndDrop.getTriggeringPrincipal(event);
(async () => {
if (
urls.length >=
Services.prefs.getIntPref("browser.tabs.maxOpenBeforeWarn")
) {
// Sync dialog cannot be used inside drop event handler.
let answer = await OpenInTabsUtils.promiseConfirmOpenInTabs(
urls.length,
window
);
if (!answer) {
return;
}
}
gBrowser.loadTabs(urls, {
inBackground,
replace,
allowThirdPartyFixup: true,
targetTab,
newIndex,
userContextId,
triggeringPrincipal,
csp,
});
})();
}
if (draggedTab) {
delete draggedTab._dragData;
}
}
};
Alles anzeigen
Müsste soweit alles auf Deutsch übersetzt sein.
Mfg.
Endor
Dear Japanese Autor, you are absolutely welcome to joy in to this forum.
Thank you for this new Version. It would be great if we could communicate with you.
Kind regards
Endor