I was recently working on a web app with a very, very clever Rails developer who needed to add a a series of hierarchically nested lists (a ‘tree view’), the deepest level of which contained checkboxes to control the data displayed on a graph. Like most good Rails devs, he thought “I bet there’s a Gem for this,” and 2 minutes later, a monstrosity of third-party scripts and awkward icons were cluttering up our young app.
As it turns out, the functionality he wanted could be added with 6 lines of jQuery (5 lines with CoffeeScript):
$(".collapse-tree a").click(function() {
var listItem = $(this).parent("li");
listItem.children("ul").slideToggle();
$(this).toggleClass("open");
return false;
});
While jQuery’s extensibility is one of its greatest strengths, and the many brilliant plugins available often solve a lot of problems and open up a world of options to the novice developer, if you’re an experienced front-end or back-end developer looking to hack together an interface, plugins are not for you.
jQuery plugins for common interface elements like slideshows, dropdown menus, tabs, and the like are a fantastic resource for beginners and hobbyists trying to add functionality to their websites, but if you think of yourself as a developer, you’re better than that. jQuery plugins try to be all things to all people, but if you just need a simple tabbed content box, you’re going to be loading in a lot of code that you’ll never even use.
If you have a basic understanding of JavaScript DOM manipulation, you can easily roll your own re-usable solution with only a short time investment. The benefits of writing your own jQuery modules are extensive: you’ll save thousands of lines of code, avoid version compatibilty issues, and dramatically speed up debugging through your familiarity with the code. Write your code flexibly and modularly, save it as a Gist and next time you need it, you’ll spend even less time than you would have including and referencing a plugin.
Some Common Examples
I keep a library of GitHub Gists that includes snippets of copy-and-pastable jQuery interactivity modules, and using the Sublime Text Gist Package, I include them wherever I need them and often share them with coworkers and fellow developers. You’ll notice that none of these snippets contain any exceptionally clever customization options or fancy CSS. They’re meant as a baseline to give you the interactivity you need without adding any styling or behaviour you don’t.
Rather than thinking of these snippets as ‘plugins’, I think of them more as ‘modules’, and try to keep them in my modules.scss and modules.js files for easy debugging and reference.
Tabs
Just a simple unordered list with same-page links to the associated divs. Just match the IDs to the hrefs and you’re good to go.
<ul class="tabs">
<li><a href="#tab1" class="active">Tab 1</a></li>
<li><a href="#tab2">Tab 2</a></li>
</ul>
<div class="tab active" id="tab1">
<!-- tab 1 content -->
</div>
<div class="tab" id="tab2">
<!-- tab 1 content -->
</div>function tabs(container){
$(container).find(".tabs").on("click", "li > a", function(e){
e.preventDefault();
$(".tab").removeClass("active");
$(".tabs").find("a").removeClass("active");
var targetTab = $(this).attr("href");
$(targetTab).addClass("active");
$(this).addClass("active")
});
}$(function() {
tabs("body");
});.tabs {
overflow: hidden;
&>li {
display: inline-block;
vertical-align: top;
&>a {
display: inline-block;
text-decoration: none;
color: #272727;
padding: 10px 15px;
margin-right: 5px;
border-radius: 5px 5px 0 0;
background: #fff;
position: relative;
z-index: 10;
&.active {
background: #f1f1f1;
}
}
}
}
.tab {
display: none;
margin-top: -1px;
position: relative;
z-index: 5;
&.active {
display: block;
}
}
Vertical Accordion
This one is pretty much exactly the same as the tabs, using the href attribute of a link to target an element.
.accordion-toggle {
display: block;
}<div class="accordion">
<a href="#panel1" class="accordion-toggle">Panel 1</a>
<div class="accordion-content" id="panel1">Panel 1 Content</div>
<a href="#panel2" class="accordion-toggle">Panel 2</a>
<div class="accordion-content" id="panel2">Panel 2 Content</div>
<a href="#panel3" class="accordion-toggle">Panel 3</a>
<div class="accordion-content" id="panel3">Panel 3 Content</div>
</div>function accordion(){
var toggle = $(".accordion-toggle");
var content = $(".accordion-content");
content.hide();
content.first().show();
toggle.on("click", function(e){
e.preventDefault();
var targetContent = $(this).attr("href");
content.slideUp();
$(targetContent).slideDown();
});
}accordion();Multi-Level Navigation
Supports up to 2 levels of nested unordered lists, sub-navigation appears on hover, but could easily be altered to work on click with some javascript.<nav class="multi-level-nav">
<ul>
<li>
<a href="#">Pants</a>
<ul>
<li><a href="#">Mens</a></li>
<li><a href="#">Womens</a></li>
</ul>
</li>
<li>
<a href="#">Shirts</a>
<ul>
<li><a href="#">Mens</a></li>
<li>
<a href="#">Womens</a>
<ul>
<li><a href="#">Blouses</a></li>
<li><a href="#">T-shirts</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#">Dresses</a></li>
<li><a href="#">Sweaters</a></li>
<li><a href="#">Socks</a></li>
</ul>
</nav>.multi-level-nav {
ul {
list-style: none;
padding-left: 0;
& > li {
display: inline-block;
}
ul {
position: absolute;
left: -9999px;
z-index: 15;
}
}
li {
position: relative;
}
&>ul > li:hover {
& > ul {
left: 0;
}
}
li li:hover {
ul {
left: 100%;
top: 0;
}
}
}
Dropdowns
Just a simple show/hide element attached to a click event. Click the trigger to show the dropdown, then click off the dropdown to hide it.<div class="dropdown">
<a href="#" class="dropdown-trigger">Trigger Dropdown</a>
<ul class="dropdown-content">
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>;
</ul>
</div>function dropdowns(){
$(".dropdown-trigger").click(function() {
$(this).next(".dropdown-content").toggleClass("show");
return false;
});$("html").click(function() {
$(".dropdown-content").removeClass("show");
});$(".dropdown, .dropdown-trigger, .dropdown-content").click(function(event) {
return event.stopPropagation();
});
}dropdowns();function dropdowns(){
$(".dropdown-trigger").click(function() {
$(this).next(".dropdown-content").toggleClass("show");
return false;
});$("html").click(function() {
$(".dropdown-content").removeClass("show");
});$(".dropdown, .dropdown-trigger, .dropdown-content").click(function(event) {
return event.stopPropagation();
});
}dropdowns();Work Smart Not HardThere are many situations in which a jQuery plugin can save you a lot of time dealing with cross-browser compatibilty issues or responsive design, and help keep you under budget when you're facing time pressure. For many complex interactions and features, using a plugin is often the most sensible choice. However, if you're looking to add some basic interactivity to your project, it doesn't hurt to ask yourself a couple questions before dropping in that popular new plugin: could I code this myself in the next 20 minutes? How much of the code in this plugin will I actually be using? How many lines of CSS will I have to override to make this fit into my design?If you've got some handy little scripts of your own you'd like to share, link them up in the comments and I'll add them to the list!