Chapter 8. Working with JavaScript
The whole Internet would not have been the same without JavaScript, and so is Bootstrap. The JavaScript plugins from Bootstrap account for a chunk of Bootstrap's success. By having them, Bootstrap has allowed all of us to use modals, alerts, tooltips, and other plugins out of the box.
Therefore, the main focus of this chapter is to explain the main Bootstrap JavaScript plugins by using them in our web application. In the previous chapters, we used a few plugins. The purpose of this chapter is to go deep into this subject. The key points that we will cover now are:
- General usage of Bootstrap JavaScript plugins
- Data attributes
- Modals
- Tooltips
- Popover
- Affix
Understanding JavaScript plugins
As I said, Bootstrap offers a lot of JavaScript plugins. They all come together when we download the framework, and all of them are ready for use when the bootstrap.js
file is loaded in HTML, although each plugin can be downloaded individually as well from the Bootstrap website.
Tip
Minifying JavaScript
In the production stage, you can use the minified version of Bootstrap JavaScript. We are not using that right now for learning purposes, but it is recommended that you use the minimal version when you go live.
The library dependencies
While we were setting up our development environment, we spoke about the need to import the jQuery library. Actually, jQuery is now the only required external dependency for Bootstrap.
Check out the bower.json
file in the Bootstrap repository for further information about dependencies.
Tip
Bower
Bower is a package management control system for client-side components. To use Bower, you must have both Node and npm installed. Bower was developed by the developers of Twitter.
Data attributes
HTML5 introduced the idea of adding custom attributes to document tags in order to store custom information. Therefore, you can add an attribute to a tag with the data-*
prefix, retrieve the information in JavaScript, and not get started with some plugin in your browser. An overwhelming majority of web browsers do support the use of custom data attributes.
With that ideology, Bootstrap implemented all the plugins to be used with just data attributes. This goes towards the framework idea to increase the speed of development and prototyping. This is because you can make use of plugins without typing JavaScript code.
To control that methodology, Bootstrap implemented an API so that you can access all plugins through only data attributes. Sometimes, however, you may want to turn off access through the API. To do so, insert the following command at the beginning of your JavaScript code:
$(document).off('.data-api');
To disable the API for some specific plugins, prepend the plugin namespace. For instance, to disable the alerts API, type this:
$(document).off('.alert.data-api');
Bootstrap JavaScript events
There is a set of events that Bootstrap produces for each plugin. They are triggered usually before and after the event starts. To exemplify this, let's say that we have a Bootstrap modal (you will learn about using modals in this chapter; don't worry) and we will call it to open by JavaScript:
$('#some-modal').modal();
When this happens, Bootstrap triggers the events called show.bs.modal
and shown.bs.modal
. The first one is called before the open modal call and the other is called after the action. Let's say we want to customize our modal before it is shown. To do this, we must use the first event:
$('#some-modal').on('shown.bs.modal', function(e) { // do some customization before shown });
The events can be used for all plugins. Just change the namespace (in this case, .modal
is the namespace) to achieve the result.
Awesome Bootstrap modals
It's time to learn how to use modals! Modals are really present nowadays in web development and Bootstrap plugins, for that is really complete and easy to use. To use it, let's go back to our main web application page, the one containing the feeds.
First, we add the .hide
helper class to the div.alert
that we created at the #main
column. We will play with alerts later. Now, go to the #tweet
button on the navigation bar. We want to open a modal for tweets when clicking on this button. So, add the markup to the element:
<!-- modal launch button -->
<button id="tweet" class="btn btn-default pull-right visible-xs-block" data-toggle="modal" data-target="#tweet-modal">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
Tweet
</button>
What we did is the call to open a modal, recognized by the #tweet-modal
ID and the data-toggle="modal"
data attribute. We could also have done that via JavaScript with this code:
$('#tweet-modal').modal();
Create the modal by adding the next HTML code. We have created all the modals at the end of our HTML code, outside of all Bootstrap elements and right before the loading of the JavaScript libraries:
<div class="modal fade" id="tweet-modal" tabindex="-1" role="dialog"> <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">×</span> </button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> Modal content </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>
Reload the web application, click on the Tweet button and see the magic happen! This code is a little more complex, so let's explain each part separately. The following screenshot shows what the first draft of our modal looks like. Now let's understand what we did.
Modal general and content
The first tag used to initiate a modal is a <div>
with the .modal
class. Note that we also added the .fade
class to create the effect of fade in and fade out when the modal appears and disappears.
Inside the .modal
element, we created two more nested tags. The first one is .modal-dialog
, which will wrap all of the modal dialog. Inside it, we created .modal-content
, which will hold the content of the modal itself.
The modal header
Next, inside .modal-content
we have the .modal-header
element. In the modal header, we can add some title information about the modal. In our example, we have also added a close button that hides the modal using a data-dismiss="modal"
data attribute.
The modal body
The modal body is where you should place the main content of the modal. A cool feature inside the modal is the ability to use scaffolding.
To use the grid system inside the modal body, you do not need to create a container. Just create a .row
inside .modal-body
and start adding columns, as shown in the following example in bold:
<div class="modal fade" id="tweet-modal" tabindex="-1" role="dialog"> <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">×</span> </button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> <div class="row"> <div class="col-sm-2">Use</div> <div class="col-sm-4">the</div> <div class="col-sm-6">grid system</div> </div> </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>
The modal footer
At the end of the modal, you can create a .modal-footer
element to place some other components, such as buttons, as we did in the previous example.
Modal general and content
The first tag used to initiate a modal is a <div>
with the .modal
class. Note that we also added the .fade
class to create the effect of fade in and fade out when the modal appears and disappears.
Inside the .modal
element, we created two more nested tags. The first one is .modal-dialog
, which will wrap all of the modal dialog. Inside it, we created .modal-content
, which will hold the content of the modal itself.
The modal header
Next, inside .modal-content
we have the .modal-header
element. In the modal header, we can add some title information about the modal. In our example, we have also added a close button that hides the modal using a data-dismiss="modal"
data attribute.
The modal body
The modal body is where you should place the main content of the modal. A cool feature inside the modal is the ability to use scaffolding.
To use the grid system inside the modal body, you do not need to create a container. Just create a .row
inside .modal-body
and start adding columns, as shown in the following example in bold:
<div class="modal fade" id="tweet-modal" tabindex="-1" role="dialog"> <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">×</span> </button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> <div class="row"> <div class="col-sm-2">Use</div> <div class="col-sm-4">the</div> <div class="col-sm-6">grid system</div> </div> </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>
The modal footer
At the end of the modal, you can create a .modal-footer
element to place some other components, such as buttons, as we did in the previous example.
The modal header
Next, inside .modal-content
we have the .modal-header
element. In the modal header, we can add some title information about the modal. In our example, we have also added a close button that hides the modal using a data-dismiss="modal"
data attribute.
The modal body
The modal body is where you should place the main content of the modal. A cool feature inside the modal is the ability to use scaffolding.
To use the grid system inside the modal body, you do not need to create a container. Just create a .row
inside .modal-body
and start adding columns, as shown in the following example in bold:
<div class="modal fade" id="tweet-modal" tabindex="-1" role="dialog"> <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">×</span> </button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> <div class="row"> <div class="col-sm-2">Use</div> <div class="col-sm-4">the</div> <div class="col-sm-6">grid system</div> </div> </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>
The modal footer
At the end of the modal, you can create a .modal-footer
element to place some other components, such as buttons, as we did in the previous example.
The modal body
The modal body is where you should place the main content of the modal. A cool feature inside the modal is the ability to use scaffolding.
To use the grid system inside the modal body, you do not need to create a container. Just create a .row
inside .modal-body
and start adding columns, as shown in the following example in bold:
<div class="modal fade" id="tweet-modal" tabindex="-1" role="dialog"> <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">×</span> </button> <h4 class="modal-title">Modal title</h4> </div> <div class="modal-body"> <div class="row"> <div class="col-sm-2">Use</div> <div class="col-sm-4">the</div> <div class="col-sm-6">grid system</div> </div> </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>
The modal footer
At the end of the modal, you can create a .modal-footer
element to place some other components, such as buttons, as we did in the previous example.
The modal footer
At the end of the modal, you can create a .modal-footer
element to place some other components, such as buttons, as we did in the previous example.
Creating our custom modal
Now that you have learned how to use a Bootstrap modal, let's customize it for our example. First, let's add some content inside our .modal-body
and edit .modal-header
and .modal-footer
a little:
<div class="modal fade" id="tweet-modal" tabindex="-1" role="dialog"> <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">×</span> </button> <h4 class="modal-title">Dog a new tweet</h4> </div> <div class="modal-body"> <textarea class="form-control" rows="4" placeholder="What you want to bark?" maxlength="140"></textarea> </div> <div class="modal-footer"> <span class="char-count pull-left" data-max="140">140</span> <button type="button" class="btn btn-default" data-dismiss="modal"> Close </button> <button type="button" class="btn btn-primary"> Tweet </button> </div> </div> </div> </div>
Here, we added a heading to .modal-header
, a textarea in .modal-body
and a <span>
element with the .char-count
class in the footer.
The goal here is to type a tweet inside the textarea
element and update the character count in the footer to show how many characters are left for the user to enter.
For styling, go to the CSS and add a style rule for .char-count
:
#tweet-modal .char-count { padding: 0.7rem 0; }
Refresh the web browser and see the result of the tweet modal, as shown in the following screenshot. Now, we need to add some JavaScript to count the number of remaining characters to tweet.
So, for the JavaScript for the character count, open (or create it if you do not have it yet) the main.js
file. Ensure that you have the document ready to create the script, by having the following code in your file:
$(document).ready(function() { // add code here });
Then, we must create a function that updates the remaining characters each time a letter is typed. Therefore, let's create an event handler for keyup
.
The keyup
event came from jQuery, which has a lot of event handlers that are triggered on different actions. There are also other events such as click
, hover
, and so on. In this case, keyup
will trigger when you release a key that you pressed.
The basic usage to create a bind event is from a selector, call the .on
function passing at the first argument of the event type (in this case, keyup
), followed by the handler (in our case, a function). Here, we have presented the JavaScript code, and the event handler is in bold so as to highlight the usage:
$(document).ready(function() {
var $charCount, maxCharCount;
$charCount = $('#tweet-modal .char-count')
maxCharCount = parseInt($charCount.data('max'), 10);
$('#tweet-modal textarea').on('keyup', function(e) {
var tweetLength = $(e.currentTarget).val().length;
$charCount.html(maxCharCount - tweetLength);
});
});
Note
We used the keyup
event handler to trigger the event after the key is released and the character is typed. Therefore, the new length of textarea
is already computed when we make a comparison.
A tool for your tip
Tooltips are a very useful component for describing in detail an element or a web page. For example, when you have an image and want to describe it further, you add a tooltip. When users hover over the image, they see further information.
In our case, we will use tooltips for the buttons present in every tweet, such as Reply
, Retweet
, and Start
. This Bootstrap plugin component is pretty simple and useful in many cases. To start it, just add the markup in bold to the tweets in the middle column (<li>
in the ul#feed
element):
<ul id="feed" class="list-unstyled"> <li> <img src="imgs/doge.jpg" class="feed-avatar img-circle"> <div class="feed-post"> <h5>Doge <small>@dogeoficial - 3h</small></h5> <p>You can't hold a dog down without staying down with him!</p> </div> <div class="action-list"> <a href="#" data-toggle="tooltip" data-placement="bottom" title="Reply"> <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> </a> <a href="#" data-toggle="tooltip" data-placement="bottom" title="Retweet"> <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> <span class="retweet-count">6</span> </a> <a href="#" data-toggle="tooltip" data-placement="bottom" title="Start"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> </a> </div> </li> <li> <img src="imgs/laika.jpg" class="feed-avatar img-circle"> <div class="feed-post"> <h5>Laika <small>@spacesog - 4h</small></h5> <p>That's one small step for a dog, one giant leap for giant</p> </div> <div class="action-list"> <a href="#" data-toggle="tooltip" data-placement="bottom" title="Reply"> <span class="glyphicon glyphicon-share-alt" aria-hidden="true"></span> </a> <a href="#" data-toggle="tooltip" data-placement="bottom" title="Retweet"> <span class="glyphicon glyphicon-refresh" aria-hidden="true"></span> <span class="retweet-count">6</span> </a> <a href="#" data-toggle="tooltip" data-placement="bottom" title="Star"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> </a> </div> </li> </ul>
As you can notice, by using data attributes, you just need to add three of them to make a tooltip. The first one is data-toggle
, which says the type of toggle. In our case, it is tooltip
. The data-placement
attribute is concerned with the placement of the tooltip (obviously). In this case, we set it to appear at the bottom, but we can set it to left
, top
, bottom
, right
, or auto
. Finally, we add the title
attribute, which is not a data attribute, because HTML already has the attribute title, so we can call it by this attribute.
Refresh the web app in the browser, hover the icon and you will see that… nothing happens! Unlike the other plugins, the tooltip and popover Bootstrap plugins cannot be activated simply through data attributes. They did this because of some issues, so it must be initialized through a JavaScript command. Therefore, add the following line to the main.js
file:
$(document).ready(function() { ... // to rest of the code $('[data-toggle="tooltip"]').tooltip(); });
The [data-toggle="tooltip"]
selector will retrieve all the tooltip elements and start it. You can also pass some options inside while calling the .tooltip()
start function. The next table shows some main options (to see all of them, refer to the official documentation of Bootstrap) that can be passed through JavaScript or data attributes:
Option |
Type |
Default |
Description |
---|---|---|---|
|
Boolean |
|
This adds fade in and fade out animation to a tooltip. |
|
String or function |
|
This is the placement position of the tooltip. The options are the same as those mentioned for the usage with data attributes ( |
|
String |
|
If you provide a selector, the tooltip will be delegated to the specified target. |
|
String |
|
The trigger to the tooltip will be shown. The options are |
The tooltip plugin also has some useful methods for doing things such as showing all tooltips. You can call them using the .tooltip()
method. As mentioned, if you want to show all tooltips, just use $('.tooltip-selector').tooltip('show')
. The other options are hide
, toggle
, and destroy
.
Pop it all over
In some cases, you may want to show more information that does not fit in a simple tooltip component. For that, Bootstrap has created popovers, which are components that create small overlays of content to show detailed secondary information.
The popover plugin is an extension of the tooltip plugin, so if you are using separate plugins, you must load both to make it work. Also, just like tooltips, popovers cannot be activated simply through data attributes. You must call them via JavaScript to make them work.
Let's use a popover in our web app example, on the right-hand-side column, the one identified by div#who-follow
. We will add the popover to the Follow buttons, and for that, we need to do two things. The first one is to change the <button>
element to an <a>
element and then add the popover markup.
Tip
Why do we need to change buttons to links in popover?
Actually, we don't have to change the buttons' markup; we will do that just because of cross-browser compatibility. There are some browsers that do not support all the functionalities, such as the click Dismiss option present in the popover.
First, about the <buttons>
inside the div#who-follow
element. Change them to <a>
elements in the HTML. Also add the role="button"
and tabindex="-1"
attributes to the links to fix the issue of cross-browser compatibility:
<div id="who-follow" class="card"> <div class="card-header"> Who to follow </div> <div class="card-block"> <ul class="list-unstyled"> <li> <img src="imgs/cat.jpg" class="img-rounded"> <div class="info"> <strong>Crazy cats</strong> <a href="#" role="button" tabindex="-1" class="btn btn-default"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Follow </a> </div> </li> <li> <img src="imgs/ration.jpg" class="img-rounded"> <div class="info"> <strong>Free ration alert</strong> <a href="#" role="button" tabindex="-1" class="btn btn-default"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Follow </a> </div> </li> </ul> </div>
The code in bold refers to the changes from button to link. Now, we must add the popover markup. It is pretty simple and follows most of the data attributes presented in the tooltip plugin:
<div id="who-follow" class="card"> <div class="card-header"> Who to follow </div> <div class="card-block"> <ul class="list-unstyled"> <li> <img src="imgs/cat.jpg" class="img-rounded"> <div class="info"> <strong>Crazy cats</strong> <a href="#" role="button" tabindex="-1" class="btn btn-default" data-toggle="popover" data-trigger="focus" title="You may want to follow"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Follow </a> </div> </li> <li> <img src="imgs/ration.jpg" class="img-rounded"> <div class="info"> <strong>Free ration alert</strong> <a href="#" role="button" tabindex="-1" class="btn btn-default" data-toggle="popover" data-trigger="focus" title="You may want to follow"> <span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Follow </a> </div> </li> </ul> </div>
Just like the popover, add the following line to the JavaScript code to make popovers appear:
$(document).ready(function() { … // the rest of the JavaScript $('[data-toggle="popover"]').popover(); });
Refresh the web browser, click on the Follow button and see the popover appearing to the right of the button. Now we will make some changes using the options to customize it. First of all, let's create the content that will appear inside the popover and change its placement in JavaScript:
$(document).ready(function() { … // rest of the JavaScript var popoverContentTemplate = '' + '<img src="imgs/breed.jpg" class="img-rounded">' + '<div class="info">' + '<strong>Dog Breeds</strong>' + '<a href="#" class="btn btn-default">' + '<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>' + 'Follow' + '</a>' + '</div>'; $('[data-toggle="popover"]').popover({ placement: 'bottom', html: true, content: function() { return popoverContentTemplate; } }); });
In the preceding code, we changed the placement of the popover to bottom
and set the content that will appear inside the popover to be HTML with the html: true
option. The content was provided by a function that simply returned the popoverContentTemplate
variable.
For instance, we could have used the template in very different ways that are more optimized, but we did this to show the method of adding HTML content onto a popover via JavaScript and using a function for that. We could have called and used some options of the target clicked button inside the function by accessing the current scope in the this
variable.
Popover events
Popovers and tooltips provide some nice events. As was said before, Bootstrap triggers some events when plugin elements appear, hide, and are inserted. To play with these, let's use the show.bs.popover
event, which is an event that is fired immediately when the popover
is show
. In this case, we want to create an action before the popover
is show
. We want to change the text of the Follow button that we clicked on to Following, while changing the icon next to the text from a plus sign to an okay sign. We can take advantage of the show.bs.popover
Bootstrap event to make these changes. In the JavaScript file, insert the following delegation to the popovers:
$(document).ready(function() { … // the rest of the JavaScript code $('[data-toggle="popover"]').on('show.bs.popover', function() { var $icon = $(this).find('span.glyphicon'); $icon.removeClass('glyphicon-plus').addClass('glyphicon-ok'); $(this).append('ing'); }); });
The scope of this event is the element of data-toggle
, which is the Follow button. We query the icon inside the button, and change it from glyphicon-plus
to glyphicon-ok
. Finally, we append the infinitive ing
to Follow, which means that we are now following Crazy cats or Free ration alert suggestions:
To add a cherry to the pie, let's change the color of the icon from blue to green when the okay icon appears:
div#who-follow li .info .glyphicon-ok { color: #5cb85c; }
Refresh the web browser and click on the Follow button. You should see something similar to this screenshot:
There are many other places where the Bootstrap events can be used. This is a nice example where we want to change the element that we are interacting with. Keep in mind to change it whenever you need some related interaction.
Popover events
Popovers and tooltips provide some nice events. As was said before, Bootstrap triggers some events when plugin elements appear, hide, and are inserted. To play with these, let's use the show.bs.popover
event, which is an event that is fired immediately when the popover
is show
. In this case, we want to create an action before the popover
is show
. We want to change the text of the Follow button that we clicked on to Following, while changing the icon next to the text from a plus sign to an okay sign. We can take advantage of the show.bs.popover
Bootstrap event to make these changes. In the JavaScript file, insert the following delegation to the popovers:
$(document).ready(function() { … // the rest of the JavaScript code $('[data-toggle="popover"]').on('show.bs.popover', function() { var $icon = $(this).find('span.glyphicon'); $icon.removeClass('glyphicon-plus').addClass('glyphicon-ok'); $(this).append('ing'); }); });
The scope of this event is the element of data-toggle
, which is the Follow button. We query the icon inside the button, and change it from glyphicon-plus
to glyphicon-ok
. Finally, we append the infinitive ing
to Follow, which means that we are now following Crazy cats or Free ration alert suggestions:
To add a cherry to the pie, let's change the color of the icon from blue to green when the okay icon appears:
div#who-follow li .info .glyphicon-ok { color: #5cb85c; }
Refresh the web browser and click on the Follow button. You should see something similar to this screenshot:
There are many other places where the Bootstrap events can be used. This is a nice example where we want to change the element that we are interacting with. Keep in mind to change it whenever you need some related interaction.
Making the menu affix
The affix plugin is present only in version 3 of Bootstrap (it was removed in version 4), and it aims to toggle the position of an element between fixed and relative, emulating the effect of position: sticky
, which is not present in all browsers.
We will apply the sticky effect the left #profile
element although we do not have enough elements to make a scroll on our web page. Therefore, to make it simple, replicate the <li>
in ul#feed
to increase the number of items in the list. Do this three times or more to make a scroll in your web browser.
In div#profile
, add the markup related to affix:
<div id="profile" class="col-md-3 hidden-sm hidden-xs" data-spy="affix" data-offset-top="0">
…
// rest of the profile HTML
</div>
Refresh the web browser. You will see that the affix is not working yet. Since we are making the left column with a fixed position with the affix plugin, it is removing the entire column from the grid, making the columns glitch from left to right.
So, we need a workaround for that. We must create some piece of JavaScript code using the events triggered for the plugin.
Let's use the
affix.bs.affix
event, which is an event fired just before the affixing of the element:
$(document).ready(function() { … // rest of the JavaScript code $('#profile').on('affix.bs.affix', function() { $(this).width($(this).width() - 1); $('#main').addClass('col-md-offset-3'); }).on('affix-top.bs.affix', function() { $(this).css('width', ''); $('#main').removeClass('col-md-offset-3'); }); });
Thus, we have played with some tricks in the preceding JavaScript code.
In the first delegated event, .on('affix.bs.affix', handler)
,when the element switches to position: fixed
, we keep the width of the left column. It would change the width because the .col-md-3
class does not have a fixed width; it uses a percentage width.
We also added the offset to the middle column, corresponding to the detached left column, the .col-md-offset-3
class.
The affix-top.bs.affix
event does the opposite action, firing when the element returns to the original top position and removing the custom width and the offset class in the middle column.
To remove the fixed width and return to the .col-md-3
percentage width, just add the $(this).css('width', '')
line. Also remove the .col-md-offset-3
class from the #main
content.
Refresh the web browser, scroll the page, and see the result, exemplified in the next screenshot. Note that the profile is fixed on the left while the rest of the content scrolls with the page:
Finishing the web app
To finish the web application example, we just need to create another modal when we click on the Messages link at the navigation bar.
To create it, we will use the same methodology used to create the modal for the Tweet button. So, add the data attributes' markups to the Messages link in .nav.navbar-nav
, as follows:
<ul class="nav navbar-nav">
<li class="active">
<a href="#">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Home
</a>
</li>
<li>
<a href="#">
<span class="badge">5</span>
<span class="glyphicon glyphicon-bell" aria-hidden="true"></span>
Notifications
</a>
</li>
<li>
<a href="#" role="button" data-toggle="modal" data-target="#messages-modal">
<span class="glyphicon glyphicon-envelope" aria-hidden="true"></span>
Messages
</a>
</li>
<li class="visible-xs-inline">
<a href="#">
<span class="glyphicon glyphicon-user" aria-hidden="true"></span>
Profile
</a>
</li>
<li class="visible-xs-inline">
<a href="#">
<span class="glyphicon glyphicon-off" aria-hidden="true"></span>
Logout
</a>
</li>
</ul>
The highlighted code says that this link plays the role
button, toggling a modal identified by the #messages-modal
ID. Create the base of this modal at the end of the HTML code, just after #tweet-modal
:
<div id="messages-modal" class="modal fade" tabindex="-1" role="dialog"> <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">×</span> </button> <h4 class="modal-title">Dog messages</h4> <button type="button" class="btn btn-primary btn-message">New message</button> </div> <div class="modal-body"> </div> </div> </div> </div>
We made some changes in comparison to #tweet-modal
. Firstly, we removed .modal-footer
from this modal, since we do not need these options in the modal. Like almost the entire framework, Bootstrap allows us to include or exclude elements as per our wishes.
Secondly, we created a new button, New message, in the header, identified by the .btn-message
class. To present the button correctly, create the following CSS style:
#messages-modal .btn-message { position: absolute; right: 3em; top: 0.75em; }
Now let's create the content inside the modal. We will add a list of messages in the modal. Check out the HTML with the content added:
<div class="modal fade" id="messages-modal" tabindex="-1" role="dialog"> <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">×</span> </button> <h4 class="modal-title">Dog messages</h4> <button type="button" class="btn btn-primary btn-message">New message</button> </div> <div class="modal-body"> <ul class="list-unstyled"> <li> <a href="#"> <img src="imgs/laika.jpg" class="img-circle"> <div class="msg-content"> <h5>Laika <small>@spacesog</small></h5> <p>Hey Jonny, how is down there?</p> </div> </a> </li> <li> <a href="#"> <img src="imgs/doge.jpg" class="img-circle"> <div class="msg-content"> <h5>Doge <small>@dogeoficial </small></h5> <p>Wow! How did I turned in to a meme?</p> </div> </a> </li> <li> <a href="#"> <img src="imgs/cat.jpg" class="img-circle"> <div class="msg-content"> <h5>Cat <small>@crazycat</small></h5> <p>You will never catch me!</p> </div> </a> </li> <li> <a href="#"> <img src="imgs/laika.jpg" class="img-circle"> <div class="msg-content"> <h5>Laika <small>@spacesog</small></h5> <p>I think I saw you in Jupiter! Have you been there recently?</p> </div> </a> </li> </ul> </div> </div> </div> </div>
To finish our job, we just create some style in the CSS in order to display our list correctly:
#messages-modal .modal-body { max-height: 32rem; overflow: auto; } #messages-modal li { padding: 0.75rem; border-bottom: 0.1rem solid #E6E6E6; } #messages-modal li:hover { background-color: #E6E6E6; } #messages-modal li a:hover { text-decoration: none; } #messages-modal li img { max-width: 15%; } #messages-modal .msg-content { display: inline-block; color: #000; } #messages-modal .msg-content h5 { font-size: 1em; font-weight: bold; }
In this CSS, we simply set a maximum height for the modal body, while adding a scroll overflow. For the list and the link, we changed the style for hover and adjusted the font weight, size, and color for display.
Refresh the web browser, click on the Messages link in the navigation bar and see your nice modal, as follows:
Summary
In this chapter, we finished our web application example. The main objective here was to learn about the Bootstrap plugins that we had not described before.
First, you learned about data attributes and how to use them with Bootstrap. After that, we saw both the possible ways to call plugins: via pure JavaScript or just through data attributes APIs.
We started and finished plugins with modals. Modals are one of the main plugins in Bootstrap because they are very versatile and customizable. Thus, they are fit for multiple contexts where you need some interaction with the user but do not want to move to another page.
In the middle of the chapter, we talked about two plugins that are closely related. They are the tooltip and the popover. Both came from the same initial plugin but with different contexts. Tooltips are used for auxiliary content, and popovers are something midway between a modal and a tooltip, so they can display more content compared to tooltips, but not too much intrusive like modals.
Creating a web application that is Twitter-like is an important kind of knowledge, since this can be replicated to different sources. Web applications have revolutionized the Web in different ways, and Bootstrap has taken the lead by helping us create faster and more beautiful web pages.
In the next chapter, we will step into an even more challenging example—we will build a dashboard web application from scratch! Just like the web application presented in this chapter, web dashboards are very popular across the Internet, and building one will place us at the same stratum as some of the best web developers. Ready for the advanced level?