0

I have a very basic jQuery plugin which I load into my webpage like so:

(function() {
    var tk = document.createElement('script');
    tk.src = '//www.test.com/scripts/jq_plugin.js';
    tk.type = 'text/javascript';
    tk.async = 'true';
    tk.onload = tk.onreadystatechange = function() {
        var rs = this.readyState;
        if (rs && rs != 'complete' && rs != 'loaded') return;
    };
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(tk, s);
})();

Then, I call the plugin like so:

$(function(){
    $('#test').jq_plugin();
});

But when the page loads I am getting this error:

Uncaught TypeError: undefined is not a function
(anonymous function)

I understand why - the plugin is being called before the script is loaded. I know a quick and dirty hack is just to use a setTimeout() around the plugin call but I don't want to do that. I've tried inserting the script before and after jQuery but get the same result.

How can I do this without a timeout?

This is a stripped down version of the plugin:

(function ( $ ) {
    $.fn.jq_plugin = function(options){
        return this.each(function() {
            return $(this).click(onClick);
            function onClick(e){
                console.log('ID: '+$(this).attr('id'));
            }           
        });
    };
}( jQuery ));
MP_Webby
  • 916
  • 1
  • 11
  • 35
  • 2
    Call the plugin in the `onreadystatechange` handler function. – Barmar Aug 06 '14 at 16:21
  • I don't really want to do that. The snippet that loads the script is for people to download and add to their site. The plugin serves as an API of sorts. There could also be a large number of elements calling the plugin. – MP_Webby Aug 06 '14 at 16:24
  • That's the nature of loading things asynchronously. Anything that depends on it has to be done in the callback. – Barmar Aug 06 '14 at 16:29
  • Why don't they just put ` – Barmar Aug 06 '14 at 16:30
  • The reason I have avoided ` – MP_Webby Aug 06 '14 at 16:42
  • You can't have your cake and eat it. If you want the script to load asynchronously, then you have to use async programming methods to use it. – Barmar Aug 06 '14 at 16:49
  • Sadly this is true. Similar problem discussed here and good info on RequireJS for anyone else interested: http://stackoverflow.com/questions/4915201/why-use-something-like-require-js-rather-than-simply-creating-a-script-element – MP_Webby Aug 06 '14 at 16:55

1 Answers1

1

You create an onload/onreadystatechange, but all it does is return. You need to be checking that before you try and call the plugin.

You could either put your code that uses the plugin inside of that onload function

tk.onload = tk.onreadystatechange = function() {
    var rs = this.readyState;
    if (rs && rs != 'complete' && rs != 'loaded'){
         $(function(){
              $('#test').jq_plugin();
         });
    }
};

Of you could set a boolean tkHasLoaded = false and then set it to true in the onload function. Check that before trying to use the plugin.

idrumgood
  • 4,904
  • 19
  • 29