In jQuery, if you want to observe an event on certain element, you can choose to use .bind() or .live().

$('#page_title').bind('click', function(){
     $(this).html('you clicked me');
});

Alternatively, you can write the above using shortcut:

$('#page_title').click(function(){
     $(this).html('you clicked me');
});

However, the first format allows you to bind multiple events to the same element with same call back method.

$('#page_title').bind('mouseover mouseout', function(){
     $(this).html('you didn't me');
});

In jQuery, you can also use .live() method.

$('#page_title').live('click', function(){
     $(this).html('you clicked me');
});

According to jQuery doc, .live() attaches a handler to the event for all elements which match the current selector, now or in the future. The difference lies in the word in the future. You could attach a handler to the event for the element even the element doesn’t exist! So you could run the following code before the document is fully loaded.

$('#page_title').live('click', function(){
     $(this).html('you clicked me');
});

However, if you use .bind() method, you must make sure that the document element already exists before you observe it. Otherwise, the event handler won’t be triggered. This is especially useful when you are using Ajax in your website. You could observe the element before the Ajax loads. So you don’t have to rebind the event to the element everytime Ajax finished loading.E.g, normally you will do this :

$.ajax({
   type: "POST",
   url: "some.php",
   data: "name=John&location=Boston",
   success: function(msg){
     $('#page_title').live('click', function(){
          $(this).html("you clicked me");
    });
   }
 });

This is very troublesome and every time you have to reattach those event handlers to the event on the elements. So what you could is adding the event observer even before you add the Ajax:

$('#page_title').live('click', function(){
          $(this).html("you clicked me");
}); 

$.ajax({
   type: "POST",
   url: "some.php",
   data: "name=John&location=Boston",
   success: function(msg){
       //...anything here
   }
 });

But do you find any problem with the above code?

$.ajax({
   type: "POST",
   url: "some.php",
   data: "name=John&location=Boston",
   success: function(msg){
     $('#page_title').live('click', function(){
          $(this).html("you clicked me");
    });
   }
 });

Yes, you shouldn’t use .live(), you should use .bind() instead. If you use .live() here, then every time the Ajax finished loading, the element will add a event handler, although they are the same functionality but different reference. So the Ajax loads twice, you click on the ‘page_title’, it should alert twice.

So remember to use .live() on the same element once only.
Read the rest of this entry »

Recently I have done a project using prototype. However, the performance of jQuery seems much faster than prototype although the difference is not very huge. (check out Dojo vs JQuery vs MooTools vs Prototype Performance Comparison) The other reason is that jQuery community is so huge that more solutions to a problem can be easily found. So I listed out some comparison in methods between prototype and jQuery.

compare prototype and jQuery

prototype method jQuery method comments
$('manager') $('#manager') Prototype $(selector), selector default is the id of the element
$$('#manager') $('#manager') prototype $$ returns an array of prototype element. jQuery $() selector returns a jQuery object reference those matching elements
new Element('input', {'class': 'digit'}) $("< input class='digit' >")  
$('manager').removeClassName('red'); $('#manager').removeClass('red')  
$('manager').addClassName('red'); $('#manager').addClass('red')  
$$('#manager').invoke('addClassName', 'red'); $('#manager').addClass('red') jQuery will automatically apply the method to all the matching elements
$$('#manager').each(function(ele){ele.addClassName('red')}) $('#manager').addClass('red') You don't have to iterate through an array for jQuery
$('manager').observe('click', function(){alert('clicked')}) $('#manager').click(function(){alert('clicked')});  
$$('#manager').each(function(ele){alert(ele.readAttribute('id')}) $.each($('#manager'), function(){alert($(this).attr('id')}) In jQuery earch iterator, the 'this' always refers to the DOM element, in order to use jQuery object method, you should add the jQuery wraper around 'this'
$('manager').readAttribute('name') $('#manager').attr('name')  
$('manager').update("the name") $('#manager').html("the name")  
$('manager').down('div'); $('#manager').find('div')  
$('manager').up('div'); $('#manager').parents('div') In jQuery, .parent() only travels one level up the DOM tree, however parents() will travels all the way up to DOM root

In jQuery, when you use a jQuery wrapper to select some elements, it will be returned as a jQuery Object. E.g. if you run the following code in firebug console:

var div = jQuery("#id_of_div");
alert(div.id);

You may expect it to alert “id_of_div”. However, the result is undefined. You feel surprised especially for developer like me who was using Prototype before. The reason actually is quite simple. In prototype, it extends native DOM elements, so when you use $() to select a DOM elements, all the DOM native methods as well as those methods prototype extend Elements are available. However, in jQuery, the idea is never to extend the native DOM elements, instead every selector you use will return jQuery Object. So you can only use those jQuery Object methods like .attr to read the id of the element. Since it is not a DOM element but a jQuery Object, so you can’t use the native DOM methods like .id or .tHead for tables. So you can do the following instead:

var div = jQuery("#id_of_div");
alert(div.attr("id");

This should give you correct result. What about the one below:

var div = jQuery("#id_of_div").get(0);
alert(div.attr("id"));

This time it will give you a javascript error. The error message is .attr is not a function. The reason is that get(index) will return the DOM element at the index of the jQuery Object returned from the selector. In this case only one element is returned. (the element with id id_of_idv)

So in order to call native DOM method you can use get(index). Or if you want to use jQuery Object method, you should wrap a native DOM element with jQuery, which will convert the DOM element into a jQuery Object, so all the methods will be available. Then what about the following:

var div = jQuery("#id_of_div").first();
alert(div.attr("id"));

You may think that this will give you a javascript error as well since .first() and get(0) should be the same thing. However, you are wrong. .first() function will return a jQuery Object as well. “Given a jQuery object that represents a set of DOM elements, the .first() method constructs a new jQuery object from the first matching element.”-jQuery Doc description. So the call to .attr() method is valid.

So remember one of the main difference between prototype and jQuery is that the way they handles elements and .get(0) and first() is different. The get(0) returns a DOM element and the first() returns a jQuery Object.
Read the rest of this entry »