Bootstrap JavaScript

Open a modal with a button

Description: Add a button “Open”. The click must open a modal with a title, a text and a Close button.

Hint:

  • Use data-bs-toggle="modal", data-bs-target and data-bs-dismiss="modal".

Solution

<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#ex1">Open</button>
<div class="modal fade" id="ex1" tabindex="-1" aria-labelledby="ex1Label" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h1 class="modal-title fs-5" id="ex1Label">Hello</h1>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">This is a modal.</div>
      <div class="modal-footer"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button></div>
    </div>
  </div>
</div>
Live preview

const m = document.getElementById('ex1');
document.querySelector('[data-bs-toggle="modal"]').click();
await new Promise(r => setTimeout(r, 700));
console.log('open: ' + m.classList.contains('show'));
m.querySelector('.modal-footer .btn').click();
await new Promise(r => setTimeout(r, 700));
console.log('open after Close: ' + m.classList.contains('show'));
Console output (real Chrome)

open: true
open after Close: false

How it works

  • The button opens the element with the id from data-bs-target.
  • modal-dialog-centered puts the box in the vertical center.

Read Modal.

Create an accordion with three items

Description: Make an accordion with three items. The first is open at the start, and opening another one must close the first.

Hint:

  • Use accordion, accordion-item, accordion-button and data-bs-parent.

Solution

<div class="accordion" id="acc">
  <div class="accordion-item">
    <h2 class="accordion-header"><button class="accordion-button" type="button" data-bs-toggle="collapse" data-bs-target="#a1" aria-expanded="true" aria-controls="a1">Item 1</button></h2>
    <div id="a1" class="accordion-collapse collapse show" data-bs-parent="#acc"><div class="accordion-body">Text of item 1</div></div>
  </div>
  <div class="accordion-item">
    <h2 class="accordion-header"><button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#a2" aria-expanded="false" aria-controls="a2">Item 2</button></h2>
    <div id="a2" class="accordion-collapse collapse" data-bs-parent="#acc"><div class="accordion-body">Text of item 2</div></div>
  </div>
  <div class="accordion-item">
    <h2 class="accordion-header"><button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#a3" aria-expanded="false" aria-controls="a3">Item 3</button></h2>
    <div id="a3" class="accordion-collapse collapse" data-bs-parent="#acc"><div class="accordion-body">Text of item 3</div></div>
  </div>
</div>
Live preview

document.querySelector('[data-bs-target="#a3"]').click();
await new Promise(r => setTimeout(r, 800));
['a1', 'a2', 'a3'].forEach(id => console.log(id + ' open = ' + document.getElementById(id).classList.contains('show')));
Console output (real Chrome)

a1 open = false
a2 open = false
a3 open = true

How it works

  • data-bs-parent="#acc" connects the items, so Bootstrap closes the others.
  • After the click on item 3, only item 3 is open.

Read Collapse and Accordion.

Create tabs with three panels

Description: Create three tabs. Clicking a tab must show only its own panel.

Hint:

  • Use nav nav-tabs, data-bs-toggle="tab" and tab-content with tab-pane.

Solution

<ul class="nav nav-tabs" role="tablist">
  <li class="nav-item" role="presentation"><button class="nav-link active" id="t1" data-bs-toggle="tab" data-bs-target="#p1" type="button" role="tab" aria-controls="p1" aria-selected="true">Home</button></li>
  <li class="nav-item" role="presentation"><button class="nav-link" id="t2" data-bs-toggle="tab" data-bs-target="#p2" type="button" role="tab" aria-controls="p2" aria-selected="false">Profile</button></li>
  <li class="nav-item" role="presentation"><button class="nav-link" id="t3" data-bs-toggle="tab" data-bs-target="#p3" type="button" role="tab" aria-controls="p3" aria-selected="false">Contact</button></li>
</ul>
<div class="tab-content border border-top-0 p-3">
  <div class="tab-pane fade show active" id="p1" role="tabpanel" tabindex="0">Home panel</div>
  <div class="tab-pane fade" id="p2" role="tabpanel" tabindex="0">Profile panel</div>
  <div class="tab-pane fade" id="p3" role="tabpanel" tabindex="0">Contact panel</div>
</div>
Live preview

document.getElementById('t3').click();
await new Promise(r => setTimeout(r, 500));
console.log('active panel: ' + document.querySelector('.tab-pane.active').textContent);
console.log('active tab: ' + document.querySelector('.nav-link.active').textContent);
Console output (real Chrome)

active panel: Contact panel
active tab: Contact

How it works

  • Each tab button points to a panel with data-bs-target. Bootstrap switches the classes active and show.

Read Navs and Tabs.

Create a carousel with three slides

Description: Make a carousel with three slides, previous and next buttons and three indicators.

Hint:

  • Use carousel slide, carousel-inner, carousel-item active and the control buttons with data-bs-slide.

Solution

<div id="cx" class="carousel slide" style="max-width: 420px">
  <div class="carousel-indicators">
    <button type="button" data-bs-target="#cx" data-bs-slide-to="0" class="active" aria-label="Slide 1"></button>
    <button type="button" data-bs-target="#cx" data-bs-slide-to="1" aria-label="Slide 2"></button>
    <button type="button" data-bs-target="#cx" data-bs-slide-to="2" aria-label="Slide 3"></button>
  </div>
  <div class="carousel-inner">
    <div class="carousel-item active"><img src="images/photo.jpg" class="d-block w-100" alt="Slide 1"></div>
    <div class="carousel-item"><img src="images/photo.jpg" class="d-block w-100" alt="Slide 2"></div>
    <div class="carousel-item"><img src="images/photo.jpg" class="d-block w-100" alt="Slide 3"></div>
  </div>
  <button class="carousel-control-prev" type="button" data-bs-target="#cx" data-bs-slide="prev"><span class="carousel-control-prev-icon" aria-hidden="true"></span><span class="visually-hidden">Previous</span></button>
  <button class="carousel-control-next" type="button" data-bs-target="#cx" data-bs-slide="next"><span class="carousel-control-next-icon" aria-hidden="true"></span><span class="visually-hidden">Next</span></button>
</div>
Live preview

const cx = document.getElementById('cx');
const idx = () => [...cx.querySelectorAll('.carousel-item')].findIndex(i => i.classList.contains('active')) + 1;
cx.querySelector('.carousel-control-next').click();
await new Promise(r => setTimeout(r, 900));
console.log('after Next: slide ' + idx());
cx.querySelector('.carousel-control-next').click();
await new Promise(r => setTimeout(r, 900));
console.log('after Next again: slide ' + idx());
cx.querySelector('.carousel-control-next').click();
await new Promise(r => setTimeout(r, 900));
console.log('after Next at the end: slide ' + idx() + ' (it goes round)');
Console output (real Chrome)

after Next: slide 2
after Next again: slide 3
after Next at the end: slide 1 (it goes round)

How it works

  • Exactly one carousel-item must have the class active at the start.
  • After the last slide, the carousel goes back to the first one.

Read Carousel.

Add a tooltip to a button

Description: Add a tooltip “Save the file” to a button, which opens when the user hovers on it.

Hint:

  • Use data-bs-toggle="tooltip", data-bs-title and start it with new bootstrap.Tooltip().

Solution

<button type="button" class="btn btn-success" id="savebtn" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Save the file">Save</button>
<script>
  document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(function (el) { new bootstrap.Tooltip(el); });
</script>
Live preview

const b = document.getElementById('savebtn');
b.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
await new Promise(r => setTimeout(r, 400));
const t = document.querySelector('.tooltip');
console.log('tooltip shown: ' + (t !== null) + ', text: ' + (t ? t.textContent.trim() : ''));
Console output (real Chrome)

tooltip shown: true, text: Save the file

How it works

  • Tooltips are not started automatically. The small script finds all elements with data-bs-toggle="tooltip" and starts them.

Read Tooltips and Popovers.

Create an offcanvas sidebar which opens from the left

Description: A “Menu” button must open a sidebar from the left side, with two links and a close button.

Hint:

  • Use offcanvas offcanvas-start, data-bs-toggle="offcanvas" and data-bs-dismiss="offcanvas".

Solution

<button class="btn btn-dark" type="button" data-bs-toggle="offcanvas" data-bs-target="#sidebar" aria-controls="sidebar">Menu</button>
<div class="offcanvas offcanvas-start" tabindex="-1" id="sidebar" aria-labelledby="sidebarLabel">
  <div class="offcanvas-header">
    <h5 class="offcanvas-title" id="sidebarLabel">Menu</h5>
    <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
  </div>
  <div class="offcanvas-body">
    <a class="d-block mb-2" href="#">Home</a>
    <a class="d-block" href="#">Contact</a>
  </div>
</div>
Live preview

const s = document.getElementById('sidebar');
document.querySelector('[data-bs-toggle="offcanvas"]').click();
await new Promise(r => setTimeout(r, 700));
console.log('open: ' + s.classList.contains('show'));
s.querySelector('.btn-close').click();
await new Promise(r => setTimeout(r, 700));
console.log('open after close: ' + s.classList.contains('show'));
Console output (real Chrome)

open: true
open after close: false

How it works

  • offcanvas-start places the panel on the left side. The toggle button opens it, and the close button closes it.

Read Offcanvas.

Create a button which switches the page to dark mode

Description: A button must switch the page between light and dark mode.

Hint:

  • Change the attribute data-bs-theme of the html element.

Solution

<button type="button" class="btn btn-outline-secondary" id="themeSwitch">Switch theme</button>
<script>
  document.getElementById('themeSwitch').addEventListener('click', function () {
    var root = document.documentElement;
    root.setAttribute('data-bs-theme', root.getAttribute('data-bs-theme') === 'dark' ? 'light' : 'dark');
  });
</script>
Live preview

const bg = () => getComputedStyle(document.body).backgroundColor;
console.log('start: ' + (document.documentElement.getAttribute('data-bs-theme') || 'light') + ' -> ' + bg());
document.getElementById('themeSwitch').click();
console.log('after the 1st click: ' + document.documentElement.getAttribute('data-bs-theme') + ' -> ' + bg());
document.getElementById('themeSwitch').click();
console.log('after the 2nd click: ' + document.documentElement.getAttribute('data-bs-theme') + ' -> ' + bg());
Console output (real Chrome)

start: light -> rgb(255, 255, 255)
after the 1st click: dark -> rgb(33, 37, 41)
after the 2nd click: light -> rgb(255, 255, 255)

How it works

  • Bootstrap colors come from CSS variables, which change when data-bs-theme changes.
  • To remember the choice of the user, also save it in localStorage.

Read Color Modes.