The trouble with new

We have a simple JavaScript class:

function User(firstName, lastName) {
  this.name = firstName + " " + lastName;
}

We create a new User:

var ed = new User("Ed", "Spencer");
alert(ed.name); //alerts 'Ed Spencer'
alert(window.name); //undefined

All is well. Unless we forgot the ‘new':

var ed = User("Ed", "Spencer");
alert(ed.name); //ed is undefined
alert(window.name); //alerts 'Ed Spencer'

Curses! That’s not what we want at all. By omitting the ‘new’ keyword, the JavaScript engine executes our ‘User’ constructor in the current scope, which in this case is the global window object. With the scope (‘this’) set to window, setting ‘this.name’ is now the same as setting ‘window.name’, which is not what we’re trying to do.

Here’s the problem though, omitting the ‘new’ keyword is still perfectly valid syntax. We know at design time if ‘new’ must be used or not, and can use a little trick to make it act as though ‘new’ was indeed used:

function User(firstName, lastName) {
  if (!(this instanceof User)) {
    return new User(firstName, lastName);
  }
  
  this.name = firstName + " " + lastName;
}

Because the ‘new’ keyword sets up a new context, we can just test to see if ‘this’ is now an instance of our class. If it’s not, it means the user has omitted the ‘new’ keyword, so we do it for them. John Resig has an example of this over on his blog.

This is all very well and good, but I don’t think we should use it. The reason is that we’re hiding a pseudo syntax error from the developer, instead of educating them with its correct usage. If we hide this mistake in each class we write, our unknowing developer will remain unknowing, and run into a wall when they repeat their mistake on classes that don’t fix it for them.

Instead, I suggest the following:

function User(firstName, lastName) {
  if (!(this instanceof User)) {
    throw new Error("You must use the 'new' keyword to instantiate a new User");
  }

  this.name = firstName + " " + lastName;
}

The only difference of course is that we’re throwing an Error instead of fixing the developer’s mistake. The benefit is that their syntax won’t actually work unless they write it correctly. This is good because our erstwhile developer is prompted to fix their code and understand why it was wrong. Better informed developers leads to better code.

Well, hopefully.

Read my BDD article in this month’s JS Magazine

I have an article on Behaviour Driven Development for JavaScript in June’s edition of the excellent JavaScript Magazine.

If you haven’t seen or read the magazine before (it’s quite new), it’s well worth the few dollars charged. The magazine format allows for in-depth articles that require more space, time and effort to write than a typical blog post, and which therefore often go unwritten.

The thrust of my article is that too much of our JavaScript goes untested, but that nowadays it’s easy to fix that. I go through an example of a client side shopping cart, using the JSpec BDD library. Even if you don’t buy/read the magazine, I highly recommend checking out JSpec and other libraries like it. As JavaScript powered applications become the norm, BDD will only become more important in ensuring our applications work properly, so now is a good time to start.

Also in this month’s issue is a guide to using the Canvas tag, tips on how to use build scripts to optimise your JavaScript for each environment, AJAX security pointers and a roundup of community news.

‘function’ in JavaScript – operator vs statement

In JavaScript we have at least 4 ways of defining functions:

function myFunction() { alert('hai!'); }
var myFunction = function() { alert('hai!'); }
var myFunction = function myFunctionName() { alert('hai!'); }
var myFunction = new Function("alert('hai!');")

These are not all the same, and the crucial thing here is the word ‘function’ as used in each case. In the first example we’re using the function statement, and in the second and third examples we’re using the function operator. We’ll come back to the fourth example later.

So what’s the difference between the function statement and the function operator? Well first we need to understand a bit about anonymous functions. Most of us are familiar with using anonymous functions as event listeners – something like this:

this.on('render', function() {... do some stuff when 'this' has rendered ...});

In this example we’ve passed in a function without a name as a listener callback. But what do we mean when we say a function does have a name? Do we mean this:

var myFunction = function() {... do some stuff ...};

No we don’t. Assigning a function to a variable does not give it a name. The function assigned to our variable above is still an anonymous function. To give a function a name we need to do something like this:

var myFunction = function myFunctionName() {... do some stuff ...};

Now we have declared a function with the name myFunctionName and assigned it to the variable myFunction. Giving a function a name in this way adds a read-only name property to it:

var myVar = function captainKirk() {... do some stuff ...};

alert(myVar.name); //alerts 'captainKirk'

//we can't update it though
myVar.name = 'williamShatner';
alert(myVar.name); //still 'captainKirk'

Coming back to our very first example, we can see that we’re using a different form here – the function statement:

function myFunction() { alert('hai!'); }

Under the hood, what this is actually doing is something like this:

myFunction = function myFunction() { alert('hai!'); }

The function statement created a named function and assigns it to a variable of the same name. Note that in this case although the function name and the variable name are the same, they don’t have to be:

function myFunction() { alert('hai!'); }
alert(myFunction.name); //alerts 'myFunction'

//assigning this function to another variable preserves the function name
var myVar = myFunction;
alert(myVar.name); //alerts 'myFunction'

Let’s take a look at the last of our four initial examples:

var myFunction = new Function("alert('hai!');")

Functions defined this way are always anonymous, and cannot be given a name. In general you shouldn’t define functions this way, for several reasons:

  • The function body has to be parsed by the JS engine every time it is run, compared to just once for a normal function definition. This is slow
  • Functions defined this way do not inherit the current scope. If you define a function this way the only scope it inherits is the global scope, which means it does not have access to any variables or functions in your current scope chain
  • Defining functions this way requires the body to be entered as a string, which should sicken you enough not to use it.

One last thing to note is that if you use the function operator, it has to be within the context of an expression. For example you can’t do this:

function() {alert('hai!');}

That doesn’t work because it’s not part of an expression – the function isn’t being assigned to anything and you get a syntax error. If you want to run an anonymous function and not assign it to a variable, it can be done like this, which runs the function straight away:

(function() {alert('hai!');})();

For further reading on this check out the Mozilla function reference docs.

Why you should be using History in your ExtJS applications

I’ve been making a few updates to the ExtJS API documents application recently. The actual updates include remembering which tabs you have open and using Ext.History to go between tabs (you can follow the forum post or see a beta version).

That’s not quite ready yet, but what has been made very clear to me is that any ExtJS application with more than one view should be using Ext.History. With History we get urls inside the application itself, we can parse them and dispatch accordingly. For example, I’m using a Rails-like Router, which lets you define an internal url map like this:

map.connect(":controllers/:action/:id");
map.connect(":controllers/:action");

The router knows how to decode urls based on the regular expression-like syntax above, and parse the matches into an object – for example:

#users/new    <= becomes {controller: 'users', action: 'new'}
#users/edit/2 <= becomes {controller: 'users', action: 'edit', id: 2}
#colours      <= becomes {controller: 'colours'}

You can of course define any url matching scheme using the connect() function. I then use a simple Dispatcher, which looks at the decoded parameters. It finds the appropriate controller and calls that action on the controller, passing any other parameters as arguments. For example:

#users/new      <= calls UsersController's "new" action
#colours/edit/2 <= calls ColoursController's "edit" action, with {id: 2} as the argument

And so on. Each controller knows what to do for that action. It’s easy then to say to someone “go to http://myapp.com/admin#users/152/comments” – which will take them straight to the comments that user 152 has written. Compare that with saying: “go to http://myapp.com/admin, then click the List Users tab, then find the user called Joe Bloggs, then double click the bubble icon next to his name”. It’s obvious which approach is better.

You don’t even need to use something as elaborate as a router, just a simple switch statement or some regular expressions would be enough for many applications. Once you’ve got Ext.History setup, you could do something as simple as:

//decodes a url and decides how to dispatch it
dispatch = function(token) {
  switch (token) {
    case "users"    :   displayUsers();   break;
    case "users/new":   displayNewUser(); break;
    case "users/2/edit: editUser(2);      break;
    default:            displayDefault(); break;
  };
};
Ext.History.on('change', dispatch);

//Call dispatch on initial page load as Ext.History's change event is not fired here
Ext.History.init(function() {
  var token = document.location.hash.replace("#", "");
  dispatch(token);
});

Obviously you don’t hard code user IDs like that but it’s easy to see how to roll your own. With just a few lines of code, you’ve decoded a url into a function to call, which can do anything you need it to. All your internal navigation needs to do is call Ext.History.add(“some/new/url”), which will now be picked up by your dispatch code.

It’s important to only route like this for idempotent actions (i.e. actions which display data rather than change it), so that data changing actions are not repeated. This is equivalent to using GET and POST correctly in normal web applications.

When the simplest implementation takes just a few lines of code, what reason could there be not to be using it?

Custom containers with ExtJS

ExtJS has several built-in Container classes – classes which can contain one or more other Ext.Components (such as Grids, Forms, other Panels, etc). The most obvious example of a Container is the Ext.Panel class, along with its subclasses such as Ext.TabPanel, Ext.form.FormPanel and Ext.Window. With each container class you can add a bunch of components, like this:

//a child component to be added to the container below
var myComponent = new Ext.Panel({html: 'component 1'});

//Ext.Panel is a subclass of Ext.Container
var myPanel = new Ext.Panel({
  items: [
    myComponent,
    {html: 'component 2'},
    {html: 'component 3'}
  ]
});

Which will just create a Panel with three other Panels as its child components (‘panel’ is the default xtype, so we don’t have to specify it). More to the point, you can add and remove components from the Container like this:

myPanel.add({html: 'component 4'});
myPanel.remove(myComponent);

As myPanel is an Ext.Container subclass, the methods add() and remove() automatically add or remove child components from within the Container, and take care of any rendering that needs to be performed. Most of the time this is great, but what if you want to write your own custom Container? Say you had a bunch of shortcut links which performed some action in your application, and for styling or other reasons you want to put them into markup like this:

<div class="x-shortcuts-wrapper">
  <div class="x-shortcuts-header"></div>
  <div class="x-shortcuts">
    <!-- child components to go here -->
  </div>
  <div class="x-shortcuts-footer"></div>
  <button class="x-shortcuts-add">Add</button>
</div>

You might write something like this:

Ext.ns('MyApp');
/**
 * @class MyApp.Shortcuts
 * @extends Ext.Container
 * Container for application shortcuts
 */
MyApp.Shortcuts = Ext.extend(Ext.Container, {
  /**
   * Creates the HTML markup for the shortcuts container
   * @param {Ext.Container} ct The container into which this container will be rendered
   */
  onRender: function(ct) {
    this.el = ct.createChild({
      cls: 'x-shortcuts-wrapper',
      children: [
        {cls: 'x-shortcuts-header'},
        {cls: 'x-shortcuts'},
        {cls: 'x-shortcuts-footer'},
        {cls: 'x-shortcuts-add', tag: 'button'}
      ]
    });
    
    MyApp.Shortcuts.superclass.onRender.apply(this, arguments);
    
    this.shortcutsHolder = this.el.child('.x-shortcuts');
  },
  
  //tells the container which element to add child components into
  getLayoutTarget: function() {
    return this.shortcutsHolder;
  }
});

So our onRender method is responsible for creating some markup, which must be assigned to this.el. We’re also calling the onRender() function of the superclass (Ext.Container) to make sure nothing is missed out.

The critical elements here are the getLayoutTarget() function, and the last line on onRender(). Usually when you subclass Ext.Container, the add() and remove() functions add and remove from this.el, which would result in something like this:

<div class="x-shortcuts-wrapper">
  <div class="x-shortcuts-header"></div>
  <div class="x-shortcuts"></div>
  <div class="x-shortcuts-footer"></div>
  <button class="x-shortcuts-add">Add</button>
  <!-- child components will end up here -->
</div>

To prevent this from happening, we obtain a reference to the element we want components to actually be rendered to, and return that with getLayoutTarget(). After that the Container will once again do your bidding.

As of the time of writing getLayoutTarget() is not to be found anywhere in the Ext documentation (version 2.2), so my thanks go to Condor and Animal for answering my question on the ExtJS forum thread.

To round off the example, say your Shortcut class looked something like this:

/**
 * @class MyApp.Shortcut
 * @extends Ext.Component
 * Clickable shortcut class which renders some HTML for a standard application shortcut
 */
MyApp.Shortcut = function(config) {
  var config = config || {};
 
  //apply some defaults
  Ext.applyIf(config, {
    text: 'Shortcut Name',
    icon: 'default_shortcut.gif'
  });
 
  //call the superclass constructor
  MyApp.Shortcut.superclass.constructor.call(this, config);
};
Ext.extend(MyApp.Shortcut, Ext.Component, {
  onRender: function(ct) {
    this.el = ct.createChild({
      cls: 'x-shortcut',
      children: [
        {
          tag: 'img',
          src: this.initialConfig.icon
        },
        {
          tag:  'span',
          html: this.initialConfig.text
        }
      ]
    });
    
    MyApp.Shortcut.superclass.onRender.apply(this, arguments);
  }
});

Ext.reg('shortcut', MyApp.Shortcut);

Then our container would be created like this:

new MyApp.Shortcuts({
  items: [
    new MyApp.Shortcut({text: 'Shortcut 1', icon: 'shatner.gif'}),
    {xtype: 'shortcut', text: 'Shortcut 2', icon: 'nimoy.gif'},
    {xtype: 'shortcut'}
  ]
});

Which would produce HTML like this:

<div class="x-shortcuts-wrapper">
  <div class="x-shortcuts-header"></div>
  <div class="x-shortcuts">
    <div class="x-shortcut">
      <img src="shatner.gif" />
      <span>Shortcut 1</span>
    </div>
    <div class="x-shortcut">
      <img src="nimoy.gif" />
      <span>Shortcut 2</span>
    </div>
    <div class="x-shortcut">
      <img src="default_shortcut.gif" />
      <span>Shortcut Name</span>
    </div>
  </div>
  <div class="x-shortcuts-footer"></div>
  <button class="x-shortcuts-add">Add</button>
</div>

JavaScript bra size calculator

One of the more mesmerizing websites I’ve worked on recently was for a lingerie boutique in the UK. Aside from the unenviable task of having to look at pictures of women in lingerie all day, I was also forced (forced!) to write a bra size calculator.

The theory behind bra size calculation is arcane and somewhat magical. Understanding of it does not come easily to man nor beast, so it is lucky that I, falling cleanly into neither category, have passed through pain and torment to save you the trouble.

Check it out.

Pleasing, no? The code looks like this, and can be found here:

var BraCalculator = {
  
  /**
   * The string to be returned when the result could not be calculated.
   */
  unknownString: "Unknown",
  
  cupSizes: ["A", "B", "C", "D", "DD", "E", "EE", "F", "FF", "G", "GG", "H", "HH", 
             "J", "JJ", "K", "KK", "L", "LL", "M", "MM", "N", "NN"],
  
  /**
   * Returns the correct bra size for given under bust and over bust measurements
   * @param {Number} underBust The measurement taken under the bust (in inches)
   * @param {Number} overBust The measurement taken over the bust (in inches)
   * @return {String} The correct bra size for the given measurements (e.g. 32C, 40DD, etc)
   */
  calculateSize: function(underBust, overBust) {
    var bandSize = this.calculateBandSize(underBust);
    var cupSize  = this.calculateCupSize(bandSize, overBust);
    
    if (bandSize && cupSize) {
      return bandSize + cupSize;
    } else {
      return this.unknownString;
    };
  },
  
  /**
   * Calculates the correct band size for a given under bust measurement
   * @param {Number} underBust The measurement under the bust
   * @return {Number} The correct band size
   */
  calculateBandSize: function(underBust) {
    var underBust = parseInt(underBust, 10);
    return underBust + (underBust % 2) + 2;
  },
  
  /**
   * Calculates the Cup size required given the band size and the over bust measurement
   * @param {Number} bandSize The measured band size (should be an even number)
   * @param {Number} overBust The measurement taken over the bust
   * @return {String} The appropriate alphabetical cup size
   */
  calculateCupSize: function(bandSize, overBust) {
    var bandSize = parseInt(bandSize, 10);
    var overBust = parseInt(overBust, 10);
    var diff     = overBust - bandSize;
    
    var result   = this.cupSizes[diff][/diff];
    
    //return false if we couldn't lookup a cup size
    return result ? result : false;
  }
};

And to apply it to your own pages, use something a bit like this:

jQuery(document).ready(function(){
  //add listeners to band and cup measurement text boxes
  jQuery('#back').keyup(Honeys.updateBraSizeCalculation);
  jQuery('#cup').keyup(Honeys.updateBraSizeCalculation);
});

var Honeys = {
  updateBraSizeCalculation: function() {
    var back = jQuery('#back')[0].value;
    var cup  = jQuery('#cup')[0].value;
    
    if (back.length > 0 && cup.length > 0) {
      jQuery('#fit')[0].value = BraCalculator.calculateSize(back, cup);
    };
  }
};

Now we’re talking UK sizes here, so exercise extreme caution! It should be trivial to adapt to your country with our lovely conversion charts.

Don’t pretend you’re not going to play with it. You know you are. Like, right now.

Useful Rails javascript expansions for EXTJS

If you’re using Edge Rails (or > 2.1, which isn’t out at time of writing), and are using the EXT JS framework anywhere, here are a couple of handy javascript include tag expansions to clean up your views. Just chuck them into any file in your config/initializers directory:

ActionView::Helpers::AssetTagHelper.register_javascript_expansion :ext => ['ext/adapter/ext/ext-base', 'ext/ext-all']

ActionView::Helpers::AssetTagHelper.register_javascript_expansion :ext_grid_filter => ['ext/ux/menu/EditableItem', 'ext/ux/menu/RangeMenu', 'ext/ux/grid/GridFilters', 'ext/ux/grid/filter/Filter', 'ext/ux/grid/filter/StringFilter', 'ext/ux/grid/filter/DateFilter', 'ext/ux/grid/filter/ListFilter', 'ext/ux/grid/filter/NumericFilter', 'ext/ux/grid/filter/BooleanFilter']

The top one includes the relevant EXT base files and the second one includes all the Grid Filters from the excellent Filter Grid plugin (see http://ccinct.com/lab/filter-grid/.

Include them as usual like this:

javascript_include_tag :ext, :ext_grid_filter, :cache => 'ext_javascripts'

Getting EXT PagingToolbars to save state

A problem that has recently had me pulling my hair out is how to save state in an EXT PagingToolbar.

Ext makes it easy to save the state of most of its components – by default it does this by setting a cookie with the relevant configuration info, then just reading it back when you load the component again. I’ve been using it to save the state of a few EXT grids I’ve been using on a recent project, this saves config such as which columns you have visible, which column you’re sorting by, and how the columns are ordered.

That works great, and is trivial to implement – just set your provider (see http://extjs.com/deploy/dev/docs/?class=Ext.state.CookieProvider) and be sure to give your grid an id in its config – this is used as the key in the state provider and needs to be unique for each component.

The problem comes when you’re using a paging toolbar though, as this does not save state, so every time you view the grid you’re back to page 1. You can add state behaviour to the paginator by piggybacking the grid’s state store, here’s how it’s done:

Ext.PagingToolbar.override({
  init : function (grid) {
    this.grid = grid;        
    this.grid.on("beforestatesave", this.saveState, this);    
    Ext.util.Observable.capture(grid.store, this.onStateChange, this);
  },
  saveState : function(grid, state) {
    state.start = grid.store.lastOptions.params.start;
  },
  onStateChange : function(ev, store, records, options) {
    if (ev == "load") {this.grid.saveState(); };
  }
});

Basically we’re intercepting the attached Grid’s saveState() event and appending the current start value as stored in the Grid’s DataStore (e.g. if you’re looking at page 3 with 25 rows per page then start = 50). If you examine the contents of your state provider using Firebug (Ext.state.Manager.getProvider().state, then look for the key that matches the id of your grid), you’ll see that there is now a record for ‘start’, which grabbed the correct value from the Grid’s store.

All you need to do then is retrieve that value from the state provider and load your store accordingly:

store = new Ext.data.Store({... your store config ...});

grid = new Ext.grid.GridPanel({
  id: 'unique_grid_id',
  store: store,
  ... other grid config ...
});

//shorthand way of retrieving state information
var state = Ext.state.Manager.getProvider();

var start = state.get(options.id).start || 0);
store.load({params: {start: start, limit: 25}});

If the start value for this grid has never been set it’ll default to zero – e.g. the first page. Next time you come back to this grid it’ll take you right back to where you were, including all column setup and sorting behaviour you have specified.

Rails asset tag expansions

If you’re using edge rails you may have noticed that you can now define your own JavaScript expansions (if you’re not on edge this will be included in the imminent 2.1 release). The default expansion that comes with rails looks like this:

javascript_include_tag :defaults

Which grabs application.js as well as the prototype/scriptaculous javascripts and includes them all (only do that if you need it all – it adds ~150kb to your page). But say you’ve got a line which looks like this:

javascript_include_tag 'my_js_file', 'another_js_file', 'and_another'

And say you want to include the same set of files on a different page – it turns out Rails makes it really easy to DRY this up. Make a new file in the config/initializers directory (I call my asset_tag_expansions.rb) and add a line like the following (don’t forget to restart your server afterwards):

ActionView::Helpers::AssetTagHelper.register_javascript_expansion :my_js=> ['my_js_file', 'another_js_file', 'and_another']

Now in your views you can simply put:

javascript_include_tag :my_js

You can of course register as many of these as you like, and include as many of your own expansions on the same javascript_include_tag line as you want, e.g.:

javascript_include_tag :my_js, :another_expansion, :and_another

The same applies to stylesheets:

ActionView::Helpers::AssetTagHelper.register_stylesheet_expansion :public_styles=> ['reset', 'layout', 'home']
  stylesheet_link_tag :public_styles

Finally, although you’re getting all that onto one line, each asset file is still being requested separately by your browser, each time making another nasty expensive HTTP request. Rectify that:

stylesheet_link_tag :public_styles, :cache => 'public'
  javascript_include_tag :my_js, :another_expansion, :and_another, :cache => 'public'

This bundles up your three stylesheets and concatenates them into a single file, which is called public.css in this case. In the example above this means two less trips to the server to retrieve the stylesheet files, therefore a faster loading page. This is helpful because it enables you to maintain small, targeted stylesheets in development which makes finding the relevant CSS declarations easier, without the performance hit of all those HTTP requests when in production.

One final option is to use the :all expansion, which just grabs everything in the stylesheets or javascripts directory. Be careful with that though as you’ve got to be sure assets are being loaded in the right order (especially for JavaScript), and that you really need all that asset weight on each page.

Follow

Get every new post delivered to your Inbox.

Join 2,605 other followers

%d bloggers like this: