O
class Tab {
constructor(options) {
if (options.tabHead.length !== options.tabBody.length) {
console.error('Длина массивов должна быть одинаковая');
return false;
}
const selector = options.selector;
this.tabDom = (typeof selector === 'string') ? document.querySelector(selector) : selector;
this.tabHead = options.tabHead;
this.tabBody = options.tabBody;
this.defaultOpenTab = options.defaultOpenTab;
this.createText();
this.insertToDom();
this.addEventListeners();
}
createText() {
const tabHeadText = this.tabHead.map((item, i) => {
const active = (this.defaultOpenTab - 1 === i) ? 'active' : '';
return <div class="tab__head__item ${ active } ">${ item }</div>\n;
}).join('');
const tabBodyText = this.tabBody.map((item, i) => {
const active = (this.defaultOpenTab - 1 === i) ? 'active' : '';
return `<div class="tab__body__item ${ active } ">${ item }</div>\n`;
}).join('');
this.tabHeadAndBodyText = `
<div class="tab__head__container">
${tabHeadText}
</div>
<div class="tab__body__container">
${tabBodyText}
</div>
`;
}
insertToDom() {
this.tabDom.innerHTML = '';
this.tabDom.insertAdjacentHTML('beforeend', this.tabHeadAndBodyText);
}
addEventListeners() {
const allTabHeadItem = Array.from(this.tabDom.querySelectorAll('.tab__head__item'));
const allTabBodyItem = Array.from(this.tabDom.querySelectorAll('.tab__body__item'));
allTabHeadItem.forEach((item, i) => {
item.addEventListener('click', e => {
allTabBodyItem.forEach(item1 => {
if (item1.classList.contains('active')) {
item1.style.maxHeight = 0;
}
item1.classList.remove('active');
});
allTabHeadItem.forEach(item1 => {
item1.classList.remove('active');
});
allTabHeadItem[i].classList.add('active');
allTabBodyItem[i].classList.add('active');
allTabBodyItem[i].style.maxHeight = allTabBodyItem[i].scrollHeight + 'px';
});
});
const fromResize = () => {
const activeBodyItem = allTabBodyItem.find(item => item.classList.contains('active'));
activeBodyItem.style.maxHeight = activeBodyItem.scrollHeight + 'px';
}
const debounceFunc = debounce(fromResize, 200);
window.addEventListener('resize', debounceFunc);
}
}
function debounce(f, t) {
return function (args) {
let previousCall = this.lastCall;
this.lastCall = Date.now();
if (previousCall && ((this.lastCall - previousCall) <= t)) {
clearTimeout(this.lastCallTimer);
}
this.lastCallTimer = setTimeout(() => f(args), t);
}
}
const tab = new Tab({
selector: '.tabs',
tabHead: [
'Первый tab',
'Второй tab',
'Третий tab',
'Четвертый tab'
],
tabBody: [
'Ты как меня нашёл 1',
'Lorem ipsum dolor sit amet, consectetur, adipisicing elit. Harum repudiandae laboriosam magnam deleniti velit odit sint incidunt consectetur dicta tempore natus reprehenderit, mollitia vitae architecto, repellendus suscipit in animi quibusdam.',
'Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст',
'Пошли кушать'
],
defaultOpenTab: 2
});@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap");
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
min-height: 100%;
font-family: "Roboto", sans-serif;
}
:root {
--transitionDuration: 0.5s;
--transitionTimingFunction: ease-in-out;
}
section {
padding: 40px 0;
}
.container {
max-width: 1200px;
display: block;
margin: 0 auto;
padding: 0 15px;
width: 100%;
}
.tab__head__container {
display: grid;
grid-template-columns: repeat( auto-fit, minmax(150px, 1fr) );
--size: 15px;
grid-gap: var(--size);
}
.tab__head__item {
background-color: gray;
color: white;
padding: var(--size);
cursor: pointer;
border: 2px solid transparent;
transition-property: border-color, background-color;
transition-duration: var(--transitionDuration);
transition-timing-function: var(--transitionTimingFunction);
}
.tab__head__item.active {
border-color: red;
background-color: #dbdb43;
}
.tab__body__container {
margin-top: 40px;
padding: 20px;
border: 2px solid black;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: flex-start;
}
.tab__body__item {
display: inline-block;
max-height: 0px;
overflow: hidden;
opacity: 0;
visibility: hidden;
transform: scale(0) translate(200px, 200%);
transition-property: visibility, opacity, transform, max-height;
transition-timing-function: var(--transitionTimingFunction);
transition-duration: var(--transitionDuration);
}
.tab__body__item.active {
opacity: 1;
visibility: visible;
max-height: 200px;
transform: scale(1);
}
.as-console-wrapper {
height: 0px;
overflow: hidden;
}
@media (max-width: 300px) {
.tab__head__container {
grid-template-columns: 1fr;
}
}<section>
<div class="container">
<div class="tabs">
</div>
</div>
</section>Vertical deposits:class Tab {
constructor(options) {
if (options.tabHead.length !== options.tabBody.length) {
console.error('Длина массивов должна быть одинаковая');
return false;
}
const selector = options.selector;
this.tabDom = (typeof selector === 'string') ? document.querySelector(selector) : selector;
this.tabHead = options.tabHead;
this.tabBody = options.tabBody;
this.defaultOpenTab = options.defaultOpenTab;
this.createText();
this.insertToDom();
this.addEventListeners();
}
createText() {
const tabHeadText = this.tabHead.map((item, i) => {
const active = (this.defaultOpenTab - 1 === i) ? 'active' : '';
return <div class="tab__head__item ${ active } ">${ item }</div>\n;
}).join('');
const tabBodyText = this.tabBody.map((item, i) => {
const active = (this.defaultOpenTab - 1 === i) ? 'active' : '';
return `<div class="tab__body__item ${ active } ">${ item }</div>\n`;
}).join('');
this.tabHeadAndBodyText = `
<div class="tab__head__container">
${tabHeadText}
</div>
<div class="tab__body__container">
${tabBodyText}
</div>
`;
}
insertToDom() {
this.tabDom.innerHTML = '';
this.tabDom.insertAdjacentHTML('beforeend', this.tabHeadAndBodyText);
}
addEventListeners() {
const allTabHeadItem = Array.from(this.tabDom.querySelectorAll('.tab__head__item'));
const allTabBodyItem = Array.from(this.tabDom.querySelectorAll('.tab__body__item'));
allTabHeadItem.forEach((item, i) => {
item.addEventListener('click', e => {
allTabBodyItem.forEach(item1 => {
if (item1.classList.contains('active')) {
item1.style.maxHeight = 0;
}
item1.classList.remove('active');
});
allTabHeadItem.forEach(item1 => {
item1.classList.remove('active');
});
allTabHeadItem[i].classList.add('active');
allTabBodyItem[i].classList.add('active');
allTabBodyItem[i].style.maxHeight = allTabBodyItem[i].scrollHeight + 'px';
});
});
const fromResize = () => {
const activeBodyItem = allTabBodyItem.find(item => item.classList.contains('active'));
activeBodyItem.style.maxHeight = activeBodyItem.scrollHeight + 'px';
}
const debounceFunc = debounce(fromResize, 200);
window.addEventListener('resize', debounceFunc);
}
}
function debounce(f, t) {
return function (args) {
let previousCall = this.lastCall;
this.lastCall = Date.now();
if (previousCall && ((this.lastCall - previousCall) <= t)) {
clearTimeout(this.lastCallTimer);
}
this.lastCallTimer = setTimeout(() => f(args), t);
}
}
const tab = new Tab({
selector: '.tabs',
tabHead: [
'Первый tab',
'Второй tab',
'Третий tab',
'Четвертый tab'
],
tabBody: [
'Ты как меня нашёл 1',
'Lorem ipsum dolor sit amet, consectetur, adipisicing elit. Harum repudiandae laboriosam magnam deleniti velit odit sint incidunt consectetur dicta tempore natus reprehenderit, mollitia vitae architecto, repellendus suscipit in animi quibusdam.',
'Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст Большой текст',
'Пошли кушать'
],
defaultOpenTab: 2
});@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap");
*, *::before, *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
min-height: 100%;
font-family: "Roboto", sans-serif;
}
:root {
--transitionDuration: 0.5s;
--transitionTimingFunction: ease-in-out;
}
section {
padding: 40px 0;
}
.container {
max-width: 1200px;
display: block;
margin: 0 auto;
padding: 0 15px;
width: 100%;
}
.tab__head__container {
display: grid;
grid-template-rows: 1fr;
justify-content: start;
--size: 15px;
grid-gap: var(--size);
}
.tab__head__item {
background-color: gray;
color: white;
padding: var(--size);
cursor: pointer;
border: 2px solid transparent;
transition-property: border-color, background-color;
transition-duration: var(--transitionDuration);
transition-timing-function: var(--transitionTimingFunction);
}
.tab__head__item.active {
border-color: red;
background-color: #dbdb43;
}
.tab__body__container {
margin-top: 40px;
padding: 20px;
border: 2px solid black;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: flex-start;
}
.tab__body__item {
display: inline-block;
max-height: 0px;
overflow: hidden;
opacity: 0;
visibility: hidden;
transform: scale(0) translate(200px, 200%);
transition-property: visibility, opacity, transform, max-height;
transition-timing-function: var(--transitionTimingFunction);
transition-duration: var(--transitionDuration);
}
.tab__body__item.active {
opacity: 1;
visibility: visible;
max-height: 200px;
transform: scale(1);
}
@media (max-width: 300px) {
.tab__head__container {
grid-template-columns: 1fr;
}
}<section>
<div class="container">
<div class="tabs">
</div>
</div>
</section>