Code Review: jQuery Waypoints

2011-06-20 00:00:00 +0100 by Alex R. Young
*Code Review* is a series on DailyJS where I take a look at an open source project to see how it's built. Along the way we'll learn patterns and techniques by JavaScript masters. If you're looking for tips to write better apps, or just want to see how they're structured in established projects, then this is the tutorial series for you.

jQuery plugins are often distributed in a state that could be easily
improved upon. It's common to see them without much in the way of
documentation, licensing, or tests. I've written about jQuery
before on
DailyJS, and I remember being impressed by it. Let's take a look at what
sets this jQuery plugin apart.

About jQuery Waypoints

jQuery Waypoints (GitHub: imakewebthings / jquery-waypoints,
License: MIT and GPL) by Caleb Troughton makes it easy to execute a
function whenever an element is scrolled to. It can be used to create
sticky elements,
infinite scrolling,
or many other novel user interface enhancements.

Even though it's a relatively simple plugin, it has a website,
documentation, examples, a GitHub page, appropriate licensing, and even unit tests!
It's also extremely popular, with 469 watchers on GitHub.


To trigger a function when an element is scrolled to, just use the
waypoint function:

$('.entry').waypoint(function() {
  alert('You have scrolled to an entry.');

There are also global functions, like
\$.waypoints('viewportHeight') and


The project's source is contained in one file,
waypoints.js. The author also distributes a minimised build.

The first thing I noticed about this project was the detailed comments.
Most variables and functions have been documented, which makes it
extremely easy to follow the source (and generate documentation).

A classic anonymous wrapper is used to safely house the plugin, but this
one has parameters:

(function($, wp, wps, window, undefined){
  // Plugin goes here
})(jQuery, 'waypoint', 'waypoints', this);

Even though these variables aren't dynamic, they give the author (or
contributors) some flexibility and makes the code feel a little bit more
succinct. Most of the plugin's "state" variables are kept within this

The methods exposed by the plugin are set in an object called
methods. The appropriate method is delegated at runtime
based on this object when jQuery.fn.waypoint is called:

var methods = {
  init: function(f, options) {
    // ... snip

$.fn[wp] = function(method) {
  if (methods[method]) {
    return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
  // ... snip

This adds jQuery.fn.waypoint and uses apply so
this will be the current jQuery object in
methods. This is a neat little delegation pattern often
used by jQuery plugins.

One reason this pattern has been used is because jQuery's authors
recommend avoiding polluting jQuery's namespace with lots of methods.
Rather than naming methods like this:
jQuery.fn.waypointRemove the following should be used:
jQuery.fn.waypoint('remove'). Options can still be passed,
which is why Array.prototype.slice is used to prepare the
method's arguments.

Further down the file jQMethods is used in a very similar
fashion to set up the \$.waypoints() methods:

$[wps] = function(method) {
  if (jQMethods[method]) {
    return jQMethods[method].apply(this);
  else {
    return jQMethods["aggregate"]();

Finally, default settings are defined and some events are bound to

Code Style

I noticed that Caleb uses \$varName to denote objects that
have been wrapped by jQuery:

var $this = $(this);

This should stop people from accidentally calling jQuery more than once.

I don't think there's any duplication of jQuery's built-in
functionality; he uses \$.error(), \$.grep,
and \$.each. I've seen a few plugins resort to Underscore
for anything relating to iterators.

He also correctly uses =</code> and <code>!, so
I imagine he's a fan of
The Good


The tests are written with Jasmine
and jasmine-jquery, which
means they can be executed in a browser: jQuery Waypoint

They're written in a BDD style:

describe('jQuery Waypoints', function() {
  // ... snip
  it('should create a waypoint', function() {


When writing jQuery plugins it's a good idea to take a look at existing
ones for some guidance. jQuery Waypoints has some tried and tested
patterns that work well. It also includes tests and documentation!