Order of format matters in respond_to block

This is a standard Rails code. I am using Rails 2.3.5 .

class UsersController < ApplicationController
  def index
    @users = User.all
    respond_to do |format|
      format.html
      format.js  { render :json => @users }
    end
  end
end

Accidentally in one of my controllers the order of formats got reversed. The altered code looks like this.

class UsersController < ApplicationController
  def index
    @users = User.all
    respond_to do |format|
      format.js  { render :json => @users }
      format.html
    end
  end
end

I thought order of format declaration does not matter. I was wrong.

> curl -I http://localhost:3000/users
HTTP/1.1 200 OK
Connection: close
Date: Mon, 25 Jan 2010 22:32:16 GMT
ETag: "d751713988987e9331980363e24189ce"
Content-Type: text/javascript; charset=utf-8
X-Runtime: 62
Content-Length: 2
Cache-Control: private, max-age=0, must-revalidate

Notice the the Content-Type of in the response header is text/javascript in stead of text/html .

Well I guess the order of format matters. I hope it is fixed in Rails 3.

How animate really works in jQuery

jQuery has animate method which is just awesome. Today I looked into jQuery source code to see exactly how animate works.

I will take a simple case of animating a div from height of 34 to 100.

Here is test case.

$(function(){
  $('#lab').css({background: 'yellow', height: '34px', margin: '10px'});

  $('a').click(function(){
    $('#lab').animate({height: '100'});
      return false;
    });
});

Html markup is .

<a href=''>click me</a>
<div id='lab'>Hello World</div>

Inside the animate for each property an fx object is created.

jQuery.each( prop, function( name, val ) {
  var e = new jQuery.fx( self, opt, name );
}

Calling new on jQuery.fx returns a JavaScript object instance.

fx: function( elem, options, prop ) {
	this.options = options;
	this.elem = elem;
	this.prop = prop;

	if ( !options.orig ) {
		options.orig = {};
	}
}

Next in the animate method is a call to e.custom .

start = 34;
end = 100;
unit = 'px';
e.custom( start, end, unit );

start, end and unit values are gleaned from the current state of div.

Here is custom method .

custom: function( from, to, unit ) {
	this.startTime = now();
	this.start = from;
	this.end = to;
	this.unit = unit || this.unit || "px";
	this.now = this.start;
	this.pos = this.state = 0;

	var self = this;
	function t( gotoEnd ) {
		return self.step(gotoEnd);
	}

	t.elem = this.elem;

	if ( t() && jQuery.timers.push(t) && !timerId ) {
		timerId = setInterval(jQuery.fx.tick, 13);
	}
},

As you can see every 13 milliseconds a call to step method is made.

step method is where real calculation is done. Here is the code.

step: function( gotoEnd ) {
  var t = now();
  var n = t - this.startTime;
  this.state = n / this.options.duration;
  pos = jQuery.easing['swing'](this.state, n, 0, 1, this.options.duration);
  this.now = this.start + ((this.end - this.start) * this.pos);
  this.update();
}

this.startTime is the time when the call to animate was invoked. The step method is called periodically from custom method. So the value of t is constantly changing. Based on the value of t, value of n will change. Some of the values of n I got was 1, 39, 69, 376 and 387.

While invoking animate method I did not specify a speed. jQuery picked up the default speed of 400. In this case the value of this.options.duration is 400. The value of state would change in each run and it would something along the line of 0.0025, 0.09, 0.265, 0.915 and 0.945 .

If you don’t know what easing is then you should read this article by Brandon Aaron. Since I did not specify easing option, jQuery will pickup swing easing .

In order to get the value of next position this easing algorithm needs state, n and duration. When all of it was supplied then pos would be derived. The value of pos over the period of animation would change and it would be something like 0, 0.019853157161528467, 0.04927244144387716, 0.9730426794137726, 0.9973960708808632.

Based on the value of pos value of now is derived. And then update method is called to update the screen.

update method has following code that invokes _default method.

jQuery.fx.step._default)( this )

_default method has following code which finally updates the element.

fx.elem.style[ fx.prop ] = Math.max(0, fx.now);

fx.now value was set in the custom method and here that value was actually applied to the element.

You will have much better understanding of how animate works if you look at the source code. I just wanted to know at a high level what’s going on and these are my findings.

Handling JSON parsing natively in jQuery 1.4 and what changed from jQuery 1.3

With the popularity of JavaScript JSON has become very very popular. JSON which stands for JavaScript Object Notation is a popular way to send and receive data between browser and server.

jQuery makes it extremely easy to deal with JSON data. In the below example server sends a success message to browser. The JSON data looks like this.

{ 'success': 'record was successfully updated' }

The jQuery code to handle JSON data looks like this.

$.ajax({
   type: "GET",
   url: "test.js",
   dataType: "json",
   success: function(json){
     $('#result').text(json.success);
   }
 });

It all looks good and the code works with jQuery 1.3 .

However if you upgrade to jQuery 1.4 then above code will stop working. Why? jQuery 1.4 does strict JSON parsing using native parse method and any malformed JSON structure will be rejected.

How jQuery 1.3 parses JSON structure

jQuery 1.3 uses JavaScript’s eval to evaluate incoming JSON structure. Open firebug and type following example.

s = " { 'success' :  'record was updated' } "
result = eval('(' + s + ')');
console.log(result);

You will get a valid output.

Note that all valid JSON structure is also valid JavaScript code so eval converts a valid JSON structure into a JavaScript object. However non JSON structure can also be converted into JavaScript object.

JSON specification says that all string values must use double quotes. Single quotes are not allowed. What it means is that following JSON structures are not valid JSON.

{ 'foo' : 'bar' }
{ foo: 'bar' }
{ foo: "bar" }
{ "foo" : 'bar' }

Even though above strings are not valid JSON if you eval them they will produce a valid JavaScript object. Since jQuery 1.3 uses eval on strings to convert JSON structure to JavaScript object all the above mentioned examples work.

However they will not work if you upgrade to jQuery 1.4 .

jQuery 1.4 uses native JSON parsing

Using eval to convert JSON into JavaScript object has a few issue. First is the security. It is possible that eval could execute some malicious code. Secondly it is not as fast as native parse methods made available by browsers. However browsers adhere to JSON spec and they will not parse malformed JSON structures. Open firebug and try following code to see how native browser methods do not parse malformed JSON structure. Here is the link to the announcement of Firefox support for native JSON parsing . John Resig mentioned the need for jQuery to have native JSON parsing support here .

s = " { 'success' :  'record was updated' } "
result = eval('(' + s + ')');
console.log(result); /* returns valid JavaScript object */

result2 = window.JSON.parse(s);
console.log(result2); /* throws error */

As you can see a string which was successfully parsed by eval failed by window.JSON.parse . It might or might not fail in chrome. More on that later. Since jQuery 1.4 will rely on browsers parsing the JSON structure malformed JSON structures will fail.

In order to ensure that JSON is correctly parsed by the browsers, jQuery does some code cleanup to make sure that you are not trying to pass something malicious. You will not be able to test this thing directly using firebug but if you make an AJAX request and from server if you send response the you can verify the following code.

Following JSON structure will be correctly parsed in jQuery 1.3 . However the same JSON structure will fail in jQuery 1.4 . Why? Because of dangling open bracket [ .

' { "error" : "record was updated" }'

jQuery 1.4 has following code that does some data cleanup to get around the security issue with JSON parsing before sending that data to browser for parsing. Here is a snippet of the code.

// Make sure the incoming data is actual JSON

// Logic borrowed from http://json.org/json2.js

if (/^[\],:{}\s]*$/.test(data.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, "@")
	.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, "]")
	.replace(/(?:^|:|,)(?:\s*\[)+/g, "")))

Not all browsers parse JSON same way

Earlier I mentioned that following JSON structure will not be correctly parsed by browsers.

” { 'a':1 } ”

All browsers will fail to parse above JSON structure except chrome . Look at this blog titled Cross Browser JSON parsing to get more insight into this issue.

I have malformed JSON and I want to use jQuery 1.4

If you have malformed JSON and you want to use jQuery 1.4 then you should send the datatype as text and then convert the returned JSON structure using eval. Here is one way you can do that.

$.ajax({url: "/url",
  dataType: "text",
  success: function(data) {
    json = eval("(" + data + ")");
    // do something with json

  }
});

Ben Alman suggested another way in the comment section .

/* this should be the very first JavaScript inclusion file */
<script type=”text/javascript” language=”javascript”>window.JSON = null;</script>

jQuery attempts to parse JSON natively. However if native JSON parsing is not available then it falls back to eval. Here by setting window.JSON to null browser is faking that it does not have support for native JSON parsing.

Here are the two commits which made most of the changes in the way parsing is done.

Use JSONLint if you want to play with various strings to see which one is valid JSON and which one is not.

How jQuery 1.4 fixed rest of live methods

If you look at jQuery 1.3 documentation for live method you will notice that the live method is not supported for following events: blur, focus, mouseenter, mouseleave, change and submit .

jQuery 1.4 fixed them all.

In this article I am going to discuss how jQuery brought support for these methods in jQuery. If you want a little background on what is live method and how it works then you should read this article which I wrote sometime back.

focus and blur events

IE and other browsers do not bubble focus and blur events. And that is in compliance with the w3c events model. As per the spec focus event and blur event do not bubble.

However the spec also mentions two additional events called DOMFocusIn and DOMFocusOut. As per the spec these two events should bubble. Firefox and other browsers implemented DOMFocusIn/DOMFocusOut . However IE implemented focusin and focusout and IE made sure that these two events do bubble up.

jQuery team decided to pick shorter name and introduced two new events: focusin and focusout. These two events bubble and hence they can be used with live method. This commit makes focusin/focusout work with live method. Here is code snippet.

if ( document.addEventListener ) {
	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
		jQuery.event.special[ fix ] = {
			setup: function() {
				this.addEventListener( orig, handler, true );
			},
			teardown: function() {
				this.removeEventListener( orig, handler, true );
			}
		};

		function handler( e ) {
			e = jQuery.event.fix( e );
			e.type = fix;
			return jQuery.event.handle.call( this, e );
		}
	});
}

Once again make sure that you are using focusin/focusout instead of focus/blur when used with live .

mouseenter and mouseleave events

mouseenter and mouseleave events do not bubble in IE. However mouseover and mouseout do bubble in IE. If you are not sure of what the difference is between mouseenter and mouseover then watch this excellent screencast by Ben.

The fix that was applied to map for focusin can be replicated here to fix mousetner and mouseleave issue. This is the commit that fixed mouseenter and mouseleave issue with live method.

jQuery.each({
	mouseenter: "mouseover",
	mouseleave: "mouseout"
}, function( orig, fix ) {
	jQuery.event.special[ orig ] = {
		setup: function( data ) {
			jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
		},
		teardown: function( data ) {
			jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
		}
	};
});

Event detection

Two more events are left to be handled: submit and change. Before jQuery applies fix for these two events, jQuery needs a way to detect if a browser allows submit and change events to bubble or not. jQuery team does not favor browser sniffing. So how to go about detecting event support without browser sniffing.

Juriy Zaytsev posted an excellent blog titled Detecting event support without browser sniffing . Here is the a short and concise way he proposes to find out if an event is supported by a browser.

var isEventSupported = (function(){
    var TAGNAMES = {
      'select':'input','change':'input',
      'submit':'form','reset':'form',
      'error':'img','load':'img','abort':'img'
    }
    function isEventSupported(eventName) {
      var el = document.createElement(TAGNAMES[eventName] || 'div');
      eventName = 'on' + eventName;
      var isSupported = (eventName in el);
      if (!isSupported) {
        el.setAttribute(eventName, 'return;');
        isSupported = typeof el[eventName] == 'function';
      }
      el = null;
      return isSupported;
    }
    return isEventSupported;
  })();

In the comments section John Resig mentioned that this technique can also be used to find out if an event bubbles or not.

John committed following code to jQuery.

var eventSupported = function( eventName ) {
	var el = document.createElement("div");
	eventName = "on" + eventName;

	var isSupported = (eventName in el);
	if ( !isSupported ) {
		el.setAttribute(eventName, "return;");
		isSupported = typeof el[eventName] === "function";
	}
	el = null;

	return isSupported;
};

jQuery.support.submitBubbles = eventSupported("submit");
jQuery.support.changeBubbles = eventSupported("change");

Next task is to actually make a change event or a submit event bubble if ,based on above code, it is determined that browse is not bubbling those events .

Making change event bubble

On a form a person can change so many things including checkbox, radio button, select menu, textarea etc. jQuery team implemented a full blown change tracker which would detect every single change on the form and will act accordingly.

Radio button, checkbox and select changes will be detected via change event. Here is the code.

click: function( e ) {
	var elem = e.target, type = elem.type;

	if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
		return testChange.call( this, e );
	}
},

In order to detect changes on other fields like input field, textarea etc keydown event would be used. Here it the code.

keydown: function( e ) {
	var elem = e.target, type = elem.type;

	if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
		(e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
		type === "select-multiple" ) {
		return testChange.call( this, e );
	}
},

IE has a proprietary event called beforeactivate which gets fired before any change happens. This event is used to store the existing value of the field. After the click or keydown event the changed value is captured. Then these two values are matched to see if really a change has happened. Here is code for detecting the match.

function testChange( e ) {
		var elem = e.target, data, val;

		if ( !formElems.test( elem.nodeName ) || elem.readOnly ) {
			return;
		}

		data = jQuery.data( elem, "_change_data" );
		val = getVal(elem);

		if ( val === data ) {
			return;
		}

		// the current data will be also retrieved by beforeactivate

		if ( e.type !== "focusout" || elem.type !== "radio" ) {
			jQuery.data( elem, "_change_data", val );
		}

		if ( elem.type !== "select" && (data != null || val) ) {
			e.type = "change";
			return jQuery.event.trigger( e, arguments[1], this );
		}
}

Here is the commit that fixed this issue.

jQuery.event.special.change = {
	filters: {
		focusout: testChange,

		click: function( e ) {
			var elem = e.target, type = elem.type;

			if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
				return testChange.call( this, e );
			}
		},

		// Change has to be called before submit

		// Keydown will be called before keypress, which is used in submit-event delegation

		keydown: function( e ) {
			var elem = e.target, type = elem.type;

			if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
				(e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
				type === "select-multiple" ) {
				return testChange.call( this, e );
			}
		},

		// Beforeactivate happens also before the previous element is blurred

		// with this event you can't trigger a change event, but you can store

		// information/focus[in] is not needed anymore

		beforeactivate: function( e ) {
			var elem = e.target;

			if ( elem.nodeName.toLowerCase() === "input" && elem.type === "radio" ) {
				jQuery.data( elem, "_change_data", getVal(elem) );
			}
		}
	},
	setup: function( data, namespaces, fn ) {
		for ( var type in changeFilters ) {
			jQuery.event.add( this, type + ".specialChange." + fn.guid, changeFilters[type] );
		}

		return formElems.test( this.nodeName );
	},
	remove: function( namespaces, fn ) {
		for ( var type in changeFilters ) {
			jQuery.event.remove( this, type + ".specialChange" + (fn ? "."+fn.guid : ""), changeFilters[type] );
		}

		return formElems.test( this.nodeName );
	}
};

var changeFilters = jQuery.event.special.change.filters;

}

Making submit event bubble

In order to detect submission of a form, one needs to watch for click event on a submit button or an image button. Additionally one can hit ‘enter’ using keyboard and can submit the form. All of these need be tracked.

jQuery.event.special.submit = {
	setup: function( data, namespaces, fn ) {
		if ( this.nodeName.toLowerCase() !== "form" ) {
			jQuery.event.add(this, "click.specialSubmit." + fn.guid, function( e ) {
				var elem = e.target, type = elem.type;

				if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
					return trigger( "submit", this, arguments );
				}
			});

			jQuery.event.add(this, "keypress.specialSubmit." + fn.guid, function( e ) {
				var elem = e.target, type = elem.type;

				if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
					return trigger( "submit", this, arguments );
				}
			});
		}
	},

	remove: function( namespaces, fn ) {
		jQuery.event.remove( this, "click.specialSubmit" + (fn ? "."+fn.guid : "") );
		jQuery.event.remove( this, "keypress.specialSubmit" + (fn ? "."+fn.guid : "") );
	}
};

As you can see if a submit button or an image is clicked inside a form the submit event is triggered. Additionally keypress event is monitored and if the keyCode is 13 then the form is submitted.

live method is just pure awesome. It is great to see last few wrinkles getting sorted out. A big Thank You to Justin Meyer of JavaScriptMVC who submitted most of the patch for fixing this vexing issue.

Hidden feature of jQuery - calling a method on a jQuery collection

I was going through the Adding keyboard navigation and noticed that Remi replaced this code

$('.coda-slider-wrapper ul a.current').parent().next().find('a').click();

with this code

var direction = 'next';
$('.coda-slider-wrapper ul a.current').parent()[direction]().find('a').click();

I had never seen anything like that. In the above mentioned article, Remi used next and prev methods. However I wanted to know all the options I could pass since this feature is not very documented.

Snippet from jQuery source code

Here is code from jQuery that makes that above method work.

jQuery.each({
	parent: function(elem){return elem.parentNode;},
	parents: function(elem){return jQuery.dir(elem,"parentNode");},
	next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
	children: function(elem){return jQuery.sibling(elem.firstChild);},
	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
}, function(name, fn){
	jQuery.fn[ name ] = function( selector ) {
		var ret = jQuery.map( this, fn );

		if ( selector && typeof selector == "string" )
			ret = jQuery.multiFilter( selector, ret );

		return this.pushStack( jQuery.unique( ret ), name, selector );
	};
});

As you can see, a variety of selectors can be passed to jQueryCollection[].

If you want to give a try, any jQuery enabled site should perform all of the below mentioned code without any problem.

var a = $('a:first');
var log = console.log;

log(a['parent']());
log(a['parents']());
log(a['next']());
log(a['prev']());
log(a['nextAll']());
log(a['prevAll']());
log(a['siblings']());
log(a['children']());
log(a['contents']());

Use end more often in jQuery while building DOM elements

I want to create following markup dynamically using jQuery.

<div>
  <p>
    This is p
  </p>
</div>

Following jQuery code will do the work.

$(document).ready(function() {
  var div = $('<div></div>');
  var p = $('<p></p>').text('this is p')
                      .appendTo(div);

  $('body').append(div);
});

A better way to accomplish the same is presented below.

$('<div></div>')
  .append('<p></p>')
    .find('p')
    .text('this is p')
    .end()
  .appendTo('body');

Using .end() you can go back one level. And you can use .end() any number of times to get out of a deeply nested tag.

$('<div></div>')
  .append('<p></p>')
    .find('p')
    .append('<span></span>')
      .find('span')
      .text('this is span')
      .end()
    .end()
  .appendTo('body');

JavaScript Basics Quiz

Let’s look at some JavaScript questions.

Question 1

What’s the output.

x = 90;
function f(){
  console.log(x);
  var x = 100;
}
f();

Answer 1

The result is undefined . In JavaScript a variable exists in the scope of a function and that variable can be defined anywhere in the function. To find out more about lexical scope read here and here .

Question 2

Go to prototype homepage open firebug and execute following code.

var a = ['a','b','c'];
var result = '\n';
for (i in a){
  result += 'index: '+ i + ' value:' + a[i] + '\n';
}

Now go to jQuery homepage and execute the same code. Notice the difference in output. Why the difference?

Answer 2

Prototype adds additional methods to Array using Array.prototype . Those methods show up when you iterate through them. If you want to ignore methods added through Array.prototype then use this code.

var a = ['a','b','c'];
var result = '\n';
for (i in a){
  if (a.hasOwnProperty(i))
    result += 'index: '+ i + ' value:' + a[i] + '\n';
}

Question 3

In order to find if an element with id foo is present, one can do

if ($('#foo').length > 0)
  console.log('id foo is present');

How can you make the conditional statement shorter.

Answer 3

In JavaScript following items evaluate to false in a conditional statement: undefined, null, false, empty string, NaN, 0

if ($('#foo'))
  console.log('id foo is present');

Question 4

What is the output in this case. Notice that function bar is defined after the return statement.

function foo(){
  console.log(z);
  console.log(bar());
  return true;

  function bar(){
    return 'this is bar';
  };

  var z = 'zzz';
};

foo();

Answer 4

Output is

undefined
this is bar
true

Question 5

What’s output in this case.

function logit(n){console.log(n);}

for(i=1;i<5;i++){
 setInterval(function(){logit(i)},2000);
}

Answer 5

The result would be output 5 5 5 5 and all the four output will appear together in one shot. Then after 2 seconds another set of similar data would appear. This would continue forever.

Question is why do I see the output in one single shot and why do I see value 5 for all four cases.

Browsers execute JavaScript in a single thread. While that thread is busy executing ‘for loop’ the thread makes note of additional instructions like setInterval. Since the thread is already running ‘for loop’, the same thread can’t run setInterval. So the thread finishes the ‘for loop’ and then looks up additional tasks to be performed. It find setInterval task to be waiting. It executes the function. While it is executing the function ,by virtue of closure, the value of i is 5. Hence you see ` 5 5 5 5` and you see all that in one single shot.

Correct implementation would be

function logit(n){console.log(n);}

var counter = 0;
var timer = setInterval(function() {
	logit(counter);
	counter++
	if (counter == 5) {
		clearTimeout(timer);
	}
},
2000);

Above code would print 0 1 2 3 4 at an interval of 2 seconds.

Question 6

What’s the output in this case.

flight = { status: 'arrived'}
console.log(typeof(flight.status));
console.log(typeof(flight.toString));
console.log(flight.hasOwnProperty('status'));
console.log(flight.hasOwnProperty('toString'));

Answer 6

string
function
true
false

Question 7

What’s output in this case.

function Person(name) { this.name = name;}
Person.prototype.welcome = function(){ return 'welcome ' + this.name}

p = new Person('John');

console.log(p.welcome.call(p));

o = {name: 'Mary'}

console.log(Person.prototype.welcome.call(o));

Answer 7

welcome John
welcome Mary

Question 8

JavaScript has Math library which can be used like this

Math.max(6,7,8) // result is 8

If I provide an array with certain values then how would you find the max value for that array.

a = [1,2,3];

Answer 8

This answer builds up on the answer provided in #7 .

You can try this but it will fail.

Math.max(a) //output is NaN

You can try this but it will fail too.

Math.max.call(Math,a); // output is NaN

This will work

Math.max.apply(Math,a); //output is 3

apply method works because it accepts an array as the argument. call method passes the individual params to the called method directly and hence it does not work. You can read more about JavaScript apply and call methods here .

How live method works in jQuery. Why it does not work in some cases. When to use livequery.

Following code has been tested with jQuery 1.3.2 version .

All the JavaScript code mentioned in this blog should be tried on firebug.

The super popular live method was added to jQuery 1.3 . It works just great. Except when it does not work. As per the documentation this method does not work in following cases: blur, focus, mouseenter, mouseleave, change, submit .

How binding events work in jQuery

$('a').click(function(){
  console.log('clicked');
});

In above case click event is bound to all the links in the document. jQuery stores such binding information as data attribute of the bound element. This is how I can access the list of all functions bound to an element.

$('a').data('events');// Object click=Object

If a new link is dynamically added then that new link will not get this click behavior. Tosolve this problem I can use live method.

Trying out live event

$('a').live('click',function(){
  console.log('clicked');
});

If I add a new a tag dynamically then that tag will automatically get the new click behavior. That’s great.

Just like the previous section, now I am going to find the events bound to a element. However when I execute following code I get undefined .

$('a').data('events')); //undefined

Why is that. In the previous section I showed that all the events bound to an element are stored as the data attribute of that element. Well, live is different. live events are not bound to the element directly. They are bound to the top level ‘document’. I can verify this by trying out this code

jQuery.data(document, 'events').live; //Object

How does live method work

live methods do not set anything on elements directly. All the event handlers are set at the document level. It means that in order for live methods to work, event bubbling is required. If you don’t know what event bubbling is then read her . It also means that event should not be stopped while it is propagating to document. If event propagation is stopped then event handlers bound at the document level will never know about that event and live method will fail.

The strategy to let someone else deal with the event is called event delegation. You can read more about event delegation here .

When live method is called then a binding is done at the document level. Loosely translated this is what is basically happening.

$(document).bind('click', function(event){
  var $target = $(event.target);
  if($target.is('p')){
    console.log('p was clicked');
  }
});

As you can see when a click on p event bubbles all the way to the top then that event is captured by document and necessary action is taken if the target element matches.

It is clear that if the click event is stopped before it reaches document then live method will not work. I will show you an example.

<div id='parent'>
 Languages
 <p>Java</p>
 <p>Javascript</p>
</div>

$('p').live('click',function(e){
  console.log('p was clicked');
});

If I click on Java or Javascript I get a message on console. live is working great. Now I’ll stop the event propagation when event reaches to div.

$('p').live('click',function(e){
  console.log('p was clicked');
});

$('#parent').click(function(e){
  console.log('stopping propagation');
  e.stopPropagation();
});

Now you will notice that live is no more working.

live does not work when event bubbling is not supported

In the previous section I showed that when event does not bubble up to document then live fails. It means that all the events that do not bubble will not work. Which means that events like blur, focus, mouseenter, mouseleave, change and submit which do bubble in IE will not work in IE. However note that these events will continue to work in Firefox.

<select id='lab1a' name="sweets" multiple="multiple">
<option>Chocolate</option>
<option selected="selected">Candy</option>
<option>Taffy</option>
<option selected="selected">Caramel</option>
<option>Fudge</option>
<option>Cookie</option>
</select>
<div id='lab1b' style='color:red;'></div>

$("#lab1a").live('change',function () {
  var str = "";
  $("select option:selected").each(function () {
    str += $(this).text() + " ";
  });
  $("#lab1b").text(str);
});

Above code will work in firefox but it will not work in IE.

Here is an example of an event that does not work in IE: onchange event.

DOM models suggest that onchange event should bubble . However msdn documentation clearly says that onchange event does not bubble .

Make all the live method problems go away

To recap live method will not work in following cases:

  • live method works on event propagation, if an event is stopped while it is bubbling then live will not work.
  • IE does not support bubbling for certain events. live method on those events will not work in IE.

There is a way to get around to both the problems.

Brandon Aaron developed livequery plugin which was finally merged into jQuery as live method. livequery plugin solves both the problems listed above and the code works in IE too.

First step is to include this plugin

<script src="http://github.com/brandonaaron/livequery/raw/master/jquery.livequery.js" type="text/javascript"></script>

Now try this code.

$('p').livequery('click',function(e){
  alert('p was clicked');
});

$('#parent').click(function(e){
  alert('stopping progpagation');
  e.stopPropagation();
});

$("#lab1a").livequery('change',function () {
  var str = "";
  $("select option:selected").each(function () {
    str += $(this).text() + " ";
  });
  $("#lab1b").text(str);
});

<select id='lab1a' name="sweets" multiple="multiple">
  <option>Chocolate</option>
  <option selected="selected">Candy</option>
  <option>Taffy</option>
  <option selected="selected">Caramel</option>
  <option>Fudge</option>
  <option>Cookie</option>
</select>
<div id='lab1b' style='color:red;'></div>
<div id='parent'>
 Languages
 <p>Java</p>
 <p>Javascript</p>
</div>

If I click on ‘Java’ or ‘Javascript’ I will get proper response even though event propagation is being stopped. Also even though change event does not bubble in IE, above code works in IE.

livequery works because livequery ,unlike live, method does not do binding at the document level. livequery does binding at the element level. You can find that out by running following code.

$('p').data('events');

Above code will produce result if I am using livequery. Above code will not produce any result if I am using live method.

The key piece of code in the plugin that makes all this work is

// Create a timeout to check the queue and actually run the Live Queries

$.livequery.timeout = setTimeout($.livequery.checkQueue, 20);

Every 20 milliseconds livequery runs all the bindings defined in livequery and then binds the matched element with the event.

By understanding the internals of how live and livequery are implemented, now you can choose to use livequery in certain cases where live will not work. Also it helps to understand how live actually works.

Live method finds elements and then throws it away. Not very efficient.

A typical use of live method is something like this.

$('p').live('click',function(e){
  console.log('p was clicked');
});

As it has already been discussed a live method registers events at document level.

However when $('p').live(...) is evaluated then jQuery first goes and finds all the p elements. And then what does it do with those elements. Nothing. That’s right. jQuery throws away all those p elements which were just found without using them. What a waste.

If your application has a lot of live methods and this might slow down the performance of the application.

A better solution would have been to design an API like this one:

$.live('p', 'click', function(){..});

jQuery is flexible and I can create my own live method but it will add to the confusion. Another solution would be to make the call to live method without first finding all those p element. Here is how it can be done.

var myDocument = $(document);
myDocument.selector = 'p';
myDocument.live('click', function(){
  console.log('p was clicked');
});

In the above case no element will be selected only to be thrown away. This is much better.

Seeing is believing

In the previous section, I showed how live method can be made to work without first selecting the elements. However a friend of mine asked me if I could conclusively prove that in the real live method a find is actually done. And in my solution a find call is not done.

Here I am showing you the overriding find method. In this method I am overriding the original find method. I will put a log message before passing the find method to the original method.

(function() {
  var originalFindMethod = jQuery.fn.find;
  jQuery.fn.find = function() {
    console.log('find was called');
    originalFindMethod.apply(this, arguments);
  };
})();

$(document).ready(function() {
  $('p').live('click', function() {
    console.log('p was clicked');
  });
});

In the above case you will get message on firebug console confirming that find is indeed invoked when live method is called.

Here is revised version of live. Try this one.

(function() {
  var originalFindMethod = jQuery.fn.find;
  jQuery.fn.find = function() {
    console.log('find was called');
    originalFindMethod.apply(this, arguments);
  };
})();

$(document).ready(function() {
  var myDocument = $(document);
  myDocument.selector = 'p';
  myDocument.live('click', function() {
    console.log('p was clicked');
  });
});

Above version does not print ‘find was called’.

Encapsulation in JavaScript

JavaScript does not allow you to define a method as public or private. This is a limitation users need to get around to, because in real life you don’t want to expose all methods as public method.

Here is a simple implementation of the case where you want to verify input code.

function verifycode(code){
  console.log(code.length);
  return code.length == 4 ? true : false;
}

function info(code){
  if (verifycode(code)){
    console.log(code + ' is valid');
  } else {
    console.log(code + ' is wrong');
  }
}

info('abcd');
info('rty');

In the above implementation anyone can call the method verifycode. Not good. Here is one way to fix this problem.

var Lab = Lab || {};
Lab = (function() {
	var verifycode = function(code) {
		console.log(code.length);
		return code.length == 4 ? true: false;
	}
	return {
		info: function(code) {
			if (verifycode(code)) {
				console.log(code + ' is valid');
			} else {
				console.log(code + ' is wrong');
			}
		}
	}
})();

Lab.info('abcd');
Lab.info('rty');
Lab.verifycode('abcd'); //verifycode is private

Another way to solve the same problem would be to create a constructor function. Here is an implementation.

function Lab(code) {
        this.code = code;
	var verifycode = function() {
		return code.length == 4 ? true: false;
	};
	this.info = function() {
		if (verifycode()) {
			console.log(code + ' is valid');
		} else {
			console.log(code + ' is wrong');
		}
	}
}
(new Lab('abcd')).info();

Here is another way to solve the same problem. In this case I have moved all the public methods to prototype.

function Lab(code) {
	this.code = code;
	this.verifycode = function() {
		l = code.length;
		return l == 4 ? true: false;
	};
}

Lab.prototype.info = function() {
	if (this.verifycode()) {
		console.log(this.code + ' is valid');
	} else {
		console.log(this.code + ' is wrong');
	}
};

(new Lab('abcd')).info();

Integrating JavaScriptLint with mvim and getting rid of annoying warnings

I use JavaScriptLint along with JavaScriptLint.vim on mvim to catch any JavaScript syntax error or missing semicolons. It works great except in cases when I am chaining methods like this.

var select_col1 = $('<select></select>')
  .addClass('ram_drop_down')
  .addClass('ram_drop_down_col1')
  .attr('name','adv_search['+random_num+'_row][col1]')
  .attr('id',random_num+'_ram_drop_down_col1');

In such cases JavaScriptLint had warnings for me.

unexpected end of line. It is ambiguous whether these lines are part of the same statment.

JavaScriptLint wants me to put the dot at the end of the line and not at the beginning of the line. Well, I like having dots at the beginning of lines and I wanted to turn off such warning.

JavaScriptLint comes with a default config file. I copied the config file to a personal directory and disabled the warning.

before: +ambiguous_newline
after: -ambiguous_newline

Also I had to comment out +process jsl-test.js at the very bottom. Now tell your plugin to to use this configuration file rather than the default one. Add the following line to your vimrc file.

let jslint_command_options = '-conf "/Users/neeraj/vim/plugin/jslint/jsl.custom.conf" -nofilelisting -nocontext -nosummary -nologo -process'

This is the vim settings I use and it has been configured to take care of it. Just go to vimrc.local and change the path to your config file. Also don’t forget to remove " at the beginning of the line to uncomment it.

Wrap your function with self invoking jQuery instead of performing find/replace

Following code is tested with jQuery 1.3 .

I have following code which depends on jQuery.

var Search = {
  initAction: function($elm) {
	  if ($elm.attr('value').length === 0) {
		  $elm.attr('value', 'search');
		}
	},

	blurAction: function($elm) {
		if ($elm.attr('value') === 'search') {
			$elm.attr('value', '');
		}
	}
};

Search.initAction($('#query_term_input'));
Search.blurAction($('#query_term_input'));

Everything is cool.

Next, company decides to use a cool JavaScript widget that depends on Prototype library. After adding the Prototype library my code starts failing. I have been asked to fix my code.

I can obviously go through the code and do a mass find $ and replace $ with jQuery. This is error prone.

A better solution would be to make use of self invoking function and redefine $ to jQuery .

var Search = (function($) {
	return {
		initAction: function($elm) {
			if ($elm.attr('value').length === 0) {
				$elm.attr('value', 'search');
			}
		},

		blurAction: function($elm) {
			if ($elm.attr('value') === 'search') {
				$elm.attr('value', '');
			}
		}

	}; // return

})(jQuery);

Search.initAction(jQuery('#query_term_input'));
Search.blurAction(jQuery('#query_term_input'));

Understanding this in Javascript object literal

Here is code.

var foo = {

   first: function(){
     console.log('I am first');
   },

   second: function(){
     console.log('I am second');
   },
};

foo.first();
foo.second();

Everything works fine.

Now there is a need for function second to call function first. Try this and it will fail.

var foo = {

   first: function(){
     console.log('I am first');
   },

   second: function(){
     console.log('I am second');
     first();
   },
};

foo.second();

One way to fix this problem is to hardcode value foo inside the second function. Following code works.

var foo = {

   first: function(){
     console.log('I am first');
   },

   second: function(){
     console.log('I am second');
     foo.first();
   },
};

foo.second();

Above code works but hardcoding the value of foo inside the object literal is not good. A better way would be to replace the hardcoded name with this .

var foo = {

   first: function(){
     console.log('I am first');
   },

   second: function(){
     console.log('I am second');
     this.first();
   },
};

foo.second();

All is good.

Chasing this

Javascript allows one to create function inside a function. Now I am changing the implementation of method second. Now this method would return another function.

var foo = {

   first: function(){
       console.log('I am first');
   },

   second: function(){
     return function(){
         this.first();
     }
   },
};

foo.second()();

Also note that in order to invoke the returned function I have double ()() at the end.

Above code does not work. It did not work because this has changed. Now this in second function refers to the global object rather than referring to the foo object.

Fix is simple. In the function second store the value of this in a temporary variable and the inner function should use that temporary variable. This solution will work because of Javascript’s inherent support for closure.

var foo = {

   first: function(){
       console.log('I am first');
   },

   second: function(){
     var self = this;
     return function(){
         self.first();
     }
   },
};

foo.second()();

jQuery custom events

Following code has been tested with jQuery 1.3 .

Javascript is all about interactions. When an event happens then something should happen. For example hover, click, focus, mouseover etc are basic events which are used on a regular basis. jQuery provides a method called bind to bind an action to an event. For example, if we want an alert message when we click on a link then that can be done like this.

$('a').bind('click', function(){
 alert('I have been clicked');
});

jQuery also allows developers to make use of custom events. How it is going to help us, we are going to see it shortly. First let’s take a look at a basic calendar application.

This is a simple javascript calendar which primarily does four things: render calendar itself, pull data from API and update calendar with API data, ability to collapse event information and ability to expand event information.

Code looks like this.

function redrawForMonth(d){
  //business logic to render calendar

   $('#monthly_calendar_umbrella').updateCalendarWithAPIData();
   $('#monthly_calendar_umbrella').ExpandAllEvents();
};

function updateCalendarWithAPIData(){
  //business logic to get the data from API and appending data to appropriate date cell

};

function CollapseAllEvents(){
 //business logic

};

function ExpandAllEvents(){
 //business logic

};

In the above case we have four methods. If all the implementation is filled out and helper methods are added then ,in total, we’ll have tons of methods.

And slowly, it’ll become difficult to see which methods act on the main element monthly_calendar_umbrella.

Let’s look at the same functionality if implemented using jQuery custom events.

$('#monthly_calendar_umbrella')

 .bind('redrawForMonth',function(e,d){

 })

 .bind('updateCalendarWithAPIData',function(e,d){

 })

 .bind('CollapseAllEvents',function(e){

 })

 .bind('ExpandAllEvents',function(e){

 })

First difference, you will notice is how nicely all the actions possible on the main element are laid out. In this case just one look at the code tells me that four actions can be performed on the main element. This was not so obvious from the first version of the code.

In this case, I am binding events such as ‘redrawFroMonth’ to the element. Obviously ‘redrawForMonth’ is not a native event such as ‘click’ or ‘submit’. This is what I mean by binding ‘custom events’ to elements. In this case ‘redrawForMonth’ is a custom event.

The other thing that is not so obvious is the shift in focus. Traditional javascript programming has been too obsessed with the elements that is clicked or submitted that causes an action. The emphasis has been too much on keeping the code around the element that creates an action. In this case the code has been developed around the element that is being acted upon.

Now, the last part of the discussion is how to trigger custom events. Well, jQuery has a method called trigger .

Note that while binding a function is passed. The first parameter of that function is always an event handler. In the below example I am passing only one parameter even though the function takes two parameters: event handler element and the parameter I defined.

$('#monthly_calendar_umbrella').trigger('redrawForMonth',new Date())

jQuery base code to create a jQuery plugin

Following code has been tested with jQuery 1.3 .

Recently I was discussing how to create a jQuery plugin with a friend of mine. In the end I had a base code that should work as a starting point of any jQuery plugin.

Take a look here .

jQuery.Data for inspecting jQuery internals and for storing information

Following code has been tested with jQuery 1.3 .

Let’s say that I have bound all the links to display an alert.

$('a').bind('click',function(e){
  e.preventDefault();
  alert('clicked');
});

Mine is a large application and a co-worker has added another javascript file which does this

$('a').bind('click',function(e){
  e.preventDefault();
  alert('hello');
});

Now if I click on a link I get two alerts. Not good. One way to debug would be to go through all the included javascript files.

However it would be cool if there is a way to find all the click handlers associated with an element.

jQuery has data method which it uses internally to store information. jQuery uses data method to store all the handlers associated with an element. We could use this information to our advantage. Here I am trying to find out all the click handlers associated with the first link.

var output = jQuery.data($('a').get(0),'events');

jQuery.each(output.click, function(key,value){
 alert(value);
});

The output looks like this

function (e) { e.preventDefault(); alert("clicked"); }
function (e) { e.preventDefault(); alert("hello"); }

jQuery.data method is also very useful if you want to store some information about an element. For example, in an application you need to store information about people. In the html page you are only displaying names. And when a name is clicked then you want to display age, hometown and the company they work for. You can store information about each user using jQuery.data and you can retrieve it when user name is clicked.

Event propagation and peventDefault

Let’s look at sample html.

<div id='parent'>
  Languages
  <p>Java</p>
  <p>Javascript</p>
</div>

And here is the javascript code. Run the code with jQuery-1.3.2 .

$(document).ready(function(){
  $('#parent').click(function(){
    alert('parent was clicked');
  });
  $('#parent p').click(function(){
    alert('p was clicked');
  });
});

When you click on Java then you will get two alerts. That is because the click on element p will propagate outward and it will be caught by element div which has onclick trigger.

If you do not want the event to propagate then here is a way to stop it.

$(document).ready(function(){
  $('#parent').click(function(){
    alert('parent was clicked');
  });
  $('#parent p').click(function(e){
    alert('p was clicked');
    e.stopPropagation();
  });
});

Stopping the default behavior

Converting a regular html link into an AJAX request is easy. One of the things you need to do is to return false so that the click operation does not perform its default behavior.

$('a').bind('click',function(){
   alert('clicked');
   return false;
});

However there is another way to handle such cases. preventDefault stops the default behavior. The same code could be written as

$('a').bind('click',function(e){
   e.preventDefault();
   alert('clicked');
});

Not sure why but I have noticed that e.preventDefault() should be the first line in the function. If I switch the order of e.preventDefault and alert message in the above javascript then it does not work in Firefox/mac.

What is JSONP?

This is part II of How to create dynamic javascript widget.

What problem JSONP solves?

Browsers do not allow cross-domain Ajax requests. For example if you try to make Ajax request to http://www.eventsinindia.com/events/14633.js [update: link not working] to get event data you will get following error.

Access to restricted URI denied.

In order to get around this security problem you can do any number of things including sending the Ajax request to your server which will get the JSON data from the eventsinindia.com API. Or use iframe. Both of these solutions are implemented and discussed in this article .

However in some cases JSONP solves this problem much more elegantly.

Before we discuss JSONP some basics ?

Before looking at JSONP let’s cover some basics. When a html page includes a javascript file then the html code looks something like this.

<script src="http://neeraj.name/javascripts/color.js" type="text/javascript"></script>

There are two things to notice here. First is that the source of the javascript file could be cross-domain. It means your html page can point the source of your javascript file to http://neeraj.name/javascripts/cache/all.js and all.js will be loaded by the browser. This feature which allows cross-domain loading of javascript file is the basis of JSONP.

The second thing to notice is that the javascript written in color.js is immediately evaluated after the source file has been loaded. For example the content of color.js could be this.

alert('hello');

When the html page is loaded you will get an alert.

Let’s recap: In the above section I showed you how you can point the source of your javascript file to a domain that is not yours (cross-domain) and the code loaded from the domain is immediately evaluated.

What is JSONP?

From the above section it is clear that if by some means we could dynamically create a script node and point the source of that node to cross-domain and if the remote site returns a javascript function then that function will be evaluated.

However in the world of JSON we only get JSON data from the remote server. If we want to stick the returned JSON data on our page then that data needs be used by a javascript function. And that’s where JSONP comes in handy.

Let’s take an example. If you make a call to http://www.eventsinindia.com/events/14633.js you will get JSON data back.

{"name": "Craft Classes" , "start_date": "2009-05-01" , ....}

However what you really want is to do is to stick this data on your html page by invoking a javascript function like this

AddThisDataToPage({"name": "Craft Classes" , "start_date": "2009-05-01" , ....});

What needs to be done is while making a call to http://www.eventsinindia.com/events/14633.js pass a parameter called callback . So in this case the full url would look something like this

http://www.eventsinindia.com/events/14633.js?callback=AddThisDataToPage

Remember callback is a special word here. By using callback we are telling API to wrap the response JSON data with a call to function named AddThisDataToPage.

Click on following two links to see the difference. The first link is returning pure JSON data while the second link will return a javascript function.

http://www.eventsinindia.com/events/14633.js

http://www.eventsinindia.com/events/14633.js?callback=AddThisDataToPage

Using JSONP with jQuery

jQuery makes it easy to use JSONP. Look for documentation on how to use JSONP with jquery here .

Callback is not the name everyone uses

Most of the people use callback as the key word to identify client is asking for JSONP data. However some people use a different keyword. For example flickr uses the keyword jsoncallback

This returns JSON data

http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json

In this case callback is being passed but flickr ignores it.

http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&callback=show

In this case callback is being passed but the name is jsoncallback.

http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=show

Providing support for JSONP

All the APIs should provide support for JSONP. Enabling JSONP support is easy if you are using Rails 2.3 or any Rack compliant framework. In Rails 2.3 all you need to do is stick this file in lib as jsonp.rb and then add one line to the environment.rb .

#environment.rb

Rails::Initializer.run do |config|
  .....
  config.middleware.use 'Jsonp'
end

That’s it. Now you are providing support of JSONP with the keyword being callback.

Security

Since the data from external source is read and then that data is evaluated on run time by Javascript, there is potential for security breach. So be careful when you are using JSONP. Only load data from a trusted source.

$stdout.sync = true to flush output immediately

Try this.

5.times do
  putc('.')
  sleep(2)
end

I was hoping that I will get a dot after every two seconds. But that’s not what happens when you run the code. I see nothing for first 10 seconds then I see five dots in one shot. This is not what I wanted.

I started looking around at the documentation for IO class and found the method called sync= which if set to true will flush all output immediately to the underlying OS.

The reason why OS does not flush immediately is to minimize the IO operation which is usually slow. However in this case you are asking OS to not to buffer and to flush the output immediately.

$stdout.sync = true
5.times do
  putc('.')
  sleep(2)
end

Functional scope in Javascript and how Javascript continues to surprise me

Javascript continues to surprise me. Check out this code.

function foo(){

var x = 100;
alert(x);

for (var x = 1; x <= 10; x++){
}

alert(x);
};

foo();

What do you think the value of second alert will be. I thought it would be 100 but the answer is 11. That’s because the scope of a local variable in Javascript is not limited to the loop. Rather the scope of a local variable is felt all over the function.

Before you look at the next piece of code remember that defining a variable without the var prefix makes that variable a global variable.

fav_star = 'Angelina'; /* it is a global variable */

function foo(){

  var message = 'fav star is ' + fav_star ;
  alert(message);

  var fav_star = 'Jennifer';
  var message2 = 'fav star is ' + fav_star;
  alert(message2);
};

foo();

What do you think would be the alert value first time? I thought it would be Angelina but the correct answer is undefined. That is because it does not matter where the variable is defined. As long as the variable is defined anywhere within a function then that variable will be set to undefined. It is when the statement is executed then the value of the variable changes from undefined to Jennifer.

Thanks to Subba for bringing this feature of Javascript to my attention and for discussing it.

Javascript tip - Do not pollute global namespace with utility functions

I am learning Javascript and as I do more Javascript work I am learning not only the language but also the best practices. Today I am developing a Javascript calendar. In the process of creating the calendar I created a bunch of utility functions that are available at global namespace.

What are we talking about

My main concern is that as Javascript develeoper I should not be polluting global namespace. I could write the calendar code like this.

showCalendar = function(options,d){
};

calendarHeaderMonth = function(opts){
};

calendarHeaderWeek = function(opts){
};

calendarData = function(opts){
};

drawCalendar = function(opts,d){
};

getCellID = function(year,month,day){
};

// use showCalendar

showCalendar({},new Date());

You can see that the main method that I want to expose to global namespace is showCalendar. However I am also exposing six other functions to global namespace. It means that if some user has declared a global namespace function named getCellID then my getCellID is going to collide with the user’s function. This is not good.

Goal

The goal is to refactor the code in such a way that only one method showCalendar is exposed to the global namespace. In order to test the code at the very end of the javascript I will invoke a call to method getCellID.

showCalendar = function(options,d){
};

calendarHeaderMonth = function(opts){
};

calendarHeaderWeek = function(opts){
};

calendarData = function(opts){
};

drawCalendar = function(opts,d){
};

getCellID = function(year,month,day){
};

// use showCalendar

showCalendar({},new Date());

// this call should fail but is not failing now

getCellID(2009,5,4);

The above call to getCellID is currently being executed successfully. It means I have polluted the global namespace. I am going to fix it.

Solution

The solution is to put all the code inside a function. In a function all the variables and functions declared are scoped only to that function. Out of that function, inner functions cannot be used. Inside this function only one method showCalendar would be exposed.

Here is the solution.

(function(){

  // by not declaring var this variable is going to be at global namespace

  showCalendar = function(options,d){
  };

  var calendarHeaderMonth = function(opts){
  };

  var calendarHeaderWeek = function(opts){
  };

  var calendarData = function(opts){
  };

  var drawCalendar = function(opts,d){
  };

  var getCellID = function(year,month,day){
  };

})();

showCalendar({},new Date());

// this call will fail

getCellID(2009,5,4);

In the above case the call to showCalendar was successful. However call to getCallID failed. That’s good. It means I am not polluting the global namespace.

If you notice carefully in the above case after declaring an anonymous function I am invoking that function by having () at the end. You can read more about self-invoking function here .