my work, life, and ideas

Posts Tagged ‘html5’

JavaScript MVC Pattern

There are a lot of excellent JavaScript frameworks to choose from that provide some sort of MVC pattern. Of the most popular frameworks under this broad umbrella include Backbone.js, Sencha ExtJS, and SproutCore. All of these frameworks have their strengths, but I really crave simplicity. I really don’t want to have to read about a framework for a couple hours and fiddle with it before I become productive. I really don’t want to scrap all of the “legacy” JavaScript written and attempt to shoehorn the framework into my project. I really don’t need all those super fancy UI widgets. You might be thinking the same thing, but you recognize that the way you’ve been organizing and/or writing JavaScript is flawed. The biggest mistake I see again and again is that the patterns we adhere to when writing in our favorite server side language are thrown to the wind when using JavaScript. Why? Why? Why? I could speculate and throw my theories out there, but none of that really matters. The thing that matters most is that you have recognized that something is wrong and you’d like to correct it.

I’d like to offer up a pattern I follow when writing JavaScript.
Let’s take a look at the JavaScript MVC pattern I follow.

First things first. In your JavaScript directory, create the following folders.

  • controllers
  • models
  • views
  • handlers
  • pages

Handlers? Pages? What? No worries. I will discuss each of these and of course you can fit and mold this pattern to your needs. My examples assume you’re using jQuery, but you could use MooTools, prototype, or none of them.

Models:

As an example lets say you have some data that represents projects. Create a file under your models directory called project.js. I like to do “Object-Oriented” JavaScript so maybe your project.js would look like this.

Project = function(projectId) {
  this.projectId = projectId;
}
 
Project.prototype.find = function(projectId) {
  $.getJSON('projects/' + this.projectId + '.json', function(data) {
    //do whatever with your data
  }
}

I’d also like to point out that I often like to write the JSON or XML I need (when I can) to the page so that I don’t make superfluous network calls. In this example I created a function called find that makes an Ajax call, but it could be just as simple to read JSON from a hidden element with a custom attribute called “data” on it like so.

/*
* Reads JSON from a hidden element on the page with an attribute called 'data'
* Example: <input type="hidden" />
*/
 
Project.prototype.all = function(dataSelector) {
  return $.parseJSON(dataSelector.attr('data'));
}

My philosophy on JavaScript models is to keep them centered on the retrieval of the data they represent. Nothing more, nothing less.

Views:

This is the area where I feel most people go wrong and is generally my biggest gripe. How many times have you cracked open a .js file and found N-instances of the selector flying all over the code. Let me clarify. For example, you have a project carousel widget on your site and the selector has an id, namely projects. So everywhere, you look

 $('#projects').something

is recklessly abundant all throughout the code. Good luck re-factoring or repurposing that, even _with_ tests, especially after a few months.

Now, had you captured all the selectors for your projects view in a file managed under the views directory and properly added a layer of encapsulation. It would have taken you 2 seconds to swap whatever existing selectors there were with a new one or perhaps extended your projects view. Sometimes I like to use a view factory to encapsulate my views. Again, you don’t have to use the factory pattern you could just run the prototype pattern directly. Here is an example:

ProjectViewFactory = (function() {
 
  function BaseProjectView() { this.name ="baseProjectView"; }
  BaseProjectView.prototype.getProjectDataSelector = function() { return $('#projects'); }
 
  function CarouselProjectView() { this.name = "carouselProjectView"; }
  //I hand rolled a simple inheritance mechanism, you can find it under my Github account as inheritance.js
  CarouselProjectView.inheritsFrom(BaseProjectView);
  CarouselProjectView.prototype.getProjectDataSelector = function() { return $('#carouselProjects'); }
  CarouselProjectView.prototype.getNextSelector = function() { return this.getProjectDataSelector.select('.next'); }
  CarouselProjectView.prototype.getPreviousSelector = function() { return this.getProjectDataSelector.select('.previous'); }
 
  return {
    getCarouselProjectView: function() {
      return new CarouselProjectView();
    }
  }
}();

The fundamental concept is to align your view widgets on a page to a file managed under the views directory. Anytime, you use a selector it better be in a file like this. Never leak a selector outside the views directory. It is a very simple and straightforward rule to remember.

Controllers:

I like to keep my controllers slim and trim akin to the principle used very often in the Rails community.
Your controllers should be passed the appropriate views required to activate and listen for the appropriate binding events (ie click, mouseover, etc). The controller should only bind the events and then hand the rest of the actual duties off to what I call a handler (we’ll discuss handlers next). Here is an example:

ProjectsController = (function() {
 
   return {
 
   bindEvents : function(projectsView) {
     var projectModel = new Project();
     var projectHandler = new ProjectHandler(projectsView, projectModel);
 
     projectsView.getNextSelector.click(function() {
       projectHandler.updateToNext();
     });
 
     projects.getPreviousSelector.click(function() {
       projectHandler.updateToPrevious();
     });
    }
  }
})();

Handlers:

I’d like to introduce one more letter in the MVC acronym, “H”. A handler is in charge of the dirty work bound to the event triggered. So you can imagine that with a project carousel with a next and previous button that several different things might happen like an image transition, description, numbering, etc.

ProjectHandler = function(projectView, projectModel) {
  this.projectView = projectView; this.projectModel = projectModel;
}
 
ProjectHandler.prototype.updateToPrevious = function() {
  // fill in the details here
}
ProjectHandler.prototype.updateToNext = function() {
  // fill in the details here
}

Pages:

The last and final piece of the puzzle. So a page may consist of many different things including a project carousel, recommendations, comments, and whatever else you can dream up. Assuming you followed the rules given above that means you’ve developed a projects, recommendations, and comments controller along with their corresponding views, models, and handlers.
So a page might look something like this:

SomeAwesomePage = (function() {
  return {
    bindEvents: function() {
      //initialize the views needed here
      ProjectsController.bindEvents(projectsView);
      RecommendationsController.bindEvents(recommendationsView);
      CommentsController.bindEvents(commentsView);
    }
  }
})();

Following this pattern lends itself to a very flexible and modular design. It is totally agnostic to other frameworks that you might already be using. The beauty part of this approach is that you can take a pure JavaScript approach without the bulkiness or dependency on yet another pre-defined framework and spin it to the needs of your project. I always encourage testing JavaScript. Recently I’ve been pairing this pattern with Jasmine.


Getting Started With Processing.js Tutorial

Processing.jsThis past week I’ve had the opportunity to really dig in and give processing.js a work out. For those not familiar with the technology, processing.js is a JavaScript library based on the Java based processing library available for download at http://dev.processing.org/. Processing.js uses the HTML5 Canvas element to draw shapes and designs while using a similar API to the one defined by the Java library.

I found the barrier to entry was unnecessarily frustrating due to the lack of a _good_ beginners tutorial calling out common pitfalls. But don’t let this sway you, because once you move past this, it is really fun.

Here are the things they don’t tell you about getting started.

    1. You should download the basic examples zip from the their site.
    2. You’ll want to grab the processing.init.js and the processing.js from the zip or tarball to include on your page.
    3. As you begin coding you must tag any processing.js script on your page with
      <script type=“application/processing”>
      //your script here
      </script>
    4. You must have a corresponding
      <canvas width=“200px” height=“200px”></canvas>

      tag after your script in order for it to render the drawing. Make height and width whatever size you’d like.

    5. Another note is that you can have multiple canvases on your page, you’re not limited to one.
    6. The processing.init.js looks for
      <script type=“application/processing”></script>

      tag on your page and performs the processing.js initialization, if you don’t have this included on your page nothing will be drawn.

    7. An alternative to using the processing.init.js and <script type=”application/processing”></script> is to use the datasrc attribute on the canvas tag.
      <canvas datasrc=”your_processing_script.js></canvas>

    These are just some of the things I ran into and I hope this helps anyone trying to get started with processsing.js. Next time I will post something using the processing.js library.