AlexSexton.com $('human#alex thoughts').filter(':not(.bs)');

8Mar/103

Superclassy Inheritance with Javascript Video

Here is the uncut director's edition of my talk given on February 20th, 2010 concerning Inheritance patterns in Javascript. Please forgive the rambling, and the bit of extra footage on either end of the talk.

Superclassy Inheritance with Javascript - Alex Sexton - NCJS 02/20/10 from yayQuery on Vimeo.

<3z

25Feb/1035

Using Inheritance Patterns to Organize Large jQuery Applications

Last will and testament - lolz
I want to introduce/reinforce a pattern for developing large applications with jQuery. I did not invent any of this, but I find that the resources that describe this technique are few and far-between.- so I'm taking a shot at it.

By and large, when using jQuery, developers seem to forget the paradigms they learned for well structured code in other languages. This is likely due to the fact that jQuery is effectively neutral when it comes to your structural methodology or inheritance patterns, and therefore doesn't push someone in any one direction. Many times in other libraries (See Dojo Declare/Provide/Require, or MooTools Class, etc.), a paradigm is used and exclusively offered, and then code generally ends up more uniform than the oh-so-common-massive-jquery-indented-chains that I'm sure you've seen .

I'm not going to necessarily suggest that you use any single inheritance pattern, as there are many options, and each makes sense for different people and different situations. I do however suggest that you know your options. There are a few good reads on the topic of Inheritance in javascript, and I would strongly suggest people read at least a bit of the following:

Choosing your form of modularity is an important step. If you come from a background of highly-classical inheritance (I learned Java in school, so...I know that world) then perhaps starting with a classical implementation is going to be your best choice. If you are trying to stay slim and do the things a little more in the "JavaScript way" (a term that means essentially nothing), then you might try to use prototypal inheritance. For my examples, any form of inheritance will at least work on most accounts.

I'll jump straight to a code example of this technique in use, and then describe it's setup and structure:


<div id="mySpeaker"></div>

Then we'll run our javascript:

$(function(){
  // Call a custom plugin for your object on a dom element
  $('#mySpeaker').speaker({'name': 'Alex'});

  // Have quick access to the actual speaker object
  var mySpeaker = $('#mySpeaker').data('speaker');

  // The interface of the object that you build can
  // wrap more complex dom manipulations that are
  // separated from actual program logic.
  mySpeaker.speak('I am a speaker.'); // Results in a dom update

  // This shows automatic access to correct element in the dom
});

And the html now looks more like this:

<div id="mySpeaker">
  <h1>Alex</h1>
  <p>I am a speaker.</p>
</div>

The key here is that we didn't have to call something like $elem.append('Alex') nor did we even have to consider what would happen when a speaker object was called with the speak() function. I consider this to be the key to modular development. This level of abstraction helps keep the how and the what separated (or "loosely coupled" - if you like buzzwords). The other thing that was important to note is that after we instantiate the plugin, we have a clear two-way path between our Object and our Dom Element - both have an easy way to immediately access the other. This is important, because we often have different points of entry to jump-start a routine, so being able to access the part that you need quickly and easily is important.

Implementing this technique is pretty simple, and should actually take less brain power to set up than traversing through the dom in your head to figure out a crazy chain.

Let's start with the Speaker object.

/**
 * Object Speaker
 * An object representing a person who speaks.
 */
var Speaker = {
  init: function(options, elem) {
    // Mix in the passed in options with the default options
    this.options = $.extend({},this.options,options);

    // Save the element reference, both as a jQuery
    // reference and a normal reference
    this.elem  = elem;
    this.$elem = $(elem);

    // Build the dom initial structure
    this._build();
  },
  options: {
    name: "No name"
  },
  _build: function(){
    this.$elem.html('<h1>'+this.options.name+'</h1>');
  },
  speak: function(msg){
    // You have direct access to the associated and cached jQuery element
    this.$elem.append('<p>'+msg+'</p>');
  }
};

I use an object literal here which puts me in the Prototypal Inheritance camp, I believe, but this is just an easily digestible pattern.

As you can see, there are easy-to-read, small functions, that have a clear purpose. In our use of this pattern, we call api type methods like speak() but not necessarily an internal method (like _build). You can hide your internal functions either by naming convention (not really hiding them), or by using something like the module pattern. In our simple example, I have just added an underscore to the beginning of the function to indicate that it's private.

Code that is organized like this is much easier to test and to change/read. This also allows you to change the way things function without changing the way that the Object api is used. For instance, we could change the speak method to alert the string instead of append it to the related element. We would have to change the internals of the speak function, but we could keep our call to it the same.

The bridge that we build is probably the most interesting part of this pattern. It's a different approach than many of the popular plugins take (slightly different than jquery ui), but it has a few really great benefits.

The most simple way to do this is by hand:

// Make sure Object.create is available in the browser (for our prototypal inheritance)
// Courtesy of Papa Crockford
if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}
(function($){
  // Start a plugin
  $.fn.speaker = function(options) {
    // Don't act on absent elements -via Paul Irish's advice
    if ( this.length ) {
      return this.each(function(){
        // Create a new speaker object via the Prototypal Object.create
        var mySpeaker = Object.create(Speaker);

        // Run the initialization function of the speaker
        mySpeaker.init(options, this); // `this` refers to the element

        // Save the instance of the speaker object in the element's data store
        $.data(this, 'speaker', mySpeaker);
      };
    }
  };
})(jQuery);

And that's it!

Now you have separated the creation of the plugin from the actual code itself. You are using the plugin to attach objects (with any inheritance patten) to dom elements and visa versa, but the plugin itself is just the connection and initialization code. This means that we could generalize this process further. I first saw this from Scott Gonzalez (of the jQuery UI team) and his code later became the 'widget factory' in jQuery UI. I prefer to not pass strings into my plugins in order to call functions, but it's a valid approach as some people would take issue with having to pull out the object each time they started with a dom element.

Here is some code that might get you started writing/using a 'bridge' function (bridge is what's found now in jQuery UI 1.8) that can help you attach your general code with a given plugin (since writing that same initialization plugin code multiple times would get old and defeat the whole DRY principle that our inheritance model has hopefully provided). This code is mostly courtesy of Scott Gonzalez because I couldn't think of a more stripped down elegant approach to this. I changed it to accept Objects instead of Constructor Functions because that works a little better with my example (prototypal inheritance). I also force it to call my init function in order to save myself an extra call. (This example shows Scott's use of this method along with John Resig's Simple-Inheritance implementation - also very cool.)

$.plugin = function(name, object) {
	$.fn[name] = function(options) {
		var args = Array.prototype.slice.call(arguments, 1);
		return this.each(function() {
			var instance = $.data(this, name);
			if (instance) {
				instance[options].apply(instance, args);
			} else {
				instance = $.data(this, name, Object.create(object).init(options, this));
			}
		});
	};
};

// With the Speaker object, we could essentially do this:
$.plugin('speaker', Speaker);

// At this point we could do the following
$('#myDiv').speaker({name: "Alex"});

That's about all there is to it. I'd encourage you to pick some pattern for your development that isn't just inline chaining of jQuery function calls. This way of breaking up and organizing functionality in your code serves as a quick and easy jumping-off point for testing and modularity. It's much easier to test the individual functions of a modular object than it is to write tests for a single-line chain of jQuery calls.

Also, I do get some feedback along the lines of "well, my code is not a plugin" - "this isn't applicable to my code" - but I usually tend to disagree. The stigma that a jQuery plugin has to be for general consumption is flawed. I encourage you to use the plugin architecture if you are creating functionality based on a dom element selection. For instance, if you are adding an error notification system, it would be very easy to create a notification object that attaches to a div and has the methods required for notification directly attached to it, rather than having a function that merely hides and shows random dom elements.

I am doing a round up of performance on a lot of this inheritance usage and I should get to writing another entry on that soon, but from my early tests, using reasonable inheritance is generally not that expensive. If you are pushing the limits of CPUs and browser rendering, you might have to make some sacrifices, but for the general case, the instantiation hit of inherited objects is probably well worth your while.

I'd love to hear about the way you approach this problem.

31Jan/103

Superclassy Inheritance in JavaScript Developer Day Talk Slides

I thought I would make a quick post for anyone coming here for my slides from Developer-Day here in Austin.

I plan on giving a screencast of sorts a try, and perhaps even breaking up some of the sections into a few blog posts on the subject. Encapsulation, modularity and code reuse is an interesting topic in any language, but especially when it comes to applying those ideas to real life applications and web sites.

The demo pages can be found at A Totally Realistic Demo Page for applying Inheritance in Javascript or whatever.

Thanks to Viget for having me out to speak today, it was a blast.

25Jan/100

Invalid JSON in jQuery 1.4 and beyond

I'm pretty happy about jQuery's move to only supporting valid JSON, as well as it's standardization across browsers to enforce that rule, even if native JSON parsing isn't being used. I think it's silly for people to expect things to work when they are passing invalid data back and forth. Much like no one would dare write invalid xml documents for data transfer, the same should be applied to the JSON data format. Simply put, if you aren't conforming to the JSON Standards as defined on http://json.org/ - then you aren't using JSON. You are just passing Javascript source-code back and forth. I wouldn't suggest it.

Now, I understand there are a variety of libraries and services that currently break the standard. I would strongly suggest you write to them and demand that they follow the spec. Nothing should break for their users, so it's not much too ask. Until then I wrote this little lovely plugin so you could consume criminal data sources until they get their acts together:

jQuery.getInvalidJSON = function(url, data, callback) {
  return jQuery.get(url, data, function(d){
    callback.call(this, (new Function('return ' + d))());
  }, "text");
};

This is just an unsafe eval of Javascript source that is unwisely used as a data exchange format. I don't think it belongs in jQuery, but if you are of the unlucky few that are forced to receive invalid JSON don't let it stop you from upgrading to 1.4.

<3z

8Jan/1021

Don’t let document ready slow you down.

I just wanted to quickly post about a common performance hit that I see in pages (including a bit of my old stuff), especially ones that load data on page load.

A common pattern for application development loads a page template with the application code included and then makes an asynchronous data request to load all the relevant data.

One example might be something like:

<html>
  <head>
    <script type="text/javascript" src="jquery.js" />
    <script type="text/javascript">
      $(document).ready(function(){
        // make an ajax request once the dom is ready
        $.ajax({
          url: 'ajax.php',
            success: function(data) {
              for(var i in data) {
                $('.app-container').append('<div>'+data[i]+'</div>');
              }
            }
        });
      });
  </script>
</head>
<body class="app-container">
  // Perhaps a very large dom - which makes the page load slower
</body>
</html>

The problem with this is that the request for the page content isn't made until the dom is ready, but that request doesn't require the dom at all.

Instead of wrapping the $.ajax() call in a dom ready function, try just wrapping your `success` callback function in one instead. This will allow the request to fire off as soon as possible, but will ensure the handling of the data doesn't happen until your domready event has fired.

<html>
  <head>
    <script type="text/javascript" src="jquery.js" />
    <script type="text/javascript">
      // make an ajax request right away
      $.ajax({
        url: 'ajax.php',
          success: function(data) {
            $(document).ready(function(){  //<-- Hey Guys check this out!
              for(var i in data) {
                $('.app-container').append('<div>'+data[i]+'</div>');
              };
            });
          }
        });
  </script>
</head>
<body class="app-container">
  // Perhaps a very large dom - which makes the page load slower
</body>
</html>

This should speed up the load time of your page. From my testing, there doesn't seem to be any issues with this, so I believe it's safe to use. The function will fire immediately if your domready event has already fired, and it will wait to fire if the dom isn't ready yet. You can have as many document ready calls as you want on your page without overwriting old ones, so don't worry about only defining it in one place. I would also imagine that you wouldn't need too many more than two or three if you structured your code in an intelligent way.

---

As a footnote, this is only one of many things you can do outside of dom ready to help speed up the execution of your code. If you are binding events with 'live' or if you are just defining functions, I'd suggest that you do it inside of a closure instead of inside of a dom ready function. Then put just the stuff you need to run with the dom into the dom ready function.

The reason for this is essentially the same as before. You can allocate all the function definitions and variables while the page is building, rather than afterwards. Anything that you can do asynchronously right away is going to generally be better than waiting until the document is ready. There are a few ways to make this a little better organized, but organization isn't the topic, so here is a simple example of code you might write with minimal code execution in the dom ready function. The closure that I have surrounding the entire block of code serves to make the variables have a similar scope affect as it would inside of a document ready function, though it's not absolutely necessary.

(function($){  //<-- use a closure to protect your namespace and your `$`
  // This runs immediately
  $('a').live('click', function(e){
    alert('OKBYE!');
    return true;
  });

 // define functions outside of the dom ready
 function doSomething(input) {
    $('div.something').do(input);
    // you can even use functions that require the
    // dom inside of a defined function as long
    // as you don't call it until the dom is ready
    $('div.somethingelse').click(function(){
      console.log("I don't need no dom ready");
     });
  }

  // dom ready
  $(document).ready(function(){
    // Do stuff that requires the dom, and
    // use your functions from outside
    $('a.special').click(function(e){
      doSomething('special');
    });
    // yay!
  });
})(jQuery);

It's nothing revolutionary, but I figured I'd get it out there!

6Nov/090

yayQuery Podcast 1.0

A few of the ladies and fellas from the #jquery IRC (Adam J. Sontag, Paul Irish, & Rebecca Murphey) and I decided to make a podcast on the topic of jQuery. We landed on the name yayQuery!

From Paul's blog post:

---------

We talk about...

  • Underscore.js - a great utility belt (very handy for Ruby/Python folks), comes with John Resig's microtemplating script and lots more
  • Thickbox - Rest in peace. Also alternatives: Colorbox, jQuery UI Dialog
  • jQuery on mobile. Phonegap, XUI, jQTouch, going it alone
  • Anti-Pattern of the week: css(key,val)
  • $var and Hungarian notation
  • ... and dancing

If you'd like a download:
mp3 audio (30mb), mp4 video (94mb), ogg video (61mb)

---------

I'd love to get your feedback on what you liked or didn't like. If people seem to enjoy it, we'd love to step up the production just a bit, but it doesn't really make sense quite yet.

You can also follow us on twitter (@yayQuery)  if you want updates for the next episodes and such. Yay!