137

I have a very large javascript file I would like to load only if the user clicks on a certain button. I am using jQuery as my framework. Is there a built-in method or plugin that will help me do this?

Some more detail: I have a "Add Comment" button that should load the TinyMCE javascript file (I've boiled all the TinyMCE stuff down to a single JS file), then call tinyMCE.init(...).

I don't want to load this at the initial page load because not everyone will click "Add Comment".

I understand I can just do:

$("#addComment").click(function(e) { document.write("<script...") });

but is there a better/encapsulated way?

Jeff Meatball Yang
  • 34,069
  • 26
  • 85
  • 118
  • This is a great fork of the TinyMCE compressor, that adds asynchronous loading of TinyMCE via the jQuery.tinyMCE plugin, and includes Gzip, concatenation and minification :https://github.com/bobbravo2/tinymce_compressor/blob/master/tiny_mce_gzip.php – Bob Gregor Dec 27 '12 at 19:19

2 Answers2

203

Yes, use getScript instead of document.write - it will even allow for a callback once the file loads.

You might want to check if TinyMCE is defined, though, before including it (for subsequent calls to 'Add Comment') so the code might look something like this:

$('#add_comment').click(function() {
    if(typeof TinyMCE == "undefined") {
        $.getScript('tinymce.js', function() {
            TinyMCE.init();
        });
    }
});

Assuming you only have to call init on it once, that is. If not, you can figure it out from here :)

Dreen
  • 6,128
  • 10
  • 44
  • 67
Paolo Bergantino
  • 449,396
  • 76
  • 509
  • 431
  • 3
    @Jose: Thanks :), @Jeff: No problem. As far as jQuery awesomeness goes this one is fairly unknown. – Paolo Bergantino May 26 '09 at 21:00
  • 1
    TLDR; only do this if the scripts are in the same directory. Longer version: getScript actually injects the javascript into current scrips instead of the page. what this means is any paths on the included javascript will be relative to the current document. – Tom Carchrae Nov 07 '12 at 03:39
23

I realize I am a little late here, (5 years or so), but I think there is a better answer than the accepted one as follows:

$("#addComment").click(function() {
    if(typeof TinyMCE === "undefined") {
        $.ajax({
            url: "tinymce.js",
            dataType: "script",
            cache: true,
            success: function() {
                TinyMCE.init();
            }
        });
    }
});

The getScript() function actually prevents browser caching. If you run a trace you will see the script is loaded with a URL that includes a timestamp parameter:

http://www.yoursite.com/js/tinymce.js?_=1399055841840

If a user clicks the #addComment link multiple times, tinymce.js will be re-loaded from a differently timestampped URL. This defeats the purpose of browser caching.

===

Alternatively, in the getScript() documentation there is a some sample code that demonstrates how to enable caching by creating a custom cachedScript() function as follows:

jQuery.cachedScript = function( url, options ) {

    // Allow user to set any option except for dataType, cache, and url
    options = $.extend( options || {}, {
        dataType: "script",
        cache: true,
        url: url
    });

    // Use $.ajax() since it is more flexible than $.getScript
    // Return the jqXHR object so we can chain callbacks
    return jQuery.ajax( options );
};

// Usage
$.cachedScript( "ajax/test.js" ).done(function( script, textStatus ) {
    console.log( textStatus );
});

===

Or, if you want to disable caching globally, you can do so using ajaxSetup() as follows:

$.ajaxSetup({
    cache: true
});
dana
  • 14,964
  • 4
  • 53
  • 82
  • This may not have been available when you wrote this, but note that jQuery allows you (globally) to disable this no-caching feature and allow caching again. See http://api.jquery.com/jQuery.getScript/#caching-requests (Oh, I see the $.ajax() approach you cover here is mentioned there as well.) – Peter Hansen May 22 '15 at 22:41
  • @PeterHansen - Thanks for the tip. I updated my answer with your suggestion. – dana Jun 01 '15 at 05:34
  • 4
    jQuery 1.12.0 or later support disabling the anticache inline like this: `$.getScript({url: "test.js",cache:true})` – oriadam Jul 05 '17 at 13:07