Monday 1 December 2008

grails: jQuery '$' conflicts

I'm a keen user of jQuery, which I've found to be a very robust, reliable and fairly intuitive javascript library. It offers tonnes of documentation in addition to a vast library of plugins to cater for most if not all your needs.

My experience with this library has been primarily problem-free except for one occasion when I attempted to use it in conjunction with another javascript library. Specifically, I discovered that previously working code implementing jQuery ceased to function when I imported in the scriptaculous library.

Generally jQuery has been well designed to circumvent potential collisions with other libraries through the use of a unique namespace. In spite of this, problems do occur, because of the role of the '$' function in jQuery and other competing libraries. In jQuery it is a shortcut reference to jQuery but means something different for scriptaculous. The solution to this problem is actually quite straightforward and is documented here.

Consider the following code [described in post: grails: toggling Form elements, step 3]



<g:javascript>
    $(document).ready(function() {

$("#status").change(function() {
$.ajax({
url: "/myform/issue/selectOutcome",
data: "status=" + this.value,
cache: false,
success: function(html) {$("#selectOutcome").html(html);}
});
}
);

});

</g:javascript>







This code allows us to use ajax to display/hide form elements based upon the selection made by a user from a drop down list. The code works fine, until I import in scriptaculous


<g:javascript library="scriptaculous"/>



Following this step, I discovered that the previous code stopped working. Implementing the suggestions provided by the jQuery website, I modified the above code as follows



<g:javascript>
    var $j = jQuery.noConflict();

$j(document).ready(function() {

$j("#status").change(function() {
$j.ajax({
url: "/myform/issue/selectOutcome",
data: "status=" + this.value,
cache: false,
success: function(html) {$j("#selectOutcome").html(html);}
});
}
);

});

</g:javascript>




Looking carefully at the before and after code snippets, you can see that the main difference has been to replace '$' with the variable '$j' where j is simply an alias for the function jQuery.noConflict(). This function tells jQuery to ignore the $ function so that scriptaculous or some other library can use it. Modifying the code in this way enables both the scriptaculous and jQuery code to function as expected. QED.

No comments: