xjsfl (library)
Overview
Summary
The xjsfl library is the glue that holds the rest of the framework together, defining multiple objects and methods that you can use in your day-to-day JSFL code, as well as core methods that are used by the framework alone.
Contents
- xjsfl.uri
- xjsfl.settings
- app
- folders
- uris
- newLine
- xjsfl.output
- trace(value)
- log(value)
- xjsfl.debug jsfl.file
- xjsfl.classes
- xjsfl.modules
- xjsfl
xjsfl.get
A set of functions to return objects or selections in the UI, or issue standard warnings if not available
dom()
Get the current Document DOM, or issue a standard warning if not available
Example:
var dom = xjsfl.get.dom();
if(dom)
{
// dom...
};
items()
Get the currently selected library items, or issue a standard warning if not selected
Example:
var items = xjsfl.get.items();
if(items)
{
// items...
};
selection()
Get the current selection, or issue a standard warning if nothing is selected
Example:
var sel = xjsfl.get.selection();
if(sel)
{
// sel...
};

xjsfl.utils
Miscellaneous utility functions
- applyEach(arr, func, params, argIndex)
- extend(obj, props)
- namespace(target, namespace, properties)
- trim(string)
- pad(value, length, chr, right)
- isArray(obj)
- toArray(value, delim)
- toUniqueArray(arr)
- sort(arr, reverse)
- sortOn(arr, prop, alpha)
- getValues(input, prop, option)
- getDeepValue(obj, dotPath)
- getExtremeValue(elements, prop, bias, returnElement)
- getKeys(obj)
- getArguments(args, startIndex, endIndex)
- getClass(obj)
- getPanel(name)
- parseValue(value, trim)
- randomizeValue(value, modifier)
- randomValue(a, b)
applyEach(arr, func, params, argIndex)
Run each element of an array through a callback function
Used to call functions in a loop without writing loop code or forEach closure, or checking that original argument is an array.
The following example :
applyEach(arr, func, params, argIndex);
extend(obj, props)
Extends an object or array with more properties or elements
Extend an object with new properties:
xjsfl.utils.extend({a:1, b:2, c:3}, {d:4, e:5, f:6});
{a:1, b:2, c:3, d:4, e:5, f:6}
Extend an array with new elements:
xjsfl.utils.extend([1,2,3], [4,5,6]);
[1, 2, 3, 4, 5, 6]
trim(string)
Trims the whitespace from both sides of a string
Example
xjsfl.utils.trim(' Hello there \n\t');
'Hello there'
pad(value, length, chr, right)
Pads a value to a certain length with a specific character
The following example uses the defaults to pad a number to 6 digits:
trace(xjsfl.utils.pad(1, 5));
00001
The following example pads a string with right-hand padding:
trace('"' + xjsfl.utils.pad('Hello', 20, ' ', true) + '"');
"Hello "
isArray(obj)
Checks if the object is a true array or not
This method is useful when checking Array-like objects, for example function arguments or Array subclasses:
function test()
{
trace(xjsfl.utils.isArray(arguments));
}
test(1, 2, 3);
false
toArray(value, delim)
Turns a single value into an array
This example trims and splits a string on non-word characters, the default:
xjsfl.utils.toArray(' one | two | three | four | five ');
['one', 'two', 'three', 'four', 'five']
toUniqueArray(arr)
Returns a unique array without any duplicate items
This example returns a unique array from the supplied argument:
xjsfl.utils.toUniqueArray([1,2,2,2,3,3,4,2,1]);
[1, 2, 3, 4]
sort(arr, reverse)
Numeric Array sort function
The standard Array.sort() sorts alphabetically only, whereas this methods sorts numerically.
The following example sorts an array of random numbers in reverse:
sort([1,5,2,9,13,6], true);
13, 9, 6, 5, 2, 1
sortOn(arr, prop, alpha)
Optimized Array sortOn method, for sorting Arrays by child property.
This example sorts the library items array, which by default is unsorted:
items/Folder items items/Button items/Graphic items/MovieClip
var items = $library.items; xjsfl.utils.sortOn(items, 'name');
items items/Button items/Folder items/Graphic items/MovieClip
getValues(input, prop, option)
Get an Array of values from an Object, or an Array of Arrays/Objects from an Array of Objects
This method is a fairly powerful solution to grabbing nested values from Objects or elements inside Arrays, and is useful for analysis, collection and filtering of multiple objects and their properties.
This example gets the names of the items in the library:
xjsfl.utils.getValues(items, 'name');
items/Folder items items/Button items/Graphic items/MovieClip
This example gets several properties of items in the library:
xjsfl.utils.getValues(items, ['name','itemType']);
Inspect: Array (depth:4, objects:5, values:10, time:0.0 seconds) -------------------------------------------------------------------------------- array => Array [0] => Array 0: "items" 1: "folder" [1] => Array 0: "items/Button" 1: "button" [2] => Array 0: "items/Folder" 1: "folder" [3] => Array 0: "items/Graphic" 1: "graphic" [4] => Array 0: "items/MovieClip" 1: "movie clip"
This example gets several properties of items in the library, but returns them as objects:
xjsfl.utils.getValues(items, ['name','itemType'], true);
Inspect: Array (depth:4, objects:5, values:10, time:0.0 seconds) -------------------------------------------------------------------------------- array => Array [0] => Object name: "items" itemType: "folder" [1] => Object name: "items/Button" itemType: "button" [2] => Object name: "items/Folder" itemType: "folder" [3] => Object name: "items/Graphic" itemType: "graphic" [4] => Object name: "items/MovieClip" itemType: "movie clip"
The final example is in regard to using a callback, instead of a straight object property name.
You'd use a callback primarily when you want to get a sub-property of an object, for example, not an element's libraryItem instance, but the name of the libraryItem's instance, as passing "libraryItem.name" in as a key simply won't work.
This example uses a callback to an element's library item's (if it has one) name:
function getLibraryItemName(element)
{
return element.libraryItem ? element.libraryItem.name : undefined;
}
xjsfl.utils.getValues(elements, ['name', getLibraryItemName]);
Inspect: Array (depth:2, objects:4, values:8, time:0.0 seconds)
--------------------------------------------------------------------------------
array => Array
[0] => Array
0: "green_star"
1: "star"
[1] => Array
0: "grey_oval"
1: "oval"
[2] => Array
0: "red_rectangle"
1: "rectangle"
[3] => Array
0: "purple_oval"
1: "oval"
Note that if using callback functions, and returning an object, the function name will be used as the sub-property key. If supplying a closure, pass a named (rather than an anonymous function) like so:
xjsfl.utils.getValues(elements, ['name', function libraryItem(element){return element.libraryItem ? element.libraryItem.name : undefined;}], true);
Inspect: Array (depth:4, objects:4, values:8, time:0.0 seconds)
--------------------------------------------------------------------------------
array => Array
[0] => Object
name: "green_star"
libraryItem: "star"
[1] => Object
name: "grey_oval"
libraryItem: "oval"
[2] => Object
name: "red_rectangle"
libraryItem: "rectangle"
[3] => Object
name: "purple_oval"
libraryItem: "oval"
getDeepValue(obj, path)
Gets properties from an object's namespace via a dot.syntax.path String
The following example gets the frame count of the first item in the library:
xjsfl.utils.getDeepValue($library.items[0], 'timeline.frameCount');
45
setDeepValue(target, path, value)
Add nested properties to an object's namespace via a dot.syntax.path String
This method safely extends any Object or instance with new properties, without first having to check each level for the existance of a parent object. It affords the developer a is a quick and safe way to build object hierarchies.
The following example extends a native Object with a new hierarchy and child properties:
var obj = {};
xjsfl.utils.setDeepValue(obj, 'a.b.c', {a:1, b:2, c:3});
Inspect: Object (depth:5, objects:3, values:3, time:0.0 seconds) -------------------------------------------------------------------------------- object => Object [a] => Object [b] => Object [c] => Object a: 1 b: 2 c: 3
getExtremeValues(elements, prop, returnElement)
Comparison function to get a max or min value within an array of objects
The following example grabs the min and max widths from the selection:
var values = xjsfl.utils.getExtremeValues($selection, 'width'); inspect(values);
Inspect: Array (depth:2, objects:0, values:2, time:0.0 seconds) -------------------------------------------------------------------------------- array => Array 0: 4.9 1: 78
The following example grabs the widest and narrowest elements in the selection, then makes those elements the new selection:
var elements = xjsfl.utils.getExtremeValues($selection, 'width', true) $selection = elements;
List: Array (depth:1, objects:0, values:2, time:0.0 seconds) -------------------------------------------------------------------------------- array => Array 0: "Item_04" 1: "Item_01"
getKeys(obj)
Get an object's keys, or all the keys from an Array of Objects
This example gets the keys from a single object:
xjsfl.utils.getKeys($library.items[0]);
Inspect: Array (depth:4, objects:0, values:10, time:0.0 seconds) -------------------------------------------------------------------------------- array => Array 0: "itemType" 1: "name" 2: "linkageExportForAS" 3: "linkageExportForRS" 4: "linkageImportForRS" 5: "linkageExportInFirstFrame" 6: "linkageIdentifier" 7: "linkageClassName" 8: "linkageBaseClass" 9: "linkageURL"
This example gets the unique keys from an Array of objects:
xjsfl.utils.getKeys($library.items);
Inspect: Array (depth:4, objects:0, values:17, time:0.0 seconds) -------------------------------------------------------------------------------- array => Array 0: "itemType" 1: "name" 2: "linkageExportForAS" 3: "linkageExportForRS" 4: "linkageImportForRS" 5: "linkageExportInFirstFrame" 6: "linkageIdentifier" 7: "linkageClassName" 8: "linkageBaseClass" 9: "linkageURL" 10: "timeline" 11: "symbolType" 12: "sourceFilePath" 13: "sourceLibraryName" 14: "sourceAutoUpdate" 15: "scalingGrid" 16: "scalingGridRect"
getArguments(args, startIndex, endIndex)
Get the arguments of a function as an Array
Often in callback functions, or when using Function.apply() you'll need the arguments of the current function as an Array.
The following example grabs arguments b and c as a 2-element Array:
function test(a, b, c, d)
{
var values = xjsfl.utils.getArguments(arguments, 1, 3);
}
[5, 6]
getClass(obj)
Get the class of an object as a string
The following example gets the class name of a File instance:
var className = xjsfl.utils.getClass(file);
File
getPanel(name)
Returns the named SWF panel if it exists
The following example grabs the xJSFL Snippets panel object:
var panel = xjsfl.utils.getPanel('xJSFL Snippets');
[object SWFPanel]
parseValue(value, trim)
Parse any string into a real datatype
Often when dealing with text files, XUL instances, XML, or other external sources, you need to parse text data into their correct datatypes. If you know the datatype you can cast or convert directly to the required type, but if you don't or you want a single function to do the casting, parseValue() is your best friend. It supports:
- Number
- Boolean
- hex (0x or #)
- XML
- Array notation
- Object notation
- JSON
- Date
- undefined
- null
The following example converts various strings to their real-word datatypes:
xjsfl.utils.parseValue('2.1'); // 2.2
xjsfl.utils.parseValue('2.0'); // 2
xjsfl.utils.parseValue('TRUE'); // true
xjsfl.utils.parseValue('#FF0000'); // 16711680
xjsfl.utils.parseValue('0xFF0000'); // 16711680
xjsfl.utils.parseValue('<xml a="1" />'); // <xml a="1" />
xjsfl.utils.parseValue('[1,2,3]'); // [1, 2, 3]
xjsfl.utils.parseValue('{'a':1}'); // {a:1}
xjsfl.utils.parseValue('Jan 01 2011'); // Sat Jan 01 20011 00:00:00 GMT+0000 (GMT Standard Time)
xjsfl.utils.parseValue('undefined'); // undefined
xjsfl.utils.parseValue(''); // null
randomizeValue(value, modifier)
Randomnly modify a seed value with a secondary modifier component
The randomize() method modifies the seed value using a numeric scalar, or String expression of the format operator, value, percent, for example:
10 // add or subtract up to 10, both + and - "10" // add or subtract up to 10, overall "+25" // add up to 25 "-1.3" // subtract up to -1.3 "+25%" // add up to 25% to the value "*50%" // multiply by up to 50%
This expression is then used to modify the original value, as follows:
The following are examples of modifying values:
// numeric value xjsfl.utils.randomizeValue(100, 25); // 116.36332936040048 xjsfl.utils.randomizeValue(100, -25); // 83.36330620920405 // numeric expressions xjsfl.utils.randomizeValue(100, "25"); // 111.75086500690269 xjsfl.utils.randomizeValue(100, "+25"); // 119.05169580381472 xjsfl.utils.randomizeValue(100, "-25"); // 78.89110620920405 xjsfl.utils.randomizeValue(100, "*2"); // 191.11471736876952 xjsfl.utils.randomizeValue(100, "/2"); // 20.64621360510172 // percentage expressions xjsfl.utils.randomizeValue(100, "25%"); // 101.85976300353933 xjsfl.utils.randomizeValue(100, "+25%"); // 115.88694308440219 xjsfl.utils.randomizeValue(100, "-25%"); // 88.5689837135059 xjsfl.utils.randomizeValue(100, "*25%"); // 11.563594997061665 xjsfl.utils.randomizeValue(100, "/25%"); // 358.00429033663547
randomValue(a, b, round)
Get a random value between 2 numbers
The following example grabs a random number between 100 and 200:
xjsfl.utils.randomValue(100, 200);
166.76074429449056
xjsfl.file
Framework-specific file functionality
- find(type, name, returnType)
- load(path, type)
- makeURI(str, context)
- makePath(str, shorten)
- isAbsolutePath(path)
find(type, name, returnType)
Finds all files of a particular type within the cascading file system
Due to the way the cascading file structure in XJSFL works, you may sometimes need to find the files you need, rather than accessing them directly. You can search for files using the following arguments:
| File / Folder | Function argument | .ext |
|---|---|---|
| module file | module, modules | jsfl |
| jsfl folder | script, scripts, jsfl | jsfl |
| libraries folder | lib ,libs, library, libraries | jsfl |
| config folder | config | xml |
| data folder | data | xml |
| settings folder | settings | xml |
| template folder | template | txt |
Note that the correct extension will be added for a file if you don't include it.
The following example finds a settings file called user.xml:
xjsfl.file.find('settings', 'user', -1);
xJSFL/user/config/settings/user/xml
load(path, 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 strcuture
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');
xjsfl.debug
Functions to help you debug erroneous JSFL code
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.
func(fn, params, scope)
Tests a callback and outputs the error stack if the call fails. Add additional parameters after the callback reference
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.
error(error)
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/
state
Turns the file debugging state on or off
The state property is the flag that turns file debugging on or off on a permanent basis (note that it will be reset each time when running scripts externally). Setting it to true wraps Flash's native fl.runScript() with xJSFL's debug.file(), which loads then evals() external code, rather than running it, in an attempt to trap errors to the listener.
The following example turns file debugging on, then runs an external file:
xjsfl.debug.state = true;
fl.runScript(xjsfl.uri + 'user/jsfl/bad-file.jsfl');
> 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
There are two important things to note about xjsfl.file.debug:
- It affects ALL future file loads, so either turn it off after you've found the error, or remove it from your code once you've solved your error
- 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.
xjsfl.classes
Mechanism to store and retrieve libraries
When creating a library, class or function that you want restored on framework initialization, the classneeds 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)
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 loaded.
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(path, debugType)
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');
If you get syntax errors in the bootstrap, and you suspect it might be from erroneous classes when loading, you can add a debug parameter, the Number 1 to alert() and errors, and 2 to trace() them:
xjsfl.classes.load('test', 1);
xjsfl.modules
A namespace in which to store module code to prevent pollution of global scope
Note that modules are registered automatically upon creation. See the Module class for more information.
load(name)
Load a module or array of modules
This method should only need to ever be called from the bootsrap files, but for the record, the syntax is documented here.
Th efollowing example loads the named module Snippets from from the modules folder:
xjsfl.modules.load('Snippets');
xjsfl
xJSFL properties and functions
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|/05%20-%20Projects/xJSFL/user/temp/test.txt
reload()
Reload the framework from disk
When developing your own libraries, sometimes you will need to reload the whole framework to reset dependancies. The following code reload the framework, including all bootstrap files:
xjsfl.ui.reload();
init(scope, trace)
Initialize the environment by extracting variables / objects / functions to global scope
The following example is the default initialize code you'll run on each script execution to initialize the framework:
xjsfl.ui.init(this);