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.

This again and again is a reason why jQuery-based pages in my apps fail to render at some customers but not at all customers...

There must be a solution to this. Or at least others who share the pain ;-)

Image my page using jQuery in the recommended way

<apex:page>
    ... 
    <apex:includeScript value="//anycdn/jquery.min.js" /> 
    <apex:includeScript value="//anycdn/jquery.plugin.min.js" />

    <script type="text/javascript">
        jQuery.noConflict();

        jQuery(document).ready(function() {
            jQuery("#id").pluginMethod();
        });
    </script>
</apex:page>

Now imagine there is a Sidebarcomponent contains Javascript code that registers another version of jQuery with the noconflict() call and using the default alias $.

Sidebar components seem to load faster and so a plugin sometimes is registering not in the jQuery I load in the same page but in the previously loaded jQuery from the Sidebar component.

My call to jQuery("#id").pluginMethod(); will fail in the Browser with a Javascript error

undefined is not a function

The screenshot from my Browsers console proves that the Dynatree plugin was NOT registered with jQuery in the same page but with the $ loaded in the sidebar component (this was proven by using sidebar="false" on the page tag).

I see no easy solution to this as my Script works properly and I cannot really change neither the sidebar Javascript code nor how a Plugin registered itself.

share|improve this question

4 Answers 4

One hacky work-around would be to look for the instance of jQuery that the plugin is registered with:

<script type="text/javascript">
jQuery.noConflict();

jQuery(document).ready(function() {
    if (typeof jQuery.pluginMethod === 'function') {
        jQuery("#id").pluginMethod();
    } else if (typeof $.pluginMethod === 'function') {
        $("#id").pluginMethod();
    }
});
</script>
share|improve this answer
    
Amazing! You made my day ;-) –  Robert Sösemann Aug 15 at 10:35
    
I leave the question open to invite others to come up with more reliable solutions. If those exist ;-). –  Robert Sösemann Aug 15 at 10:36
2  
@RobertSösemann Yeah hopefully there is a cleaner solution. –  Keith C Aug 15 at 10:47

As a shorter (and arguably cleaner) solution to @Keith C.'s answer, you can do something like:

jQuery.noConflict();

jQuery(document).ready(function() {
  var pluginHolder = (jQuery && jQuery.pluginMethod && jQuery) || ($ && $.pluginMethod && $);
  pluginHolder.pluginMethod();
});
share|improve this answer

Sounds like you should be using jQuery = $.noConflict(true);

From the jQuery documentation:

If for some reason two versions of jQuery are loaded (which is not recommended), calling $.noConflict( true ) from the second version will return the globally scoped jQuery variables to those of the first version.

This technique is especially effective in conjunction with the .ready() method's ability to alias the jQuery object, as within callback passed to .ready() you can use $ if you wish without fear of conflicts later:

<script src="other_lib.js"></script>
<script src="jquery.js"></script>
<script>
$.noConflict();
jQuery( document ).ready(function( $ ) {
// Code that uses jQuery's $ can follow here.
});
// Code that uses other library's $ can follow here.
</script>

If necessary, you can free up the jQuery name as well by passing true as an argument to the method. This is rarely necessary, and if you must do this (for example, if you need to use multiple versions of the jQuery library on the same page), you need to consider that most plug-ins rely on the presence of the jQuery variable and may not operate correctly in this situation.

share|improve this answer
up vote 0 down vote accepted

None if the answers given solved my problem in total. There were solutions that worked but were somewhat instable and hacky while others followed the jQuery documentation but did not solve my problem with the concrete code examples given.

Without knowing why, this is the code that indeed worked for me:

<apex:page standardController="Contact" sidebar="true" showHeader="true" >
    ....   
    <apex:includeScript value="//code.jquery.com/jquery-1.11.1.min.js" /> 
    <apex:includeScript value="//code.jquery.com/ui/1.11.0/jquery-ui.min.js" />
    <apex:includeScript value="//cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js" />
    <apex:includeScript value="//cdn.jsdelivr.net/jquery.dynatree/1.2.4/jquery.dynatree.min.js" />

    <script type="text/javascript">
        jQuery = $.noConflict();  // No param true needed

        jQuery(document).ready(function() {
            jQuery("#tree").dynatree();
        });
    </script>  
</apex:page>    

The cruial change to @Charles Koppelman's solution is the assignment of $.noConflict(); to jQuery and then using jQuery in my code. Passing true to noconflict or $ to the ready function absolutely made no difference in my case.

share|improve this answer

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.