Utilities

The flex framework provides a number of important utilities via the flexloader namespace. These utility methods are made available by the flexLoader.js script when you deploy an app.


API Interface: flexloader.execute(function($, App) {})


To write code that interfaces with the flex framework, the first utility that you should get familiar with is the execute() method. The execute() method should generally be used to wrap any code which is intended to interface with the flex framework api.


Example:
flexloader.execute(function($, App) {
  // api programming...
});

Any function that you pass to the execute method will be passed two parameters. The first parameter is a reference to the jQuery instance which is being used by the framework (since it's possible to have multiple instances of jQuery running on the page). The second parameter is the application object which encapsulates the entire flex framework api, and provides access to all of the app interfaces.

Another important function of the execute() method is to ensure that the framework is fully initialized before your code is executed. Since the framework loads asynchronously after your DOM is ready, there may be a short delay before it is actually ready to receive commands. The execute() method will wait until the framework is ready to go before it executes code that is passed to it.

Alternate Usage: The execute() method also supports passing the name of a named resource (which should be added via the addResource() method) as the first parameter, and then the function to execute as the second parameter. When used in this way, the function will only be executed if (and when) the named resource is successfully loaded.

Example:
flexloader.execute('myResource', function($, App) {
  // stuff to do when "myResource" is loaded
});

// example of a flag used for conditional loading of the resource
var needMyResource = true;

if (needMyResource) {
  flexloader.addResource({
    name: 'myResource',
    src: '/path/to/resource.js'
  });
}

App Extensions: flexloader.extendApp(function($, App, config) {})


The extendApp() method is a variation of the execute() method described above, but any code passed to it will actually be executed before any code passed to the execute() method. This is true up until the point at which the app is actually initialized, at which point both the execute() method and the extendApp() method will execute code passed to them in real time.

The extendApp() method is generally used for things like adding a widget template to the framework, since you want that template to be available to other code using the standard execute() method. But it is useful in any situation where your code is more or less doing "prep" work to the framework.

Another reason to use the extendApp() method is when you are writing code that can be "autoloaded". Functions passed to this method have a third "config" parameter available to them. When you use the extendApp() method in a script file that has been autoloaded, the config parameter will contain information about the script file itself and any options that may have been passed to it. This way, it's possible for your code to load additional dependency resources (such as other script libraries or css files) on it's own, or to change it's default behavior based on the config options that it was autoloaded with.

Example:
flexloader.extendApp(function($, App, config) {
  // api programming...
});

The extendApp() method recieves the jQuery object and the App object as the first two parameters just like the execute() method. But it also receives a third parameter "config", which contains script information and options set if the script was autoloaded.


Script Autoloader: flexloader.autoload('//url.to/script.js', {options object});


The autoload() method can be used to dynamically load script resources with the ability to pass them configuration options. In order to receive configuration options, the script which is autoloaded must implement the extendApp() method of code execution within the global context (meaning, the extendApp() should not be nested within another function wrapper such as execute() ).

Example: Script With Autoload Support
// filename: scriptToLoad.js
flexloader.extendApp(function($, App, config) {
  // test if the script has been autoloaded
  if (config.autoload) {
    alert(config.options.txtMessage);
  }
});
Example: Autoload Implemented
flexloader.autoload('http://www.example.com/path/to/scriptToLoad.js', {
  txtMessage: 'Autoload Complete!'
});

When a script that implements the extendApp() method of code execution is autoloaded, the config parameter received by the function passed to extendApp() will be an object that contains information about the script itself, as well as any options that may have been passed to the autoload() method. The config parameter from the example above would look like this:

{
  autoload: true,
  script: {
    protocol: 'http', // could also be https (note there is no trailing colon)
    host: 'www.example.com', // the domain the script is on
    path: '/path/to/', // the directory path of the script (with trailing slash)
    file: 'scriptToLoad.js', // the filename of the script
    basepath: 'http://www.example.com/path/to/' // full url path to script directory
  },
  options: {
    txtMessage: 'Autoload Complete!'
  }
}

If the script is not loaded via the autoload() method (i.e. it was included via script tag in the html source or added via the addResource() method, the "config" parameter will be an empty object. That is why in the first example we checked for the "config.autoload" property to be true before attempting to access additional properties of the object. The same is true of you simply use the extendApp() method in your html body directly (the config object will be empty).


Resource Loader: flexloader.addResource({resource object})


The addResource() method adds a resource to be asynchronously loaded when the app is initialized (or immediately if the app has already been initialized). You can use it to load additional scripts or css files that your project needs. This way, you can write code that conditionally includes resources on your page without the need to hard code them into your html source.


Example:
flexloader.addResource({
  src: '/path/to/script.or.stylesheet', // required, url to the resources
  missing: function() {}, // optional, return true if resource should be loaded
  ready: function() {} // optional, function to execute when resource is ready
});

The addResource() method accepts an object as a parameter. The object passed to this method should contain a "src" property which is the url to the resource to load. There are also two additional (optional) properties that you can assign to the object also.

The "missing" property (if used) should be a function that returns true if the resource is missing and needs to be loaded. If you don't specify a function to the "missing" property, then the resource will be assumed to be missing and will load unconditionally.

The "ready" property (if used) should be a function that will be executed immediately after the resource is loaded, or if the "missing" function returns false.


Resources Ready: flexloader.ready(function() { })


You can use the ready() method to execute code once all of the resources that are in the asynchronous loading queue have been loaded. If there are no resources being loaded when this method is used, the function is executed immediately. This method is very useful after you use the addResource() method and you want to make sure that the resource(s) that you just added are ready before your code execution continues.

Example:
flexloader.execute(function($, App) {
  flexloader.addResource({ src: '/path/to/script.js' });
  flexloader.addResource({ src: '/path/to/style.css' });
  flexloader.ready(function() {
    // now you can write code that is dependent on the script.js and style.css resources!
  });
});

App Ready: App.ready(function() {})


The App.ready() method allows you to write code that needs access to baseline app data (such as playlist info, producer info, discount info, etc). This method ensures that the baseline app data is ready before your code is executed.

In contrast, the flexloader.execute() method will execute code immediately after the framework is ready to receive commands, but the App.ready() method will wait until the primary application data is loaded before execution. This means that app data may not be available immediately inside the flexloader.execute() method (since app data is loaded sequentially after the framework), but it will always be available to code passed to the App.ready() method.


Example:
flexloader.execute(function($, App) {
  App.ready(function() {
    // things to do when primary app data is ready
  });
});

App Final: App.final(function() {})


The App.final() method is similar to the App.ready() method, in that it allows you to write code that operates on app data (such as playlists, producers, discounts, etc). The difference is that this method waits until ALL initial loading activity is complete before your code is executed.

In comparison, the App.ready() method will execute code immediately after the baseline app data is available (such as playlist info, but not necessarily the initial beats that are in the playlist), but the App.final() method will wait until all of the initial data loading has been finalized. This way you can be sure that every bit of data has been queried for the app before your code is executed.


Example:
flexloader.execute(function($, App) {
  App.final(function() {
    // things to do when all app data is fully loaded. This is a good time to remove a page loading screen... etc.
  });
});