Take the 2-minute tour ×
Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

ADDED DETAILS: The problem appears only on those VF pages where a custom homepage component uses another version of jQuery. Those component seems to load later and overwrite the jQuery object that was extended by BlockUI before. That's why any calls to

$(node).block()

show errors that function "block" cannot be found.


I'm experiencing constant problems when using Jquery in combination with the famous BlockUI plugin. It only seems to appear on more complex VF pages that:

  1. Have embedded Javascript
  2. Include external Javascript
  3. Have embedded VF components also include jquery and BlockUI

In the past I thought that using jquery.noConflict() like below:

<script type="text/javascript">
  $j = jQuery.noConflict();
  $j(document).ready(function() {

and <apex:includeScript> instead of <script> would take care of all this multiple loading issues that one might think of.

But BlockUI as a plugin seems to extends the Jquery operator by adding function with $j.fn.. In complex pages when I call blockUI I receive the error that $j.fn.block cannot be found.

Is there a best practise for resolving conflicts with pages that load the same Javasript library multiple times?

  • Should I rename $j in every place?
  • Should I dynamically load libraries by using $j.getScript('{!$Resource.jquery_blockUI_js}');
share|improve this question
2  
I don't use $ at all, just jQuery(...) and have no any conflicts. –  mast0r Jan 17 '13 at 12:17
    
To mastor: Is that really the case? Why does it matter if its called $j or jquery? And do you still use the noConflict method? –  Robert Sösemann Jan 17 '13 at 13:07
1  
To RobertS: no, i dont use noConflict. Just attaching a jQuery from static resource with apex:includeScript and use jQuery instead of $ –  mast0r Jan 17 '13 at 14:11
add comment

1 Answer 1

up vote 6 down vote accepted

jQuery plugins, as a best practice, should be registered on the main jQuery object, NOT on $j or other alternative references to jQuery obtained through use of jQuery.noConflict().

Depending on when/how various jQuery plugins are loaded in the page, this will make the plugins available to all alternate jQuery references (e.g. one developer's code might use $j = jQuery.noConflict(), another's might use j$ = jQuery.noConflict()), but they will all have access to all jQuery plugins registered throughout the page load on the main jQuery object.

To properly register the blockUI plugin, use the code from the plugin's download page --- this registers the plugin on the jQuery global object by, essentially, registering jQuery.fn.block = function(){}, jQuery.fn.unblock = function(){}, etc. However, this code attaches/registers its plugin within a CLOSURE, so its reference to the jQuery global object is locked in. DO NOT register plugins on a unique reference (that is, do NOT do $j.fn.pluginName = function(){}) --- always register plugins on the main jQuery object.

TO avoid reloading a given jQuery plugin multiple times, you could check for the plugin's existence before loading:

if (!jQuery.fn.block) {
    // Load the block UI plugin
} else {
   // Hurray, it's already loaded!
}

Finally, as an aside, all that jQuery.noConflict() does is to relinquish control of the $ variable (or even the jQuery variable if you pass true as a param to it --- but this is NOT a best practice). Using jQuery.noConflict() can be very helpful in Visualforce page development when you don't know how other components that you'll be using within the page will be making use of external JS libraries --- other JS libraries might use the $ variable to refer, for instance, to an old version of jQuery, or to some entirely different JS library altogether. So using something like var $j = jQuery.noConflict(), or even a namespaced version like acme.$ = jQuery.noConflict(), allows you to rest easy knowing that all calls to $j (depending on the scope of where you use it, of course) will return references to jQuery as you expect them to, and NOT to some other vendor's code or version of jQuery.

share|improve this answer
    
zachelrath: I still don't fully understand your solution. I am not at all registering any plugin. I am just loading jquery and blockui as static scripts using '<apex:includeScript>'. I will remove all noConflict lines and just use jQuery as a var name and see if that helps. –  Robert Sösemann Mar 4 '13 at 14:35
    
Does you remark about the reason to why someone should use noConflict tell me that I need to use it, as my version of jquery is colliding with an older version in the same page (Home Page component, so not same VF page but same result page)? –  Robert Sösemann Mar 4 '13 at 14:59
1  
Robert: by loading blockui "as a static script", what is happening is that the blockui jQuery plugin is getting registered on an instance of jQuery. the whole point of my discussion above is that you should register the blockui plugin on jQuery, NOT on $j or $. That is, what your script should be doing is NOT $j.fn.block , but jQuery.fn.block. As to your scenario with Home Page Components, what I'm saying is that it doesn't matter whether you use $j = jQuery.noConflict(), AS LONG AS the blockUI plugin gets attached to jQuery, and NOT JUST to $j. –  zachelrath Mar 4 '13 at 17:50
    
Thanks for your clarification. I guess I was confused by this example where a node is blocked by using an alias $(node).block(); and not jQuery(node).block(); –  Robert Sösemann Mar 5 '13 at 15:17
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.