Предисловие
Какое-то время назад я стал постепенно отказываться от jQuery в пользу нативного javascript. Это связано с тем что поддержка старых браузеров перестала быть приоритетной и на первое место вышла скорость загрузки страницы. Я не смог найти минималистичный модуль вкладок с простой html разметкой и решил написать свой.
HTML разметка
<div class="tabs"> <div class="tabs__toggle tabs__toggle_active">Вкладка 1</div> <div class="tabs__toggle">Вкладка 2</div> <div class="tabs__tab"> Содержимое первой вкладки </div> <div class="tabs__tab"> Содержимое второй вкладки </div> </div>
Если на одной странице нужно разместить несколько групп вкладок нужно просто разделить их в разные блоки `.tabs`. Расположение внутренних блоков влияет только на порядок их вывода. Вкладке по умолчанию следует добавить класс `tabs__toggle_active`.
Класс закладки
class Tab { constructor (tabs, toggle, tab) { this.tabs = tabs; this.toggle = toggle; this.tab = tab; this.init(); } init () { if (this.toggle.classList.contains('tabs__toggle_active')) { this.open(); } else { this.close(); } this.toggle.addEventListener('click', () => { this.open(); }); } open () { if (this.tabs.active === this) { // already open return; } if (this.tabs.active) { this.tabs.active.close(); } this.tabs.active = this; this.tab.style.display = 'block'; this.toggle.classList.add('tabs__toggle_active'); } close () { this.tab.style.display = 'none'; this.toggle.classList.remove('tabs__toggle_active'); } }
Конструктор принимает родительский класс группы вкладок, DOM элемент кнопки по которой открывается вкладка и DOM вкладки к которой относится данная кнопка.
Функция init проверяет является ли эта вкладка открытой по умолчанию и добавляет событие открытия по клику.
Функция open закрывает открытую вкладку при ее наличии и устанавливает ссылку на собственный экземпляр класса в свойство ‘active’ родительского класса. Так же проставляет активный класс для стилизации кнопки и свойство ‘display’ вкладки.
Функция close убирает активный класс с кнопки и скрывает вкладку.
Класс группы вкладок
export class Tabs { constructor (container) { this.container = container; this.init(); } init () { this.toggles = this.container.querySelectorAll('.tabs__toggle'); this.tabs = this.container.querySelectorAll('.tabs__tab'); if (!this.isEverythingOk()) { return; } for (let index = 0; index < this.toggles.length; index++) { new Tab (this, this.toggles[index], this.tabs[index]); } } isEverythingOk () { if (this.toggles.length !== this.tabs.length) { console.warn('Tabs toggles and tabs amounts are not matching'); return false; } else if (this.toggles.length === 0) { console.warn('There\'s no toggles for tabs'); return false; } else if (this.tabs.length === 0) { console.warn('There\'s no content tabs'); return false; } return true; } }
Конструктор принимает DOM обеъект группы вкладок (в нашем случае .tabs).
Функция init проходит циклом по всем кнопкам и создает экземпляры класса Tab группируя по принципу «первая кнопка к первой вкладке».
Функция isEverythingOk проверяет соответсвие количества вкладок количеству кнопок и их наличие, в противном случае выбрасывает предупреждение в консоль для более удобного поиска ошибок.
Функция инициализации
export default function initTabs(selector) { for (let container of document.querySelectorAll(selector)) { new Tabs(container); } }
Предназначена для тех, кто не хочет разбираться с принципами работы с DOM или просто для удобства, просто создает экземпляры класса Tabs.
Пример с использованием функции инициализации
import initTabs from 'future-tabs'; initTabs('.tabs');
Пример работы напрямую с классом
import {Tabs} from 'future-tabs'; const container = document.querySelector('.tabs'); const tabs = new Tabs(container);
В планах сделать выборку внутренних блоков в зависимости от селектора, дописывая названия элементов следуя методологии _bem.
Спасибо за внимание!
ссылка на оригинал статьи http://habrahabr.ru/post/265477/
Добавить комментарий