Skip to content

Commit d5c5f34

Browse files
committed
Allowed more than one set of tabs at the time
1 parent bdc4f77 commit d5c5f34

8 files changed

+284
-259
lines changed

README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ A simple plugin to create scrollable tabs with Bootstrap 5.
1010

1111
## Usage:
1212

13+
## Breaking change from 1.1.0+:
14+
15+
To allow more than one set of tabs, it required to add a new class to wrap the tabs `tab-wrapper`. It must be added to use it.
16+
1317
### Install:
1418

15-
- [Download the latest release](https://github.com/SupernovaIC/scrollable-tabs-bootstrap-5/archive/refs/tags/v1.0.9.zip)
19+
- [Download the latest release](https://github.com/SupernovaIC/scrollable-tabs-bootstrap-5/archive/refs/tags/v1.1.0.zip)
1620

1721
- Install with [npm](https://www.npmjs.com/): `npm i scrolling-tabs-bootstrap-5`
1822

dist/scrollable-tabs.js

+98-115
Original file line numberDiff line numberDiff line change
@@ -1,137 +1,120 @@
11
//let move = require('move');
2-
3-
const scrollBarWidths = 40;
4-
const wrapper = document.getElementsByClassName("wrapper-nav")[0];
5-
const navLink = document.getElementsByClassName("nav-item nav-link");
6-
const lastNavLink = navLink[navLink.length - 1];
7-
8-
const scrollerRight = document.getElementsByClassName("scroller-right")[0];
9-
const scrollerLeft = document.getElementsByClassName("scroller-left")[0];
10-
11-
const list = document.querySelectorAll(".list");
12-
13-
let btnTriggered = false;
14-
15-
let widthOfList = function() {
16-
let itemsWidth = 0;
17-
18-
const listLinks = document.querySelectorAll(".list a");
19-
20-
listLinks.forEach((el) => {
21-
let itemWidth = getOuterWidth(el);
22-
itemsWidth += itemWidth;
2+
// Function to initialize scrollable tabs for a specific wrapper
3+
function initializeScrollableTabs(wrapper) {
4+
const scrollBarWidths = 40;
5+
const scrollerRight = wrapper.querySelector(".scroller-right");
6+
const scrollerLeft = wrapper.querySelector(".scroller-left");
7+
const list = wrapper.querySelector(".list");
8+
const lastNavLink = list.querySelectorAll(".nav-item.nav-link")[list.querySelectorAll(".nav-item.nav-link").length - 1];
9+
let btnTriggered = false;
10+
11+
let widthOfList = function () {
12+
let itemsWidth = 0;
13+
const listLinks = list.querySelectorAll("a");
14+
15+
listLinks.forEach((el) => {
16+
let itemWidth = getOuterWidth(el);
17+
itemsWidth += itemWidth;
18+
});
19+
20+
return itemsWidth;
21+
};
22+
23+
let widthOfHidden = function (w) {
24+
w = (!w) ? 0 : w;
25+
const oW = getOuterWidth(wrapper.querySelector(".wrapper-nav")) - w;
26+
const ww = parseFloat((0 - oW).toFixed(3));
27+
const hw = (oW - widthOfList() - getLeftPosi()) - scrollBarWidths;
28+
const rp = document.body.clientWidth - (getOuterLeft(lastNavLink) + getOuterWidth(lastNavLink)) - w;
29+
30+
if (ww > hw) {
31+
return (rp > ww ? rp : ww);
32+
} else {
33+
return (rp > hw ? rp : hw);
34+
}
35+
};
36+
37+
let getLeftPosi = () => {
38+
const lp = getOuterLeft(list);
39+
const wrapperLeft = getOuterLeft(wrapper.querySelector(".wrapper-nav"));
40+
41+
return lp - wrapperLeft;
42+
};
43+
44+
let reAdjust = () => {
45+
let rp = document.body.clientWidth - (getOuterLeft(lastNavLink) + getOuterWidth(lastNavLink));
46+
47+
if (getOuterWidth(wrapper.querySelector(".wrapper-nav")) < widthOfList() && (rp < 0)) {
48+
scrollerRight.style.display = 'flex';
49+
unfade(scrollerRight);
50+
} else {
51+
scrollerRight.style.display = 'none';
52+
}
53+
54+
if (getLeftPosi() < 0) {
55+
scrollerLeft.style.display = 'flex';
56+
unfade(scrollerLeft);
57+
} else {
58+
scrollerLeft.style.display = 'none';
59+
}
60+
61+
btnTriggered = false;
62+
};
63+
64+
scrollerRight.addEventListener("click", () => {
65+
if (btnTriggered) return;
66+
67+
btnTriggered = true;
68+
69+
fade(scrollerLeft);
70+
unfade(scrollerRight);
71+
72+
let wR = getOuterWidth(scrollerRight);
73+
74+
move(list).add("left", +widthOfHidden(wR), 200).end().then(() => {
75+
reAdjust();
76+
});
2377
});
24-
25-
return itemsWidth;
26-
};
27-
28-
let widthOfHidden = function(w) {
29-
const wrapperh = document.getElementsByClassName("wrapper-nav")[0];
30-
31-
w = (!w) ? 0 : w;
32-
33-
oW = getOuterWidth(wrapperh) - w;
34-
35-
let ww = parseFloat((0 - oW).toFixed(3));
36-
37-
let hw = (oW - widthOfList() - getLeftPosi()) - scrollBarWidths;
38-
39-
let rp = document.body.clientWidth - (getOuterLeft(lastNavLink) + getOuterWidth(lastNavLink)) - w;
40-
41-
if (ww > hw) {
42-
//return ww;
43-
return (rp > ww ? rp : ww);
44-
}
45-
else {
46-
//return hw;
47-
return (rp > hw ? rp : hw);
48-
}
49-
};
50-
51-
let getLeftPosi = function() {
52-
let ww = 0 - getOuterWidth(wrapper);
53-
let lp = getOuterLeft(list[0]);
54-
55-
if (ww > lp) {
56-
return ww;
57-
}
58-
else {
59-
return lp;
60-
}
61-
};
62-
63-
let reAdjust = function() {
64-
let rp = document.body.clientWidth - (getOuterLeft(lastNavLink) + getOuterWidth(lastNavLink));
65-
66-
if (getOuterWidth(wrapper) < widthOfList() && (rp < 0)) {
67-
scrollerRight.style.cssText = 'display: flex';
68-
}
69-
else {
70-
scrollerRight.style.display = 'none';
71-
}
72-
73-
if (getLeftPosi() < 0) {
74-
scrollerLeft.style.cssText = 'display: flex';
75-
}
76-
else {
77-
scrollerLeft.style.display = 'none';
78-
}
79-
80-
btnTriggered = false;
81-
}
82-
83-
window.addEventListener('resize', function(event) {
84-
reAdjust();
85-
}, true);
8678

87-
scrollerRight.addEventListener("click", function() {
88-
if (btnTriggered) return;
79+
scrollerLeft.addEventListener("click", () => {
80+
if (btnTriggered) return;
8981

90-
btnTriggered = true;
82+
btnTriggered = true;
9183

92-
fade(scrollerLeft);
93-
unfade(scrollerRight);
84+
fade(scrollerRight);
85+
unfade(scrollerLeft);
9486

95-
let wR = getOuterWidth(scrollerRight);
87+
let wL = getOuterWidth(scrollerLeft);
9688

97-
move(document.querySelectorAll(".list")[0]).add("left", +widthOfHidden(wR), 200).end().then(x=> {
98-
reAdjust();
89+
move(list).add("left", -getLeftPosi() + wL, 200).end().then(() => {
90+
reAdjust();
91+
});
9992
});
100-
});
10193

102-
scrollerLeft.addEventListener("click", function() {
103-
if (btnTriggered) return;
104-
105-
btnTriggered = true;
106-
107-
fade(scrollerRight);
108-
unfade(scrollerLeft);
109-
110-
let wL = getOuterWidth(scrollerLeft);
111-
112-
move(document.querySelectorAll(".list")[0]).add("left", -getLeftPosi() + wL, 200).end().then(()=> {
94+
window.addEventListener('resize', () => {
11395
reAdjust();
114-
});
115-
});
96+
}, true);
11697

117-
let getOuterLeft = function(elem) {
118-
return elem.getBoundingClientRect().left;
98+
reAdjust();
11999
}
120100

121-
let getOuterWidth = function(elem) {
122-
return parseFloat(window.getComputedStyle(elem).width);
123-
}
101+
let getOuterLeft = (elem) => elem.getBoundingClientRect().left;
102+
103+
let getOuterWidth = (elem) => parseFloat(window.getComputedStyle(elem).width);
124104

125105
function fade(elem) {
126106
elem.style.display = "none";
127-
elem.style.transition="opacity 0.6s";
128-
elem.style.opacity=0;
107+
elem.style.transition = "opacity 0.6s";
108+
elem.style.opacity = 0;
129109
}
130110

131111
function unfade(elem) {
132112
elem.style.display = "block";
133-
elem.style.transition="opacity 0.6s";
134-
elem.style.opacity=1;
113+
elem.style.transition = "opacity 0.6s";
114+
elem.style.opacity = 1;
135115
}
136116

137-
reAdjust();
117+
// Initialize scrollable tabs for each tab set
118+
document.querySelectorAll('.tab-wrapper').forEach(wrapper => {
119+
initializeScrollableTabs(wrapper);
120+
});

dist/scrollable-tabs.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)