jQuery-плагин для создания адаптивных вкладок
(табы, аккордеон, спойлер)

Особенности

  • Два режима отображения: tabs, accordion + (accordion с одной вкладкой в качестве спойлера)
  • Адаптивный режим. Трансформация табов в аккордеон и обратно
    (произвольно или при заданной ширине окна браузера)
  • Поддержка тем оформления (стили темы вынесены в отдельный файл)
    Шаблон темы в .scss
  • Гибкая система методов/событий для программного управления состояниями
  • Пользовательская анимация при открытии/закрытии вкладок и смене режима

Пакетные менеджеры

Подключение

1. Подключить скрипты и стили:
        

        <!-- jQuery FlexTabs Styles -->
        <link rel="stylesheet" href="dist/jquery.flextabs.min.css">

        <!-- jQuery FlexTabs Theme Default -->
        <link rel="stylesheet" href="dist/jquery.flextabs.theme-default.min.css">

        <!-- jQuery -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

        <!-- jQuery FlexTabs -->
        <script src="dist/jquery.flextabs.min.js"></script>

        
      
2. Инициализировать плагин на группе элементов:


    $('[data-ft]').flexTabs({
      // Параметры...
    });

  
3. Применить в HTML одним из способов:
После инициализации режим отображения можно будет преобразовать на лету, см. метод changeMode
Вариант #1 — Табы
Режим по умолчанию: Табы. При ширине окна браузера менее 768px — преобразование в режим Аккордеон.
Точка перехода контролируется параметром breakpoint
Вариант #2 — Аккордеон
Режим по умолчанию: Аккордеон. Параметр breakpoint игнорируется.
Вариант #2 — Спойлер
Режим по умолчанию: Аккордеон. Параметр breakpoint игнорируется.
Тот же аккордион, но с одной вкладкой.
Если нужно убрать мерцания, возникающие в момент применения CSS-стилей при загрузке страницы,
необх. предварительно скрыть FlexTabs контейнеры, например: [data-ft] { display: none; }

Рекомендации по оформлению разметки

Параметры

Опция Тип Поум. Описание
type String 'tabs' Базовый тип разметки: "tabs" или "accordion"
breakpoint Number 768 Ширина окна браузера в px, при которой будет происходить переход из режима "tabs" в "accordion" и обратно. Работает при type = 'tabs'
responsive Boolean true Преобразование режима "tabs" в "accordion"
event String 'click' Событие переключающее вкладки. false — событие назначено не будет
fade Number 200 Базовая продолжительность анимации, мс
collapsible Boolean true Способ переключения вкладок в режиме "accordion". true — вкладки можно сворачивать и разворачивать, разворачивание новой вкладки не влечет сворачивание остальных. false — вкладки можно только разварачивать, разворачивание новой вкладки влечет сворачивание остальных
theme String 'ft-theme-default' Тема оформления (CSS-класс основного контейнера)
icon String см.1 Иконка во вкладках в режиме "accordion". false — иконка добавлена не будет
classes Object см.2 CSS-классы

1 Иконка во вкладках в режиме "accordion":



    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">>path d="M48.293 23.293l-16.293 16.293-16.293-16.293-1.414 1.561 17 17.146h1.414l17-17.146z"/></svg>'

  

2 CSS-классы:



    {
      // Общий контейнер
      container: 'ft-container',

      // Общий контейнер. Режим: Tabs
      mtb: 'ft-tabs',

      // Общий контейнер. Режим: Accordion
      mac: 'ft-accordion',

      // Контейнер для содержимого вкладок
      contents: 'ft-contents',

      // Контейнер для вкладок
      nav: 'ft-nav',

      // Вкладка
      tab: 'ft-tab',

      // Вкладка, содержащая иконку
      tabIcon: 'ft-tab-icon',

      // Контент вкладки
      content: 'ft-content',

      // Контейнер с иконкой
      icon: 'ft-icon',

      // Активная вкладка/контент
      active: 'active'
    }

  

Примеры использования параметров

JS:



    $('.example').flexTabs({
      breakpoint: 1024,
      fade: 500,
      icon: false
    });

  

HTML:

Методы

Метод Аргументы Описание
init options Инициализация
destroy - Деинициализация
reinit newOpts Реинициализация
open tab, forcibly, fade Открытие вкладки. Аргументы:
tab — индекс(Number), ID(String) или объект(Object) вкладки. Обяз. параметр.
forcibly — принудительный режим запуска (Boolean). Необяз. параметр., по умолчанию — false.
fade — продолжительность анимации, мс (String). Необяз. параметр., по умолчанию равен базовому значению
close tab, forcibly, fade Закрытие вкладки. Аргументы:
tab — индекс(Number), ID(String) или объект(Object) вкладки. Обяз. параметр.
forcibly — принудительный режим запуска (Boolean). Необяз. параметр., по умолчанию — false.
fade — продолжительность анимации, мс (String). Необяз. параметр., по умолчанию равен базовому значению
closeAll forcibly, fade Закрытие всех вкладок. Аргументы:
forcibly — принудительный режим запуска (Boolean). Необяз. параметр., по умолчанию — false.
fade — продолжительность анимации, мс (String). Необяз. параметр., по умолчанию равен базовому значению
switch tab, fade В режиме "tabs": переключение на вкладку. В режиме "accordion": переключение между состояниями "open"/"close". Аргументы:
tab — индекс(Number), ID(String) или объект(Object) вкладки. Обяз. параметр.
fade — продолжительность анимации, мс (String). Необяз. параметр., по умолчанию равен базовому значению
changeMode mode, flow, cb Смена режима отображения. Аргументы:
mode — режим, на который нужно сменить (String) "tabs" или "accordion". Обяз. параметр.
flow — глобальная(true)/поточная(false) смена режима. Необяз. параметр., по умолчанию false
cb — колбэк-функция. Сработает до выполнения метода. Необяз. параметр.

Примеры использования методов



    var options = { /* Параметры... */ },
      newOpts = { /* Новые параметры... */ },

      example = $('.example');

    // Варианты Init, Reinit, Destroy
    example.flexTabs(); // Инициализация с пар-ми поум.
    example.flexTabs(options); // Инициализация с польз. пар-ми
    example.flexTabs('init', options); // Инициализация с польз. пар-ми
    
    example.flexTabs('reinit', newOpts); // Реинициализация с новыми example
    example.flexTabs('reinit'); // Реинициализация с текущими пар-ми

    example.flexTabs('destroy'); // Деинициализация
    
    // Управление вкладками
    example.flexTabs('open', 0); // Открыть первую вкладку
    example.flexTabs('close', 0); // Закрыть первую вкладку
    example.flexTabs('closeAll'); // Закрыть все вкладки
    example.flexTabs('switch', 0); // Переключить первую вкладку

    // Смена режима отображения
    example.flexTabs('changeMode', 'tabs'); // Переключиться в режим "tabs"
    example.flexTabs('changeMode', 'accordion'); // Переключиться в режим "accordion"
    ex.flexTabs('changeMode', 'tabs', false, function() {
      // Откл. смену режима при изменении ширины окна браузера
      this.settings.responsive = false;
    }); // Переключиться в режим "tabs" принудительно

  


События

Событие Аргументы Описание
afterInit.ft e, instance После инициализации
afterOpen.ft e, instance, targetTab После открытия вкладки
afterClose.ft e, instance, targetTab После закрытия вкладки
beforeChangeMode.ft e, instance Перед сменой режима отображения
afterChangeMode.ft e, instance После смены режима отображения

Примеры использования событий


    var example = $('.example');

    example.on('afterOpen.ft', function(e, instance, targetTab) {
      console.log( 'beforeClose: ', e, instance, targetTab );
      /* Аргументы:
        e - объект события
        instance - экз. "класса" FlexTabs для элемента, на котором вызвано событие
        targetTab - объект целейвой вкладки
      */
    });

    example.flexTabs(); // Инициализация
  

Data-атрибуты

Параметры в data-атрибуте имеют наивысший приоритет. Они переопределят параметры по умолчанию, а так же пользовательские параметры заданные при инициализации. Значение атрибута - валидный JSON.

Переопределение параметров по умолчанию



    /* Изменение параметров по умолчанию (свойство): */
    FlexTabs.defaults.event = 'mouseover';

    /* Изменение параметров по умолчанию (объект): */
    $.extend(true, FlexTabs.defaults, {
      theme: 'ft-theme-new',
      fade: 0
    });

    /* Далее инициализация... */
    $('.example').flexTabs();
  
  

Темы оформления

Имя темы — CSS-класс, добавляемый основному контейнеру.

Назначить тему можно одним из способов:

— указать имя темы в атрибуте class основного контейнера (не рекомендуется):
— указать имя темы в атрибуте data-ft:
— указать имя темы в параметрах при ините:

  $('.example').flexTabs({
    theme: 'ft-theme-default'
  });
  

Для создания собственной темы можно воспользоваться шаблоном или взять за основу тему по умолчанию.

Шаблон темы в синтаксисе SCSS

URL Hash

Начиная с версии 2.0 появилась возможность использовать хеш-ссылки для активации вкладок при загрузке страницы. После активации указанных в ссылке вкладок хеш очищается.

  • Общий контейнер должен иметь свой уникальный id
  • Каждая вкладка должна быть ссылкой <a href=""></a> и иметь свой уникальный атрибут href

Пример правильно оформленных табов:

Хеш-ссылка следующего вида при загрузке страницы в контейнере с id="formats" откроет вкладки под индексами: если режим tabs — 0 (первую вкладку), если режим accordion — 0,1,2 (все перечисленные)

http://example.com/#formats=0,1,2

Вместо индексов можно указывать ID вкладок:

http://example.com/#formats=html,css,js

А также ID и индексы вперемешку:

http://example.com/#formats=1,js

Если нужно указать активные вкладки для нескольких контейнеров:

http://example.com/#formats=html,css,js&container_id=0,1

Рекомендации

  • Порядок расположения вкладок и содержимого вкладок имеет значение.
  • В навигации и в контейнере с содержимым вкладок, например,
    вместо ссылок могут быть любые элементы: <div>, <h1>, <p> и т.д.
  • ID вкладок (атрибут href) и ID содержимого (атрибут id) прописывать не обязательно. Альтернатива атрибуту "href" у вкладки — атрибут data-id. Но прописывать уникальные ID вкладкам и содержимому все же рекомендуется, чтобы сохранить привязку вкладки с ее контентом при откл. JS
  • При назначении ID вкладкам следует придерживаться правилам именования идентификаторов в CSS.
  • Активная вкладка выделяется классом active. Активных вкладок может быть несколько.
  • Атрибут data-ft у основного контейнера — не обязательный. Он используется только если необходимо изменить параметры из HTML или задать базовый тип разметки.
  • Класс ft-theme-default у общего контейнера устанавливает класс темы оформления по умолчанию. Указать класс темы можно также параметром theme

Анимация

Демо по примерам ниже

Анимация открытия вкладок


        var example = $('.example');

        example.on('afterOpen.ft', function(e, instance, targetTab) {

          // Перекл. в состояние польз. анимации
          instance.animation = 'custom';
          
          // Для режима "Accordion"
          if( instance.mode === 'accordion' ) {

            // Анимация контента вкладки
            targetTab.content.slideDown({
              duration: 600,

              // Функция плавности
              // Требует подключения доп. библиотеки:
              // https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js
              // Подробнее: https://easings.net/
              easing: 'easeOutBack',
              start: function() {

                // Анимация элементов внутри контейнера
                // Требует подключения доп. библиотеки:
                // https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.0/animate.min.css
                // Подробнее: https://daneden.github.io/animate.css/
                // Функция animateCSS() ниже
                animateCSS(targetTab.content.find('p'), 'fadeInDown', 500, 75);
              }
            });
          
          // Для режима "Tabs"
          } else {

            // Анимация контента вкладки 
            targetTab.content.fadeIn(750);

          }

        });

        // Инит
        example.flexTabs();
      

Анимация закрытия вкладок


        var example = $('.example');

        example.on('afterClose.ft', function(e, instance, targetTab) {

          // Перекл. в состояние польз. анимации
          instance.animation = 'custom';

          // Для режима "Accordion"
          if( instance.mode === 'accordion' ) {

            // Анимация контента вкладки
            targetTab.content.slideUp({
              duration: 350,

              // Функция плавности
              // Требует подключения доп. библиотеки:
              // https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js
              // Подробнее: https://easings.net/
              easing: 'easeInOutSine',
              start: function() {

                // Анимация элементов внутри контейнера
                // Требует подключения доп. библиотеки:
                // https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.0/animate.min.css
                // Подробнее: https://daneden.github.io/animate.css/
                // Функция animateCSS() ниже
                animateCSS(targetTab.content.find('p'), 'fadeOutDown', 850, 0);
              },
              complete: function() {
                // Удаляет анимационные классы, сразу после завершения анимации контейнера
                // ( для устранения нежелательного поведеня при быстром открытии/закрытии вкладок )
                // Функция animateCSSRemove() ниже
                animateCSSRemove(targetTab.content.find('p'), 'fadeOutDown');
              }
            });

          // Для режима "Tabs"
          } else {

            // Анимация контента вкладки
            targetTab.content.hide();

          }

        });

        // Инит
        example.flexTabs();
      

Анимация при переключении режима


        var example = $('.example');

        example.on('beforeChangeMode.ft', function(e, instance) {
          $(instance.it).hide();
        }).on('afterChangeMode.ft', function(e, instance) {
          $(instance.it).fadeIn(450);
        });

        // Инит
        example.flexTabs();
      

Функции: jQuery + animate.css


        function animateCSS(elements, animationName, duration, delay, callback) {

          var duration = duration >= 0 ? duration/1000 : '',
             delay = delay >= 0 ? delay/1000 : '';

          elements.addClass('animated ' + animationName)
               .css({
                 'animation-duration': duration + 's',
                 'animation-delay': delay + 's',
               });

          function handleAnimationEnd() {
            elements.removeClass('animated ' + animationName)
            .css({
               'animation-duration': '',
               'animation-delay': '',
            });
            elements.off('animationend', handleAnimationEnd);
            if (typeof callback === 'function') callback();
          }

          elements.on('animationend', handleAnimationEnd);

        }

        function animateCSSRemove(elements, animationName) {
          elements.removeClass('animated ' + animationName);
        }
      

Ajax

Общий пример загрузки содержимого с помощью AJAX


    // Добав. прелоадер в объект настроек по умолчанию
    FlexTabs.defaults.preloader = 
      '<div class="ft-preloader">' +
      '<svg width="25" height="25" viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="8.042%" y1="0%" x2="65.682%" y2="23.865%" id="a"><stop stop-color="#222" stop-opacity="0" offset="0%"/><stop stop-color="#222" stop-opacity=".631" offset="63.146%"/><stop stop-color="#222" offset="100%"/></linearGradient></defs><g transform="translate(1 1)" fill="none"><path d="M36 18c0-9.94-8.06-18-18-18" stroke="#222" stroke-width="2"><animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="0.9s" repeatCount="indefinite"/></path><circle fill="#222" cx="36" cy="18" r="1"><animateTransform attributeName="transform" type="rotate" from="0 18 18" to="360 18 18" dur="0.9s" repeatCount="indefinite"/></circle></g></svg>' +
      '</div>';

    var example = $('.example');

    example.on('afterOpen.ft', function(e, instance, targetTab) {

      // Контент загружен — выход
      if( targetTab.loaded ) return;

      // Вбросить прелоадер в область с контентом
      targetTab.preloader = $(FlexTabs.defaults.preloader);
      targetTab.content.append(targetTab.preloader);

      $.ajax({
        method: 'POST',
        url: 'ajax-content.php',
        data: {},
        success: function(data) {
          var data = $(data);

          // Убрать прелоадер
          targetTab.preloader.fadeOut(500, function() {

            // Вбросить контент вкладки
            data.hide()
             .appendTo(targetTab.content)
             .fadeIn(500);

            // Вкладка загружена
            targetTab.loaded = true;

          });
          
        },
        error: function(data) {
          // Ошибка AJAX...
        }
      });

    });

    // Инит
    example.flexTabs();            
  

HTML:

История изменений

2.0.0 - 07.03.2019

  • Полностью переработана структура плагина
  • Переработаны существующие методы, добавлены новые параметры, методы, события
  • и др., см. документацию

1.0.9 - 04.10.2018

  • Исправлены некоторые ошибки

1.0.8 - 03.10.2018

  • Добавлен колбэк onChangeMode

1.0.7 - 03.10.2018

  • Исправлено срабатывание колбэков beforeChange и afterChange при ресайзе
  • Исправлена ошибка, возникающая при клике по телу вкладки
  • Некоторые исправления в Readme.md

1.0.2 - 18.08.2018

  • Добавлена поддержка цепочек вызовов
  • Незначительные изменения в наименовании некоторых переменных
  • Некоторые правки в Readme.md

Лицензия (MIT)

Copyright (c) 2018-2019 Sergey Kravchenko

Данная лицензия разрешает лицам, получившим копию данного программного обеспечения и сопутствующей документации (в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно использовать Программное Обеспечение без ограничений, включая неограниченное право на использование, копирование, изменение, слияние, публикацию, распространение, сублицензирование и/или продажу копий Программного Обеспечения, а также лицам, которым предоставляется данное Программное Обеспечение, при соблюдении следующих условий:

Указанное выше уведомление об авторском праве и данные условия должны быть включены во все копии или значимые части данного Программного Обеспечения.

ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ, ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ, ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.

Поддержка

Решение проблем/багов плагина, а также замечания и пожелания в соответствующей теме

По всем другим вопросам: wahawaher@gmail.com