Utils (library)
Overview
Summary
The Utils library provides a static library of utility functions for accomplishing many different tasks in JSFL.
Contents
- Overview
- API
- Utils
- Object methods
- isObject(value)
- getKeys(obj)
- clone(obj)
- clone(obj)
- extend(obj, source)
- combine(keys, values)
- makeHash(obj, defaultValue)
- walk(rootElement, fnChild, fnContents, scope)
- OOP methods
- getType(obj)
- getClass(obj)
- getPrototypeChain(obj, includeSource)
- getArguments(args, startIndex, endIndex)
- getParams(fn, args)
- parseFunction(fn)
- Array methods
- isArray(obj)
- toArray(value, delim)
- toUniqueArray(arr, prop)
- sort(arr, reverse, caseInsensitive)
- sortOn(arr, prop, alpha)
- diff(arr1, arr2, type)
- Value methods
- getValues(input, prop, option)
- getNearestValue(values, value, returnIndex)
- getExtremeValues(elements, prop, returnElement)
- getDeepValue(obj, path)
- setDeepValue(obj, path, properties)
- randomizeValue(value, modifier)
- randomValue(a, b, round)
- String methods
- pad(value, length, chr, right)
- columnizeText(text, padding, delimiter, useSpaces, tabWidth)
- parseValue(value, trim)
- parseExpression(expression, delimiter, nestStart, nestEnd)
- RegExp methods
- match(str, rxGlobal, matchNames, captureIndex)
- rxEscape(value)
- rxUnescape(value)
- makeWildcard(value)
- File and URI methods
- glob(globPathOrURI, searchableOnly, asPaths, debug)
- getURIs(folder, $depth, $filesOnly, $filter, $extensions)
- getFirstValidURI(uris)
- getSearchableURIs(pathOrURI, itemType, returnPaths)
- isSearchable(pathOrURI)
- walkFolder(folder, $callback, $maxDepth, $returnURIs)
- makeTree(paths)
- Framework methods
API
Object methods
- isObject(value)
- getKeys(obj)
- clone(obj)
- clone(obj)
- extend(obj, source)
- combine(keys, values)
- makeHash(obj, defaultValue)
- walk(rootElement, fnChild, fnContents, scope)
isObject(value)
Checks if the object is a true Object or not
The following example compares various values against typeof to see if they are true objects or not:
var data = []; var values = { 'undefined': undefined, 'null': null, 'number': 1, 'boolean': true, 'string': 'hello', 'array': [1, 2, 3], 'object': {a:1, b:2, c:3}, 'date': new Date(), 'template': new Template() }; for(var name in values) { data.push({name:name, 'typeof':typeof values[name], 'isObject':Utils.isObject(values[name])}); } Table.print(data);
+-----------+-----------+----------+ | name | typeof | isObject | +-----------+-----------+----------+ | undefined | undefined | false | | null | object | false | | number | number | false | | boolean | boolean | false | | string | string | false | | array | object | false | | object | object | true | | date | object | false | | template | object | true | +-----------+-----------+----------+
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:
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:
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"
clone(obj)
Clones and object
The following example compares the difference between reassigning and cloning an object:
var obj1 = {a:1, b:2, c:3}; var obj2 = obj1 var obj3 = Utils.clone(obj1); obj1.a = 100; // update a value on the original object inspect([obj1, obj2, obj3])
Inspect: Array (depth:4, objects:3, values:9, time:0.0 seconds) -------------------------------------------------------------------------------- array => Array [0] => Object a: 100 b: 2 c: 3 [1] => Object a: 100 b: 2 c: 3 [2] => Object a: 1 b: 2 c:
extend(obj, source)
Extends an object or array with more properties or elements,,
Extend an object with new properties:
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:
Utils.extend([1,2,3], [4,5,6]);
[1, 2, 3, 4, 5, 6]
combine(keys, values)
Combines keys and values to make a new populated Object
The following example combines:
var keys = ['one', 'two', 'three'] var keys = 'one, two, three'; // alternative format - words are split on commas and trimmed var values = [1, 2, 3]; inspect(Utils.combine(keys, values));
Inspect: Object (depth:4, objects:0, values:3, time:0.0 seconds) -------------------------------------------------------------------------------- object => Object one: 1 two: 2 three: 3
makeHash(obj, defaultValue)
Makes a Hash object from a source value
The following example :
var keys = 'option1, option2, option3'; var hash = Utils.makeHash(keys); inspect(hash);
Inspect: Object (depth:4, objects:0, values:3, time:0.0 seconds) -------------------------------------------------------------------------------- object => Object option1: false option2: false option3: false
Alternatively, you can pass in any object with existing properties, and use them as the basis for your new hash:
var hash = Utils.makeHash(new LibraryItem(), null); inspect(hash);
Inspect: Object (depth:4, objects:0, values:11, time:0.0 seconds) -------------------------------------------------------------------------------- object => Object itemType: null name: null linkageExportForAS: null linkageExportForRS: null linkageImportForRS: null linkageExportInFirstFrame: null linkageIdentifier: null linkageClassName: null linkageBaseClass: null linkageURL: null shortName: null
walk(rootElement, fnChild, fnContents, scope)
Generic function to recurse a data structure, processing nodes and children with callbacks
The following example walks both an Array and an Object:
var arr = [1, 2, 3, 4, [5, 6, 7, 8, [9, 10, 11, 12, 13], 14, 15, 16, 17], 18, 19, 20, 21]; var obj = {a:1, b:2, c:3, d:4, e:{a:5, b:6, c:7, d:8, e:{a:9, b:10, c:11, d:12, e:13}, f:14, g:15, h:16, i:17}, f:18, g:19, h:20, i:21 }; function process(value, index, depth) { trace('\t'.repeat(depth) + '[' +index+ '] ' + '"' + value + '"'); } Utils.walk(arr, processChild);
[0] "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21" [0] "1" [1] "2" [2] "3" [3] "4" [4] "5,6,7,8,9,10,11,12,13,14,15,16,17" [0] "5" [1] "6" [2] "7" [3] "8" [4] "9,10,11,12,13" [0] "9" [1] "10" [2] "11" [3] "12" [4] "13" [5] "14" [6] "15" [7] "16" [8] "17" [5] "18" [6] "19" [7] "20" [8] "21"
[0] "[object Object]" [a] "1" [b] "2" [c] "3" [d] "4" [e] "[object Object]" [a] "5" [b] "6" [c] "7" [d] "8" [e] "[object Object]" [a] "9" [b] "10" [c] "11" [d] "12" [e] "13" [f] "14" [g] "15" [h] "16" [i] "17" [f] "18" [g] "19" [h] "20" [i] "21"
You can also provide a second function, that can be used to get the contents of custom objects should they not be interable using a standard loop.
This example processes the contents of Folder objects on the hard drive:
// the function to process the children function process(element, index, depth) { trace ('\t'.repeat(depth) + '/' + element.name); } // the function to identify the children function getContents(element) { return element instanceof Folder ? element.contents : null; } // start processing var folder = new Folder('{user}temp/'); Utils.walk (folder, process, getContents)
/temp /a /new /folder /test.jsfl /document.doc /hello /hello.txt /test.txt /some file.as /spreadsheet-edit.csv /test copy.txt /test.jsfl /this /is /a /new /file.txt
OOP methods
- getType(obj)
- getClass(obj)
- getPrototypeChain(obj, includeSource)
- getArguments(args, startIndex, endIndex)
- getParams(fn, args)
- parseFunction(fn)
getType(obj)
A better typeof function
The typeof operator in JavaScript is a little unreliable about what it returns, so geType() attempts to do a better job of it.
The following example gets the type for a variety of input values (and also demonstrates Utils.getClass()):
var data = []; var values = { // null 'undefined' : undefined, 'null' : null, // Native 'Number' : 1, 'Boolean' : true, 'String' : 'hello', 'RegExp' : /a-z/, 'Array' : [1, 2, 3], 'Object' : {a:1, b:2, c:3}, 'Function' : function(){}, 'XML' : <a value="1" />, 'Error' : new Error(), 'Date' : new Date(), 'Math' : Math, 'Window' : window, // JSFL 'Timeline' : $timeline, 'Document' : $dom, // xJSFL 'JSON' : JSON, 'Template' : new Template(), 'Timer' : new Timer(), }; for(var name in values) { data.push ( { 'value':name, 'Object.toString':String(values[name]), 'typeof':typeof values[name], 'Utils.getType':Utils.getType(values[name]), 'Utils.getClass':Utils.getClass(values[name]), } ); } Table.print(data);
+-----------+-------------------------------------------------------+-----------+---------------+----------------+ | value | Object.toString | typeof | Utils.getType | Utils.getClass | +-----------+-------------------------------------------------------+-----------+---------------+----------------+ | undefined | undefined | undefined | undefined | null | | null | null | object | null | null | | Number | 1 | number | number | Number | | Boolean | true | boolean | boolean | Boolean | | String | hello | string | string | String | | RegExp | /a-z/ | function | regexp | RegExp | | Array | 1,2,3 | object | array | Array | | Object | [object Object] | object | object | Object | | Function | function () {... | function | function | Function | | XML | <root>... | xml | xml | XML | | Error | Error | object | error | Error | | Date | Wed Aug 08 2012 21:07:30 GMT+0100 (GMT Daylight Time) | object | date | Date | | Math | [object Math] | object | math | Math | | window | [object Window] | object | window | Window | | Timeline | [object Timeline] | object | timeline | Timeline | | Document | [object Document] | object | document | Document | | JSON | [class JSON] | object | object | JSON | | Template | [object Template path=""] | object | object | Template | | Timer | [object Timer time="0 milliseconds"] | object | object | Timer | +-----------+-------------------------------------------------------+-----------+---------------+----------------+
getClass(obj)
Attempts to get the class of an object as a string.
The getClass() method attempts to get the class name of an object using a variety of methods:
- The native class of an object, i.e. Number, String, Date
- The value contained within the object's toString() method, where the return value is of the format [object ClassName ... ]
- The name of the function used to construct the object
- Defaults to Object or returns null if the value is null or undefined
See the example above in Utils.getType() for the comparison between typeof, Utils.getType() and Utils.getClass().
getPrototypeChain(obj, includeSource)
Gets the prototype chain of an object
The following example gets the prototype chain for an ElementCollection:
var collection = $('*'); inspect(Utils.getPrototypeChain(collection), 1);
Inspect: Array (depth:1, objects:5, values:0, time:0.0 seconds) -------------------------------------------------------------------------------- array => Array [0] => ElementCollection [1] => Collection [2] => Object [3] => Object [4] => Object
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 = Utils.getArguments(arguments, 1, 3); }
[5, 6]
getParams(fn, args)
Get the arguments of a function as an Object
The following example gets the named parameters of a function call:
function test(a, b, c, d, e) { inspect(Utils.getParams(test, arguments)); } test(1, 2, 3);
Inspect: Object (depth:4, objects:0, values:5, time:0.0 seconds) -------------------------------------------------------------------------------- object => Object a: 1 b: 2 c: 3 d: undefined e: undefined
parseFunction(fn)
Parses a function source into an object
The following example parses a function into component parts:
inspect(Utils.parseFunction(inspect, 'inspect'));
Inspect: Object (depth:4, objects:1, values:8, time:0.0 seconds) -------------------------------------------------------------------------------- object => Object signature: "function (obj, $depth, $label, $functions, $options, $callback)" name: "inspect" [params] => Array 0: "obj" 1: "$depth" 2: "$label" 3: "$functions" 4: "$options" 5: "$callback"
Array methods
- isArray(obj)
- toArray(value, delim)
- toUniqueArray(arr, prop)
- sort(arr, reverse, caseInsensitive)
- sortOn(arr, prop, alpha)
- diff(arr1, arr2, type)
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(Utils.isArray(arguments)); } test(1, 2, 3);
false
toArray(value, delim)
Turns a single string of tokens into an array of trimmed tokens, by splitting at non-word characters, or a supplied delimiter,,It either returns an existing array, splits a string at delimiters, or wraps the single value in an array,
This example trims and splits a string on non-word characters, the default:
Utils.toArray(' one | two | three | four | five ');
['one', 'two', 'three', 'four', 'five']
toUniqueArray(arr, prop)
Returns a unique array without any duplicate items,
This example returns a unique array from the supplied argument:
Utils.toUniqueArray([1,2,2,2,3,3,4,2,1]);
[1, 2, 3, 4]
sort(arr, reverse, caseInsensitive)
Basic numeric Array sort function (native sort() sorts by string)
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 function modifies the input Array
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; Utils.sortOn(items, 'name');
items items/Button items/Folder items/Graphic items/MovieClip
diff(arr1, arr2, type)
Returns the difference between two arrays
The following example traces the various differences between 2 Arrays:
var A = [1,2,3,4,5,6,7,8]; var B = [5,6,7,8,9,10,11,12]; trace('Only A : ' + Utils.diff(A, B, -1)); trace('Common : ' + Utils.diff(A, B, 0)); trace('Only B : ' + Utils.diff(A, B, 1));
Only A : 1,2,3,4 Common : 5,6,7,8 Only B : 9,10,11,12
Value methods
- getValues(input, prop, option)
- getNearestValue(values, value, returnIndex)
- getExtremeValues(elements, prop, returnElement)
- getDeepValue(obj, path)
- setDeepValue(obj, path, properties)
- randomizeValue(value, modifier)
- randomValue(a, b, round)
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:
Utils.getValues(items, 'name');
items/Folder items items/Button items/Graphic items/MovieClip
This example gets several properties of items in the library:
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:
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; } 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:
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"
getNearestValue(values, value, returnIndex)
Gets the nearest value to a target value from an array of values
The following example gets the nearest value to the correct value required for kbs for teh Flash publish profile:
var kbs = [8, 16, 20, 24, 32, 48, 56, 64, 80, 112, 128, 160]; var value = Utils.getNearestValue(kbs, 28); trace(value);
32
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 = 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 = 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"
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:
Utils.getDeepValue($library.items[0], 'timeline.frameCount');
45
setDeepValue(obj, path, properties)
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 = {}; Utils.setDeepValue(obj, 'a.b.c', {x:1, y:2, z:3});
Inspect: Object (depth:5, objects:3, values:3, time:0.0 seconds) -------------------------------------------------------------------------------- object => Object [a] => Object [b] => Object [c] => Object x: 1 y: 2 z: 3
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 Utils.randomizeValue(100, 25); // 116.36332936040048 Utils.randomizeValue(100, -25); // 83.36330620920405 // numeric expressions Utils.randomizeValue(100, "25"); // 111.75086500690269 Utils.randomizeValue(100, "+25"); // 119.05169580381472 Utils.randomizeValue(100, "-25"); // 78.89110620920405 Utils.randomizeValue(100, "*2"); // 191.11471736876952 Utils.randomizeValue(100, "/2"); // 20.64621360510172 // percentage expressions Utils.randomizeValue(100, "25%"); // 101.85976300353933 Utils.randomizeValue(100, "+25%"); // 115.88694308440219 Utils.randomizeValue(100, "-25%"); // 88.5689837135059 Utils.randomizeValue(100, "*25%"); // 11.563594997061665 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:
Utils.randomValue(100, 200);
166.76074429449056
String methods
- pad(value, length, chr, right)
- columnizeText(text, padding, delimiter, useSpaces, tabWidth)
- parseValue(value, trim)
- parseExpression(expression, delimiter, nestStart, nestEnd)
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(Utils.pad(1, 5));
00001
The following example pads a string with right-hand padding:
trace('"' + Utils.pad('Hello', 20, ' ', true) + '"');
"Hello "
columnizeText(text, padding, delimiter, useSpaces, tabWidth)
Converts a delimited block of text to tab-separated columns
Sometimes when generating output, it's useful to have declarations in columns, such as CSV output or perhaps variable declarations, and this method allows you to do that.
It takes a block of text (a string), and determines the columns based on a delimiter character, then outputs the same text with the space between the rows expanded to create a grid of text.
The following example demonstrates taking some comma-delimited text and converting to tabular format:
var data = <xml> Rank,Artist,Song,Year 1,Queen,Bohemian Rhapsody,1975 2,John Lennon,Imagine,1980 3,Robbie Williams,Angels,1997 4,Beatles,Hey Jude,1968 5,Nirvana,Smells Like Teen Spirit,1991 6,Oasis,Live Forever,1994 7,Oasis,Wonderwall,1995 8,U2,One,1992 9,Verve,Bitter Sweet Symphony,1997 10,U2,With Or Without You,1987 </xml> trace(Utils.columnizeText(data, 0, ','));
Rank Artist Song Year 1 Queen Bohemian Rhapsody 1975 2 John Lennon Imagine 1980 3 Robbie Williams Angels 1997 4 Beatles Hey Jude 1968 5 Nirvana Smells Like Teen Spirit 1991 6 Oasis Live Forever 1994 7 Oasis Wonderwall 1995 8 U2 One 1992 9 Verve Bitter Sweet Symphony 1997 10 U2 With Or Without You 1987
The following example (more relevent to coding!) generates ActionScript 3.0 declarations in columns, for Bitmap items in the library:
function process(element) { var name = element.shortName.replace(/\.\w+$/, '').toCamelCase(); var type = ActionScript.getClass(element, true); text += 'var {name}\t:Sound\t= new {type}();\n'.inject(name, type); } var text = ''; $$(':sound:exported').sort().each(process); trace('import sounds.*;\n') trace(Utils.columnizeText(text));
import sounds.*; var damage :Sound = new Damage(); var explosion :Sound = new Explosion(); var laserShoot :Sound = new Laser(); var notify :Sound = new Notify(); var powerUp :Sound = new PowerUp();Note that the above code demos in some browsers may show spaces; this is not the case in JSFL, unless the useSpaces parameter is set to true!
parseValue(value, trim)
Parse any string into a real datatype. Supports Number, Boolean, hex (0x or #), XML, XMLList, Array notation, Object notation, JSON, Date, undefined, null
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:
Utils.parseValue('2.1'); // 2.2 Utils.parseValue('2.0'); // 2 Utils.parseValue('TRUE'); // true Utils.parseValue('#FF0000'); // 16711680 Utils.parseValue('0xFF0000'); // 16711680 Utils.parseValue('<xml a="1" />'); // <xml a="1" /> Utils.parseValue('[1,2,3]'); // [1, 2, 3] Utils.parseValue('{"a":1}'); // {a:1} Utils.parseValue('Jan 01 2011'); // Sat Jan 01 20011 00:00:00 GMT+0000 (GMT Standard Time) Utils.parseValue('undefined'); // undefined Utils.parseValue(''); // null
parseExpression(expression, delimiter, nestStart, nestEnd)
Parses a compound CSS (or CSS-like) expression into single elements, respecting :nested(:tokens, [like=these,ones])
The parseExpression function is mainly used internally to the framework to parse out discrete components from comma-delimited CSS and XUL Control shorthand expressions, which cannot reliably be accomplished with RegularExpressions because of nesting concerns.
The following example demonstrates splitting a complex XUL expression, versus parsing it:
var expression = 'title:Create Bitmap definitions,columns:[120,200],dropdown:Options={one:1,two:2,three:3},checkbox:Selected Only=true' var controls1 = expression.split(','); var controls2 = Utils.parseExpression(expression); inspect(controls1, 'Split'); inspect(controls2, 'Parse');
Splitting is bad, as it doesn't respect the nested groups:
Split: Array (depth:4, objects:0, values:7, time:0.0 seconds) -------------------------------------------------------------------------------- array => Array 0: "title:Create Bitmap definitions" 1: "columns:[120" 2: "200]" 3: "dropdown:Options={one:1" 4: "two:2" 5: "three:3}" 6: "checkbox:Selected Only=true"
However, parsing respects the nested identifiers such as (), [], and {}:
Parse: Array (depth:4, objects:0, values:4, time:0.0 seconds) -------------------------------------------------------------------------------- array => Array 0: "title:Create Bitmap definitions" 1: "columns:[120,200]" 2: "dropdown:Options={one:1,two:2,three:3}" 3: "checkbox:Selected Only=true
RegExp methods
- match(str, rxGlobal, matchNames, captureIndex)
- rxEscape(value)
- rxUnescape(value)
- makeWildcard(value)
match(str, rxGlobal, matchNames, captureIndex)
Performs a global RegExp match but returns a 2D Array of local match Arrays, or Objects if matchNames are supplied
This method saves you running 2 separate RegExp loops to extract both global and local matchs, and also packages assigning match values to named properties.
The following example matches object methods from the source of the Event.jsfl file in the framework core, and passes in names that the parameter:
var contents = new File('//core/jsfl/libraries/flash/Events.jsfl').contents; var rx = /(\w+):function\((.*)\)/; var matches = Utils.match(contents, rx, ['name', 'arguments']); inspect(matches);
Inspect: Array (depth:4, objects:6, values:18, time:0.0 seconds) -------------------------------------------------------------------------------- array => Array [0] => Object match: "add:function(type, callback, name, scope)" name: "add" arguments: "type, callback, name, scope" [1] => Object match: "remove:function(type, name)" name: "remove" arguments: "type, name" [2] => Object match: "removeAll:function(type)" name: "removeAll" arguments: "type" [3] => Object match: "get:function(type, name)" name: "get" arguments: "type, name" [4] => Object match: "toString:function()" name: "toString" arguments: "" [5] => Object match: "fire:function(event)" name: "fire" arguments: "event"
As you can see in this example, the returned 2D Array of match objects can be both iterated over, and the matches used, much more conveniently than numbered match indices:
for each(var match in matches) { format('{name} => {arguments}', match.name, match.arguments); }
add => type, callback, name, scope remove => type, name removeAll => type get => type, name toString => fire => event
rxEscape(value)
Escapes a string for use in RegExp constructors
The following example escapes a string to be used in a RegExp constructor:
trace(Utils.rxEscape('/()[]{}^$.*+?'));
\/\(\)\[\]\{\}\^\$\.\*\+\?
rxUnescape(value)
Unescapes a string used in RegExp constructors
The following example unescapes an escaped RegExp string:
trace(Utils.rxUnescape('\/\(\)\[\]\{\}\^\$\.\*\+\?'));
/()[]{}^$.*+?
makeWildcard(value)
Converts a wildcard (*) string into a non-greedy RegExp
The following example creates a RegExp match from a wildcard String, which could be used to match filenames:
var rx = Utils.makeWildcard('core/*.*', true); trace(rx);
/^core\/.*?\..*?$/
File and URI methods
- glob(globPathOrURI, searchableOnly, asPaths, debug)
- getURIs(folder, $depth, $filesOnly, $filter, $extensions)
- getFirstValidURI(uris)
- getSearchableURIs(pathOrURI, itemType, returnPaths)
- isSearchable(pathOrURI)
- walkFolder(folder, $callback, $maxDepth, $returnURIs)
- makeTree(paths)
glob(pathOrURI, pattern, searchableOnly, debug)
Returns a list of URIs for a glob string
Globbing is a powerful technique borrowed from Unix and PHP in order to match file paths by way of wildcard pattern matching. It allows developers to match files, folders and subfolders with a fairly simple syntax.
xJSFL has a slightly simpler implementation than the full glob implementation, and uses only stars (*) and double-stars (**) to match same-level and recursive-level elements. Both stars and double-stars are "expanded" during the match, that is, they match all characters of a path, with the double-star token matching / characters as well.
Put simply, the syntax is:
* // a single star matches files and folders *.* // a single star and a dot and a star matches files only (those with an extension) / // a trailing slash matches folders only ** // a double-star matches all characters (including /), making the search recursive
These can be combined with each other as follows:
* // a single star matches files and folders in the current folder */ // a single star and a trailing slash matches only folders in the current folder *.* // a single star with a dot and a star matches all files in the current folder ** // double-stars match files and folders recursively **/ // double-stars and a trailing slash match only folders recursively **.* // double-stars with a dot and a star match only files recursively
And they can (and should) also be mixed with other characters, to return more complex matches:
*.jsfl // match all jsfl files in the current folder t*/ // match only folders that start with "t" in the current folder *asset* // match any files or folders that contain the word "asset" in the current folder **.png // match all PNG files in the current and sub folders **/*.png // match all PNG files in sub folders **/*assets/ // match all folders with the suffix "assets" in any sub folders assets/**.* // match all files from the assets folder or its children
Utils.glob() uses URI.toURI() internally, so supports all its functionality like placeholder tokens and relative paths, meaning that you can pass a variety of glob paths in:
Utils.glob('*'); // files and folders in the current file's folder Utils.glob('../*.*'); // files in the current file's parent folder Utils.glob('c:/temp/**/'); // all folders under the absolute path c:/temp/ Utils.glob('file:///c|/temp/**'); // all files and folders under the absolute URI c:/temp/ Utils.glob('{user}**'); // all files and folders in the xJSFL user folder
The following example creates a variety of simple glob patterns (all from the same root folder) and inspects their results:
// define patterns var patterns = { files: 'c:/test/*.*', folders: 'c:/test/*/', filesAndFolders:'c:/test/*', allRecursive: 'c:/test/**', allImages: 'c:/test/**.png', allVideos: 'c:/test/**.flv', allFolders: 'c:/test/**/', allAssets: 'c:/test/assets/**.*', allCustom: 'c:/test/**a*', } // get results var results = {}; for(var name in patterns) { var path = patterns[name]; var pattern = path.replace('c:/test/', ''); results[name + ': "' +pattern+ '"'] = Utils.glob(path, false, true); } // inspect inspect(results);
In the following results, the glob patterns have been highlighted in red:
Inspect: Object (depth:4, objects:9, values:57, time:0.0 seconds) -------------------------------------------------------------------------------- object => Object [files: "*.*"] => Array 0: "c:/test/read me.txt" [folders: "*/"] => Array 0: "c:/test/assets/" 1: "c:/test/jsfl/" [filesAndFolders: "*"] => Array 0: "c:/test/assets/" 1: "c:/test/jsfl/" 2: "c:/test/read me.txt" [allRecursive: "**"] => Array 0: "c:/test/assets/" 1: "c:/test/assets/images/" 2: "c:/test/assets/images/image 1.png" 3: "c:/test/assets/images/image 2.png" 4: "c:/test/assets/images/image 3.png" 5: "c:/test/assets/videos/" 6: "c:/test/assets/videos/backup/" 7: "c:/test/assets/videos/backup/video 4.flv" 8: "c:/test/assets/videos/backup/video 5.flv" 9: "c:/test/assets/videos/backup/video 6.flv" 10: "c:/test/assets/videos/video 1.flv" 11: "c:/test/assets/videos/video 2.flv" 12: "c:/test/assets/videos/video 3.flv" 13: "c:/test/jsfl/" 14: "c:/test/jsfl/files.jsfl" 15: "c:/test/jsfl/libraries/" 16: "c:/test/jsfl/libraries/animation tools.jsfl" 17: "c:/test/jsfl/libraries/custom functions.jsfl" 18: "c:/test/jsfl/main.jsfl" 19: "c:/test/jsfl/ui.jsfl" 20: "c:/test/read me.txt" [allImages: "**.png"] => Array 0: "c:/test/assets/images/image 1.png" 1: "c:/test/assets/images/image 2.png" 2: "c:/test/assets/images/image 3.png" [allVideos: "**.flv"] => Array 0: "c:/test/assets/videos/backup/video 4.flv" 1: "c:/test/assets/videos/backup/video 5.flv" 2: "c:/test/assets/videos/backup/video 6.flv" 3: "c:/test/assets/videos/video 1.flv" 4: "c:/test/assets/videos/video 2.flv" 5: "c:/test/assets/videos/video 3.flv" [allFolders: "**/"] => Array 0: "c:/test/assets/" 1: "c:/test/assets/images/" 2: "c:/test/assets/videos/" 3: "c:/test/assets/videos/backup/" 4: "c:/test/jsfl/" 5: "c:/test/jsfl/libraries/" [allAssets: "assets/**.*"] => Array 0: "c:/test/assets/images/image 1.png" 1: "c:/test/assets/images/image 2.png" 2: "c:/test/assets/images/image 3.png" 3: "c:/test/assets/videos/backup/video 4.flv" 4: "c:/test/assets/videos/backup/video 5.flv" 5: "c:/test/assets/videos/backup/video 6.flv" 6: "c:/test/assets/videos/video 1.flv" 7: "c:/test/assets/videos/video 2.flv" 8: "c:/test/assets/videos/video 3.flv" [allCustom: "**a*"] => Array 0: "c:/test/assets/images/image 1.png" 1: "c:/test/assets/images/image 2.png" 2: "c:/test/assets/images/image 3.png" 3: "c:/test/jsfl/libraries/animation tools.jsfl" 4: "c:/test/jsfl/main.jsfl" 5: "c:/test/read me.txt"
The Code Examples module also has some sample glob code in:
xJSFL/modules/Code Examples/jsfl/utils/glob.jsfl
getURIs(folder, $depth, $filesOnly, $filter, $extensions)
Returns a list of URIs for a given glob path, folder reference and optional condition
Get URIs is used to grab URIs from a folder and its subfolders.
The following example :
Utils.getURIs(folder, $depth, $filesOnly, $filter, $extensions);
getFirstValidURI(uris)
Returns the first valid path or URI from an Array of paths and/or URIs
This function is useful when you're working across various machines in a studio, and you need to ensure to get a base path.
The following example checks 3 paths, and returns the last one:
var uris = [ 'file:///E|/some/folder/', 'file:///X|/server/path to/another/folder/', 'file:///C|/temp/', ]; var uri = Utils.getFirstValidURI(uris); trace(uri);
file:///C|/temp/
getSearchableURIs(pathOrURI, itemType, returnPaths)
Returns URIs which are searchable as defined within manifest.xml files in parent folders
The following example gets all searchable folders from the Snippets folder. Note that the assets/icons/ folder was skipped, as it contains a manifest.xml file with the folder.searchable node set to false:
var uris = Utils.getSearchableURIs('//modules/Snippets/', 'folders'); inspect(uris);
Inspect: Array (depth:4, objects:0, values:11, time:0.0 seconds) -------------------------------------------------------------------------------- array => Array 0: "file:///E|/Projects/xJSFL/modules/Snippets/" 1: "file:///E|/Projects/xJSFL/modules/Snippets/assets/" 2: "file:///E|/Projects/xJSFL/modules/Snippets/assets/templates/" 3: "file:///E|/Projects/xJSFL/modules/Snippets/assets/templates/jsfl/" 4: "file:///E|/Projects/xJSFL/modules/Snippets/config/" 5: "file:///E|/Projects/xJSFL/modules/Snippets/config/snippets/" 6: "file:///E|/Projects/xJSFL/modules/Snippets/flash/" 7: "file:///E|/Projects/xJSFL/modules/Snippets/flash/WindowSWF/" 8: "file:///E|/Projects/xJSFL/modules/Snippets/jsfl/" 9: "file:///E|/Projects/xJSFL/modules/Snippets/jsfl/libraries/" 10: "file:///E|/Projects/xJSFL/modules/Snippets/ui/"
isSearchable(pathOrURI)
Checks is a folder is searchable, depending on its manifest
The following example grabs the URIs within Snippets/assets/ and checks which of them are searchable (icons and source are both set to be non-searchable as they have so many files):
var uris = Utils.getURIs('//modules/Snippets/assets/'); for each(uri in uris) { format('{uri} => {state}', URI.toPath(uri, true), Utils.isSearchable(uri)); }
E:/Projects/xJSFL/modules/Snippets/assets/icons/ => false E:/Projects/xJSFL/modules/Snippets/assets/source/ => false E:/Projects/xJSFL/modules/Snippets/assets/templates/ => true
walkFolder(folder, $callback, $maxDepth, $returnURIs)
Recursively trawl a folder's contents, optionally calling a callback per element
Recurse folder provides a standard method to recurse folders, with its default functionality returning an Array of all file paths. It can also be passed a callback function in order to process each file and folder it iterates over.
Note that $ arguments may passed in any order as they are different data types.
Default action
The following example lists the contents of the c:/temp/test folder:
var paths = Utils.walkFolder('c:/temp/test'); trace(paths.join('\n'));
c:/temp/test c:/temp/test/a folder c:/temp/test/a folder/another folder c:/temp/test/a folder/another folder/test.jsfl c:/temp/test/a folder/test.fla c:/temp/test/a folder/test.txt c:/temp/test/document.doc c:/temp/test/some file.as c:/temp/test/test copy.txt
Using a callback
The following example supplies a callback with which to process the items it iterates over:
function callback(element, index, level, indent) { trace (indent + '/' + element.name); } Utils.walkFolder('c:/temp/test/', callback);
/test /a folder /another folder /test.jsfl /test.fla /test.txt /document.doc /some file.as /test copy.txt
Skipping file or folder items
The following example shows how files and folders can be skipped by returning a Boolean false from the callback function, in this case if they have the letter "a" in their name (skipping a folder will also skip any files or folders in that folder):
function callback(element, index, level, indent) { return element.name.indexOf('a') == -1; } var paths = Utils.walkFolder('c:/temp/test/', callback); trace(paths.join('\n'));
c:/temp/test c:/temp/test/document.doc c:/temp/test/test copy.txt
Note that the element parameter of the callback will always be a File or Folder instance, so you can access any properties of those classes.
makeTree(source)
Returns a multiline string, showing the file/folder hierarchy of an input array of paths or URIs
The following example traces out a tree of the user's JSFL folder:
trace(Utils.makeTree('//user/jsfl/'));
/libraries /load-modules.jsfl /readme.txt /snippets /Animation /PNG sequence to SWF.jsfl /Propogate element names across frames.jsfl /Development /ActionScript /Declare stage instances.jsfl /Export SWC.jsfl /Export class definitions.jsfl /Tools /Execute JSFL.jsfl /Inspect built-in object.jsfl /Inspect variable.jsfl /xJSFL /Change Module Panel publish location.jsfl /Sync module SWFs.jsfl /Library /Delete empty folders.jsfl /Export classes.jsfl /Inspect selected items.jsfl /Select items by property.jsfl /Smooth bitmaps.jsfl /Spreadsheet-edit properties.jsfl /Wrap bitmaps in classes.jsfl /Stage /Apply tints.jsfl /Assign unique names.jsfl /Create test squares.jsfl /Make circular.jsfl /Randomize selected elements.jsfl /Set 9-slice guides.jsfl /Tools /Find.jsfl /_libraries /manifest.xml /uri.jsfl
Framework methods
getPanel(name)
Returns the named SWF panel if it exists
The following example grabs the xJSFL Snippets panel object:
var panel = Utils.getPanel('xJSFL Snippets');
[object SWFPanel]
getStack(error, shorten)
Returns an array of the the currently executing files, paths, lines, and code,
getStack() is used throughout xJSFL for debugging, finding callling file URIs, and many other things.
The following example dumps the current call stack when function c() is called (most-recent calls are first):
function a(){ b(); } function b(){ c(); } function c() { inspect(Utils.getStack()); } a();
Inspect: Array (depth:4, objects:4, values:20, time:0.0 seconds) -------------------------------------------------------------------------------- array => Array [0] => Object line: 12 code: "c()" file: "test.jsfl" path: "E:/Projects/xJSFL/dev/" uri: "file:///E|/Projects/xJSFL/dev/test.jsfl" [1] => Object line: 9 code: "b()" file: "test.jsfl" path: "E:/Projects/xJSFL/dev/" uri: "file:///E|/Projects/xJSFL/dev/test.jsfl" [2] => Object line: 8 code: "a()" file: "test.jsfl" path: "E:/Projects/xJSFL/dev/" uri: "file:///E|/Projects/xJSFL/dev/test.jsfl" [3] => Object line: 15 code: "" file: "test.jsfl" path: "E:/Projects/xJSFL/dev/" uri: "file:///E|/Projects/xJSFL/dev/test.jsfl"
bind(scope, fn)
Binds the scope of a function to another object permanently
When referencing a function on another object dynamically, the scope that function will be in, when called, is the scope where the reference was first created. The way round this is to use function.apply() or function.call(), but both these methods are only temporary.
Utils.bind() returns an interim function that is permanently bound to the supplied scope, which makes it easier to call in future.
The following example demonstrates 3 ways of calling a function, but the first two are called in the Window scope, not the object scope:
var object = { value:1, test:function() { trace('> ' + this.value) } } func1 = object.test; func2 = object['test']; func3 = Utils.bind(object, object['test']);
> undefined > undefined > 1
Comments are closed.