Yelotofu

Yelotofu ~ “In building standards compliant sites we are creating a better Web for the future.”

jQuery.com website redesign

The long overdue redesign of jQuery.com has finally landed! I like the new design as it's more intuitive and inline with jQuery UI's design. This redesign will certainly help pitch jQuery to new comers; for many the decision to go with another framework has purely been based on the ugliness of the old jQuery website, that should hopefully change now.

Old:
old jQuery.com design

New:
new jQuery.com design

However, I still see much room for improvement. The website clearly lacks that magical touch you could easily achieve with a sprinkle of FX and UI. The fade-in boxes on the homepage don't work for me and display erratically when you mouse over them quickly. Hopefully the jQuery team will change this soon.

That said, hats off to the team as they have done an excellent job, as always, in giving us this redesign and of course — jQuery. Thanks!

jQuery: Shuffle Plugin

I recently came across a really compact array shuffling function on JSFromHell.com, which I thought would make a nifty jQuery plugin.

This jQuery shuffle plugin could be applied to any HTML element or Array object.

 
(function($){
  $.fn.shuffle = function() {
    return this.each(function(){
      var items = $(this).children();
      return (items.length)
        ? $(this).html($.shuffle(items))
        : this;
    });
  }
 
  $.shuffle = function(arr) {
    for(
      var j, x, i = arr.length; i;
      j = parseInt(Math.random() * i),
      x = arr[--i], arr[i] = arr[j], arr[j] = x
    );
    return arr;
  }
})(jQuery);
 

Due to line wrapping issues in this post I inserted a few hard carriage returns in the above snippet (sorry).

Example 1: shuffle an unordered list

 
$('ul').shuffle();
 

Example 2: shuffle an array

 
var arr = [1,2,3,4,5,6];
arr = $.shuffle(arr);
 

There is a demo here. And for those interested I encourage you to download the plugin for closer inspection.

JavaScript: Event Delegation

Recently, I've been hearing much about event delegation. Many new to this concept seem to be baffled by the term. However, it really is a simple idea when you realise what's involved.

Put simply, event delegation is the practice of directing events on parent DOM elements who then listen on their children for events.

To understand event delegation and why it works you should read this ppk article before continuing — JavaScript Event Order.

Back? OK, so now you know about event capturing and bubbling the concept is easier to comprehend.

Event delegation takes advantage of the fact that actions performed on a child element always bubbles up to the top. Traditionally events are handled on the element that fired it, for example (excuse my jQuery) :

$('button').click(function(e) {
  alert('You clicked on me?');
});

Now rather than handling the click event shown above on the element itself we could delegate it to a parent because we know all events eventually bubble to the top, so

$('html').click(function(e) {
  if ( $(e.target).is('button') )
    alert('You clicked on me?');
});

produces the same result as the first code snippet.

Did you notice e.target? This is the essence of event delegation. As the event bubbles it keeps a mental note of its starting position in its pocket; e.target is a reference to the first element the event started bubbling from. In the above code sample that would be button.

That's event delegation in a nutshell!

Now, you might be asking - why should I use this rather than traditional one-to-one event handling?

Here are a few reasons:

  • In event delegation you bind one event handler to handle events on multiple elements. In traditional event handling you have to create a thousand event handlers to handle a thousand events. As you would expect event delegation is less resource expensive and could result in quicker response times
  • If Ajax or DOM manipulation happens, re-binding event handlers usually follow. Event delegation avoids re-binding by listening to a parent you know won't be manipulated, i.e. html, body or the website container.
  • Event delegation makes for cleaner code if you have a large webapp demanding lots of event handling.
  • No need to worry about event order and bubbling issues as we're now taking advantage of this effect

In conclusion. Event delegation is not a replacement for Event handling - both have their uses depending on situation. Event delegation requires more planning and could be harder to debug due to the inherent abstractions. You just can't beat the humble event handler if all you want is a link opening in a new browser window. That said, you'd be mad not to use it if you have a complex app with thousands of event objects doing various operations from submitting a form to loading Ajax content.

Further reading:

jQuery UI Spinner

After contributing jQuery Numeric Stepper to the jQuery UI community. Paul Bakaus kindly asked whether I'd like to merge it with the official jQuery UI Spinner, of which I was more than happy to do out of pure love for jQuery.

The jQuery UI Spinner widget will be available with the soon to be released jQuery UI v1.6.

Here's a demo of the current incarnation.

Also, check out Subversion if you're interested in getting the latest and greatest.

jQuery Numeric Stepper

As an experiement I ported over my Accessible Numeric Stepper into a jQuery widget and added some accessibility enhancements and new features in the process.

This widget utilises ui.core.js - a factory method object for creating widget classes. Widgets in jQuery are essentially plugins at heart but built to follow stricter coding standards in order to unify the underlying quality between developers. It also adds convenient mouse interaction classes and option settings among other things.

The result is jQuery Numeric Stepper an unofficial jQuery UI widget. Features include:

  • min, max, start and step size settings
  • supports decimal values and decimal step sizes
  • supports currency values
  • keyboard and mousewheel interaction - increment/decrement values via cursor keys, +/- keys and mousewheel

Download latest source code here

Bugs? Missing feature? Code improvements? Let me know!

Update: Features seen here are now part of the official jQuery UI Spinner, set for the 1.6 release of jQuery UI. More details.

Loving jQuery

In recent weeks I have come to love jQuery. jQuery is this lightweight, elegant and so-much-fun-to-code-with JavaScript library. You may already have it in your source code if you're using either the latest version of WordPress or Drupal.

jQuery is so easy to get to grips with, the documentation is simple to follow and complete with loads of code samples.

jQuery's elegance comes in the form of its ability to select DOM nodes through CSS-like syntax (i.e., CSS queries) in a compact way—brilliant for those who are already very familiar with CSS!

Most or even all actions start with a CSS query, which in a sense promotes the use of unobtrusive JavaScript as it's simply easier to use the $() syntax than add a function directly into HTML.

jQuery is also very much down to earth in a practical way providing a few neat toggle functions:

  • toggle — show/hide selected elements
  • slideToggle — show/hide selected elements with slide Up/Down effects
  • toggleClass — add/remove a class from selected elements

There are also some handy plugins such as the Flash plugin and the ifixpng plugin, which fixes PNG transparency for img elements and CSS backgrounds in IE.5 and IE6.

If something isn't built-in, extending jQuery is ridiculously easy via custom plugins. Here's one way you could define a custom plugin:

 
jQuery.fn.myPlugin = function() {
    // Your plugin code goes in here
}

To take advantage of jQuery's chainability you need only add a single line returning the current context object—this:

 
jQuery.fn.myPlugin = function() {
    // Your plugin code goes in here
    return this;
}

To demonstrate how easy jQuery is to extend I created a simple one line plugin to toggle fadeIn and fadeOut effects, see below.

jQuery fadeToggle plugin:

jQuery.fn.fadeToggle = function(s, fn){
    return (this.is(":visible"))
        ? this.fadeOut(s, fn)
        : this.fadeIn(s, fn);
};

Example usage:

jQuery(function($){
    $(".toggler").click(function(){
        $(".content").fadeToggle();
    });
});

A demo of jQuery fadeToggle plugin in action

High Performance Ajax Applications

Julien Lecomte, author of the YUI Compressor gave a talk on High Performance Ajax Applications. He refers to some of the tricks we learnt from Steve Souders' research on the 14 rules for faster-loading web sites but also gives us more insight specifically on fine tuning JavaScript to perform up a gear. I hope you learn a few neat tricks from this video, I know I did. :)

[source: YUIBlog]

Unobtrusive, Accessible and Standards Compliant Numeric Stepper (revisited)

July last year I wrote a small tutorial on how to build an Unobrustive, Accessible and Standards Compliant Numeric Stepper. As of today it remains the most high traffic page on my site. I can see there is interest out there in a HTML and JavaScript based Numeric Stepper since the most searched for terms are:

  1. javascript numeric stepper
  2. html numeric stepper
  3. numericstepper javascript

So with some downtime on my hands I did some code refactoring and added a few Accessibility improvements: Now, when the Textbox has focus pressing the up or down arrow cursor keys will increment or decrement the numeric value respectively. Also with the cursor keys you can now navigate between the Textbox and plus and minus buttons without resorting to the Mouse pointer.

Test the new cursor key feature with this example

As an aside, the Dojo Toolkit has a Numeric Stepper as part of Dijit, the Dojo Widgit Library. They call it a NumericSpinner. It's pretty powerful though looks bad with CSS switched off. Additionally, the Dojo Toolkit tends to add proprietary attributes to your HTML, hence breaking validation.

Get latest version (NumericStepper v0.1.2)

Building an Unobtrusive, Accessible and Standards Compliant Numeric Stepper

First off, if you're looking for a quick solution feel free to skip directly to the download link at the end of this article. For those who are interested in the intricate details please read on...

What is a Numeric Stepper?

Well, the answer is simple. It's a form control and looks like this...

A Numeric Stepper

It has an intuitive look that does not require much brain power to figure out how to use. The name itself suggests it's restricted to numeric values. The plus and minus signs indicate an ability to step up or down. The steps must be of equal size maintaining consistency. The great thing about Numeric Steppers is users can either enter a value or use the plus and minus buttons to arrive at a target value.

Flash UI developers have long since enjoyed this form control. In fact, it wasn't until Flash came out with their UI components before I even heard of a Numeric Stepper!

What is it used for?

Numeric Steppers are not always useful. They are designed to solve a specific UI problem. Scenarios where Numeric Steppers would be of use are:

  • In shopping baskets; so users can quickly change quantities.
  • When choosing number of years experience in a skill or profession. Some forms may contain many such questions so Numeric Steppers will facilitate quick mouse action.
  • When choosing number of children or family members. There is no logical upper limit to this question so a drop down is out of the question. A simple input box will serve well but means the user will have to leave their mouse; find the correct keyboard key; then enter a value. With a Numeric Stepper they'd simply click the mouse button a few times in succession to obtain their target value.

These are just but a handful of scenarios. I'm sure there are much more good usage examples out there.

Pity they didn't think of it earlier?

There is no equivalent HTML form control for the Numeric Stepper. I guess when forms were conceived there was no urgent need for them or the concept just didn't exist back then. The rise of Ajax and rich UI interfaces have boosted the industry's appetite for greater interactivity in forms. The chances of a Numeric Stepper playing more useful roles in forms is much greater now.

With that thought in mind we start our journey on building our own...

Building the Numeric Stepper

With help from JavaScript and a few basic form controls we can easily create our very own Numeric Stepper. The ingredients are: a standard text input, two buttons, a container to wrap it all up; and JavaScript to handle the associated events.

The HTML

<span class="numeric-stepper">
<input name="ns_textbox" size="2" type="text" />
  <button type="submit" name="ns_button_1" value="1" class="plus">+</button>
  <button type="submit" name="ns_button_2" value="-1" class="minus">-</button>
</span>

Example 1: The HTML structure

You may notice submit buttons are used rather than "button" buttons. This is so if JavaScript is not available the Numeric Stepper will degrade gracefully. Clicking on the buttons will cause a form submit hence allowing developers to take event handling to the backend. I won't go into details of how to do the backend as it's out of the scope of this article.

I must stress that form submit on button click is NOT what we are after for JavaScript enabled browsers. Using unobtrusive Javascript we want to increment/decrement the input box value by a step size on button click. We also want the JavaScript to restrict it to numerical values only; and apply an upper and lower limit. The code is too much to present here so I'm only going to show the important parts:

The JavaScript

var NumericStepper = {
  register : function(name, minValue, maxValue, stepSize){
    ...
    textbox.onkeypress = function(e){
      if(window.event){
        keynum = e.keyCode;
      } else if(e.which){
        keynum = e.which;
      }
      keychar = String.fromCharCode(keynum);
      numcheck = /[0-9-]/;
      if (keynum==8)
        return true;
      else
        return numcheck.test(keychar);
    };
    ...
  }
  ...
  ,stepper:function(textbox, val){
    if (textbox == undefined)
      return false;
    if (val == undefined || isNaN(val))
      val = 1;
      if (textbox.value == undefined || textbox.value == '' || isNaN(textbox.value))
        textbox.value = 0;
      textbox.value = parseInt(textbox.value) + parseInt(val);
      if (parseInt(textbox.value) &lt; NumericStepper.minValue)
        textbox.value = NumericStepper.minValue;
      if (parseInt(textbox.value) &gt;NumericStepper. maxValue)
        textbox.value = NumericStepper.maxValue;
    }
  ...
}

Example 2: Numeric Stepper; no clothes

Our Numeric Stepper is nearly complete. It doesn't look much like one at the moment; but with a little help from CSS we can give our Numeric Stepper some clothes.

The CSS

.numeric-stepper {
  width:3.425em;
  height:1.6em;
  display:block;
  position:relative;
  overflow:hidden;
  border:1px solid #555;
}
 
.numeric-stepper input {
  width:75%;
  height:100%;
  float:left;
  text-align:center;
  vertical-align:center;
  font-size:125%;
  border:none;
  background:none;
}
 
.numeric-stepper button {
  width:25%;
  height:50%;
  font-size:0.5em;
  padding:0;
  margin:0;
  z-index:100;
  text-align:center;
  position:absolute;
  right:0;
}
.numeric-stepper button.minus {
  bottom:0;
}

The final product: Unobtrusive, Accessible and Standards compliant.

The idea of clothes/skins is fascinating for our Numeric Stepper as it allows us to change its look and feel with some CSS trickery. Take a look at this graphical example.

The Source Code

You can get hold of version 0.1 of the Numeric Stepper source code by following this download link.

I have tested it on FF2, Opera 8.5, IE5.5, IE6, IE7 and Safari. Works well but the buttons look a little weird in Safari though still usable.

Bugfixes, code enhancements, feature requests & improvements are welcome. Please do let me know if you use this code though and if you find it at all useful!

Update: version 0.1.2 adds some accessibility enhancements.