Filtering Tab control with animated indicator
by HugeHugh
HTML
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<ul class="list-unstyled list-inline nav-tab-filter-anim">
<li data-filter="None" class="active">All</li>
<li data-filter="Content">Content</li>
<li data-filter="NewsArticle">News</li>
<li data-filter="Slideshow">Slideshow</li>
<li data-filter="Extension">Extension</li>
</ul>
CSS
ul.nav-tab-filter-anim {
border-bottom: 1px solid #E0E0E0;
margin: 0 0 1px 0;
}
ul.nav-tab-filter-anim > li {
padding: 10px 16px;
cursor: pointer;
color: #8B8E93;
}
ul.nav-tab-filter-anim > li:hover {
background: #fbfbfb;
}
ul.nav-tab-filter-anim > li.active {
padding: 10px 15px;
font-weight: bold;
color: #383D53;
}
.nav-tab-filter-anim-wrapper {
position: relative;
overflow: hidden;
}
.nav-tab-filter-anim-line {
position: absolute;
bottom: 0;
height: 3px;
background: #383D53;
left: -40px;
width: 40px;
transition: left 200ms ease, width 200ms ease;
}
JavaScript
;(function ( $, window, document, undefined ) {
"use strict";
// Create the defaults once
var pluginName = "NavTabFilterAnim",
defaults = {
propertyName: "value"
};
// The actual plugin constructor
function Plugin ( element, options ) {
this.ul = $(element);
// jQuery has an extend method which merges the contents of two or
// more objects, storing the result in the first object. The first object
// is generally empty as we don't want to alter the default options for
// future instances of the plugin
this.settings = $.extend( {}, defaults, options );
this._defaults = defaults;
this._name = pluginName;
this.init();
}
// Avoid Plugin.prototype conflicts
$.extend(Plugin.prototype, {
init: function () {
var self = this;
this.wrapper = this.ul.wrap('<div class="nav-tab-filter-anim-wrapper"/>').parent();
this.slider = $('<div class="nav-tab-filter-anim-line"/>');
this.wrapper.append(this.slider);
$('>li', this.ul).on('click.navtab', function(e) {
e.preventDefault();
var li = $(this);
li.siblings().removeClass('active');
li.addClass('active').trigger('anim.navtab');
}).on('anim.navtab', function() {
var li = $(this);
self.slider.css({
width: li.outerWidth() + 'px',
left: li.position().left + 'px'
});
li.parent().trigger('filter-change', [li.data('filter')]);
}).filter('.active').trigger('anim.navtab');
},
destroy: function() {
$('>li', this.ul).off('click.navtab anim.navtab');
this.slider.remove();
this.ul.unwrap();
}
});
// A really lightweight plugin wrapper around the constructor,
// preventing against multiple instantiations
$.fn[ pluginName ] = function ( options ) {
// get the arguments
var args = $.makeArray(arguments),
after =...