Category Archives: Javascript

Fun with JavaScript Closures + Scoping

It’s easy to forget that variable scoping in JavaScript is at the function level and not a the block level like what you get with C/C++/C#/Java/etc. This can have some counter intuitive implications when you’re dealing with closures. Consider the following example:

var closure;

for(var i = 0; i <= 5; i++) {
  var x = i * i;
  if( i == 1 ) {
    closure = function() { alert(x); };
  }
}

closure();

What do you think the output of the alert box will be? At first blush it's easy to think it will be 1 because the variable x is declared within the for loop.

Run Code

In reality, though, the output is 25 because despite the variable declaration in the for loop, the code is functionally equivalent to this:

var closure;
var x;

for(var i = 0; i <= 5; i++) {
  x = i * i;
  if( i == 1 ) {
    closure = function() { alert(x); };
  }
}

closure();

This is important to remember when working with closures in loops.

So how do solve this problem? Manually create a new scope by creating and invoking an anonymous function.

var closure;

for(var i = 0; i <= 5; i++) {
  var x = i * i;
  if( i == 1 ) {
    (function(x) {
      closure = function() { alert(x); };
    })(x);
  }
}

closure();

Run Code

With the newly introduce lexical scope, the program returns 1 as one would expect.

The speed of jQuery.append(…)

I’ve been doing some JavaScript performance optimization recently and I thought I’d share some of my findings regarding jQuery.

The project I’m working involves creating large DOM trees of elements from data, and I’ve been trying to speed things up. Initially I was using jQuery.append(...) combined with document.createElement(...) in something along these lines:

var foo = $(document.createElement("span")).attr("bar", "baz");
$(parent).append(foo);

The reason for this style is because I want to be able to keep around references to the created object so I can use it later and not be forced to use selectors.

While doing some profiling, I became concerned that the append call was taking too much time, so I did some testing. Some articles I’ve read indicated that it was better to do string concatenation to create a massive strings of the elements that you wanted to create and the use a single jQuery.append(...) call to create the elements at the end. I tested that scenario as well.

My test code:

(function() {
	var start = new Date();
	var root = document.createElement("span");
	for(var i = 0; i < 100000; i++) {
		root.appendChild(document.createElement("span"));
	}
	var end = new Date();
	alert("Raw appendChild: " + (end.valueOf() - start.valueOf()));
})();

(function() {
	var start = new Date();
	var root = $(document.createElement("span"));
	for(var i = 0; i < 100000; i++) {
		root.append(document.createElement("span"));
	}
	var end = new Date();
	alert("jQuery append: " + (end.valueOf() - start.valueOf()));
})();

(function() {
	var start = new Date();
	var root = $(document.createElement("span"));
	var inners = "";
	for(var i = 0; i < 100000; i++) {
		inners += "";
	}
	root.append(inners);
	var end = new Date();
	alert("jQuery from string: " + (end.valueOf() - start.valueOf()));
})();

(function() {
    var start = new Date();
    var root = document.createElement("span");
    var inners = "";
    for(var i = 0; i < 100000; i++) {
        inners += "";
    }
    root.innerHTML = inners;
    var end = new Date();
    alert("innerHTML: " + (end.valueOf() - start.valueOf()));
})();

Run Code

The numbers I get are as follows on my Mac in Firefox are as follows (creating 10k span elements).

Raw appendChild: 304 ms
jQuery append: 5492 ms
Concatenated string (jQuery Append): 6040 ms
Concatenated string (raw innerHTML): 208 ms

My results were somewhat inconsistent. Initially when I was running this test I did see jQuery append with the concatenated string to be faster, but when running tests later, it was a bit slower. In general, I think the conclusion of the article is correct. String concatination is better than many calls to jQuery.append(...), but it doesn’t hold a candle to just doing the raw DOM manipulations. This makes sense since jQuery still has to parse the string you give it (it doesn’t feed it raw into the innerHTML) and then call the raw DOM methods directly. Lesson learned.

Tri-State Checkbox

I’ve created a WAI-ARIA compliant javascript checkbox control (MIT/BSD/GPL licensed).


Demo available here.

Source code is available here.

This continues on my previous post regarding checkbox images, I’ve enhanced the images to include a disabled state for both the mixed and checked states.

checkboxes

jQuery Plugins

Yesterday I spent several hours going through the UI jQuery plugins and compiled a list of the most interesting to me. Bear in mind that in many cases interesting to me is driven by the fact that I work with scheduling software.

  • FullCalendar month-view calendar that supports drag and drop of events (demo)
  • AutoScroll script to automatically scroll an element as you near an edge
  • jCal large, multi-day day picker control
  • jEditable control that allows arbitrary text to edited inline when clicked
  • jGrowl plugin to create a Growl-like effect on a web page
  • Growl another plugin to create a Growl-like effect on a web page
  • DynaTree dynamic tree view (demo)
  • jScrollPane javascript scroll bars (demo)
  • Purr yet another Grow-like effect on a web page. This one has the nicest visual presentation of those listed.(demo)
  • QuickSearch javascript search field that eliminates non-matching elements from a table
  • SemanticTabs jQuery tabs
  • uiTableFilter filters elements of a table based on a search field
  • Throbber jQuery loading circle (demo)
  • TimePicker jQuery timepicker

Labelify for ASP.NET 1.1

If you haven’t tried it already, Labelify is a great jQuery plugin that gives text fields default value labels so that you can either provide hints to your users, or to save space and not have separate labels for each field.

The plugin works by setting the contents of the text field to the title text and setting it to a special style whenever the field holds its default value. As soon as the field receives focus, the default value is removed and the user is free to type whatever they like.

One problem that must be overcome is that the script must remove these title values from the fields before the form gets submitted if the user doesn’t type something else in the fields. If it doesn’t the field submits bogus data, and may also cause the form to not pass validation. The script solves this problem by listening to the submit event on the form, and removing any remaining values that it had placed in the text fields when the page was loaded. The problem is, when a form is submitted via the submit(); method in Javascript, the event does not fire. This can be a big problem in ASP.NET because many of the controls auto-post back, which involves submitting the form via JavaScript.

To correct this problem, you can attach an event handler to a relevant event on the items in the page that could trigger a problematic post-back so that interacting with that item will explicitly trigger the submit event in jQuery. For example, the following code will respond to the click event on all ASP.NET link buttons:

// Hack to allow the ASP.NET link buttons to work with our labelify labels...
$("a[href^=javascript:__doPostBack]").click(function() {
  $(this).parents("form").triggerHandler("submit");
});

As second problem encountered in ASP.NET is that post-backs will cause the page to be re-rendered, sometimes with text pre-populated in the text fields from before the post-back was initiated. This text is considered the default value for these fields, which is a problem because labelify displays the title text whenever the text field’s value matches its default value.

To get around this, I created an updated version of labelify that will allow you to specify that you only want label text to be displayed if the value of the text field is empty, and have it ignore the default value for the field.

To use this updated version, the original Javascript to create the labelified fields would go from this:

$(document).ready(function(){
  $(":text").labelify();
});

to this:

$(document).ready(function(){
  $(":text").labelify({ replaceEmptyOnly: true });
});

jQuery Resources

I’ve been using jQuery a lot for developing some new web interface code for work. This page provides links to a lot of other resources for effectively using jQuery.

Javascript Date Pickers

I’ve been looking for a good date picker for a project I’m working on, so I though I’d post the best results I’ve found so far.

  • UI jQuery Datepicker The standard datepicker available in the jQuery UI library. Pretty nice, though the visuals could use some work. The colors in the default control need some work.
  • http://www.filamentgroup.com/examples/datepicker/ Based on the original codebase for the ui.datepicker jQuery control, this is a very impressive date range picker. Not completely in a reusable form at this point, but good nonetheless.
  • Calendar This datepicker has a great visual appearance. It is build on top of the Mootools libary. This was actually my choice for a straight up datepicker until I realized that using jQuery and Mootools isn’t a walk in the park.