JavaScript & jQuery: The workflow

The article is a combination of personal research and largly an extract from the third party materials listed at the end.

General practices

Create element

Shorthand for creating element and assigning various properties.

var $div = $('<div>', {id: 'myid', css: {color: 'green'}, click: handlerFunction});

Note that you don’t need to write <div></div> or even to close it. You can set all kind of attributes plus the following jQuery methods val, css, html, text, data, width, height, or offset.

Create function

Robust, flexible and easy-to-debug way to create function. Just use it, no excuses for being lenghty.

// 1) enclose declaration with a separate scope
var functionName = (function(){
    // 2) declare a variable to assign function to
    var fn;
    // 3) make sure to give function a descriptive identifier
    fn = function functionName(here,go,the,arguments) {
    // 4) clean up `functionName` function created by JScript
    //    make sure to either prepend assignment with `var`,
    //    or declare `functionName` at the top of the function
    var functionName = null;
// 5) finally return function referenced by `fn`
return fn;

Once again for copy-pasting:

var functionName = (function(){
    var fn;
    fn = function functionName(here,go,the,arguments) {
    var functionName = null;
    return fn;

If you really want to dig into why you need to do this read the named function expressions demystified.


A little bit of OOP.

Class constructor
function myClass(){
    if ( !(this instanceof myClass) ) {
        return new myClass();
    // constructur logic
var myClassInstance = myClass();
Class inheritance and encapsulation
function ParenClassName(){
    if ( !(this instanceof ParenClassName) ) {
        return new ParenClassName();
    var privateMethods = {
        aPrivateMethod: //function
    var publicMethods = {
        aPublicMethod: //function
    $.extend(this, publicMethods);

function SubClassName(){
    if ( !(this instanceof SubClassName) ) {
        return new SubClassName();
    $.extend(this, new ParenClassName());

Define shortcuts

Gurantee that the keywords correspond to their values.

var TRUE = true,
window = window;

Check variable type

Don’t use typeof, use $.type() instead.

JavaScript is disabled

How to detect and react when javascript is disabled.


Add class="no-js", to <html> element. Then replace it with class="js" using JavaScript:

$(function() {

Now you can

.no-js a:hover {
    background: #000;

Then you can use the hover rule and make it fade instead of instantly changing.

Timeout and loops

  • Use doTimeout instead of the native setTimeout.
  • Use TimerX instead of the native setInterval.

Looped timeout or interval will not wait unitl what was called has finished and 2 executions of the same logic can clash. Instead use:

(function loopA(){
    $.doTimeout( 'someid', 100, loopA);

and for asyncronous actions like ajax and animation:

(function loopA(){
        $.doTimeout( 'someid', 100, loopA);

Organise event handlers

var myButtonEventHandlers =
    click: //  a handler function
    keypress: // a handler function


IE slideDown() effect (i.e. Jumpy Animation)

Concerning slideDown() andslideUp()animations. All info and credits in Dan Switzer blog.

Animated items always have display:block

It’s not a bug but simply one to know on the go. jQuery always makes element display:block for the time of the animation. Only FadeIn and FadeOut don’t – they only change opacity.

IE font antialiasing

It concerns animating opacity. Simply remove the filter attribute. Example:

$('#myid').fadeOut('slow', function() {'filter');
Mouse over and out
  • Use hoverIntent instead of default mouseover, mouseout or hover events.
  • Use $().dequeue().stop() instead of just $().stop().
  • If you use $().fadeIn() or $().fadeOut() replace it with $().animate() because if the built in fading is stopped in the middle of the animation then the element might get stuck with that certain opacity.
  • Consider that the animation duration varies depending on how much does the CSS property value differ from the target value.
var fadeIn= (function(){
    var fn;
    fn = function fadeIn() {
        $hoverHelper.dequeue().stop().animate({"opacity":1}, {
            duration: animationDuration *(1-parseFloat($hoverHelper.css('opacity')))
    var fadeIn= null;
    return fn;

var fadeOut= (function(){
    var fn;
    fn = function fadeOut() {
        $hoverHelper.dequeue().stop().animate({"opacity":0}, {
            duration: animationDuration *parseFloat($hoverHelper.css('opacity')),
            complete: function(e) {
    var fadeOut= null;
    return fn;
var $myEl = $("#myid"),
animationDuration = 200,
$hoverHelper = $("<span>", {
    class: "hover-helper"
    css: {"opacity": 0}
    over: fadeIn,
    timeout: 300,
    out: fadeOut

If you target only the latest non-IE browsers you can use CSS transitions like that:

a {
    -moz-transition:            all 0.3s ease-out;  /* FF4+ */
    -o-transition:          all 0.3s ease-out;  /* Opera 10.5+ */
    -webkit-transition:     all 0.3s ease-out;  /* Saf3.2+, Chrome */
    transition:             all 0.3s ease-out;
    color: blue;
a:hover {
    color: red;
Animate to CSS class or CSS selector

Instead of writing the CSS values of the properties you want to animate in the JavaScript file you can animate directly to a CSS class. To achiveve this you need to use jQuery UI which provides animation for addClass(), removeClass(), toggleClass().

In order to animate to a exact selector, not just class, you need animateToSelector plugin. Useful in cases of mouseover and mouseout animation because the target CSS selector can be .no-js a:hover.

Complex animation

If you have animations that depend on the completition of other objects’ animations you should read how to control advanced callbacks, probably the group callback part.

Animation Performance

Concerning the case where you have multiple objects animated with the same animation. The solutions is to animate the CSS rule itself, not the style properties of each element. The jQuery RuleAnimation plugin does that. It requires jQuery Rule plugin.

Unpack / Unminimize

There is a tool that attempts to regain formatting from minimized JavaScript files :

return false VS event.preventDefault()

Let’s have the following code:

$('body').click(function(e){console.log('&lt;body&gt; was clicked')});
$('a').click(function(e){console.log('"&lt;a&gt;" was clicked')});

By defalt when <a> is clicked both events for <a> and <body> will be triggered. The output will be: "<a>" was clicked
"<body>" was clicked
This is called event propagation. Any ancestor (element higher in hierarchy that has the current element in its content) will be notified of events happening within it. If this ancestor (here the <body>) has subscribed/listens/registered to the click event and a nested element, nomatter how deep in hierarchy, (here the <a>) is clicked then two events will be triggered.

We can say that a DOM element owns all elements within it. If anything inside happends we have to notifier the owner. For more on events read the section dedicated on that topic.

If you click on our anchor element but you have return false; no event propagation will happen and therefore the body element wont be notified. If you only want to stop the anchor defaut action (go to the location stated in the href attribute) then use e.preventDefault() where “e” is the first parameter in the callback.

Other howtos

You can find a list of common JavaScript usages at

Debugging / Fixing bugs

This is the process of finding bug in the logic.

  • Use Firebug to analyze the execution flow
  • Use `breakspoints` and `watch expressions` to set shortcuts to a certain point in execution flow
  • Analyze values and compare to the expected values

After you install Firebug add some extras:

  • Syntax highlighting for Firebug Script tab by FireRainbow
  • View the data that jQuery adds to html elements in Firebug HTML tab by FireQuery
  • Anything you like from Firebug swarm

A breakpoint is the line number in a javascript file on which we want to pause the execution flow. It is the line number because usually it’s easier to mark the line we want to pause then the cursor position. Firebug though offer the debugger; command which can be inserted anywhere in the code, which means the execution pause can be in the middle of a line if we have several stated oprations. Example:

console.log('normal flow'); debugger; console.log('debug');

Firebug also comes with a console terminal. Whatever you enter is executed as JavaScript. It’s also active when the execution is paused. The code you enter while paused is executed in the context/scope of the pause location. You can access all variables and also the this keyword. When it’s not paused the this keyword refers to window.

Watch expressions are simply conditions on whether to pause at the marked breakpoint. Sometimes the code we want to analyze is inside of a loop or is called multiple times and we want to view only one scenario. In this case we can set a watch expression. Something like:


If you want to find out the events and handlers that are registered to an element read the beginning of the Event section.


JavaScript events notification can travel in 2 directions. One starts with the root node and then move to its descendants following the CSS path of the element that fired/triggered/dispatched the event. This is “event capturing“.

The other, obviously, is simply in the opposite direction. This is “event bubbling“. This is what jQuery uses. You can get all registered (doesn’t include the delegated) events and handlers on certain element by calling $.data(DOMelement, 'events').


Events in jQuery can have namespaces:

var $a = $('a.clicker');
$a.bind('click.naviation', aHandler);
$a.bind('hover.naviation', aHandler);
$a.bind('click.ajax', aHandler);
  • Unbind only the click that is responsible for ajax call: $a.unbind('click.ajax')
  • Or unbind all events that have something to do with navigation: $a.unbind('.navigation')
  • Namespaces are also useful in
  • ion of events.

Custom events / push notifications

Register you events just like any other ($el.bind('poop', handlerFunc)) and send notifications when it’s appropriate via $el.trigger('poop')

Support more events

Detecting a the mouse wheel is not builtin event. You have to use mousewheel plugin for that. jQuery UI comes with some more special events like drag and drop. You can build your own just like Brandon’s multiclick event. Read Ben Alman’s article for more examples and details on special events.

jQuery have 2 undocumented events (getData and setData) triggered when $.data() is called to get or set data. The $.data() method also offers event-like namespacing so that you can do $.data(domEl,'dogs.brown',{...});

Advanced callback control

To have more control over callbacks we need to create a $.Deferred() object

var dfd = $.Deferred();

Here are some attempts to clarify what $.Deferred() object is:

  • It offer a way to register a group callback, a callback that will be executed only after all tasks in the group end. Like registering a callback to an entire namespace.
  • It’s similar to opening a ticket and then adding dependancies. To close the ticket you can fix the dependancies and mark it as resolved or rejected it.
  • It still exists after it’s closed and if you access it you can check its resolution status. You can also freely add more callbacks which will be executed immediatelly.

To close Deferred object either dfd.resolve() or dfd.reject() should be called. After that, all callbacks from the corresponding category are fired. There are three callback categories depending on the outcome of the deferred object:

  • resolved Callbacks are registered via dfd.done() ( dfd.success() is an alias in AJAX objects) or first parameter of dfd.then(doneCallback, rejectedCallback)
  • rejected Callbacks are registered via (dfd.error() is an alias in AJAX objects) or second parameter of dfd.then(doneCallback, rejectedCallback)
  • rejected or resolved Callbacks are registered via dfd.complete() – natively supported only by the deferred object returned from a AJAX call but it can be emulated

Other then resolve and reject you can use resolveWith rejectWith to close a Deferred object. They have an additional parameter context which will correspond to the this object in the callbacks registered the proper callback category.

You must not let unrelated tasks to close the Deferred object. None of resolve, resolveWith, reject, rejectWith should be accessible to such tasks. You can get an encapsulated version of the Deferred object which exposes only the callback hook methods (done, success, fail, error, complete) by running dfd.promise().

Emulating dfd.complete

As mentioned above rejected or resolved callback category only exists for Deferred objects returned by AJAX calls but we can emulate that behaviour by creating a secondary Deferred object.

var animation = (function(){
    var fn;
    fn = function animation() {
        var dfd = $.Deferred();
        $('#myid').animate( 300, dfd.resolve );
        var dfdControl = $.Deferred();
        dfd.then(dfdControl.resolve, dfdControl.resolve);
        return dfd.promise();
    var animation = null;
    return fn;
Group callback

Let’s there be an element that contains rotating random quotes and fading effect between the change. We dont’t care about the interval right now. We just need to make sure that we have received the new quote and we have a faded out box which we need to replace the content of before we show the next one.

var ajax = (function(){
    var fn;
    fn = function ajax() {
        return $.get('/random/quote');
    var ajax = null;
    return fn;
var fadeOutAnimation = (function(){
    var fn;
    fn = function fadeOutAnimation() {
        var dfd = $.Deferred();
        $('#quoteContainer').fadeOut( 1000, dfd.resolve );
        return dfd.promise();
    var fadeOutAnimation = null;
    return fn;
var fadeInAnimation = (function(){
    var fn;
    fn = function fadeInAnimation(ajaxResult) {
        // replace quote and fade in
    var fadeInAnimation = null;
    return fn;

$.when( ajax(), fadeOutAnimation()).then(fadeInAnimation);

Correctly define user action

Some user operations are lenghty and repeatedly fire events. Instead firing the callback immediatelly we bettter wait for the operation it to actually end. Thus we are optimizing performance and actually meet user expectations for the graphical interface more closely.

Problem becomes clear when you compare the keydown + keyup and keypress. If we want to detect how much time does the user spend holding a key down then we register a keydown event and then a keyup event. When don’t register keypress event because it fires multiple times while the key is hold.

Some situations are not that simple. We must stop immediate callback by defining timeout. Ben Alman made such pluigin with two kinds of timeouts called: throttle and debounce. Both create a function from the real callback.

Every time $.debounce is called it creates a timeout or override its previously created timeout. The callback is only called when the timeout successfully finishes.

$.throttle will allow the callback to execute only once in certain time interval.

Small list of solutions according situation:

Event delegation

After looking into how event notifications work (see the start of Events section) we know that when event is fired all ancestors are notified.

We can use this fact and improve our JavaScript performance by attaching events only on a certain ancestor. Then we will check which desendant triggered the event and call the corresponding handler. Thus we have one event with multiple handlers instead of several events with one or more handlers each.

Another benefit of using event delegation is that we don’t have to register the events once again for the dynamically added elements.

jQuery 1.4.2+ provides $.delegate(). Before this version you can still register event to an ancestor an then check the current event target in the handler.

Misc events facts

Some useful facts

  • In ajax callbacks this is reference to the options.
  • Event handlers can be set to use a custom context (this object) by declaring the handler parameter using: $.proxy(function, context).
  • If an event is not firing and you have trouble finding why check if there’s stopPropagation in your code or in the plugins that you use.
  • There’s a native javascript event contextmenu which is triggered when context menu shows or just when secondary mouse button is clicked. Still unclear. Supported by the main browsers and IE6+.

Make up for CSS deficiency

Regulated columns

If you want columns with equal height use equalizecols.

When the aim is columns with equalized baselines (bottom) then head to equalizebottoms plugin. Here the important is that the columns end at the same vertical point.

Vertical Center

Your container should be having position:relative.Your vertically centered element: position:absolute;. If it’s position:static (the default) it would drag its siblings with it. The javascript:

var recalaculate = function() {
    $centeredEl.css('top', - ($container.height() - $centeredEl.height())/2);

Usually on listing pages when you show only excerpts the user wants to read/reach the rest of  the information. Instead the “read more” links make the whole excerpt area a link using biggerLink.

Multiple columns

  • Split long lists in columns with makeacolumnlists
  • All current implementations of multiple columns for general content are poor. If you want a solution just for paragpraphs + images use columnizer. Otherwise wait until CSS3 Multi-column layout is widely supported.

Style parent when an descendant is active

All CSS rules go in one direction – from parent to children. We can’t reverse it. Even if you want to change the parent when a link is hovered you can’t. You are not able to ask the browsers via CSS : “Please make all paragraphs that are contained in a form element yellow”. This is clearly decoration and not application behaviour but we can’t express it in CSS.  To overcome this limit use the higlight plugin.

Unify CSS properties

Get the jQuery CSS hooks. They provide cross-browser getters and setters for all kind of CSS properties including some that are part of CSS3. Thus enabling animation on such properties like text-shadow.

Table usability

Use the fixed headers with every table you have. If you need a table with fixed height then look into an alternative plugin by Nova Software.

Stylish numbered lists (OL)

Add a class to each list item in ordered lists so that you can style them according order. If you want follow this tutorial. Use this technique until nth-child selector doesn’t become cross-browser.

Improving native user interface and interaction

Components. This is how I call all plugins that improve native user interface and interaction with the web. Not every jQuery plugin is a component. Here’s what I mean:

  • Components are not simply widgets. You can’t call the ability of autosaving a wordpress post via AJAX a widget but it does improve the interaction.
  • Components are not plugins that fix browser issues, they level up browser and web application abilities
  • Components keep the balance between what a web designer thinks is possible and what is actually possible for the HTTP and the browsers.

What you can find below is a standartised list with components classified by purpouse.

Create, Read, Update, Delete

  • Non native form appearance (custom form design)

    Use jQtransform (if you found jNice, don’t use it, it is a bit old). It’s not documented anywhere but jQtransform actually polutes the jquery namespace. I have plans to fix this myself in the future. Right now you can customise elements by calling:

    • jqTransform – on forms
    • jqTransRadio – on radio buttons
    • jqTransTextarea – on text areas
    • jqTransSelect – on select boxes
    • jqTransCheckBox – on check boxes
    • jqTransInputText – on text fields
    • jqTransInputButton – on submit and reset inputs

    If you need custom file input field use Uniform. Don’t use Uniform for anything else because it will not make buttons and the selectbox dropdowns customisable.

  • Autoenlarging textarea

    To make your textarea automatically change height as you type use jquery elastic.

  • Labels in the input text fields

    If you want to save some screen real estate use the In-Field Labels plugin which hides the input labels and show the text inside the fields.

  • Range input via slider

    Useful for date intervals, amount range and choosing integer or number from range. jQuery UI slider and an additional implementation aimed for easy select field replacement.

  • Text input formatting
    • If you want to conform the input text fields to certain format like telephone number, date, or bank acccount number use the masked input plugin. It can define groups, separators and placeholders while also restricting the allowed input characters.
    • If you want to separate the information into several inputs then use jquery autotab plugin.
    • If you want to autoformat numbers and currencies use autoNumeric. There is a clone github repository which seems to be updated.
  • Upload multiple files
    • Before the entire html form is submitted. Use uploadify. Some will argue that it is based on Adobe flash and therefore evil but it offers the most intuive interaction.
    • Along with the submission of the entire form Use multiple file upload plugin.
  • Step by Step form

    If your html form is rather large transform it into a wizard with few steps using formToWizard plugin

  • Validation

    Use the jQuery Validation plugin. Don’t change this plugin to an alternative. If you need tooltips error notifications for your next project, don’t search for another plugin. Still use this one with tooltips plugin. Example for tooltip error notification:

        errorPlacement: function(error, element)
            // add relation error-to-element until validation plugin
            // starts providing `element` argument is `success` callback
            if (!$.data(error[0],'element')) {
            if (!$.data(element[0],'qtip')) {
                    content: error,
                    position: {
                        my: 'bottom center',
                        at: 'top center'
                    show: {
                        event: false,
                        ready: true
                    hide: false,
                    style: {
                        classes: 'ui-tooltip-red' // Make it red... the classic error colour!
            } else {
                // update error message
                element.qtip('option', 'content.text', error);
        success: function(error)
  • AJAX submission of input

    Use the form plugin. Automatic collection of input, serialization, API, a lot of  options.

  • Autocompletition

    I won’t dig into autocompletition plugins. There a great number of plugins which can’t be summerized into one or two.

    Just a note on autocompletition. Always make sure to define the autocompletition event right.

Waiting for image(s) to load

Image interaction

  • Selection over image

    Place a rectangluar selection box over the image via imgAreaSelect. imgAreaSelect has a lot more options than jCrop.

  • Crop image

    Crop can’t happen on the client side. You must write a server-side algorithum to create the cropped version. On imgAreaSelect web page there are few links describing how to do so with PHP.

  • Annotate image

    Leave notes on certain area of the image using Img Notes. It uses imgAreaSelect. If you want a product that already have the looks turn to jQuery Notes plugin. jQuery Notes plugin uses a php file to handle notes on serverside and also plans a new version where you’ll be able to add notes to any element. jQuery Notes doesn’t reuse the existing imgAreaSelect plugin and implements a its own selection solution.

  • 360 Rotation

    It can be either 2-4 directional that have a commercial alternative with zoom support or spherical 360 rotation. There’s also a virtual tour plugin which is a horizontal 360 with the ability to add notes defined via <area> tags.

  • Galleria has loads of options, API and JavaScript themes

Back button, browser history events

Jquery BBQ monitors the hash (# part) of page url and fires events accordingly any changes. It supports bookmarking as well.


For custom scrollbars use jScrollbar plugin. It requires mousewheel plugin because the mousewheel is not a built in event.

In order to optimise the distance user has to move the mouse cursor in order to scroll you can make a google wave styled scrollbar.

If you searching for anything related with scrolling read a good article by webdesign14 about such plugins.

Autoload more content

Plugins that provide the “endless page effect” by autoinserting more content. Several plugins, yet to be filtered.

Always in viewport animated

Force an element always to be in the part of the page which is visible in the browser by sliding this element up and down.

User feedback

  • Use star rating plugin because it offers a fallback support via radio buttons. It has a svn repository hosted on google code. If you plan to have non-integer ratings you also need jQuery metadata plugin. For ajax submission of the rating get jQuery form plugin.If you want a product  that already has the ability to set custom images for every star and you can sacrifice the graceful degradation than try jQuery Raty.


Alternative content presentation and interaction

  • Roundabout is a carousel that can move elements in diffrent trajectories. To simulate perspective it does change size, opacity and overlapping order.

Video widgets

Misc widgets



Saves user’s and your hosting’s bandwidth, provides lower network latency, minimizes the number of connections with your hostname. Use is as follows:

&lt;script src="//"&gt;&lt;/script&gt;

See the latest google hosted jquery available and more info. You can deploy the same technique for jQuery UI and several other libraries.

Use event delegation

See the Events delegation section for information.


ID in selector

Instead of $('#content div') use $('#content').find('div');

Selector context VS .find()

Instead of $('div', $container) use $container.find('div'). It’s more efficient and easier to read.


Use a doctype which offer wide variety of tags. More tags means quicker access to selectors. HTML5 offer more tags then XHTML.

DOM manipulation

It’s quicker to modify DOM elements when they are not inserted into the DOM flow. If you can, $.detach() your elements prior any modifications and then $.append() them to their parent once again. Othewise you can $.clone() the element, modify it and then replace it.

If you have to insert multiple elements into the DOM flow don’t insert them one by one. Use document fragment instead:

var fragment = document.createDocumentFragment();
$elements.each(function(i, el) {

Storing element info

Instead $('el').data(key,value) use $.data(domEl, key, value)

Strings concatanation

When forming a large string from several small ones :  += is faster than concat() or pushing in array and then .joining it

Unexpected JavaScript behaviour

How to please the capricious JavaScript. In its nature writing JavaScript is freaky expirience. Not mentioning browser differences but JavaScript inconsitencies itself. This article covers some of them. A list of documented such behaviours can be found at and some more at and more at

Paul Irish Video Tutorial on jQuery source code
Paul Irish jQuery performance presentation
Adam Sontag JavaScript & jQuery debugging presentation
Peter-Paul Koch on js event triggering
Animating by altering CSS rules
Rebecca Murphey on jQuery fundamentals
Paul Irish HTML5 presentation (october 2010)
Yahoo Performances Rules
JavaScript utilities framework
Mozilla on “Writing efficient CSS”
IRC and JavaScript rules
Juriy Zaytsev (kangax) explores JavaScript by example
Juriy Zaytsev (kangax) on JavaScript named function expressions
Non chat related facts from jQuery irc channel bot-t
jQuery FAQ
YUI: Animating multiple elements
John Resign presentation
Paul Irish and Jonathan Neal joint, in association w/ Boaz Sender and Zoltan Hawryluk

No responses keep track

you can or


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code lang="" line="" inline="" escaped="" first_line="" wrap=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" inline="" escaped="" first_line="" wrap="">