Showing posts with label jQuery. Show all posts
Showing posts with label jQuery. Show all posts

6 January 2012

jQuery Event handler Attachments live, delegate, on

JQuery has powerful event handlers, from 1.0 jquery has a bind function to handle the events of the selectors.

For example
<script type = "text/javascript" >
 $('div.#help').bind('click', function () {
  alert('clicked the Help');
 });
</script>

Above click event is bind to the selector (i.e div element with ID 'Help'), so when a user clicked on the div element the event triggered and alert shown.

With new version new functions for the event handler is also introduced. From 1.3 live function is introduced, this function will attach event handler to document and calls the handler when event occurs on all elements that match the selectors. As with ajax, dynamic content can be added to the page at any time, the bind function will attach events handlers to only existing elements, for those elements added through the ajax, we need to call the bind function once again. This is repeating of same function calling. For this .live came to help, Live will attach event handler to the document and calls the event handler when the event occur on the selector, so the selector may exist or may added in future.

$(selector).live(events, data, handler); // jQuery 1.3+

As the event handler is attached to the document, the events bubble, or propagate, from the deepest, innermost element (the event target) in the document where they occur all the way up to the body and the document element. This is slowest one so in next version i.e 1.4 a new function .delegate is introduced.

.delgate function will attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements. here the improvement is the event handler is not attached to document but to the set of root elements.

$(document).delegate(selector, events, data, handler); // jQuery 1.4.3+

Here is a example
$("table").delegate("td", "click", function() {
  $(this).toggleClass("chosen");
});

Above snippet attach a handler to click event to the selector "table", but calls the handler only when event occurs on "td", which is a selector passed as first argument, therefore td shall exist while this function executed or may be added to the table in future.

One important note from jQuery Documentation
Since the .live() method handles events once they have propagated to the top of the document, it is not possible to stop propagation of live events. Similarly, events handled by .delegate() will propagate to the elements to which they are delegated; event handlers bound on any elements below it in the DOM tree will already have been executed by the time the delegated event handler is called. These handlers, therefore, may prevent the delegated handler from triggering by calling event.stopPropagation() or returning false.

Now in the latest version 1.7 .live and .delegate is replaced with .on which perform the action of the above said functions.

The syntax for the function
$(document).on(events, selector, data, handler); // jQuery 1.7+

If selector (the second argument) is not passed then the event handler attached the document and handler is called when the event occurs on the document(root element). If the selector is passed then the event handler called only event occur on the selector.

Here is a example
$("body").on("click", "p", function(){
      $(this).after("<p>Paragraph Clicked! </p>");
    });

Performance
The event like click are occur rarely, so it will not have a impact on performance. But event like mousemove will occur many time per second. so we must be carefull when we use the events like mousemove, we must cache, so that the calculation will not need to happen on every call.

jQuery can process simple selectors of the form tag#id.class very quickly when they are used to filter delegated events. So, "#myForm", "a.external", and "button" are all fast selectors. Delegated events that use more complex selectors, particularly hierarchical ones, can be several times slower--although they are still fast enough for most applications. Hierarchical selectors can often be avoided simply by attaching the handler to a more appropriate point in the document. For example, instead of $("body").on("click", "#commentForm .addNew", addComment) use $("#commentForm").on("click", ".addNew", addComment).

15 November 2011

Drupal use two different jquery version with noconflict

While developing a website using drupal, we had a requirement, this requirement can be achieved using simple function available on recent release of jQuery, but in drupal 6 core has jQuery 1.2.6 and also if we update the jQuery with drupal module jQuery_update, we shall have only 1.3.2. So next, we can add recent release of jQuery1.7 through theme. Our new requirement will work now fine, hey we appreciate ourselves. But after a few minutes, we will come to know that many other jQuery function stopped working. After debugging, we will know that both version of jQuery is loaded in the same page, so version conflict.

What is the solution?

After digging the net and with reference to the jQuery documentation, I came to know that jQuery has a feature Using jQuery with Other Libraries i.e jQuery can be used with other libraries like mootools,  prototype etc. in a single webpage. To enable this feature jQuery has a function called noConflict.

How to use this function.
<html>
 <head>
   <script src="prototype.js"></script>
   <script src="jquery.js"></script>
   <script>
     jQuery.noConflict();
     
     // Use jQuery via jQuery(...)
     jQuery(document).ready(function(){
       jQuery("div").hide();
     });
     
     // Use Prototype with $(...), etc.
     $('someid').hide();
   </script>
 </head>
 <body></body>
 </html>

Above example demonstrates how jquery can be used with other library. $ is used in both libraries so because of conflict javascript will stop execution.  jQuery.noConflict() line will release the $ variable from jQuery, so we have to write using jquery instead of $ in the jQuery program, this makes the prototype to use $ and execute the code. this way the both libraries run smoothly.

In the same way, we can use the two different version of jQuery in a single page (Drupal). By default drupal core will add jQuery 1.2.6 So in your code you add the latest jQuery and call the noConflict function like the below sample code. Below sample code use a shortcut $j, so from here instead of $ you may use the
$j to access the functions from jQuery 1.7.
<script src="jquery-latest.js"></script>
   <script>
     var $j = jQuery.noConflict();
     
     // Use jQuery via $j(...)
     $j(document).ready(function(){
       // isNumeric function introduced in latest version 1.7
       alert($j.isNumeric(12));
     });
     
     // Use $ for 1.2.6 version $(...), etc.
     $('#someid').hide();
   </script>


If you are using a plugin which is depends on 1.7 then use as below

<script src="jquery-latest.js"></script>
   <script>
     jQuery.noConflict();
     
     // Use jQuery via $j(...)
     jQuery(document).ready(function($){
       // we may use usual code here
       alert($.isNumeric(12));
     });
     
     // Use $ for 1.2.6 version $(...), etc.
     $('#someid').hide();
   </script>