Bootstrap for D3

Complete remplacement of bootstrap.min.js using d3 instead of jQuery.

Based on bootstrap 3.3.7 and build to work with d3 v4.

Support all the so-called data-api.

d3 bootstrap

Overview

This is a reimplementation of the javascript of Bootstrap using d3 instead of jQuery

It support all the data-api that bootstrap use :

  • data-dismiss="alert"
  • data-dismiss="modal"
  • data-toggle="modal"
  • data-toggle="dropdown"
  • data-toggle="tab"
  • data-toggle="pill"
  • data-toggle="collapse"
  • data-toggle="popover"
  • data-toggle="tooltip"
  • data-toggle="button"
  • data-slide="..."
  • data-slide-to="..."
  • data-ride="carousel"
  • data-spy="affix"
  • data-spy="scroll"
  • data-parent="#..."
  • data-target="#..."

There's also availble a small "extra" module that allow to create some bootstrap the "d3 way" and there's a limited support for adminLTE javascript too (only what I needed for my project)

Download

From gitHub

Follow the link, or :

$ git clone https://github.com/sebt3/d3-bootstrap.git

Using composer

$ composer require sebt3/d3-bootstrap:dev-master

Using a cdn

<script src="https://cdn.jsdelivr.net/gh/sebt3/d3-bootstrap@0.5.2/dist/d3-bootstrap-withextra.min.js"></script>

Template

Here is a minimum template:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
    <title>Bootstrap 101 Template</title>

    <!-- Bootstrap -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>
    <h1>Hello, world!</h1>

    <!-- d3 -->
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <!-- d3-bootstrap -->
    <script src="https://cdn.jsdelivr.net/gh/sebt3/d3-bootstrap@0.5.2/dist/d3-bootstrap-withextra.min.js"></script>
  </body>
</html>

Alerts

Bootstrap use Javascript to allow you to close the "dismissible alerts".

The presence of the attribute data-dismiss="alert" select the button that will close the alert on click (it doesnt have to be a button actually)

<div class="alert alert-warning alert-dismissible" role="alert">
  <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
  <strong>Warning!</strong> Better check yourself, you're not looking too good.
</div>

will produce :

Add the classes "in fade" to the alert to add a nice fading effect :

Custom events

All alert events are fired on the alert itself (i.e. at the <div class="alert">)

Event Type Description
close.bs.alert This event fires immediately when the close instance method is called.
closed.bs.alert This event is fired when the alert has been closed (will wait for CSS transitions to complete).
d3.select('.alert.alert-warning.fade').on('closed.bs.alert', function () {
  // do something…
})

Buttons

Bootstrap offer a set of features for buttons.

Modals

Modal are opened using a button (can also be a link as long as the the attributes data-toggle="modal" and data-target="#..." are set)

The attribute data-target="#..." should match the ID of the modal. The modal's code can be placed anywhere as it's hidden by default and fullscreen otherwise.

The modal can be closed by any button (or link) having the attribute data-dismiss="modal".

Add the class "fade" to the modal to add a nice fading effect

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
  Launch demo modal
</button>

<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title" id="myModalLabel">Modal title</h4>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>

Custom events

All modal events are fired at the modal itself (i.e. at the <div class="modal">).

Event Type Description
show.bs.modal This event fires immediately when the "show" event start.
shown.bs.modal This event is fired when the modal has been made visible to the user (will wait for CSS transitions to complete).
hide.bs.modal This event is fired immediately when the hide instance method has been called.
hidden.bs.modal This event is fired when the modal has finished being hidden from the user (will wait for CSS transitions to complete).
d3.select('#myModal').on('hidden.bs.modal', function () {
  // do something...
})

Extra: Creating a modal

Using the extra.js file, you have acces to functions to create modal.

d3.select('#myContainer').call(bs.modal()
	.class('modal-danger')
	.id('deletePackage')
	.title('Delete Package')
	.body(bs.h3('You're about to delete a package'))
	.footer(bs.union()
		.item(bs.p('Warning: this action cannot be undone'))
		.item(bs.button.submit().class('btn-danger').url('/som/url/to/submit'))
	)
);

Check and Radio buttons

Checkbox and radio buttons have to be contained in a class="btn-group" div that also have this attribute set data-toggle="buttons"

<div class="btn-group" data-toggle="buttons">
  <label class="btn btn-primary active">
    <input type="radio" name="options" id="option1" autocomplete="off" checked> Radio 1 (preselected)
  </label>
  <label class="btn btn-primary">
    <input type="radio" name="options" id="option2" autocomplete="off"> Radio 2
  </label>
  <label class="btn btn-primary">
    <input type="radio" name="options" id="option3" autocomplete="off"> Radio 3
  </label>
</div>

Collapses

Collapses are objects that can hide part of their content. It can go from the very simple example bellow to accordions.

The button (or link) that trigger the collapsed content have to be identified by the attribute data-toggle="collapse" and identify the target using data-target="#..." or href="#...".

<a class="btn btn-primary" role="button" data-toggle="collapse" href="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
  Link with href
</a>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
  Button with data-target
</button>
<div class="collapse" id="collapseExample">
  <div class="well">
    ...
  </div>
</div>
...

Custom events

Event Type Description
show.bs.collapse This event fires immediately when the show instance method is called.
shown.bs.collapse This event is fired when a collapse element has been made visible to the user (will wait for CSS transitions to complete).
hide.bs.collapse This event is fired immediately when the hide method has been called.
hidden.bs.collapse This event is fired when a collapse element has been hidden from the user (will wait for CSS transitions to complete).
d3.select('#collapseExample').on('hidden.bs.collapse', function () {
  // do something…
})

Panels

The same strategy can be used on many things. Panels are a good example :
<div class="panel-group">
  <div class="panel panel-default">
    <div class="panel-heading">
      <h4 class="panel-title">
        <a data-toggle="#collapse1" href="#collapse1">
          Collapsed list group
        </a>
      </h4>
    </div>
    <div id="collapse1" class="panel-collapse collapse">
      <ul class="list-group">
        <li class="list-group-item">One</li>
        <li class="list-group-item">Two</li>
        <li class="list-group-item">Three</li>
      </ul>
      <div class="panel-footer">Footer</div>
      </div>
    </div>
  </div>
</div>
  • One
  • Two
  • Three

Accordions

And this is a demo of accordion. If you want to see it's code, go have a look in the bootstrap documentation.

Please note that accordions use an extra tag : data-parent="#..." to identify the accordion as a whole.

HTML stands for HyperText Markup Language. HTML is the main markup language for describing the structure of Web pages. Learn more.

Bootstrap is a powerful front-end framework for faster and easier web development. It is a collection of CSS and HTML conventions. Learn more.

CSS stands for Cascading Style Sheet. CSS allows you to specify various style properties for a given HTML element such as colors, backgrounds, fonts etc. Learn more.

Tabs

Tabs and pills work exactly the same way. Beside the class, you'll need to add the attribute data-toggle="tab" and a way to identify the target tab-content to open using either data-target="#..." or href="#...".

<ul class="nav nav-tabs">
  <li role="presentation" class="active"><a data-toggle="tab" href="#home">Home</a></li>
  <li role="presentation"><a data-toggle="tab" href="#menu1">Menu 1</a></li>
  <li role="presentation"><a data-toggle="tab" href="#menu2">Menu 2</a></li>
</ul>
<div class="tab-content">
  <div id="home" class="tab-pane fade in active">
    <h3>Home</h3>
    <p>Some content.</p>
  </div>
  <div id="menu1" class="tab-pane fade">
    <h3>Menu 1</h3>
    <p>Some content in menu 1.</p>
  </div>
  <div id="menu2" class="tab-pane fade">
    <h3>Menu 2</h3>
    <p>Some content in menu 2.</p>
  </div>
</div>

HOME

Some content.

Custom events

Event Type Description
show.bs.tab This event fires on tab show, but before the new tab has been shown.
shown.bs.tab This event fires on tab show after a tab has been shown.
hide.bs.tab This event fires when a new tab is to be shown (and thus the previous active tab is to be hidden).
hidden.bs.tab This event fires after a new tab is shown (and thus the previous active tab is hidden).
d3.select('a[data-toggle="tab"]').on('shown.bs.tab', function () {
  this // displayed tab
})

Extra: Creating tabs

Using the extra.js file, you have acces to functions to create tabs.

d3.select('#myContainer').call(bs.tabs()
	.tab('Home', bs.mdViewer().src('# Home
Some contents.'))
	.tab('Menu 1', bs.mdViewer().src('# Menu 1
Some content in menu 1.'))
	.tab('Menu 2', bs.mdViewer().src('# Menu 2
Some content in menu 2.'))
);

Tooltips

Bootstrap tooltips overwrite the default browser tooltips.

To activate the bootstrap tooltip on a link (or else), you need to add the attribute data-toggle="tooltip". The attribute title will be used as content (just like with regular tooltips). Optionnaly you can choose the placement using data-placement="left", value supported are : top, bottom, left, right.

<a href="#" data-toggle="tooltip" title="Hooray!" data-placement="left">this link has a tooltip on the left</a>
this link has a tooltip on the left

Custom events

Event Type Description
show.bs.tooltip This event fires immediately when the show instance method is called.
shown.bs.tooltip This event is fired when the tooltip has been made visible to the user (will wait for CSS transitions to complete).
hide.bs.tooltip This event is fired immediately when the hide instance method has been called.
hidden.bs.tooltip This event is fired when the tooltip has finished being hidden from the user (will wait for CSS transitions to complete).
inserted.bs.tooltip This event is fired after the show.bs.tooltip event when the tooltip template has been added to the DOM.
d3.select('a[data-toggle="tooltip"]').on('hidden.bs.tooltip', function () {
  // do something…
})

Popovers

Popovers are a bit like tooltips but are activated on click. Thuss no link will be followed.

You need to add the attribute data-toggle="popover" to activate popovers. It also support the data-placement attribute. Additionnaly to the title, a popover body have to be declared in the attribute data-content="...".

<a href="#" data-toggle="popover" data-placement="right" title="Popover Header" data-content="<a href=/index.html>Some content</a> <b>inside</b> <i>the</i> popover">Toggle popover there -></a>
Toggle popover there ->

Custom events

Event Type Description
show.bs.popover This event fires immediately when the show instance method is called.
shown.bs.popover This event is fired when the popover has been made visible to the user (will wait for CSS transitions to complete).
hide.bs.popover This event is fired immediately when the hide instance method has been called.
hidden.bs.popover This event is fired when the popover has finished being hidden from the user (will wait for CSS transitions to complete).
inserted.bs.popover This event is fired after the show.bs.popover event when the popover template has been added to the DOM.
d3.select('a[data-toggle="popover"]').on('show.bs.popover', function () {
  // do something…
})

Carousels

Carrousel behave just like with regular bootstrap.

Bellow is the example from W3schools

Event Type Description
slide.bs.carousel This event fires immediately when the slide instance method is invoked.
slid.bs.carousel This event is fired when the carousel has completed its slide transition.
d3.select('#myCarousel').on('slide.bs.carousel', function () {
  // do something…
})

Extra: Creating carousels

Using the extra.js file, you have acces to functions to create carousels.

d3.select('#myContainer').call(bs.carousel()
	.pic('/path/to/img1.png', 'Alt for img1')
	.pic('/path/to/img2.png', 'Alt for img2')
	.pic('/path/to/img3.png', 'Alt for img3')
);

Affix

Affix are object that keep on screen. The menu of this page is an affix. But unlike what you can usually do using plain css, affix can be fixed for only a portion of the document.

Affix are activated using the attribute data-spy="affix".

The most top position an affix can have is the position it is given initially. The most bottom allowed position to an affix can also be set using the attribute data-affix-end="#..." to identify a DOM element which position will be used as maximum.

The "affixed" element will be switched between these 3 classes : "affix-top", "affix" and "affix-bottom". Customize accordingly.

These are the elements within this document used for the affix :

<ul id="nav" data-spy="affix">
<!-- Affixed content -->
</ul>
...
<section data-affix-end="#nav">
<!-- item that mark the end of the affix position -->
</section>

Custom events

Bootstrap's affix plugin exposes a few events for hooking into affix functionality.

Event Type Description
affix.bs.affix This event fires immediately before the element has been affixed.
affixed.bs.affix This event is fired after the element has been affixed.
affix-top.bs.affix This event fires immediately before the element has been affixed-top.
affixed-top.bs.affix This event is fired after the element has been affixed-top.
affix-bottom.bs.affix This event fires immediately before the element has been affixed-bottom.
affixed-bottom.bs.affix This event is fired after the element has been affixed-bottom.
d3.select('[data-spy="affix"]').on('affix-top.bs.affix', function () {
  // do something…
})

ScrollSpy

Usually ScrollSpy are put inside an affix. This document is no exeption. A scrollSpy track the scroling position to identify what's on screen and activate (setting class="active") the menu item inside the scrollSpy.

d3-bootstrap add a scrolling effect on click on the nav items(using d3 transition).

Here is what's used within this document :

<body data-spy="scroll" data-target=".scrollspy">
 ...
 <div class="col-md-3 scrollspy">
  <ul id="nav">
   <li><a href="#overview">Overview</a></li>
   <li><a href="#download">Overview</a></li>
   <li><a href="#template">Overview</a></li>
   ...
  </ul>
 </div>
...
 <section id="#overview">
  <h2> Overview</h2>
 ...
 </section>
...
 <section id="#download">
  <h2> Download</h2>
 ...
 </section>
...
 <section id="#template">
  <h2> Template</h2>
 ...
 </section>
 ...

Events

Event Type Description
activate.bs.scrollspy This event fires whenever a new item becomes activated by the scrollspy.
d3.select('.scrollspy a[href="#overview"]').on('activate.bs.scrollspy', function () {
  // do something…
})

Demo of the affix-end ability

A space filler to allow you see the "affix-bottom" position for this document affix.

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu.