Brian
Brian

Reputation: 486

Can I use Ext's loader to load non-ext scripts/object dynamically?

In my ExtJS 4.0.7 app I have some 3rd party javascripts that I need to dynamically load to render certain panel contents (some fancy charting/visualization widgets).

I run in to the age-old problem that the script doesn't finish loading before I try to use it. I thought ExtJS might have an elegant solution for this (much like the class loader: Ext.Loader).

I've looked at both Ext.Loader and Ext.ComponentLoader, but neither seem to provide what I'm looking for. Do I have to just "roll my own" and setup a timer to wait for a marker variable to exist?

Upvotes: 8

Views: 10418

Answers (5)

Joe Holloway
Joe Holloway

Reputation: 28948

Here's an example of how it's done in ExtJS 4.1.x:

Ext.Loader.loadScript({
    url: '...',                    // URL of script
    scope: this,                   // scope of callbacks
    onLoad: function() {           // callback fn when script is loaded
        // ...
    },
    onError: function() {          // callback fn if load fails 
        // ...
    } 
});

Upvotes: 11

Krzysztof FF
Krzysztof FF

Reputation: 41

This is exactly what newest Ext.Loader.loadScript from Ext.4-1 can be used for.

See http://docs.sencha.com/ext-js/4-1/#!/api/Ext.Loader-method-loadScript

Upvotes: 4

Brian
Brian

Reputation: 486

For all you googlers out there, I ended up rolling my own by borrowing some Ext code:

 var injectScriptElement = function(id, url, onLoad, onError, scope) {
      var script = document.createElement('script'),
          documentHead = typeof document !== 'undefined' && (document.head || document.getElementsByTagName('head')[0]),
          cleanupScriptElement = function(script) {
               script.id = id;
               script.onload = null;
               script.onreadystatechange = null;
               script.onerror = null;

               return this;
          },
          onLoadFn = function() {
              cleanupScriptElement(script);
              onLoad.call(scope);
          },
          onErrorFn = function() {
              cleanupScriptElement(script);
              onError.call(scope);
          };

      // if the script is already loaded, don't load it again
      if (document.getElementById(id) !== null) {
           onLoadFn();
           return;
      }

      script.type = 'text/javascript';
      script.src = url;
      script.onload = onLoadFn;
      script.onerror = onErrorFn;
      script.onreadystatechange = function() {
          if (this.readyState === 'loaded' || this.readyState === 'complete') {
              onLoadFn();
          }
      };
      documentHead.appendChild(script);
      return script;
  }


var error = function() {
    console.log('error occurred');
}

var init = function() {
    console.log('should not get run till the script is fully loaded');
}

injectScriptElement('myScriptElem', 'http://www.example.com/script.js', init, error, this);

Upvotes: 1

Mchl
Mchl

Reputation: 62387

From looking at the source it seems to me that you could do it in a bit of a hackish way. Try using Ext.Loader.setPath() to map a bogus namespace to your third party javascript files, and then use Ext.Loader.require() to try to load them. It doesn't look like ExtJS actually checks if required class is defined in the file included.

Upvotes: 0

Molecular Man
Molecular Man

Reputation: 22386

I've looked at both Ext.Loader and Ext.ComponentLoader, but neither seem to provide what I'm looking for

Really looks like it's true. The only thing that can help you here, I think, is Loader's injectScriptElement method (which, however, is private):

var onError = function() {
  // run this code on error
};
var onLoad = function() {
  // run this code when script is loaded
};
Ext.Loader.injectScriptElement('/path/to/file.js', onLoad, onError);

Seems like this method would do what you want (here is example). But the only problem is that , ... you know, the method is marked as private.

Upvotes: 5

Related Questions