The Blog

7
Jan

Behold! (JavaScript Views)

Posted by | Development | Leave a reply.

Spaghetti is great. Spaghetti code, not so much. Let's make sure we don't have to untangle our JS code, shall we?

Spaghetti is great. Spaghetti code, not so much.

JavaScript has the propensity to be very untidy – if you let it, it will sprawl all over the place. Hundreds of global variables scattered across dozens of files, messy half-measures towards object-orientation, mixed in seemingly at random with ungrouped functions – anyone who’s had a client bring them a failed project from some other development team knows just how bad it can get.

JavaScript also has the potential to be neat and tidy, and keep private variables and methods truly private – if you know how. Closures and an understanding of prototypical inheritance are the secrets, of course – but these are general purpose tools. For more specific scenarios – say, attaching logic to an existing or dynamically created view – tidy encapsulation is just the beginning of the suite of features we covet.

We’d like to be able to declare and bind to page elements all in one spot, so we never duplicate jQuery selectors unnecessarily, it’s clear what we’ve bound when looking at the view, and we can easily re-use those bindings through a variety of functions. Heck, while we’re at it, we’d like to be able to bind events to these elements using the same mapping we’ve just created (maybe with some nice syntactical sugar to simplify statements), and assign arbitrary functions within our view to handle the events.

All of this should be neatly encapsulated within a JavaScript ‘class’, and instantiable when and where we desire; and as long as we’re dreaming, how about a nice, modular system that keeps private variables and methods from being exposed to other classes, automatically offers us safe, localized references to jQuery, underscore or whatever other libraries we’re using, and offers us the ability to initialize the module under conditions of our choosing.

Pinch yourself, it’s not a dream. After a few projects working with Backbone and Marionette, I was loath to do without those tidy and functional views and all the features above (and more) on future projects, even those that aren’t a good fit for Backbone. Thus, Behold! A view framework was written.

Behold is for those who like the tidy encapsulation and functionality that frameworks like Chaplin and Marionette provide for js views, but don’t need everything that Backbone offers, and can’t justify the extra weight of it.

Sold on the concept already? Go take a look at the Github Repo.

Need more convincing? Carry on, then.

Contents

Why Views

Why Behold

Dependencies

Usage Example

More Details

Why Views

What are js views? In a nutshell, the intent of a js view is to provide a neat encapsulation for all the ui binding, event handling and functionality associated with a given page, or set of pages. Novice JavaScript often involves terrible spaghetti code, spread throuhgout onevent handlers in the html, bunches of script tags littered randomly through the markup, and an ugly mess of global variables and functions sitting in a single master file.

With Views enabled by a library like Behold, you instead have nicely encapsulated modules that don’t leak private variables or declare any new global variables (unless you really want to, or forget to prepend var to your variable declaration, since no framework can save you from sloppy coding).

With Views, all of your ui binding is scoped to a root element, keeping selectors performant; all of your ui binding can be declared in a single object, keeping the bindings easy to find and use throughout the code, reducing wasteful rebinding across functions; all of your event binding can take advantage of existing ui binding, is also declared in a single, easy to find object, and keeps its functions enclosed within the view, eliminating the chance of overriding like named functions by declaring them globally, or conflicting with other libraries you’ve added.

In other words, Views can be the answer to keeping your site’s JavaScript tidy and maintainable, whether you have a few pages that just need some animation added, a js-based browser plugin, or a complex webapp.

Why Behold

If you need:
* routing,
* Collections,
* client-side models of db tables,

you should check out a full MVC framework like Backbone and one of the many frameworks building on it, such as the two mentioned above, or similar frameworks like Angular or Ember.

If, on the other hand, you just need:

  • Modular encapsulation that keeps global objects to a minimum, and keeps private variables really private;
  • Easy, organized declaration of UI elements to bind to, with automatic binding and all the niceties that jQuery has to offer immediately available;
  • Similarly easy and organized event binding, which are automatically bound upon view initialization, can be bound and unbound as a unit, and are compatible with the jQuery style bindings you’re used to (including supporting event namespacing);
  • Clear organization and encapsulation of functions being bound to, or that operate on a given view;
  • and similar helpful functionality (see below for more details)

then Behold is for you.

Dependencies

jQuery, or API-compatible replacement library, such as Zepto.

Underscore – Optional – if not supplied, Behold includes a stripped down, native-reliant re-implementation of some of underscore’s functionality. See below for more details.

Usage Example

In your JavaScript entry point of execution:

var gApp = new Behold.Application();

$(document).ready(function(){
gApp.start(); // Initializes all registered modules
});

Then, in any other JavaScript file included in the page (you can include it before or after your entry point, so long as it will be loaded before whatever criteria you’ve selected for executing start() on your application object):

/**
 * Module constructor functions are passed four arguments by default.
 * self = A reference to the module.
 * app = A reference to the application object that the module has been registered on.
 * $ = A reference to the jQuery library.
 * _ = A reference to the underscore library, or our fill in if underscore is not present and passed in.
 * Additional parameters can be fed into the constructor function by adding them, comma seperated, after the
 * constructor function (see below).
 */
gApp.module("moduleName", function(self, app, $, _){
    // Variables declared with var are private to this closure.
    // Convention is to preface the variable name with an underscore to visually indicate this.
    var _Header = Behold.extend({ // _Header is now a constructor for a new Behold View.
            el:"#header", // Root element
            ui:{ // ui bindings
                // the key 'fbLogin' will automatically be bound to the element with the id #fbHeaderLogin, found
                // somewhere beneath the root element #header
                // Any valid jQuery selector can be used
                fbLogin:"#fbHeaderLogin",
                gpLogin:"#gpHeaderLogin"
            },
            events:{ // event bindings
                // A click event will automatically be bound to the element with the key 'fbLogin' within the ui
                // object, as seen above. When this event fires, the 'onClick' handler within this view will be triggered.
                "click @ui.fbLogin":"onClick"
            },
            /**
             * The initialize function will be called when this view is instantatied, and is the perfect place to put
             * code that should be run at that time, like bindings that can't live in the events object for whatever
             * reason, or function calls to make first-run changes.
             */
            initialize:function(){},
            /**
             * This is the event handler that we bound to in the events object, above. Notice it takes one parameter,
             * event, which is the jQuery Event, as per usual handler behaviour.
             */
            onClick:function(event){}
        }),
        _header; // We declare another local variable for the instantiated view.

    /**
     * Initialize this module. This function will be called automatically by Behold.Application.start().
     * In this example, if we detect that the header element is present, we instantiate the Header view.
     */
    self.initialize = function(){
        if ($("#header").length){
            _header = new _Header({} /* We can pass in options in this object, that will be available via this.options in the view */);
        }
    };
    // Here we could add a comma separated series of variables to pass into the module constructor function, after the
    // functions closing curly bracket, should we wish to.
});

More Details

View, download and/or Fork the code on GitHub.

For a detailed view into the internals of Behold,
head to the doxx pages.


31
Dec

2014 Review: Day 10

Posted by | Development | Leave a reply.

Last day of 2014, last day of our look back at the Art & Logic Developer Blog’s year…

"I Saw the Figure 5 in Gold" by Charles Demuth

“I Saw the Figure 5 in Gold” by Charles Demuth

 

My turn again, in which I think about software development, and how important it is that clients understand its actual nature, and how it differs from other kinds of work…

Continue reading


30
Dec

2014 Review: Day 9

Posted by | Development | Leave a reply.

Taking an opportunity to look back at some of our most-read posts from this year, in case you missed them the first time, as the last few days of the year slip by us…

blogpost_ipython_screenshot3

 

In our penultimate look back at 2014’s developer blog, Fran Bull talks about using interactive widgets inside of IPython notebooks:

Continue reading


29
Dec

2014 Review: Day 8

Posted by | Development | Leave a reply.

Taking an opportunity to look back at some of our most-read posts from this year, in case you missed them the first time, as the last few days of the year slip by us…

William Allen White

William Allen White

My turn! Earlier this year I wrote about a little Twitterbot that I wrote to periodically tweet out snippets of lyrics from songs by the band They Might Be Giants…

Continue reading


26
Dec

2014 Review: Day 7

Posted by | Development | 2 Replies.

As 2014 winds down, we’ll take an opportunity to look back at some of our most-read posts from this year, in case you missed them the first time. 

Via JMack on StackOverflow

Via JMack on StackOverflow

Christopher Keefer is back, showing a useful technique for selectively hiding option values from inside of select controls:

Continue reading


25
Dec

2014 Review: Day 6

Posted by | Development | Leave a reply.

As 2014 winds down, we’ll take an opportunity to look back at some of our most-read posts from this year, in case you missed them the first time. 

Photo by Richard Atkinson, http://www.flickr.com/photos/richardatuct/6719197685/

Photo by Richard Atkinson, http://www.flickr.com/photos/richardatuct/6719197685/

 

Noah Miller gives us a useful list of git commands that are handy to have at your fingertips….if you can remember them:

Continue reading


24
Dec

2014 Review: Day 5

Posted by | Development | Leave a reply.

As 2014 winds down, we’ll take an opportunity to look back at some of our most-read posts from this year, in case you missed them the first time. We’re halfway done! 

CGWinPage

Here on day 5 of our year-end blog review, Christopher Keefer shows us how to create custom information windows for Google Maps:

Continue reading


23
Dec

2014 Review: Day 4

Posted by | Development | Leave a reply.

As 2014 winds down, we’re taking an opportunity to look back at some of our most-read posts from this year, in case you missed them the first time. 

django-logo-negative

Vlad Orlenko wrote a couple of great posts on integrating social logins and posting with web apps written using the Django web app framework:

Continue reading


22
Dec

2014 Review: Day 3

Posted by | Development | Leave a reply.

As 2014 winds down, we’ll take an opportunity to look back at some of our most-read posts from this year, in case you missed them the first time. 

 

4319953731_fa8659d820_b

 

Steve Huey took us on a quick tour of a key/value store for iOS that’s built on top of the ubiquitous Sqlite:

Continue reading


19
Dec

2014 Review: Day 2

Posted by | Development | Leave a reply.

As 2014 winds down, we’ll take an opportunity to look back at some of our most-read posts from this year, in case you missed them the first time. 

photo by Mara 1, https://www.flickr.com/photos/flametree/3644003076

photo by Mara 1, https://www.flickr.com/photos/flametree/3644003076

 

Back in May, Noah Miller took a look at what you need to know about creating plug-ins for the gulp build system:

Continue reading


Art & Logic has been developing software on a work-for-hire basis since 1991. We have worked with over 900 clients in a diverse set of industries, including education, aerospace, music technology, consumer electronics, entertainment, financial services, and many more.


2 North Lake Avenue, Suite 1050
Pasadena, CA 91101
626-427-7184


Contact Us
Copyright 1995–2015 Art & Logic, Inc. All rights reserved. All trademarks associated with the registered trademark "Art & Logic," including but not limited to "ArtLogic" and "artandlogic.com," are owned by Art & Logic, Inc. Terms of Use and Privacy Policy