Как внутри таба сделать еще 2 таба
Перейти к содержимому

Как внутри таба сделать еще 2 таба

  • автор:

Как создать 2 таба внутри другого таба?

У мене стоит вот такая задача: «Есть окно с тремя кнопками(табами) и контентом к которому можно обратится при нажатии на эту кнопку. При нажатии на третью кнопку вместо контента появляются 2 новые кнопки при нажатии на которые появляется окно с контентом. «

Проблема вот в чем: Сами кнопки я создал, но вот обратится к ним через JS и прописать весь выше упомянутый функционал никак не получается. Подскажите как быть и что делать?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
 html lang="en"> head> meta charset="UTF-8"> meta name="viewport" content="width=device-width, initial-scale=1.0"> meta http-equiv="X-UA-Compatible" content="ie=edge"> title>2.Tabs/title> link rel="stylesheet" href="style.css"> /head> body> h1>TABS/h1> div class="tabs-block-wrapper"> div id="tabs"> div class="tab-btn active" data-btn="1">1/div> div class="tab-btn" data-btn="2">2/div> div class="tab-btn" data-btn="3">3/div> /div> div id="contents"> div class="content active" data-content="1">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Cumque eum pariatur animi iusto quis qui impedit eligendi minima! Recusandae modi obcaecati illo ut, necessitatibus officiis nostrum eaque porro ea deserunt./div> div class="content" data-content="2">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Cumque eum pariatur animi iusto quis qui impedit eligendi minima! Recusandae modi obcaecati illo ut, necessitatibus officiis nostrum eaque porro ea deserunt./div> div class="content" data-content="3"> div class="tabs-block-wrapper"> div id="tabs"> div class="tab-btn active" data-btn="4">4/div> div class="tab-btn" data-btn="5">5/div> div class="content active" data-content="4">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Cumque eum pariatur animi iusto quis qui impedit eligendi minima! Recusandae modi obcaecati illo ut, necessitatibus officiis nostrum eaque porro ea deserunt./div> div class="content" data-content="5">Lorem ipsum dolor sit, amet consectetur adipisicing elit. Cumque eum pariatur animi iusto quis qui impedit eligendi minima! Recusandae modi obcaecati illo ut, necessitatibus officiis nostrum eaque porro ea deserunt./div> /div> /div> /div> /div> /div> script src="main.js">/script> /body> /html>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
h1 { width: 100%; text-align: center; } .tabs-block-wrapper { width: 100%; display: flex; justify-content: center; align-items: center; flex-flow: column; } #tabs { display: flex; } .tab-btn { width: 100px; height: 40px; font-size: 20px; display: flex; justify-content: center; align-items: center; border: 1px solid black; border-radius: 5px; } .tab-btn.active { background-color: blue; color: #ffffff; } #contents { max-width: 300px; width: 100%; height: 150px; border: 1px solid black; } .content { display: none; } .content.active { display: block; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
const tabs = document.getElementById('tabs'); const content = document.querySelectorAll('.content'); const changeClass = el => { console.log(el); for(let i = 0; i  tabs.children.length; i++){ tabs.children[i].classList.remove('active'); } el.classList.add('active'); } tabs.addEventListener('click', e => { const currTab = e.target.dataset.btn; changeClass(e.target); for(let i = 0; i  content.length; i++){ content[i].classList.remove('active'); if(content[i].dataset.content == currTab){ content[i].classList.add('active'); } } })

Как внутри таба сделать еще 2 таба?

Внутри 3 таба нужно сделать еще 2. Кликаешь на 3 таб, а там вместо контента еще 2 таба. Как это реализовать?

const tabs = document.getElementById('tabs') const content = document.querySelectorAll('.content') const changeClass = el => < for (let i = 0; i < tabs.children.length; i++) < tabs.children[i].classList.remove('active') >el.classList.add('active') > tabs.addEventListener('click', e => < const currTab = e.target.dataset.btn changeClass(e.target) for (let i =0; i < content.length; i++) < content[i].classList.remove('active') if (content[i].dataset.content === currTab) < content[i].classList.add('active') >> >)
      2.Tabs 

TABS

1
2
3
Content 1
Content 2
Content 3
h1 < width: 100%; text-align: center; >.tabs-block-wrapper < width: 100%; display: flex; justify-content: center; align-items: center; flex-flow: column; >#tabs < display: flex; >.tab-btn < width: 100px; height: 40px; font-size: 20px; display: flex; justify-content: center; align-items: center; border: 1px solid black; border-radius: 5px; >.tab-btn.active < background-color: blue; color: #ffffff; >#contents < max-width: 300px; width: 100%; height: 150px; border: 1px solid black; >.content < display: none; >.content.active
  • Вопрос задан более двух лет назад
  • 2240 просмотров

Вариaнт адаптивных вкладок (tabs) на JavaScript

Для начала реализуем логику для вкладок, которые мы сверстали выше.

Вся логика сводится к тому, чтобы при переключении сравнивать значения data-атрибутов кнопок и блоков контента. Если значение data-атрибута у блока контента совпадает с data-атрибутом кнопки, то отображаем соответствующий блок контента

Отличие данного способа в том, что порядок расположения кнопок и порядок расположения блоков контента в HTML-структуре могут не совпадать, при этом переключение будет работать корректно, что невозможно при реализации вкладок по индексу

Код с комментариями

document.addEventListener('DOMContentLoaded', () => < // Структура страницы загружена и готова к взаимодействию const tabs = () => < // объявляем основную функцию для вкладок, чтобы вся логика была в одном месте const head = document.querySelector('.tabs__head') // ищем элемент с кнопками и записываем в константу const body = document.querySelector('.tabs__body') // ищем элемент с контентом и записываем в константу const getActiveTabName = () => < // объявляем функцию для получения названия активной вкладки return head.querySelector('.tabs__caption_active').dataset.tab // возвращаем значение data-tab активной кнопки >const setActiveContent = () => < // объявляем функцию для установки активного элемента контента if (body.querySelector('.tabs__content_active')) < // если уже есть активный элемент контента body.querySelector('.tabs__content_active').classList.remove('tabs__content_active') // то скрываем его >body.querySelector(`[data-tab=$]`).classList.add('tabs__content_active') // затем ищем элемент контента, у которого значение data-tab совпадает со значением data-tab активной кнопки и отображаем его > // проверяем при загрузке страницы, есть ли активная вкладка if (!head.querySelector('.tabs__caption_active')) < // если активной вкладки нет head.querySelector('.tabs__caption').classList.add('tabs__caption_active') // то делаем активной по-умолчанию первую вкладку >setActiveContent(getActiveTabName()) // устанавливаем активный элемент контента в соответствии с активной кнопкой при загрузке страницы head.addEventListener('click', e => < // при клике на .tabs__head const caption = e.target.closest('.tabs__caption') // узнаем, был ли клик на кнопке if (!caption) return // если клик был не на кнопке, то прерываем выполнение функции if (caption.classList.contains('tabs__caption_active')) return // если клик был на активной кнопке, то тоже прерываем выполнение функции и ничего не делаем if (head.querySelector('.tabs__caption_active')) < // если уже есть активная кнопка head.querySelector('.tabs__caption_active').classList.remove('tabs__caption_active') // то удаляем ей активный класс >caption.classList.add('tabs__caption_active') // затем добавляем активный класс кнопке, на которой был клик setActiveContent(getActiveTabName()) // устанавливаем активный элемент контента в соответствии с активной кнопкой >) > tabs() // вызываем основную функцию >) 

CSS классы и селекторы строго прописаны в коде, и если на странице будут другие блоки вкладок, то необходимо будет полностью копировать этот код и подставлять неоходимые значения CSS классов и селекторов прямо в скопированный код

Чтобы избежать этого, создадим новую функцию на основе предыдущей, которая будет принимать значения переданных CSS классов и селекторов и подставлять эти значения в необходимых частях кода

Функция c параметрами

Добавим для примера еще один блок с вкладками

     Tabs    
Home
Portfolio
About
Home lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia sit, repellat assumenda excepturi minima debitis atque nulla quibusdam iste eligendi voluptas, obcaecati nihil necessitatibus vel illum itaque ea molestias vero! Home lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia sit, repellat assumenda excepturi minima debitis atque nulla quibusdam iste eligendi voluptas, obcaecati nihil necessitatibus vel illum itaque ea molestias vero!
Portfolio lorem ipsum dolor sit amet, consectetur adipisicing elit. Id magni sit, enim tenetur animi eius ea, similique optio nostrum quibusdam ex, dolores dolorem. Recusandae quo molestiae modi saepe ratione numquam!
About lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia quibusdam nemo qui numquam magnam! In sunt, ut cum nulla, accusantium mollitia et illum voluptate repudiandae! Magnam alias, iure saepe animi.
Home
Portfolio
About
Contact
Home lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia sit, repellat assumenda excepturi minima debitis atque nulla quibusdam iste eligendi voluptas, obcaecati nihil necessitatibus vel illum itaque ea molestias vero!
Portfolio lorem ipsum dolor sit amet, consectetur adipisicing elit. Id magni sit, enim tenetur animi eius ea, similique optio nostrum quibusdam ex, dolores dolorem. Recusandae quo molestiae modi saepe ratione numquam!
About lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia quibusdam nemo qui numquam magnam! In sunt, ut cum nulla, accusantium mollitia et illum voluptate repudiandae! Magnam alias, iure saepe animi.
Contact lorem ipsum dolor sit amet, consectetur adipisicing elit. Quod, ullam ducimus et facere nisi a dicta, ea, quae minima sequi expedita facilis doloremque excepturi, earum soluta magni! Dolores, expedita, ea.

Теперь при объявлении функции tabs указываем параметры, которые будет принимать функция

При вызове функции, все параметры обязательны для ввода, и порядок передаваемых параметров должен соблюдаться

JavaScript код с комментариями

document.addEventListener('DOMContentLoaded', () => < // Структура страницы загружена и готова к взаимодействию const tabs = (tabsSelector, tabsHeadSelector, tabsBodySelector, tabsCaptionSelector, tabsCaptionActiveClass, tabsContentActiveClass) => < // объявляем основную функцию tabs, которая будет принимать CSS классы и селекторы const tabs = document.querySelector(tabsSelector) // ищем на странице элемент по переданному селектору основного элемента вкладок и записываем в константу const head = tabs.querySelector(tabsHeadSelector) // ищем в элементе tabs элемент с кнопками по переданному селектору и записываем в константу const body = tabs.querySelector(tabsBodySelector) // ищем в элементе tabs элемент с контентом по переданному селектору и записываем в константу const getActiveTabName = () =>< // функция для получения названия активной вкладки return head.querySelector(`.$`).dataset.tab // возвращаем значение data-tab активной кнопки > const setActiveContent = () => < // функция для установки активного элемента контента if (body.querySelector(`.$`)) < // если уже есть активный элемент контента body.querySelector(`.$`).classList.remove(tabsContentActiveClass) // то скрываем его > body.querySelector(`[data-tab=$]`).classList.add(tabsContentActiveClass) // затем ищем элемент контента, у которого значение data-tab совпадает со значением data-tab активной кнопки и отображаем его > // проверяем при загрузке страницы, есть ли активная вкладка if (!head.querySelector(`.$`)) < // если активной вкладки нет head.querySelector(tabsCaptionSelector).classList.add(tabsCaptionActiveClass) // то делаем активной по-умолчанию первую вкладку >setActiveContent(getActiveTabName()) // устанавливаем активный элемент контента в соответствии с активной кнопкой при загрузке страницы head.addEventListener('click', e => < // при клике на элемент с кнопками const caption = e.target.closest(tabsCaptionSelector) // узнаем, был ли клик на кнопке if (!caption) return // если клик был не на кнопке, то прерываем выполнение функции if (caption.classList.contains(tabsCaptionActiveClass)) return // если клик был на активной кнопке, то тоже прерываем выполнение функции и ничего не делаем if (head.querySelector(`.$`)) < // если уже есть активная кнопка head.querySelector(`.$`).classList.remove(tabsCaptionActiveClass) // то удаляем ей активный класс > caption.classList.add(tabsCaptionActiveClass) // затем добавляем активный класс кнопке, на которой был клик setActiveContent(getActiveTabName()) // устанавливаем активный элемент контента в соответствии с активной кнопкой >) > tabs('.section__tabs', '.tabs__head', '.tabs__body', '.tabs__caption', 'tabs__caption_active', 'tabs__content_active') // вызываем основную функцию tabs для синих вкладок .section__tabs tabs('.about__tabs', '.tabs__head', '.tabs__body', '.tabs__caption', 'tabs__caption_active', 'tabs__content_active') // вызываем основную функцию tabs для зелёных вкладок .about__tabs >) 

Получаем следующий результат — вкладки активны

Home lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia sit, repellat assumenda excepturi minima debitis atque nulla quibusdam iste eligendi voluptas, obcaecati nihil necessitatibus vel illum itaque ea molestias vero! Home lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia sit, repellat assumenda excepturi minima debitis atque nulla quibusdam iste eligendi voluptas, obcaecati nihil necessitatibus vel illum itaque ea molestias vero!

Portfolio lorem ipsum dolor sit amet, consectetur adipisicing elit. Id magni sit, enim tenetur animi eius ea, similique optio nostrum quibusdam ex, dolores dolorem. Recusandae quo molestiae modi saepe ratione numquam!

About lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia quibusdam nemo qui numquam magnam! In sunt, ut cum nulla, accusantium mollitia et illum voluptate repudiandae! Magnam alias, iure saepe animi.

Home lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia sit, repellat assumenda excepturi minima debitis atque nulla quibusdam iste eligendi voluptas, obcaecati nihil necessitatibus vel illum itaque ea molestias vero!

Portfolio lorem ipsum dolor sit amet, consectetur adipisicing elit. Id magni sit, enim tenetur animi eius ea, similique optio nostrum quibusdam ex, dolores dolorem. Recusandae quo molestiae modi saepe ratione numquam!

About lorem ipsum dolor sit amet, consectetur adipisicing elit. Mollitia quibusdam nemo qui numquam magnam! In sunt, ut cum nulla, accusantium mollitia et illum voluptate repudiandae! Magnam alias, iure saepe animi.

Contact lorem ipsum dolor sit amet, consectetur adipisicing elit. Quod, ullam ducimus et facere nisi a dicta, ea, quae minima sequi expedita facilis doloremque excepturi, earum soluta magni! Dolores, expedita, ea.

Вкладки на основе JavaScript классов

Для разнообразия/сравнения, можем также написать функциональность вкладок на основе JavaScript классов

Чтобы познакомиться с JavaScript классами, внизу статьи будут ссылки на документацию

В данном примере просто посмотрим еще один способ

В качестве параметров будем передавать JavaScript объект, а также выделим некоторую функциональность в отдельные методы

Код с комментариями

document.addEventListener('DOMContentLoaded', () => < // Структура страницы загружена и готова к взаимодействию class Tabs < // объявляем JavaScript класс Tabs constructor(config) < // специальный метод constructor принимает объект со значениями CSS классов и селекторов this.tabs = config.tabsSelector // записываем в экземпляр JavaScript класса переданный селектор основного элемента вкладок this.head = config.tabsHeadSelector // записываем в экземпляр JavaScript класса переданный селектор элемента c кнопками this.body = config.tabsBodySelector // записываем в экземпляр JavaScript класса переданный селектор элемента c контентом this.caption = config.tabsCaptionSelector // записываем в экземпляр JavaScript класса переданный селектор элемента кнопки this.captionActiveClass = config.tabsCaptionActiveClass // записываем в экземпляр JavaScript класса переданный активный CSS класс элемента кнопки this.contentActiveClass = config.tabsContentActiveClass // записываем в экземпляр JavaScript класса переданный активный CSS класс элемента контента >getActiveTabName(head) < // метод для получения названия активной вкладки return head.querySelector(`.$`).dataset.tab // возвращаем значение data-tab активной кнопки > setActiveContent(head, body) < // метод для установки активного элемента контента if (body.querySelector(`.$`)) < // если уже есть активный элемент контента body.querySelector(`.$`).classList.remove(this.contentActiveClass) // то скрываем его > body.querySelector(`[data-tab=$]`).classList.add(this.contentActiveClass) // затем ищем элемент контента, у которого значение data-tab совпадает со значением data-tab активной кнопки и отображаем его > onLoad(head, body) < // метод для описания логики при загрузке страницы // проверяем при загрузке страницы, есть ли активная вкладка if (!head.querySelector(`.$`)) < // если активной вкладки нет head.querySelector(this.caption).classList.add(this.captionActiveClass) // то делаем активной по-умолчанию первую вкладку >this.setActiveContent(head, body) // устанавливаем активный элемент контента в соответствии с активной кнопкой при загрузке страницы > onClick(head, body) < // метод для описания логики при клике на элемент с кнопками head.addEventListener('click', e =>< // при клике на элемент с кнопками const caption = e.target.closest(this.caption) // узнаем, был ли клик на кнопке if (!caption) return // если клик был не на кнопке, то прерываем выполнение метода if (caption.classList.contains(this.captionActiveClass)) return // если клик был на активной кнопке, то тоже прерываем выполнение метода и ничего не делаем if (head.querySelector(`.$`)) < // если уже есть активная кнопка head.querySelector(`.$`).classList.remove(this.captionActiveClass) // то удаляем ей активный класс > caption.classList.add(this.captionActiveClass) // затем добавляем активный класс кнопке, на которой был клик this.setActiveContent(head, body) // устанавливаем активный элемент контента в соответствии с активной кнопкой >) > init() < // основной метод для вызова других описанных методов const tabs = document.querySelector(this.tabs) // ищем на странице элемент по переданному селектору основного элемента вкладок и записываем в константу const head = tabs.querySelector(this.head) // ищем в элементе tabs элемент с кнопками по переданному селектору и записываем в константу const body = tabs.querySelector(this.body) // ищем в элементе tabs элемент с контентом по переданному селектору и записываем в константу this.onLoad(head, body) // вызываем метод onLoad и передаем в параметрах константы, объявленные выше this.onClick(head, body) // вызываем метод onClick и передаем в параметрах константы, объявленные выше >> new Tabs(< // создаем экземпляр JavaScript класса Tabs, и передаем значения CSS классов и селекторов элемента вкладок, которые нужно оживить - section__tabs tabsSelector: '.section__tabs', // основной элемент вкладок tabsHeadSelector: '.tabs__head', // элемент с кнопками tabsBodySelector: '.tabs__body', // элемент с контентом tabsCaptionSelector: '.tabs__caption', // элемент кнопки tabsCaptionActiveClass: 'tabs__caption_active', // активный класс кнопки tabsContentActiveClass: 'tabs__content_active', // активный класс элемента контента >).init() // вызываем основной метод init new Tabs(< // создаем экземпляр JavaScript класса Tabs, и передаем значения CSS классов и селекторов элемента вкладок, которые нужно оживить - about__tabs tabsSelector: '.about__tabs', // основной элемент вкладок tabsHeadSelector: '.tabs__head', // элемент с кнопками tabsBodySelector: '.tabs__body', // элемент с контентом tabsCaptionSelector: '.tabs__caption', // элемент кнопки tabsCaptionActiveClass: 'tabs__caption_active', // активный класс кнопки tabsContentActiveClass: 'tabs__content_active', // активный класс элемента контента >).init() // вызываем основной метод init >) 

Итоги

Данный вариант реализации всего лишь один из многих и не претендует на эталонность. Вы можете использовать как этот вариант, так и другие доступные.

В данной реализации кнопки и блоки контента можно располагать не соблюдая их порядок в HTML-структуре. Eсть проверка при загрузке страницы, если не установлена активная вкладка, то устанавливаем активной первую вкладку. Также не используются циклы, что уменьшает количество событий при переключении вкладок. При использовании CSS стилей из статьи эти вкладки логично адаптируются под любое разрешение экрана

Буду рад, если статья оказалась полезной

Спасибо за ваше внимание и уделённое время!

Двойной tab-content

На странице не может работать больше одного id. Если их несколько — выбирается первый найденный (с). Это дело можно решить (например) через классы — добавляя уникальные классы тем элементам, которые нужно открыть. Но можно немного схитрить и добавить не абы-какие, а с номерами — чтобы класс открываемой вкладки удачно совпадал с номером кликнутой кнопки (в JS счет начинается от 0, 1, 2. ) поэтому tab0, tab1, tab2 — в соответствии с кнопками.

(код мог бы быть короче, но так по моему смысл более очевиден) — Сперва перебираем и закрываем вообще все вкладки (даже те, которые и так закрыты), убираем активный класс со всех кнопок, а уже потом добавляем класс на текущую кликнутую, открываем нужные вкладки.

(function() < //Сохранили все кнопки и все вкладки. const link = document.getElementsByClassName('link'); const tab = document.getElementsByClassName('tab'); let tabN; //Перебираем все кнопки и кругами вешаем на них событие 'клик' //Плюс такого варианта в том, что при клике сразу определяется номер кнопки = это [i] for(let i = 0; i < link.length; i++)< link[i].addEventListener('click', function()< //Перебираем все вкладки и сперва делаем их всех невидимыми for(let u = 0; u < tab.length; u++)< tab[u].style.display = 'none'; >//Перебираем все кнопки и убираем с них "активный" класс for(let u = 0; u < link.length; u++)< link[u].classList.remove('active'); >//Добавляем активный класс на текущую кликнутую кнопку this.classList.add('active'); //Изначально задали переменную tabN для этого: //Ему приписываем классы 'tab' + i, причем - после клика кнопки, это i сразу //становится определенным числом - 0, 1, 2. таким образом если кликнута первая //кнопка, получается здесь написано то же, что и //tabN = document.getElementsByClassName('tab0'); tabN = document.getElementsByClassName('tab' + i); //Вот и перебираем нужные нам классы и всех их делаем видимыми. for(let u = 0; u < tabN.length; u++)< tabN[u].style.display = 'block'; >>); > >)();
.tab .active
   
bubu - 1
bubu - 2
bubu - 3
kuku - 1
kuku - 2
kuku - 3
dudu - 1
dudu - 2
dudu - 3

Если вкладок будет 100500, можно еще схитрить и заранее прописать еще одну переменную let previuos; и в самом конце клика добавить previous = i; . Тогда вначале клика можно будет скрывать табы не полным перебором всех подряд, а использовав сохраненное число из предыдущего клика — скрыть только открытые.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *