Ajax Bestiary: A Javascript Field Guide
 
Ajax Bestiary: A Javascript Field Guide
 
 

Entries from December 2009

Getting and setting values for jQuery widgets

Posted by Dave Mahon

If you come from an OOP background you’re likely used to defining class variables like this:

class MyClass {
   var internalValue1;
   var internalValue2;
   function constructor() {}
}

The values which are to be stored in your object are simple, straightforward, likely to be typed, and the compiler will detect typos in the variable names. JavaScript, as a loosely types language which treats its objects more like collections than discrete objects, can’t really offer us those protections. Conversely, that also means that we have a great deal of flexibility.

In essence, we can dynamically subclass our objects, which you have to admit is a neat trick.

So, for jQuery.UI widgets, the variables stored within our widget are not defined until we assign them. The act of assignment defines the variable name, which can then be called upon at will.

Assignment is simply:

this._setData(‘variablename’, variablevalue);

Retrieval of this value is similarly straightforward:

this._getData(‘variablename’);

This does mean that the old problem of misnamed variables is alive and well. It also means that you need to be prepared to handle an undefined response to the _getData call.

Constraining a numeric value to a range

Posted by Dave Mahon

Okay, so this doesn’t strictly have anything to do with any JavaScript library, but it’s a handy little snippet of code to keep in your arsenal.

val = Math.max(cMin, Math.min(val, cMax));

In one line of code, we’ve automatically constrained val between cMin and cMax. Note that if cMax and cMin are reversed (cMax is less than cMin) val will immediately be set to cMin (the higher of the values).

We can, of course, rectify this when cMin and cMax are assigned values by calling

cMin = Math.min(cMin, cMax);
cMax = Math.max(cmin, cMax);

Event handling in jQuery widgets

Posted by Dave Mahon

This is simple – provided you understand that the reference the keyword this refers to changes depending on when it is called.

When called during initialization, this refers to the widget you’re initializing. When the event itself is triggered, this refers to the DOM node node and not the widget.

As such, we need to introduce a new variable during initialization which the jQuery.UI library calls self which is, of course, equal to the initialization this, not triggered this. (Those of you familiar with Object Oriented Programming and by-reference calls should have no issue with this concept).

<$.widget("ui.clicker", {
   _init: function() {
      self = this;
      this.element.click(function() {
         self.increment(self);
         self.render();
      });
      this.render();
   },
   increment: function(target) {
      target.value(target.value()-1);
      //The exact handling of target.value will be shown another day
   },
   render: function() {
      this.element.text(this.value());
   },
   value: function(val) {}
});

You’ll note that we have to pass self to the increment method or the widget won’t actually be able to find itself, but the render method, which was called during initialization, is henceforth always able to correctly reference this (the widget)!

Customized context menu handling with jQuery

Posted by Dave Mahon

Can you think of some times you might want to disable the right click context menu? Or better still, insert your own behavior or application specific context menu?

This is a simple and useful trick:

element.bind('contextmenu',function(e){
    //Optional customized handling here
    return false;
});

If you don’t return false, the normal context menu will appear, which could actually be desirable, depending on what exactly you want it to do (say, exiting a field and recording it as dirty).

Helpful error handling in jQuery

Posted by Dave Mahon

If you’re going to build a reusable tool, you’re going to want to be able to detect, handle and report error messages in a nice, clean way. It will make you and any other dev happy.

The cleanest way of handling genuine errors for developers using your tool – namely, invalid input sent to a function in the library – is to log it to the console. Doing so is refreshingly straightforward:

var err = new Error();
err.name = "jQuery.widget.UI.clicker.range()";
err.message = "Both values must be numeric to assign range";
throw(err);

This snippet comes straight from the widget I threw together. I encourage you to make the name as detailed as possible. It will make debugging so much easier. You can even pinpoint the exact point of error if the problem was say, an invalid query syntax. (Handy during the development phase; not so much in a production environment!)