In the previous chapter, we discussed the Carousel Bootstrap plugin. Do you remember the HTML markup to use the plugin? It is a big markup as you can see from the following code:
<div id="carousel-notification" class="carousel slide" data-ride="carousel">
<!-- Wrapper for slides -->
<div class="carousel-inner" role="listbox">
<div class="item active">
<img src="imgs/doge.jpg" width="512">
<div class="carousel-caption">
<h3>Doge said:</h3>
<p>What are you doing? So scare. It's alright now.</p>
</div>
</div>
<div class="item">
<img src="imgs/cat.jpg" width="512">
<div class="carousel-caption">
<h3>Crazy cat said:</h3>
<p>I will never forgive you...</p>
</div>
</div>
<div class="item">
<img src="imgs/laika.jpg" width="512">
<div class="carousel-caption">
<h3>Laika said:</h3>
<p>Hey! How are you?</p>
</div>
</div>
</div>
<!-- Indicators -->
<ol class="carousel-indicators">
<li data-target="#carousel-notification" data-slide-to="0" class="active"></li>
<li data-target="#carousel-notification" data-slide-to="1"></li>
<li data-target="#carousel-notification" data-slide-to="2"></li>
</ol>
<!-- Controls -->
<a class="left carousel-control" href="#carousel-notification" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#carousel-notification" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>There is a reason why the plugin has all these lines of code. With all of that, you are able to customize the plugin for your own use. However, it would be nice if we had a simple carousel with fewer lines of code. Can we do that?
The template that we are trying to create for new plugin will have only the HTML that will reflect the same action as the preceding code:
<div id="carousel-notification" class="bootstrap-carousel"> <img src="imgs/doge.jpg" data-title="doge" data-content="Hey there!"> <img src="imgs/laika.jpg" data-title="laika" data-content="Hey …!"> <img src="imgs/cat.jpg" data-title="cat"> </div>
In the plugin, we will have only one div wrapping up everything. Inside that, we will have a sequence of img elements, each one containing the image source, the title via data-title, and the slide content via data-content.
Building a plugin from scratch is quite difficult, but we will be able to learn the concepts behind Bootstrap and master it when we finish the plugin.
First of all, let's define the directories and files that we are using. For the HTML, we will start a new one that will have the same base template that was used in all the other examples.
Inside the imgs directory, we will keep the pet images that we used in the previous chapter. In this chapter, we will not use any CSS, so do not mind that.
Create a file named bootstrap-carousel.js inside the js folder and import it in the HTML just below the bootstrap.js load (bottom of the page):
<script src="js/jquery-1.11.3.js"></script> <script src="js/bootstrap.js"></script> <script src="js/bootstrap-carousel.js"></script>
Let's create the plugin base. Inside the bootstrap-carousel.js file, add the following lines:
+function ($) {
'use strict';
// BOOTSTRAP CAROUSEL CLASS DEFINITION
// ======================
var BootstrapCarousel = function (element, options) {
this.$element = $(element);
this.options = $.extend({}, BootstrapCarousel.DEFAULTS, options);
}
BootstrapCarousel.VERSION = '1.0.0'
BootstrapCarousel.DEFAULTS = {
};
BootstrapCarousel.prototype = {
};
}(jQuery);Here, we define a new function for jQuery. First, we define a class called BootstrapCarousel that will be our plugin. The function receives the element that will be applied the carousel and options that will be passed through data attributes or JavaScript initialization.
Why the plus symbol in the beginning of the function?
The plus (+) symbol forces to treat it as an expression so that any function after it should be called immediately. Instead of this symbol, we could use others unary operators to have the same effect (such as !, ~, or ()). Without the initial symbol, the function can be seen as the declaration of a function rather than an expression, which can create a syntax error.
The variable options are then extended from the BootstrapCarousel.DEFAULT options. So, if an option is not provided, a default value will be used.
Let's define the VERSION of the plugin, the DEFAULT values, and the prototype that contains all the properties and methods for the class. Inside prototype, we will create the plugin methods and classes, and this is where the core logic will be stored.
Before creating the Bootstrap carousel logic, we must finish some tasks for plugin initialization. After prototype, let's create our plugin initialization:
+function ($) {
'use strict';
// BOOTSTRAP CAROUSEL CLASS DEFINITION
// ======================
var BootstrapCarousel = function (element, options) {
this.$element = $(element);
this.options = $.extend({}, BootstrapCarousel.DEFAULTS, options);
}
BootstrapCarousel.VERSION = '1.0.0'
BootstrapCarousel.DEFAULTS = {
};
BootstrapCarousel.prototype = {
};
// BOOTSTRAP CAROUSEL PLUGIN DEFINITION
// =======================
function Plugin(option) {
var args = arguments;
[].shift.apply(args);
return this.each(function () {
var $this = $(this),
data = $this.data('bootstrap-carousel'),
options = $.extend({}, BootstrapCarousel.DEFAULTS, $this.data(), typeof option == 'object' && option),
value;
if (!data) {
$this.data('bootstrap-carousel', (data = new BootstrapCarousel(this, options)));
}
if (typeof option == 'string') {
if (data[option] instanceof Function) {
value = data[option].apply(data, args);
} else {
value = data.options[option];
}
}
})
}
}(jQuery);The class Plugin will receive the option called and arguments for the element and call it. Do not worry about this part. This is quite a common plugin initialization that is replicated over almost all plugins.
To end the plugin initialization, add the following highlighted code after the Plugin class:
+function ($) {
'use strict';
// BOOTSTRAP CAROUSEL CLASS DEFINITION
// ======================
var BootstrapCarousel = function (element, options) {
this.$element = $(element);
this.options = $.extend({}, BootstrapCarousel.DEFAULTS, options);
}
BootstrapCarousel.VERSION = '1.0.0'
BootstrapCarousel.DEFAULTS = {
};
BootstrapCarousel.prototype = {
};
// BOOTSTRAP CAROUSEL PLUGIN DEFINITION
// =======================
function Plugin(option) {
…. // the plugin definition
}
var old = $.fn.bCarousel;
$.fn.bCarousel = Plugin;
$.fn.bCarousel.Constructor = BootstrapCarousel;
// BOOTSTRAP CAROUSEL NO CONFLICT
// =================
$.fn.bCarousel.noConflict = function () {
$.fn.bCarousel = old;
return this;
}
// BOOTSTRAP CAROUSEL CLASS LOAD
// ==============
$(window).on('load', function () {
$('.bootstrap-carousel').each(function () {
var $carousel = $(this);
Plugin.call($carousel, $carousel.data());
})
})
}(jQuery);First, we associate the plugin with jQuery by in the line $.fn.bCarousel = Plugin;. Then, set that the constructor for the class initialization will be called for $.fn.bCarousel.Constructor = BootstrapCarousel;. Here, we named our plugin bCarousel, so we will can the plugin via JavaScript:
$('some element selected').bCarousel();Then, we add the plugin again for conflict cases where you have more than one plugin with the same name.
In the last part of code, we initialize the plugin via data class. So, for each element identified by the class .bootstrap-carousel, the plugin will be initialized passing the data attributes related to it automatically.