Bulma dropdown not working
Asked Answered
I

5

17

Bulma dropdown doesn't seem to toggle on click. Below is the code snippet from the documentation:https://bulma.io/documentation/components/dropdown/

<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.0/css/bulma.min.css" rel="stylesheet"/>


<div class="dropdown is-active">
  <div class="dropdown-trigger">
    <button class="button" aria-haspopup="true" aria-controls="dropdown-menu">
      <span>Dropdown button</span>
      <span class="icon is-small">
        <i class="fa fa-angle-down" aria-hidden="true"></i>
      </span>
    </button>
  </div>
  <div class="dropdown-menu" id="dropdown-menu" role="menu">
    <div class="dropdown-content">
      <a href="#" class="dropdown-item">
        Dropdown item
      </a>
      <a class="dropdown-item">
        Other dropdown item
      </a>
      <a href="#" class="dropdown-item is-active">
        Active dropdown item
      </a>
      <a href="#" class="dropdown-item">
        Other dropdown item
      </a>
      <hr class="dropdown-divider">
      <a href="#" class="dropdown-item">
        With a divider
      </a>
    </div>
  </div>
</div>
Incurve answered 17/10, 2017 at 8:7 Comment(2)
Where is your js?Ringster
But the markup in your fiddle looks a lot different than in the documentation. Like dropdown class and dropdown-trigger classes are missing.Incurve
R
26

You need to toggle the class is-active using JavaScript. When .dropdown has .is-active it changes the display of .dropdown-menu from none to block.

Here is a basic way to implement it.

var dropdown = document.querySelector('.dropdown');
dropdown.addEventListener('click', function(event) {
  event.stopPropagation();
  dropdown.classList.toggle('is-active');
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.0/css/bulma.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU" crossorigin="anonymous">


<div class="dropdown">
  <div class="dropdown-trigger">
    <button class="button" aria-haspopup="true" aria-controls="dropdown-menu">
      <span>Dropdown button</span>
      <span class="icon is-small">
        <!--fontawesome required for the icon-->
        <i class="fa fa-angle-down" aria-hidden="true"></i>
      </span>
    </button>
  </div>
  <div class="dropdown-menu" id="dropdown-menu" role="menu">
    <div class="dropdown-content">
      <a href="#" class="dropdown-item">
        Dropdown item
      </a>
      <a class="dropdown-item">
        Other dropdown item
      </a>
      <a href="#" class="dropdown-item is-active">
        Active dropdown item
      </a>
      <a href="#" class="dropdown-item">
        Other dropdown item
      </a>
      <hr class="dropdown-divider">
      <a href="#" class="dropdown-item">
        With a divider
      </a>
    </div>
  </div>
</div>
Ringster answered 17/10, 2017 at 9:54 Comment(6)
Cool. Got it now.Incurve
One more thing I wanted to ask. Does icon work in bulma? I tried using some but aren't working.Incurve
@AakashThakur Do you mean icons in general? Or are you referring to a specific set, like fontAwesome.Ringster
Ohh I didn't include font-awesome. Got it working now.Thanks anyways.Incurve
How can I close it when it's open and I click somewhere else?Meniscus
@sol, why would this not work when overlayed on top of Google maps? I see the "active" toggling but it does nothing.Reckford
J
6

Here's a full solution that has worked well for me using vanilla JS and making sure dropdowns close when you click out of them or press the Esc key.

// Get all dropdowns on the page that aren't hoverable.
const dropdowns = document.querySelectorAll('.dropdown:not(.is-hoverable)');

if (dropdowns.length > 0) {
  // For each dropdown, add event handler to open on click.
  dropdowns.forEach(function(el) {
    el.addEventListener('click', function(e) {
      e.stopPropagation();
      el.classList.toggle('is-active');
    });
  });

  // If user clicks outside dropdown, close it.
  document.addEventListener('click', function(e) {
    closeDropdowns();
  });
}

/*
 * Close dropdowns by removing `is-active` class.
 */
function closeDropdowns() {
  dropdowns.forEach(function(el) {
    el.classList.remove('is-active');
  });
}

// Close dropdowns if ESC pressed
document.addEventListener('keydown', function (event) {
  let e = event || window.event;
  if (e.key === 'Esc' || e.key === 'Escape') {
    closeDropdowns();
  }
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.css" rel="stylesheet">

<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css" rel="stylesheet">

<body style="margin: 2rem">

<div class="dropdown">
  <div class="dropdown-trigger">
    <button class="button" aria-haspopup="true" aria-controls="dropdown-ui-actions">
      <span>Actions</span>
      <span class="icon is-small">
        <i class="fas fa-angle-down" aria-hidden="true"></i>
      </span>
    </button>
  </div>
  <div class="dropdown-menu" id="dropdown-ui-actions" role="menu">
    <div class="dropdown-content">
      <a href="#" class="dropdown-item">
        Option 1
      </a>
      <a href="#" class="dropdown-item">
        Option 2
      </a>
      <a href="#" class="dropdown-item">
        Option 3
      </a>
    </div>
  </div>
</div>

</body>
Journeyman answered 16/10, 2019 at 4:18 Comment(3)
Great, thx! Any reason why didn't you put the Keydown event inside the if dropdowns.length > 0 condition ?Donella
@Donella hmm not that I remember. I think you could probably move it.Journeyman
Great answer, helped me alot!Livvyy
F
4

Add an onclick to the button:

<button class="button" onclick="this.parentNode.parentNode.classList.toggle('is-active')">
Faxen answered 24/2, 2023 at 4:26 Comment(0)
E
2

I sniffed the javascript source listener on the docs page (I don't know why they don't make this more obvious tbh) and here it is for anyone else who may benefit.

Please note below I commented out a cookies aspect which I did not have defined and was throwing an error and seemed unimportant for my purposes.

"use strict";

document.addEventListener("DOMContentLoaded", function () {
  // Search

  var setSearchToggle = function setSearchToggle() {
    var icon = document.getElementById("searchIcon");
    var search = document.getElementById("search");
    var input = document.getElementById("algoliaSearch");

    if (!icon) {
      return;
    }

    icon.addEventListener("click", function (event) {
      search.classList.toggle("bd-is-visible");

      if (search.classList.contains("bd-is-visible")) {
        algoliaSearch.focus();
      }
    });

    window.addEventListener("keydown", function (event) {
      if (event.key === "Escape") {
        return search.classList.remove("bd-is-visible");
      }
    });
  };

  setSearchToggle();

  // Navbar

  var setNavbarVisibility = function setNavbarVisibility() {
    var navbar = document.getElementById("navbar");

    if (!navbar) {
      return;
    }

    var cs = getComputedStyle(navbar);
    var paddingX = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight);
    var brand = navbar.querySelector(".navbar-brand");
    var end = navbar.querySelector(".navbar-end");
    var search = navbar.querySelector(".bd-search");
    var original = document.getElementById("navbarStartOriginal");
    var clone = document.getElementById("navbarStartClone");

    var rest = navbar.clientWidth - paddingX - brand.clientWidth - end.clientWidth - search.clientWidth;

    var space = original.clientWidth;
    var all = document.querySelectorAll("#navbarStartClone > .bd-navbar-item");
    var base = document.querySelectorAll("#navbarStartClone > .bd-navbar-item-base");
    var more = document.querySelectorAll("#navbarStartOriginal > .bd-navbar-item-more");
    var dropdown = document.querySelectorAll("#navbarStartOriginal .bd-navbar-dropdown > .navbar-item");

    var count = 0;
    var totalWidth = 0;

    var showMore = function showMore() {};

    var hideMore = function hideMore() {};

    var _iteratorNormalCompletion = true;
    var _didIteratorError = false;
    var _iteratorError = undefined;

    try {
      for (var _iterator = all[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
        var item = _step.value;

        totalWidth += item.offsetWidth;

        if (totalWidth > rest) {
          break;
        }

        count++;
      }
    } catch (err) {
      _didIteratorError = true;
      _iteratorError = err;
    } finally {
      try {
        if (!_iteratorNormalCompletion && _iterator.return) {
          _iterator.return();
        }
      } finally {
        if (_didIteratorError) {
          throw _iteratorError;
        }
      }
    }

    var howManyMore = Math.max(0, count - base.length);

    if (howManyMore > 0) {
      for (var i = 0; i < howManyMore; i++) {
        more[i].classList.add("bd-is-visible");
        dropdown[i].classList.add("bd-is-hidden");
      }
    }

    for (var j = howManyMore; j < more.length; j++) {
      more[j].classList.remove("bd-is-visible");
    }

    for (var k = howManyMore; k < dropdown.length; k++) {
      dropdown[k].classList.remove("bd-is-hidden");
    }
  };

  setNavbarVisibility();

  // Cookies

//  var cookieBookModalName = "bulma_closed_book_modal";
//  var cookieBookModal = Cookies.getJSON(cookieBookModalName) || false;

  // Dropdowns

  var $dropdowns = getAll(".dropdown:not(.is-hoverable)");

  if ($dropdowns.length > 0) {
    $dropdowns.forEach(function ($el) {
      $el.addEventListener("click", function (event) {
        event.stopPropagation();
        $el.classList.toggle("is-active");
      });
    });

    document.addEventListener("click", function (event) {
      closeDropdowns();
    });
  }

  function closeDropdowns() {
    $dropdowns.forEach(function ($el) {
      $el.classList.remove("is-active");
    });
  }

  // Toggles

  var $burgers = getAll(".navbar-burger");

  if ($burgers.length > 0) {
    $burgers.forEach(function ($el) {
      if (!$el.dataset.target) {
        return;
      }

      $el.addEventListener("click", function () {
        var target = $el.dataset.target;
        var $target = document.getElementById(target);
        $el.classList.toggle("is-active");
        $target.classList.toggle("is-active");
      });
    });
  }

  // Modals

  var rootEl = document.documentElement;
  var $modals = getAll(".modal");
  var $modalButtons = getAll(".modal-button");
  var $modalCloses = getAll(".modal-background, .modal-close, .modal-card-head .delete, .modal-card-foot .button");

  if ($modalButtons.length > 0) {
    $modalButtons.forEach(function ($el) {
      $el.addEventListener("click", function () {
        var target = $el.dataset.target;
        openModal(target);
      });
    });
  }

  if ($modalCloses.length > 0) {
    $modalCloses.forEach(function ($el) {
      $el.addEventListener("click", function () {
        closeModals();
      });
    });
  }

  function openModal(target) {
    var $target = document.getElementById(target);
    rootEl.classList.add("is-clipped");
    $target.classList.add("is-active");
  }

  function closeModals() {
    rootEl.classList.remove("is-clipped");
    $modals.forEach(function ($el) {
      $el.classList.remove("is-active");
    });
  }

  document.addEventListener("keydown", function (event) {
    var e = event || window.event;

    if (e.keyCode === 27) {
      closeModals();
      closeDropdowns();
    }
  });

  // Clipboard

  var $highlights = getAll(".highlight");
  var itemsProcessed = 0;

  if ($highlights.length > 0) {
    $highlights.forEach(function ($el) {
      var copyEl = '<button class="button bd-copy">Copy</button>';
      var expandEl = '<button class="button is-small bd-expand">Expand</button>';
      $el.insertAdjacentHTML("beforeend", copyEl);

      var $parent = $el.parentNode;

      if ($parent && $parent.classList.contains("bd-is-more")) {
        var showEl = '<button class="button is-small bd-show"><span class="icon"><i class="fas fa-code"></i></span><strong>Show code</strong></button>';
        $parent.insertAdjacentHTML("afterbegin", showEl);
      } else if ($el.firstElementChild.scrollHeight > 480 && $el.firstElementChild.clientHeight <= 480) {
        $el.insertAdjacentHTML("beforeend", expandEl);
      }

      itemsProcessed++;

      if (itemsProcessed === $highlights.length) {
        addHighlightControls();
      }
    });
  }

  function addHighlightControls() {
    var $highlightButtons = getAll(".highlight .bd-copy, .highlight .bd-expand");

    $highlightButtons.forEach(function ($el) {
      $el.addEventListener("mouseenter", function () {
        $el.parentNode.classList.add("bd-is-hovering");
        $el.parentNode.parentNode.classList.add("bd-is-hovering");
      });

      $el.addEventListener("mouseleave", function () {
        $el.parentNode.classList.remove("bd-is-hovering");
        $el.parentNode.parentNode.classList.remove("bd-is-hovering");
      });
    });

    var $highlightExpands = getAll(".bd-snippet .bd-expand");

    $highlightExpands.forEach(function ($el) {
      $el.addEventListener("click", function () {
        $el.parentNode.firstElementChild.style.maxHeight = "none";
      });
    });

    var $highlightShows = getAll(".bd-snippet .bd-show");

    $highlightShows.forEach(function ($el) {
      $el.addEventListener("click", function () {
        var text = $el.querySelector("strong").textContent;
        var newText = text === "Show code" ? "Hide code" : "Show code";
        $el.querySelector("strong").textContent = newText;
        $el.parentNode.classList.toggle("bd-is-more-clipped");
      });
    });
  }

  setTimeout(function () {
    new Clipboard(".bd-copy", {
      target: function target(trigger) {
        return trigger.previousElementSibling.firstElementChild;
      }
    });

    new Clipboard(".bd-clipboard");
  }, 100);

  // Events

  var resizeTimer = void 0;

  function handleResize() {
    window.clearTimeout(resizeTimer);

    resizeTimer = window.setTimeout(function () {
      setNavbarVisibility();
    }, 10);
  }

  window.addEventListener("resize", handleResize);

  // Utils

  function getAll(selector) {
    var parent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document;

    return Array.prototype.slice.call(parent.querySelectorAll(selector), 0);
  }
});
Ebony answered 16/2, 2022 at 20:38 Comment(0)
A
0

correction of te answer above: I added the closeDropdowns() function, because when we click in a second menu, both menus stay opened.

// Get all dropdowns on the page that aren't hoverable.
const dropdowns = document.querySelectorAll('.dropdown:not(.is-hoverable)');

if (dropdowns.length > 0) {
  // For each dropdown, add event handler to open on click.
  dropdowns.forEach(function(el) {
    el.addEventListener('click', function(e) {
    closeDropdowns();
      e.stopPropagation();
      el.classList.toggle('is-active');
    });
  });

  // If user clicks outside dropdown, close it.
  document.addEventListener('click', function(e) {
    closeDropdowns();
  });
}

/*
 * Close dropdowns by removing `is-active` class.
 */
function closeDropdowns() {
  dropdowns.forEach(function(el) {
    el.classList.remove('is-active');
  });
}

// Close dropdowns if ESC pressed
document.addEventListener('keydown', function (event) {
  let e = event || window.event;
  if (e.key === 'Esc' || e.key === 'Escape') {
    closeDropdowns();
  }
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.5/css/bulma.css" rel="stylesheet">

<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css" rel="stylesheet">

<body style="margin: 2rem">

<div class="dropdown">
  <div class="dropdown-trigger">
    <button class="button" aria-haspopup="true" aria-controls="dropdown-ui-actions">
      <span>Actions</span>
      <span class="icon is-small">
        <i class="fas fa-angle-down" aria-hidden="true"></i>
      </span>
    </button>
  </div>
  <div class="dropdown-menu" id="dropdown-ui-actions" role="menu">
    <div class="dropdown-content">
      <a href="#" class="dropdown-item">
        Option 1
      </a>
      <a href="#" class="dropdown-item">
        Option 2
      </a>
      <a href="#" class="dropdown-item">
        Option 3
      </a>
    </div>
  </div>
</div>

</body>
Accelerando answered 13/9, 2021 at 14:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.