xjsfl (library)
Overview
Summary
The core xJSFL class holds core framework settings, manages file loading, and provides error-trapping and debugging functionality.
Contents
Concept & usage
The majority of the interaction with the xjsfl library happens in the bootstrap process, such as setting up the environment and subsequently loading classes and files.
However, the xjsfl class is the glue that holds the rest of the framework together, so it's a good idea to at least familiarise yourself with its properties and functions as it will give you insight into the basic core of the framework.
API
Initialisation
Functions to initialize and reload the framework
init(scope, scopeName, classes)
Initialize the environment by extracting variables / objects / functions to global scope, optionally reloading classes
In order to use the framework's functionality, you will first need to initialize it. This is done via xjsfl.init(), which copies the loaded framework classes, functions and variables from the extension to the supplied scope. Once initialized, you are free to use any xJSFL functionality.
Note that for external calls (for example, publishing from Komodo, or simply running the JSFL fle manually) xjsfl.init() will need to have been called before any xJSFL code is called, as external script calls are sandboxed between executions.
The Commands menu and Flash panels however, each have their own persistent scope, and init() only needs to be called once.
The following example initializes the calling scope, then runs the xJSFL inspection function:
xjsfl.init(this); inspect({a:1, b:2, c:3});
Inspect: Object (depth:4, objects:0, values:3, time:0.0 seconds) -------------------------------------------------------------------------------- object => Object a: 1 b: 2 c: 3
Note that when developing classes, you sometimes need to reload classes if you've made changes. In order not to reload the entire framework, you can simply supply the name of the changed classes, and they will be reloaded:
xjsfl.init(this, ['SomeClass']);
> xjsfl: loading library: 'SomeClass'
Note that if you plan to use other classes that also use the re-loaded class, you will need to reload them as well, as they will still reference the original class. If you don't reload, it will appear that Flash (or xJSFL) has magically gobbled your changes, when in fact it's just that the composing class or object is referencing the old composed object.
In this example, the Collection class was updated, but the current ElementSelector function and ElementCollection class need to be updated as they will still be referencing the old Collection class by way of closures:
// add the doSomethingCool() method to the Collection class // reinitialise framework and reload Collection, plus dependancies xjsfl.init(this, ['Collection', 'ElementCollection', 'ElementSelector']); // use the new Collection method, via ElementSelector and ElementCollection var collection = $('*').doSomethingCool();
reload()
Reload the framework from disk
Sometimes, especially when developing your own libraries, you may need to reload the whole framework to reset dependancies. The following code reloads the entire framework from scratch:
xjsfl.reload();
Properties
xjsfl.uri
The xJSFL installation uri
The xJSFL uri is the installation folder of your copy of xJSFL, and will be different, per machine, depending on where you installed it.
The following example traces the path to a file in the user/temp folder:
trace(xjsfl.uri + 'user/temp/test.txt');
file:///E|/Projects/xJSFL/user/temp/test.txtxJSFL has much more advanced file handling than vanilla JSFL; see the section on File handling for more information.
Settings
Core settings and cached variables
The xjsfl.settings object holds most of the variables and parameters needed to have the framework function. Usually, you won't need to touch these in your everyday xJSFL development, but they're included here for consistency.
xjsfl.settings.app
Application data Information about the Flash version the user is currently running
xjsfl.settings.folders
Common folders which may be used as placeholders in URI references, i.e. '{core}path/to/file.txt'
xjsfl.settings.uris
URIs An ordered list of base URIs which xJSFL uses when searching for files module uris are updated automatically when new modules are added
xjsfl.settings.uris.add(pathOrURI, type)
Adds URIs to the URIs list
There may be times when you want to add a new path to the URIs list.
The following example adds an 'extra libs' folder, which then allows you to load the 'CustomLib.jsfl' file by name only:
xjsfl.settings.uris.add('f:/development/jsfl/extra libs/'); xjsfl.classes.load('CustomLib');
// Loading 'Custom lib'
xjsfl.settings.newline
Newline character depending on PC or Mac
xjsfl.file
Methods to load framework assets, or handle common filesystem functionality
find(type, name, returnType)
Finds all files of a particular type within the cascading file system
Often, you can just load a file in xJSFL using a URI, or any of the methods outlined in the File handling section of the site.
However, due to the way the cascading file structure in XJSFL works (for example, you may have core, module and user config files), you may sometimes want to find the files you need, rather than accessing them directly, as you don't know in advance in which folder the right file will be.
You can search for files using the following arguments (note that the correct extension will be added for a file if you don't include it):
Folder | Function argument | default .ext | Returns |
---|---|---|---|
/jsfl | script, scripts, jsfl | jsfl | The last file |
/config | config, settings | xml | The last file |
/assets/templates | template | txt | The last file |
/jsfl/libraries | lib ,libs, library, libraries | jsfl | All files |
any other folder | other | All files |
The following example finds the main settings file xjsfl.xml, which has been overridden in the user folder, from the core folder:
var file = xjsfl.file.find('settings', 'xjsfl');
trace(file);
'file:///E|/Projects/xJSFL/user/config/xjsfl.xml'
load(pathOrName, type)
Attempts to find and run or return files from the cascading file structure
The load() method will directly load a file, or will attempt to first find, then load an existing file from within the cascading file structure, depending on the method arguments:
xjsfl.file.load('path/to/file.ext'); // load a file directly xjsfl.file.load(file, folder); // find and load a file within the framework folder structure
For more information on finding files, see the sections on folder structure and automatic file-finding.
Also, depending on the file type, the file will be executed or returned as follows:
- jsfl files will be executed
- xml files will have an XML object returned
- All other files will return plain text
The following examples load and return a file called user.xml ( returning an XML object) directly:
var xml = xjsfl.file.load(xjsfl.uri + 'user/settings/data/some file.xml'); var xml = xjsfl.file.load('user/settings/data/some file.xml'); // defaults to xjsfl folder
The following example finds, then loads and returns the same user XML file using the find file functionality:
var xml = xjsfl.file.load('some file', 'data');
The following example finds and returns the contents of a text file:
var text = xjsfl.file.load('some file.txt', 'temp');
save(pathOrURI, contents, force)
Saves data to file
The save method is a shortcut to File's save method. The following example saves some text to the same folder the script is currently running in:
xjsfl.file.save('test.txt', 'Hello there!');
trace(new File('test.txt').contents);
Hello there!
xjsfl.classes
Core methods to load and register framework libraries and classes
When creating a library, class or function that you want restored on framework initialization, the class needs to be loaded, registered and restored when needed. See the guide on Creating your own functions, libraries and classes for more details.
register(name, obj, uri)
Registers a class/function for later retrieval
When creating a library, class or function that you want restored on framework initialization, you need to first register it with the xJSFL core then the library file is automatically restored each time the framework is initialized.
The following example registers a Test class with the xJSFL core so it is loaded on future xjsfl.init()s:
function Test(value) { this.value = value; } xjsfl.classes.register('Test', Test);
load(fileRef, reload)
Load a class or array of classes from disk
This method should only need to ever be called from the bootsrap files, but for the record, the syntax is documented here.
The following example loads the jsfl file Test.jsfl from the jsfl/libraries folder:
xjsfl.classes.load('Test');
By default, xJSFL doesn't reload classes which have already been loaded, as so many classes rely on each other. To force a reload, pass true as the second parameter:
xjsfl.classes.load('Test', true);
Alternatively, you can use the $classes parameter of the xjsfl init() method to reload classes as you initialize the framework (this is useful when developing classes, and needing to update just the class, or its dependencies, without reloading the whole framework).
in xJSFL, by convention, the there is one class (usually) per file, and the file name is named after the class (this makes it easier to track down classes when loading using the cascading file system and file.find)
Note that if you get errors when loading external classes, you can check the xJSFL logs for more details, from Commands > xJSFL > View Log.
cache
Cache of class definitions
xjsfl.modules
Core methods to handle the initialization and loading of modules
create(namespace, properties, window)
Factory method to create an xJSFL module instance
Due to the way Flash and JSFL sandboxes data, xJSFL Modules need to be created, then internally stored in the xJSFL extension for future retrieval. This is done through the framework-centric xjsfl.modules.create() method.
The following example :
Test = { init:function() { trace("I'm a new Test Module!"); }, doSomething:function() { trace("Test module is doing something!"); } } Test = xjsfl.modules.create('Test', Test, this);
The next time flash loads, and assuming you have the correct manifest.xml file in the module's folder, you should see this:
> xjsfl: REGISTERING MODULE "TEST"
> xjsfl: added 1 search paths for "E:/Projects/xJSFL/modules/Test/"
find(uri, init)
Finds and returns the base URIs of all modules in a given folder and sub folders
The find method is responsible for finding and initializing modules, and is called core bootstrap to ensure all modules have their search paths added, and are ready to run when their panels load.
However, you can also call find() manually (usually in the user bootstrap) to add modules from folders external to xJSFL. You might want to do this if you have a centralised repository of code that multiple developers are contributing to.
The following example attemps to find and initialize modules on an external development drive:
xjsfl.find('f:/development/jsfl/xjsfl modules/', true);
> xjsfl: REGISTERING MODULE "ANIMATION TOOLS"
> xjsfl: added 1 search paths for "f:/development/jsfl/xjsfl modules/Animation Tools/" > xjsfl: REGISTERING MODULE "EXPORT TOOLS"
> xjsfl: added 1 search paths for "f:/development/jsfl/xjsfl modules/Export Tools/"
load(namespace)
Loads the module's bootstrap to load code locally (usually into the host panel)
Usually, this method is only ever called (automatically) by the AS3 Module framework, and is used to load the module's bootstrap file, and thus the code therin, into a panel, however you can run it manually if you wish.
The following example runs the bootstrap file of the named module Test from from the modules folder:
xjsfl.modules.load('Test');
Test bootstrap run!
xjsfl.debug
Debugging methods for file, function and errors
The xjsfl.debug object has been designed to help you debug your code by packaging boilerplate code into some handy methods, that are easy to call and provide clear Output Panel feedback on the results.
func(fn, params, scope)
Tests a callback and outputs the error stack if the call fails
The following example tests an erroneous function, where b is not defined:
function test(a) { trace(b); } xjsfl.debug.func(test, [1])
ReferenceError: b is not defined -------------------------------------------------------------------------------- 0 > test([object Array]) line: 9 file: temp.jsfl path: xJSFL/core/jsfl/temp/ 1 > line: 12 file: temp.jsfl path: xJSFL/core/jsfl/temp/
If testing functions on objects, it is important to pass the scope through through as well, or else the function's this will point to the window object, and not the object on which the function resides:
var obj =
{
settings:{a:1, b:2, c:3},
test:function()
{
trace(this.settings.a);
}
};
xjsfl.debug.func(obj.test); // TypeError: this.settings has no properties
xjsfl.debug.func(obj.test, [], obj); // 1
Also see the MDN docs on error types for throwing your own errors.
file(uriOrPath)
Attemps to run and trap errors in external script files
One of the most annoying things in JSFL development is running files which seem to fail silently. The cause of this is always errors within the loaded file which fl.runScript() won't alert you to.
xjsfl.debug.file() attempts to work round this limitation by wrapping Flash's native fl.runScript(), and instead, reading and eval()ing the contents of both the target file and any subsequent JSFL files loaded (thorugh fl.runScript(), or any of xJSFL's file loading functions), trapping any errors and printed the message to the output panel.
xjsfl.debug.file('user/jsfl/bad-file.jsfl');
Upon encountering an error, the output panel will display something like the following:
> xjsfl: Debugging "E:\projects\xJSFL\user\jsfl\bad-file.jsfl" ... The following JavaScript error occurred: At line 7 of file "error.jsfl": ReferenceError: a is not defined The following JavaScript error(s) occurred: At line 1603 of file "xjsfl.jsfl": > xjsfl: Script debugging halted
Note that because debug.file() eval()s files rather than running them, the "loaded" files are not physically run from their location on disk so any URI-specific functions like scriptDir and fl.scriptURI will fail.
To turn on or off file debugging permanently, including for fl.runScript(), see the xjsfl.debug.state flag.
error(error, testing)
Generates, logs and traces a human-readable error stack
Traces a human-readable error stack to the Output Panel
The example below is the longhand version of the example above, but uses a manual try/catch case to send the error to the debug function.
try { test(1); } catch(err) { xjsfl.debug.err(err); }
Again, the output will be the error stack:
ReferenceError: b is not defined -------------------------------------------------------------------------------- 0 > test([object Array]) line: 9 file: temp.jsfl path: xJSFL/core/jsfl/temp/ 1 > line: 12 file: temp.jsfl path: xJSFL/core/jsfl/temp/
Comments are closed.