Monday, August 6, 2012

Make that form for User friendly!

I am reading the jQuery Cookbook at the moment. I will blog some interesting examples that I am come across and pad them out - if even only slightly - in the hope that they make more sense to the untrained eye. Let's begin! Consider a form as such:

Who is going to win the Heineken cup next year?

Click on any one of the teams, notice that the radio box is selected. Then start typing in the "Other" text box. Isn't it a bit odd that the team you previously selected is still selected even though you clearly started typing in the "Other" textbox? Does the user seriously have to explictly select the "other" radio button even though an "other" indication has already been given? Now, try this. Clear out the "other" text box and select another team. Then select the "other" radio button. Notice that the "other" textbox does not have focus even though you are hardly going to click the "other" check box and not want to type anything into the corresponding text field. Good GUI should assume the user will want to behave rationally. When the "Other" radio box is selected, it makes sense that its adjacent text box should get focus. Remember good usability means the user can achieve what they want with less clicking. And remember, good usability means that things are intuitive and GUIs do not display contradictions. So with all that in mind, we can include the discussed usability guidelines and come up with something like this:

Who is going to win the Heineken cup next year?

So how did we do that? Well let's take a look at code:

Discussion:

  1. :text is a JQuery psuedo class Selector which selects all elements of type text. As per JQuery recommendations, pseudo class Selectors should be preceded with another selector or tag element otherwise the universal selector is implied. In this case we do input:text and only one text box will be selected. That's ok.
  2. The .each(function(){ means iterate overall inputs of type text and execute the specified function. Don't forget ".each" can operate on sets of elements of any size including just 1 which is the case in this example.
  3. $(this) corresponds to the object which is being operated on by each. In this case it is each input text box. If you don't believe me add:

    
      console.log("this is: " + $(this)[0].id);
    
    

    and you will see something like:

    this is: Source5Txt in the console.

  4. The inputText button and radio button are stored in the local context. This is for efficiency.
Til the next time take care of yourselves.

Sunday, August 5, 2012

How JQuery changed events...

Event handling helps to enrich any application and that most definitely includes web applications. Do this when the button is clicked! Do this when the page has finished loading! Client side JavaScript has a range of event handling options. Before the days of funky JavaScript libraries such as JQuery, when the web was in its embryonic stage, event handling was achieved purely in JavaScript. One technique was to set the event handling properties to some JavaScript code. For example:
...


Here the onclick event property is set so that the an alert message is shown when the button is clicked. The Window object, Document node and the various Element objects all have a selection of event properties. Some of the more interesting ones are:
  • window.unload - triggered when user is navigating away from from a document.
  • form.onchange - can be used to capture a change from any element in the form thru a technique known as bubbling.
  • element.onload - every document element (e.g. ,
All seemed much nicer, but IE complicated things:
  1. IE8 did not support addEventListener(). Instead you had to use attachEvent()
  2. Event handlers usually receive an Event object (http://www.w3schools.com/jsref/dom_obj_event.asp) which contains details of the event. This will contain properties such as the element that trigged the event, the name of the event and the time it was created etc. To receive this event simply add it to the event handler.
    button.addEventListener("click", function(event) {
        alert("You clicked me with an event of type!" + event.type)}, false);
    
    But you guessed it, IE8 did not support this mechanism to get details of the event and instead, you had to check the global variable window.event to get information about it. This lead to messy JavaScript code such as
    function handler(event) {
        event = event || window.event;  // got to cater for Microsoft!
    }
    
  3. The "this" keyword in the event handling code usually referred to the document element that fired the event. However in IE8's attachEvent(), the this referred to the global window.
JQuery comes to the rescue providing APIs that work in all browsers. The commonly used events (e.g click, load) have their own event registration APIs (click(), load()). Similar to JavaScript's addEventListener() the JQuery event handler APIs allow multiple event handling logic to be associated with the same event. And similar to JavaScript, JQuery event handler functions do not have to have arguments or return values but both are supported. The value add being that JQuery APIs work and all browsers - that means event objects are passed into event handlers for poor old IE8!
//add to all button elements
$("button").click(function() {alert("You clicked me");}); .
So JQuery clearly solves some problems here. Does it offer anything else? Of course... the bind() API. This allows:
  • the same handler to be executed for multiple events. Just separate the events by a space.
    // invoke myEventHanlder for any click, mousedown events for any div elements.
    $('div').bind('click mousedown', myEventHandler);  
    
  • the same handler function to be reused with different data. This is achieved by passing an Object literal as the second object in the bind API. The object literal values can then be read in the event handler via the event objects data properties.
    // call buttonClicked and pass color red to it.
    jQuery('#button1').bind('click', {team:'Leinster'}, buttonClicked);
    // call the same buttonClicked function but pass blue. 
    jQuery('#button2').bind('click', {team:'Munster'}, buttonClicked); 
    
    buttonClicked function could then be something like:
    function buttonClicked(event) {
        alert("you selected team" + event.data.team);
    }
    
  • Refer to multipe event handlers at the same time. This is achieved in JQuery by using namespaces for the events. Suppose you want to group a selection of events. You could put them all into the same namespace click.myclickevents.
    $("#myButton1").bind('click.myclickevents', myfunction());
    $("#myButton1").bind('mousedown.myclickevents', myfunction());
    
  • Because they are grouped they can be reffered to now at the same time. This comes in handy if you want to remove them.
    $("#myButton1").unbind('myclickevents');
    
In addition JQuery provides:
  • The one() API. This is similar to bind, except the eventhandlers only get called once. They are then deregistered.
  • The trigger() API. This provides the ability to manually cause event handlers (including custom events) to be invoked.
  • Live events This is like the event handling achieved with the bind() except it will also add event handling logic to new elements that are to still to be created, whereas bind() only adds it to existing elements.
The End?

Not quite. In order to stop people getting confused about the various JQuery event handling APIs JQuery unified them all into one API, the on() API. See also 1.7 release notes.

Saturday, August 4, 2012

Book Review: Even Faster Websites (Steve Souders)

Author Steve Souders (Head Performance Engineer at Google, previously Chief Performance at Yahoo) grew to fame with the YSlow Firefox plugin - a super little gizmo which gave web developers all sorts of ideas for how to speed up their web sites. The book 'High Performance Web Sites: Essential Knowledge for Front-End Engineers book' elaborated on everything the YSlow plugin was telling you. That book effectively serves a forerunner to 'Even Faster Web Sites'. In fact there is an assumption the reader has already read it, is already familiar with all the points it made and is now prepared to dig deeper.  Anyone with an interest in performance is in for a treat with this little gem.



I thought 'Even Faster Web Sites' detailed many clever techiques to boost performance. Amongst some of my favourites:
Steve Sounders
  • Create a <script> element and set its src attribute to a JavaScript file you want to download asychronously.
  • Use the script onload's event - which will only be called when the script has finished downloading - to avoid race conditions.
  • Succint explainations on how deep scope chains in JavaScript can degrade performance
  • Tips on when to use if statements, switch statements and arrays for flow control.
  • A good overview of the Comet Architectural approach and how it can be achieved.
  • Domain sharding tips: split based on resource type e.g put CSS and images on one domain, everything else on another domain.

There are also timely reminders, including:
  • That IFrames make it easy for the UserAgent to print part of a page and are a mechanism to split part of your document giving it independent characteristics.
  • IFrames are more expensive to download.
  • That a browser's busy indicator stops once the Window.onLoad event is fired.
  • Some browsers have limits on how long the JavaScript engine can run
  • Web proxies and security software can mangle the Accept-Encoding header of request so that they speed up their screening of the response from the web server in a process Souders refers to as Turle Tapping.
  • Browsers enforce their maximum connections per server rule based on the hostname in the URL not the IP address it resolves to.
  • That CSS selectors work in a "rightmost first" fashion.
It is a super book. Not just to get ideas to boost web performance but because it helps deepen architectural understanding of the web. There are many important parts in the Web tier: all the different resource types, sychronous / asychronous processing, the various ways blocking can happen, a very sophisticated object model, a funny old language by the name of JavaScript and of course the endless list of quirks from different browsers. There was a time when everything revolved around the database but now a deep understanding web is probably more important. This book most definetly helps deepen understanding of the Web Tier.