Implémentation Javascript des tabs sur Bulma

publié le 04/08/2018

javascript Bulma tabs

J'ai récemment découvert Bulma, un framework CSS. Après avoir réalisé 2 ou 3 projets avec, je dois avouer qu'il est vraiment simple à apprendre et à utiliser. Comparé à Bootstrap ou Materialize, c'est un framework vraiment léger car il ne dépend d'aucune librairie Javascript. La contrepartie de cette absence de dépendances est que c'est à nous, développeur qui l'utilisons, d'implémenter la couche JS pour que fonctionne certains composants. Rien d'incroyable, croyez-moi. De simples notions de Javascript suffisent largement pour y parvenir. Et bien souvent, la documentation de Bulma propose aussi des snippets Javascript prêts à l'emploi. Ce n'est en revanche pas le cas du composant tabs. Je vous propose donc ici mon code Javascript pour implémenter correctement ce composant.


On va partir de zéro. En quelques lignes de commande, le projet sera initialisé.

mkdir bulma-tabs
cd bulma-tabs
touch app.js app.css index.html

Maintenant que nous avons créé et structuré notre répertoire de travail, passons au contenu des 3 fichiers index.html, app.js et app.css.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Implémentation Javascript des tabs sur Bulma</title>

        <!-- installation de bulma via le CDN -->
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.1/css/bulma.min.css">
        <script defer src="https://use.fontawesome.com/releases/v5.1.0/js/all.js"></script>

        <link rel="stylesheet" href="app.css">
    </head>
    <body>
        <section class="section">
            
            <!-- entourer les tabs et leurs contenus correspondants d'un élément ayant la classe js-tabs-container. -->
            <div class="container js-tabs-container">

                <div class="tabs">
                    <ul>
                        <!-- chaque item contient un attribut data-tab dont la valeur correspond à l'ID du contenu correspondant -->
                        <li class="is-active" data-tab="tab-photos"><a>Photos</a></li>
                        <li data-tab="tab-musique"><a>Musique</a></li>
                        <li data-tab="tab-videos"><a>Vidéos</a></li>
                    </ul>
                </div>

                <!-- contenu de la tab "Photos" dont l'ID correspond à la valeur de l'attribut data-tab du lien associé -->
                <!-- le contenu initialiement visible au chargement de la page ne porte pas la classe has-display-none -->
                <!-- chacun des contenus porte la classe js-tab-content -->
                <div class="js-tab-content" id="tab-photos">
                    <article class="message is-dark">
                        <div class="message-header">Photos</div>
                        <div class="message-body">
                            Lorem amet vel ipsa excepturi soluta Commodi culpa suscipit deserunt odio soluta, voluptas? Ea ea dolore ipsum minima delectus. Odit vitae ea temporibus hic obcaecati! Reiciendis quae nisi inventore numquam?

</div>
                    </article>
                </div>

                <!-- contenu de la tab "Musique" -->
                <div class="has-display-none js-tab-content" id="tab-musique">
                    <article class="message is-info">
                        <div class="message-header">Musique</div>
                        <div class="message-body">
                            Lorem amet vel ipsa excepturi soluta Commodi culpa suscipit deserunt odio soluta, voluptas? Ea ea dolore ipsum minima delectus. Odit vitae ea temporibus hic obcaecati! Reiciendis quae nisi inventore numquam?

</div>
                    </article>
                </div>

                <!-- contenu de la tab "Vidéos" -->
                <div class="has-display-none js-tab-content" id="tab-videos">
                    <article class="message is-primary">
                        <div class="message-header">Vidéos</div>
                        <div class="message-body">
                            Lorem amet vel ipsa excepturi soluta Commodi culpa suscipit deserunt odio soluta, voluptas? Ea ea dolore ipsum minima delectus. Odit vitae ea temporibus hic obcaecati! Reiciendis quae nisi inventore numquam?

</div>
                    </article>
                </div>

            </div>
        </section>
        
        <script src="app.js"></script>

    </body>


</html>
// app.js

'use strict';

document.addEventListener('DOMContentLoaded', function () {

  var tabs = document.getElementsByClassName('tabs');
  if (tabs) {
    var _loop = function _loop() {
      var tabListItems = tabs[i].querySelectorAll('li');
      tabListItems.forEach(function (tabListItem) {

        // création d'un écouteur d'évènements sur le clic d'une tab
        tabListItem.addEventListener('click', function () {

          // suppression de la classe is-active sur chacune des tabs avant de la rajouter sur la tab qui a été cliquée
          tabListItems.forEach(function (tabListItem) {
            tabListItem.classList.remove('is-active');
          });
          tabListItem.classList.add('is-active');

          // tabName correspond à la valeur de l'attribut data-tab
          var tabName = tabListItem.dataset.tab;

          // on identifie tous les contenus possibles puis on applique la classe has-display-none si l'ID du contenu ne correspond pas à la valeur de l'attribut data-tab
          tabListItem.closest('.js-tabs-container').querySelectorAll('.js-tab-content').forEach(function (tabContent) {

            if (tabContent.id !== tabName) {
              tabContent.classList.add('has-display-none');
            } else {
              tabContent.classList.remove('has-display-none');
            }
          });
        }, false);
      });
    };

    for (var i = 0; i < tabs.length; i++) {
      _loop();
    }
  }
});
/* app.css */

 .has-display-none {
    display: none;
    visibility: hidden;
}