UIZE JavaScript Framework

MODULES Uize

1. Introduction

The Uize module is the base module that defines the Uize namespace for the UIZE JavaScript Framework, and also provides a module loader mechanism and a healthy assortment of utility belt methods.

DEVELOPERS: Chris van Rensburg

1.1. Key Features

1.1.1. Utility Belt Methods

The Uize module provides a slew of utility belt methods that can be divided into the following categories...

1.1.1.1. Module Mechanism Methods

The Uize module provides static methods for declaring your own JavaScript modules, requiring modules, and configuring the module loader mechanism to suit your application environment.

Uize.getModuleByName - returns a reference to the module of the specified name, or undefined if the module's not loaded
Uize.getPathToLibrary - returns the relative path from the current document to the folder containing the specified JavaScript file
Uize.module - lets you declare a JavaScript module that can be required by other JavaScript modules
Uize.moduleLoader - loads a JavaScript module (specified by its module name)
Uize.moduleUrlResolver - resolves the specified JavaScript module name to a URL path
Uize.package - creates a package function with the specified statics (methods and/or properties)
Uize.require - ensures that all of the specified modules are loaded before calling the specified callback function, loading required modules as necessary

1.1.1.2. Value Testing Methods

The Uize module provides a number of static methods for performing useful tests on values.

Uize.canExtend - tests if value is an object that can be extended with custom properties
Uize.inRange - tests if value is within specified value range
Uize.isArguments - tests if value is a function arguments object
Uize.isArray - tests if value is an array
Uize.isBoolean - tests if value is a boolean
Uize.isEmpty - tests if an object or array is empty, or if a non-object value is "falsy"
Uize.isFunction - tests if value is a function reference
Uize.isInstance - tests if value is an instance of a Uize.Class subclass
Uize.isList - tests if a value is a list object, such as an array
Uize.isNaN - tests if a value is the JavaScript special value NaN
Uize.isNully - tests if a value is null or undefined
Uize.isNumber - tests if a value is a number (and not NaN)
Uize.isObject - tests if a value is non-null and an object
Uize.isPlainObject- tests if a value is a plain object (an instance of JavaScript's built-in Object object)
Uize.isPrimitive - tests if a value is a JavaScript primitive (ie. string, number, or boolean)
Uize.isRegExp- tests if a value is a regular expression (ie. an instance of the RegExp object)
Uize.isSameAs - tests if two values are the same in a strict equality test, with support for NaN values
Uize.isString - tests if a value is a string

1.1.1.3. Basic Data Utilities

The Uize module provides a number of static methods for performing basic data manipulation operations that are commonly encountered.

Uize.clone - clones a value, and creates deep clones of object or array type values
Uize.copy - copies the values of properties from one or more source objects into a fresh object
Uize.copyInto - copies the values of properties from one or more source objects into a target object
Uize.copyList - copies the elements of a source list object into a fresh array
Uize.emptyOut - empties out the contents of an object or array
Uize.findRecord - finds the first record in a records array that matches specified criteria
Uize.findRecordNo - returns the index of the first record in a records array that matches specified criteria
Uize.indexIn - returns the index of a value in a values array or object
Uize.isIn - tests if a value is in a specified array or object
Uize.keys - returns an array containing the names of the properties (ie. keys) in an object
Uize.lookup - creates a lookup object from an array of values
Uize.map - iterates over an array or object and applies the specified value transformer to produce new values
Uize.max - returns the largest value in a values array
Uize.meldKeysValues - creates an object by melding keys from a keys array with values from a values array
Uize.merge - merges the contents of multiple source objects together into a fresh object
Uize.mergeInto - merges the contents of one or more source objects into a target object
Uize.min - returns the smallest value in a values array
Uize.pairUp - uses a list of key/value pairs to form an object
Uize.push - pushes / appends the elements from a source list onto the end of a target list
Uize.recordMatches - determines if a record object matches the specified criteria
Uize.reverseLookup - creates a reverse lookup from a specified lookup object or values array
Uize.totalKeys - counts the number of keys in an object (essentially the number of properties)
Uize.values - returns an array containing the values of the properties in an object

1.1.1.4. Iterator Methods

The Uize module provides a number of static methods for iterating over properties of objects or elements of arrays.

Uize.applyAll - calls a list of functions on a specified context, with an optional arguments list
Uize.callOn - calls a method on all values of properties in an object or elements of an array
Uize.forEach - iterates over an array, arguments object, object, or length range, calling the specified iteration handler for each element or property

1.1.1.5. Useful Value Transformers

The Uize module provides some value transformer methods for transforming or resolving values in ways that are either generally useful or useful to other UIZE modules.

Uize.capFirstChar - capitalizes the first character of a string
Uize.constrain - constrains a value to a specified range
Uize.defaultNully - defaults a value to the specified default, if the value is nully (ie. null or undefined)
Uize.escapeRegExpLiteral - escapes a string so that it can be used as a literal match portion of a regular expression string
Uize.substituteInto - substitutes the specified values into the specified string using token replacement
Uize.toNumber - coerces a value to a number, with defaulting if it cannot be coerced successfully

1.1.1.6. Dummy Functions

The Uize module provides a number of dummy functions that can be supplied as placeholders in situations where function type parameters are expected.

Uize.nop - performs no operation and returns no value (equivalent to returning undefined)
Uize.returnFalse - always returns the value false
Uize.returnTrue - always returns the value true
Uize.returnX - always returns the value of the first argument, unaltered

1.1.1.7. General Utilities

The Uize module provides the following general utility methods...

Uize.eval - lets you perform quarantined code evaluation of a JavaScript code string
Uize.getClass - gets the class of which a specified value is an instance, or returns the value if it is a class or function
Uize.global - returns a reference to the global object
Uize.laxEval - lets you perform quarantined code evaluation of a JavaScript code string, but not in JavaScript strict mode
Uize.noNew - wraps an object constructor function to make JavaScript's new operator optional
Uize.now - returns the current time in milliseconds since 1970 (POSIX time)
Uize.quarantine - generates a quarantined version of the supplied function
Uize.resolveTransformer - resolves the specified transformer (of any type) to a transformer function
Uize.substituteInto - substitutes one or more substitution values into a string
Uize.since - returns the amount of time in milliseconds since the specified date

1.1.2. Quarantined Code Execution

The Uize module provides static methods to facilitate the quarantined execution of JavaScript code, which can be divided into two types: quarantined code evaluation and quarantined nested functions.

1.1.2.1. What is Quarantined Code Execution?

Quarantined code execution is the execution of some JavaScript from within a deep local scope, but where the code being executed is executed outside of that deep scope - in a "quarantined" scope.

In the quarantined scope, the only scope that the quarantined code has access to in its scope chain is the global scope. The executed code is, thereby, quarantined from the local scope so that it cannot accidentally contaminate (or be contaminated by) the local scope, by accessing or assigning to identifiers within the local scope (or anywhere else up the local scope's scope chain).

This is best illustrated by an example...

NON-QUARANTINED

function foo () {
  var bar = 5;
  eval ('var baz = 10; alert (bar);');  // doesn't throw error, but we'd want it to
}

foo ();

In the above example, some code is being evaluated inside a function scope using JavaScript's built-in eval function. Now, for argument's sake, let's say that this code has a typo in it where it was supposed to access the baz variable that it defined, but it's actually trying to access a bar variable. If the surrounding scope in which the eval call is being made contains a bar variable, then the code will not produce an error as it should and will appear to work, but it will have a bug.

This kind of cross-contamination between evaluated code and a deep local scope can be alleviated by using either of the Uize.eval or Uize.laxEval methods, as follows...

QUARANTINED

function foo () {
  var bar = 5;
  Uize.eval ('var baz = 10; alert (bar);');  // throws an error, as we would like
}

foo ();

In the above example, we have replaced the use of JavaScript's built-in eval function with a call to the Uize.eval method. The code being evaluated is now evaluated in a quarantined fashion so that it no longer has access to scope inside the foo function, and the only scope it has access to is the global scope. In this example, the global scope does not define a bar variable, so the code being evaluated produces a JavaScript error as we would like and exposes the typo in the code.

Now, the global scope could always still have identifiers that could cross-contaminate with code being evaluated using the Uize.eval or Uize.laxEval methods, but the potential for such cross-contamination is much reduced, especially as you consider that the deeper and deeper you go into nested scopes, the more identifiers get "tacked" on as a result of an increasingly long scope chain. The most important thing is that the Uize.eval and Uize.laxEval methods allow you to quarantine code evaluation from the current / local scope within which the methods are called.

1.1.2.2. Quarantined Code Evaluation

The Uize module provides two static methods to facilitate quarantined evaluation of JavaScript code strings.

The general wisdom is to avoid using JavaScript's built-in eval function at all costs, and this is, for the most part, good advice. However, JavaScript is a dynamic language, and when you're doing more sophisticated (and risky) things with JavaScript such as dynamic code construction, it becomes useful to evaluate strings that contain JavaScript code.

Now, a risk with careless use of JavaScript's eval function from deep within the nested functions of your code is that you may not be intending to have the code evaluated within the scope of your deep function.

It could be a benefit to the code you're eval'ing that it has access to the scope of the function in which you're eval'ing it, but it may also be a curse in two respects...

1)  the code being eval'ed may unexpectedly conflict with identifiers in your function's scope (or any scope up the scope chain)
2)  function closures within the code being eval'ed will hang on to your function's scope state (with "interesting" memory usage implications)

To address these risks and to allow you to perform quarantined code evaluation, the Uize module provides methods for strict mode quarantined evaluation and non-strict mode quarantined evaluation.

1.1.2.2.1. Strict Mode Quarantined Evaluation

To perform quarantined code evaluation in JavaScript strict mode, the Uize.eval method can be used.

SYNTAX

evalResultANYTYPE = Uize.eval (codeToEvalSTR);

EXAMPLE

function foo () {
  var bar = 5;
  Uize.eval ('bar = 10');  // throws an error, because bar is not declared inside eval'd code
  alert (bar);
}

foo ();

In the above example, the code being evaluated in the call to the Uize.eval method results in a JavaScript error being thrown. This is for two reasons:

1)  the Uize.eval method evaluates the code in a quarantined fashion, so it doesn't have access to the bar variable defined in the local scope
2)  the Uize.eval method evaluates code using JavaScript strict mode, so the code that now appears to assigning a value to a variable not declared in the global scope (the only scope that the quarantined code evaluation has access to) throws an error because this is not permitted in strict mode
1.1.2.2.2. Non-strict Mode Quarantined Evaluation

To perform quarantined code evaluation in non-strict mode, the Uize.laxEval method can be used.

SYNTAX

evalResultANYTYPE = Uize.laxEval (codeToEvalSTR);

EXAMPLE

function foo () {
  var bar = 5;
  Uize.laxEval ('bar = 10');  // doesn't throw an error, but doesn't set value of local scope bar
  alert (bar);  // alerts "5", because the quarantined eval'd code didn't set local bar variable
}

foo ();

In the above example, the code being evaluated in the call to the Uize.laxEval method does not throw a JavaScript as the Uize.eval method would, but it still doesn't set the value of the bar variable in the local scope. There are two things in play here...

1)  the Uize.laxEval method evaluates the code in a quarantined fashion, so it doesn't have access to the bar variable defined in the local scope
2)  the Uize.laxEval method evaluates code using non-strict mode, so it allows the quarantined code to assign a value to a variable that is not declared in the quarantined code's scope chain, which has the effect of declaring bar as a global variable rather than throwing an error (as would be the case in strict mode)

1.1.2.3. Quarantined Nested Functions

To declare a function from within some deep local scope, but have that function be quarantined from the local scope, one can use the Uize.quarantine method.

The Uize.quarantine method allows us to essentially generate a quarantined version of the supplied function. When the quarantined function is then called, it won't have access to the same scope chain that the original function had access to - it will only have access to the global scope.

SYNTAX

quarantinedFunctionFUNC = Uize.quarantine (sourceFunctionFUNC);

The behavior of the Uize.quarantine method is best illustrated by an example...

EXAMPLE

var bar = 10;

function Foo () {
  var bar = 5;
  this.baz = function () {
    alert (bar);
  };
  this.qux = Uize.quarantine (this.baz);
}

var myFoo = new Foo ();

myFoo.baz ();  // alerts 5, because the baz method has access to the Foo scope
myFoo.qux ();  // alerts 10, because it is quarantined from the Foo scope, and global bar is 10

In the above example, the instance method baz of the Foo object is defined inside the constructor. As a result, it has access to the Foo scope and the bar variable defined in it, and it alerts the value of local bar variable when it is called. Now, the qux instance method, on the other hand, is defined as being a quarantined version of the baz instance method, so it will only have access to the global scope when called.

As a result, when the baz method is called on the instance myFoo, it alerts "5", which is the value of the bar variable in the Foo scope. In contrast, when the qux method is called on myFoo, it alerts "10", which is the value of the bar variable in the global scope - because it is quarantined from the Foo scope, it only has access to the global scope and the global bar variable.

1.1.2.3.1. Benefits of Uize.quarantine Over Uize.eval or Uize.laxEval

The quarantining effect of the Uize.quarantine method can also be achieved by using either of the Uize.eval or Uize.laxEval methods, but the Uize.quarantine method has a few benefits over the quarantined code evaluation methods...

1.1.2.3.1.1. Quarantine Existing Functions

The Uize.quarantine method lets you create a quarantined version of a function that already exists.

This is something that you can't easily do with the Uize.eval or Uize.laxEval methods - you'd basically have to manually re-implement the Uize.quarantine method.

1.1.2.3.1.2. Easier to Write Code in Function Form

The Uize.quarantine method lets you write quarantined code using a regular function, which is just plain easier to do.

By writing quarantined code in function form, you can avoid getting caught up in the character escaping and multi-line string concatenation issues associated with constructing a JavaScript code string for evaluation. This becomes increasinly an issue as the amount of code that you want to quarantine increases and constructing the code as a string becomes increasingly cumbersome.

1.1.2.3.1.3. Code in Function Form is Scrunchable

Quarantined code written in function form has the benefit of being scrunchable by the scruncher (or otherwise minified by other JavaScript minifiers or code obfuscators).

Naturally, the benefits of this will be greater the larger the quarantined code is.

1.1.2.3.1.4. Some Early Error Detection

Quarantined code written in function form will be parsed by the JavaScript interpreter early.

Unlike the Uize.eval and Uize.laxEval methods, where the quarantined code will be evaluated at runtime and where errors in the code will only surface when the code is evaluated, the function supplied to the Uize.quarantine method will be parsed just like any other function, and syntax errors (and some errors relating to non-compliance with JavaScript strict mode) will be caught early - before the quarantined code is even executed.

1.1.2.3.2. Immediately Invoked Quarantined Functions

In cases where one wishes to execute code immediately from within some deep local scope, but where one wishes to have that code be executed in a quarantined fashion, one can call the function returned by the Uize.quarantine method immediately.

EXAMPLE

// code executed before quarantined code

Uize.quarantine (function () {
  // quarantined code execution
}) ();

// code executed after quarantined code

This is just like immediate invokation of an anonymous function, except with the additional wrapper of the Uize.quarantine call.

1.2. Examples

There are no dedicated showcase example pages for the Uize module.

SEARCH FOR EXAMPLES

Use the link below to search for example pages on the UIZE Web site that reference the Uize module...

SEARCH

1.3. Implementation Info

The Uize module defines the Uize package.

1.3.1. Features Introduced in This Module

1.3.2. Features Overridden in This Module

No features have been overridden in this module.

1.3.3. Features Inherited From Other Modules

This module has no inherited features.

1.3.4. Modules Directly Under This Namespace

1.3.5. Unit Tests

The Uize module is unit tested by the Uize.Test.Uize test module.

2. Static Methods

2.1. Uize.addFolderOrgNamespaces

DIFFERENT USAGES

Add a Single Folder Organized Namespace

Uize.addFolderOrgNamespaces (namespaceSTR);

Add Multiple Folder Organized Namespaces, Specifing Them as a String Array

Uize.addFolderOrgNamespaces (namespacesARRAY);

Add Multiple Folder Organized Namespaces, Specifing Them as Multiple Arguments

Uize.addFolderOrgNamespaces (namespace1STR,namespace2STR,...,namespaceNSTR);

IMPLEMENTATION INFO

this feature was introduced in this module

2.2. Uize.applyAll

Calls the specified list of functions on the specified context, with an optional list of arguments.

The Uize.applyAll method can be useful for executing a list of event handlers, queued callbacks, a chain of constructors, etc.

DIFFERENT USAGES

Call Multiple Functions as Methods on a Context

Uize.applyAll (contextANYTYPE,functionsLIST);

Call Multiple Functions as Methods on a Context, with an Arguments List

Uize.applyAll (contextANYTYPE,functionsLIST,argumentsLIST);

Call Multiple Functions with an Arguments List

Uize.applyAll (0,functionsLIST,argumentsLIST);

2.2.1. Call Multiple Functions as Methods on a Context

In the simplest usage, a list of functions can be called as methods on a context by specifying the context as the first argument and the list of functions as the second.

SYNTAX

Uize.applyAll (contextANYTYPE,functionsLIST);

2.2.2. Call Multiple Functions as Methods on a Context, with an Arguments List

In order to call a list of functions as methods on a context and with the same set of arguments for each call, the arguments list can be specified using the optional argumentsLIST third argument.

SYNTAX

Uize.applyAll (contextANYTYPE,functionsLIST,argumentsLIST);

2.2.3. Call Multiple Functions with an Arguments List

In cases where you wish to call a list of functions with the same set of arguments for each call, but where you don't wish them to be called as methods on a context, you can simply specify the value 0 for the first argument.

SYNTAX

Uize.applyAll (0,functionsLIST,argumentsLIST);

NOTES

compare to the Uize.callOn static method
see also the other iterator methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.3. Uize.callOn

Recurses through the arbitrarily complex object specified, calling the specified method on all values that are not nully (null or undefined).

This method allows the following...

specifying a function that should be called as a method on a specified set of values
specifying the name of a method that should be called on a specified set of values

SYNTAX

Uize.callOn (objectSetARRAYorOBJ,methodSTRorFN);

EXAMPLE

function myPhantomMethod () {
  // do stuff
}

Uize.callOn (
  [instance1,instance2,instance3,instance4,instance5,instance6],myPhantomMethod
);

The above statement would be equivalent to...

function myPhantomMethod () {
  // do stuff
}

myPhantomMethod.call (instance1);
myPhantomMethod.call (instance2);
myPhantomMethod.call (instance3);
myPhantomMethod.call (instance4);
myPhantomMethod.call (instance5);
myPhantomMethod.call (instance6);

This method is most compelling when an object or array contains a dynamic set of instances on which a specific method needs to be called, or on which a specified function needs to be called as a method.

EXAMPLE

var dates = [
  new Date ('05/10/1986'),
  new Date ('01/12/1992'),
  new Date ('10/04/2003'),
  new Date ('07/01/2010')
];

Uize.callOn (
  dates,
  function () {this.setFullYear (this.getFullYear () - 1)}
);

In the above example, the call of the Uize.callOn method would shift all the dates in the dates array back by a year.

VARIATION 1

Uize.callOn (objectSetARRAYorOBJ,methodSTRorFN,argumentsARRAY);

When the optional argumentsARRAY parameter is specified, this set of arguments will be passed when calling the specified method on each of the objects in the set.

EXAMPLE

Uize.callOn (
  [instance1,instance2,instance3,instance4,instance5,instance6],'set',[{enabled:false}]
);

The above statement would be equivalent to...

instance1.set ({enabled:false});
instance2.set ({enabled:false});
instance3.set ({enabled:false});
instance4.set ({enabled:false});
instance5.set ({enabled:false});
instance6.set ({enabled:false});

VARIATION 2

Uize.callOn (instanceOBJ,methodSTRorFN);

When the instanceOBJ parameter is specified in place of the objectSetARRAYorOBJ parameter, and when the value of the instanceOBJ parameter is an instance of a Uize.Class subclass, then the specified method will be called on that instance. If the value of instanceOBJ is null or undefined, then no action will be taken. This is a convenient way to conditionally call a method on an object reference that may be null, when you might otherwise capture a local variable in order to avoid deep dereferencing twice.

INSTEAD OF...

if (page.children.possiblyNonExistentChildWidget) {
  page.children.possiblyNonExistentChildWidget.insertUi ();
}

OR...

var childWidget = page.children.possiblyNonExistentChildWidget;
if (childWidget) childWidget.insertUi ();

USE...

Uize.callOn (page.children.possiblyNonExistentChildWidget,'insertUi');

NOTES

see also the other iterator methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.4. Uize.canExtend

Returns a boolean, indicating whether or not the specified value is an object that can be extended with custom properties.

SYNTAX

canExtendBOOL = Uize.canExtend (valueANYTYPE);

A value is considered extendable if it is of type "function", or of type "object" and non-null. Function instances can be extended with custom propeerties, and non-null objects can also be extended with custom properties because this encompasses plain objects, instances of custom object classes, and list objects like instances of JavaScript's built-in Array object. Values that are not considered extendable are nully values like null and undefined, and values for JavaScript primitives, like string values, number values, and boolean values.

EXAMPLES

Uize.canExtend ({foo:'bar'});         // returns true
Uize.canExtend (['foo','bar']);       // returns true
Uize.canExtend (function () {});      // returns true
Uize.canExtend (new String ('foo'));  // returns true
Uize.canExtend (new Boolean (true));  // returns true
Uize.canExtend (new Number (42));     // returns true
Uize.canExtend (Uize.Widget);         // returns true
Uize.canExtend (Uize.Widget ());      // returns true

Uize.canExtend ('foo');               // returns false
Uize.canExtend (true);                // returns false
Uize.canExtend (42);                  // returns false
Uize.canExtend (null);                // returns false
Uize.canExtend (undefined);           // returns false

NOTES

see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.5. Uize.capFirstChar

Returns a string, that is the specified source string with its first letter capitalized.

SYNTAX

firstCharCapitalizedSTR = Uize.capFirstChar (sourceSTR);

Using this method on the value 'width' would produce the result 'Width'. This method is useful when concatenating one string to another, and where it is desirable for the new concatenated string to be camelCase. Consider the following example...

EXAMPLE

_class.instanceMethods ({
  displayPropertyValue:function (_propertyName) {
    this.setNodeValue (
      'valueOf' + Uize.capFirstChar (_propertyName),
      this.get (_propertyName)
    );
  }
});

In the above example, the instance method displayPropertyValue is being defined for a hypothetical widget class. This method accepts a string parameter, being the name of a state property whose value should be displayed in the page in an implied node of the widget, and where the implied node's name is constructed from the prefix 'valueOf' and the name of the state property with its first letter capitalized. Using this method to display the value of a width state property, the value of this property would be displayed in the implied node named valueOfWidth.

NOTES

if the first character of the source string is already capitalized, then the returned value will be the same as the source string
see also the other useful value transformers

IMPLEMENTATION INFO

this feature was introduced in this module

2.6. Uize.clone

Returns an identical clone of the specified source object.

SYNTAX

clonedObjectOBJ = Uize.clone (objectToCloneOJ);

An object that is cloned from a source object using this method will not be conjoined to the source object.

Spawning an exact copy of an object is not as simple as copying that object's properties over to a new object. That simple approach works fine if the source object is simple and only contains properties with simple string or number types. But, if the source object contains properties that are references to other objects, then the simple approach will give rise to a clone that is not 100% discrete from its source. So, subsequent manipulations within the depths of the clone's structure may be reflected in the source object. The Uize.clone method makes sure to recurse the structure of the source object and create identical new data objects within the clone that match those in the source.

The Uize.clone method supports cloning values of the following types...

string (including instances of the String object)
boolean (including instances of the Boolean object)
number (including instances of the Number object, and the special values NaN and Infinity)
object (including the value null)
arrays (instances of the Array object)
instances of the Date object
instances of the RegExp object
undefined

When you clone a value that is an instance of the String, Boolean, or Number objects, you get a new instance having the same value as the source - not a simple type of that value. For example, in JavaScript, 5 is not the same as new Number (5). So, when you use Uize.clone to clone new Number (5), you get a new Number instance with the value 5.

NOTES

The one exception to the conjoined rule is function references, which will be shared according to the current implementation.
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.7. Uize.constrain

Returns a value, being the result of constraining the specified value within the specified lower and upper limits.

SYNTAX

constrainedValueANYTYPE = Uize.constrain (valueANYTYPE,lowerLimitANYTYPE,upperLimitANYTYPE);

It is acceptable for the value of the lowerLimitANYTYPE parameter to be greater than the value of the upperLimitANYTYPE parameter, and the value of the valueANYTYPE parameter will still be constrained within the specified range - even if the lower and upper limits are swapped. So, for example, the statement Uize.constrain (percent,0,100) would be equivalent to Uize.constrain (percent,100,0).

EXAMPLES

// number constraining
Uize.constrain (-50,0,100);   // returns 0
Uize.constrain (-50,100,0);   // returns 0
Uize.constrain (0,0,100);     // returns 0
Uize.constrain (50,0,100);    // returns 50
Uize.constrain (100,0,100);   // returns 100
Uize.constrain (150,0,100);   // returns 100

// constraining with value types that are coerced to number
Uize.constrain (              // returns Uize.Class ({value:0})
  Uize.Class ({value:-50}),  // coerced to -50
  Uize.Class ({value:0}),    // coerced to 0
  Uize.Class ({value:1000})  // coerced to 100
);

// constraining with strings values
Uize.constrain ('a','b','y'); // returns 'b'
Uize.constrain ('m','b','y'); // returns 'm'
Uize.constrain ('z','b','y'); // returns 'y'

NOTES

see the related Uize.inRange static method
see also the other useful value transformers

IMPLEMENTATION INFO

this feature was introduced in this module

2.8. Uize.copy

Lets you copy the properties from one or more source objects into a freshly created object.

DIFFERENT USAGES

Create a Shallow Copy of a Source Object

freshOBJ = Uize.copy (sourceOBJ);

Copy Properties From Multiple Source Objects Into a Fresh Object

freshOBJ = Uize.copy (source1OBJ,source2OBJ,source3OBJ,...);

2.8.1. Create a Shallow Copy of a Source Object

The properties of a single source object can be shallow-copied into a fresh object by supplying a single sourceOBJ parameter.

SYNTAX

freshOBJ = Uize.copy (sourceOBJ);

2.8.2. Copy Properties From Multiple Source Objects Into a Fresh Object

The properties of multiple source objects can be shallow-copied into a fresh object by supplying an arbitrary number of source object arguments.

SYNTAX

freshOBJ = Uize.copy (source1OBJ,source2OBJ,source3OBJ,...);

EXAMPLE

var obj = Uize.copy (
  {foo:'bar',baz:'qux'},
  {baz:'QUX',hello:'world'},
  {foo:'BAR'}
);

In the above example, the contents of three source objects are being copied to a fresh object. After the copy has been created, the obj variable will have the following contents...

RESULT

{
  foo:'BAR',
  baz:'QUX',
  hello:'world'
}

As you will notice, the value of the baz property from the second source object has overwritten the value of the baz property from the first source object, while the value of the foo property from the third source object has overwritten the value of the foo property from the first source object. Values of properties from later source objects overwrite values of same-named properties from earlier source objects.

2.8.3. Null or Undefined Sources Are Ignored

Source parameters whose values are not objects will simply be ignored and will not be copied into the fresh object returned by this method.

This is a useful behavior, as it allows one to include conditionalized copy operations in a single call to this method by using the ternary operator to select between a source object and the value null or undefined for any of the sources.

EXAMPLE

var ajaxRequestParams = Uize.copy (
  ajaxRequestConfig,
  {
    svc:'feed',
    category:'popular',
    page:1,
    qty:50
  },
  hasAuth
    ? {authType:'password',user:userInfo.username,passwd:userInfo.password}
    : null
);

In the above example, a params object is being constructed for a hypothetical Ajax request. The authType, user, and passwd properties are being conditionally copied in, based upon the value of the hasAuth variable. If hasAuth is false, then the ternary operator will produce the value null and the auth properties will not be copied into the fresh object returned by the Uize.copy method.

NOTES

see the companion Uize.copyInto static method
compare to the related Uize.merge and Uize.mergeInto static methods
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.9. Uize.copyInto

Lets you copy properties into a target object from a source object.

SYNTAX

referenceToTargetOBJ = Uize.copyInto (targetOBJ,sourceOBJ);

After the property values from sourceOBJ have been copied into targetOBJ, a reference to targetOBJ is returned as the result of the method. This behavior is provided as a convenience, so that this method can be used in larger expressions where the copy is done in place and then the modified target object can be used further (similar in spirit to the in-place increment operator).

EXAMPLE

var
  targetObject = {
    foo:'How unoriginal!'
  },
  sourceObject = {
    bar:'Indeed!'
  }
;

Uize.copyInto (targetObject,sourceObject);

In the above example, after the code has been executed, targetObject will have both foo and bar properties while sourceObject will remain unchanged.

Of course, the JavaScript language allows in-place creation of anonymous objects using what's termed the "literal syntax", so you could also add properties to an object as shown in the example below...

var targetObject = {
  foo:'How unoriginal!'
};

Uize.copyInto (targetObject,{bar:'Indeed!'});

VARIATION

referenceToTargetOBJ = Uize.copyInto (targetOBJ,source1OBJ,source2OBJ,...);

The Uize.copyInto static method accepts an arbitrary number of parameters, so you can conveniently copy more than one source object into the target object.

All parameters after the targetOBJ parameter that are objects will have their properties copied into the target object, in the order in which those parameters appear in the arguments list (ie. left to right), so properties from source objects earlier in the list will be overwritten by values for those same properties from source objects later in the list.

EXAMPLE

var
  targetObject = {},
  sourceObject1 = {foo:'bar',hi:1},
  sourceObject2 = {bye:1,foo:'BAR'}
;
Uize.copyInto (targetObject,sourceObject1,sourceObject2);

In the above example, the targetObject variable will be an object with the contents {foo:'BAR',hi:1,bye:1}.

NOTES

see the companion Uize.copy static method
compare to the related Uize.merge and Uize.mergeInto static methods
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.10. Uize.copyList

Returns an array, being a copy of the specified list object.

SYNTAX

freshARRAY = Uize.copyList (listARRAYorOBJ);

While an array can be copied by using an expression like myArray.concat (), creating a copy of a list object such as a function's arguments object can be a little more cumbersome with an ugly expression like Array.prototype.slice.call (arguments) or [].slice.call (arguments) (if you're OK with creating an empty array for immediate garbage collection).

Expressions like this are hard to remember when you need to conjure them up, and they're equally unpleasant to make sense of when you see them in your code. The Uize.copyList method provides a more semantically elegant way to copy list objects, such as array instances, arguments objects, or any object with a length property whose value is a number - basically, any value that would produce the result true when passed to the Uize.isList static method.

EXAMPLE 1

Uize.copyList ({0:'foo',1:'bar',2:'baz',3:'qux',length:4});  // returns ['foo','bar','baz','qux']

In the above example, a list object is being copied to produce a fresh array containing the elements in the list object. This is a less common usage, but other objects that one may encounter during Web application development that are list objects and that you may want to create array copies of include things like DOM node lists / HTMLCollection instances.

EXAMPLE 2

function alertReversedSortedArgs () {
  alert (Uize.copyList (arguments).sort ().reverse ());  // alerts the text "qux,foo,baz,bar"
}

alertReversedSortedArgs ('foo','bar','baz','qux');

In the above example, the alertReversedSortedArgs function is alerting the reverse-sorted list of arguments that are passed to it. Because the arguments object is not a true array, the Array object's sort and reverse instance methods can't be called on it, but if the arguments list object is copied using the Uize.copyList method, then the sort and reverse methods can be called on the new array that is returned by this method.

NOTES

see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.11. Uize.defaultNully

Returns the specified default value if the first argument is nully (ie. its value is null or undefined).

SYNTAX

defaultedValueANYTYPE = Uize.defaultNully (valueANYTYPE,defaultANYTYPE);

In JavaScript, the values null and undefined are technically different, but in many instances in your code you may wish to treat them as equivalent, often when you are defaulting arguments of functions or properties of objects. While you can test to see if a value is either null or undefined by simply comparing the value to undefined in a loose equality (eg. if (myValue == undefined) {...}), certain tools like jslint may complain about that, forcing you to do two explicit strict equality checks (as in if (myValue === null || myValue === undefined) {...}). The Uize.defaultNully method provides a convenient way to perform this type of test and defaulting.

INSTEAD OF...

function (myArgument0,myArgument1) {
  if (myArgument0 === null || myArgument0 === undefined) {
    myArgument0 = 'some default value';
  }
  // do more stuff
}

USE...

function (myArgument0,myArgument1) {
  myArgument0 = Uize.defaultNully (myArgument0,'some default value');
  // do more stuff
}

NOTES

see the related Uize.isNully static method
see also the other useful value transformers

IMPLEMENTATION INFO

this feature was introduced in this module

2.12. Uize.emptyOut

Empties out the specified source object or array and returns a reference to the source.

SYNTAX

sourceOBJorARRAY = Uize.emptyOut (sourceOBJorARRAY);

Using this method to empty out an array is equivalent to setting the array's length to 0, while using this method to empty out an object results in all the object's properties being deleted. When the value null or undefined is specified for the sourceOBJorARRAY parameter, then this method will do nothing and simply return the value of the sourceOBJorARRAY parameter.

EXAMPLE

Uize.copyInto (Uize.emptyOut (userData),userDataDefaults);

In the above example, a userData object has accumulated a large amount of user data and we wish to reset it to some initial default state. Because references to the object may be shared by many parts of an application's code, we want to re-initiatialize it by modifying its contents, restoring its state to that of the userDataDefaults object. The Uize.emptyOut method lets us first empty out the object, after which it is passed as the source for the Uize.copyInto method call where we copy back in the contents of the userDataDefaults object.

NOTES

compare to the Uize.isEmpty static method
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.13. Uize.escapeRegExpLiteral

Returns a string, being the specified source string escaped so that it can be used as a literal match when constructing a regular expression string.

SYNTAX

escapedRegExpLiteralSTR = Uize.escapeRegExpLiteral (regExpLiteralSTR);

Using this method, any string can be escaped so that it can be used in creating a regular expression where that string can be matched as a literal match. Strings may sometimes contain special regular expression characters, such as the ( (open parenthesis), ) (close parenthesis), . (period), ? (question mark), and other characters that have special meaning in the context of regular expression strings. If you wanted to use a regular expression to match a string that contained any of these special characters, then the special characters would have to be escaped. The Uize.escapeRegExpLiteral method takes care of this for you. Consider the following example...

EXAMPLE

function replaceAllCaseInsensitive (sourceStr,toReplaceStr,replacementStr) {
  return sourceStr.replace (
    new RegExp (Uize.escapeRegExpLiteral (toReplaceStr),'gi'),
    replacementStr
  );
}

In the above example, we are defining a function that will replace all occurrences of a specified string within a source string with the specified replacement string, and where matching is case insensitive.

Now, the replace instance method of JavaScript's String object can accept a string as a match parameter, but when a string is specified the replacement is not case insensitive and is only for the first occurrence. So, we have to use a regular expression to specify what to replace, so that we can make use of the "g" (global) and "i" (case insensitive) regular expression switches. The problem, however, with using a regular expression is that the string to replace may contain regular expression special characters, so we can't just use it as is when creating the RegExp instance - we have to escape the special characters. So, we use the Uize.escapeRegExpLiteral method to escape the string to replace before supplying it to the RegExp object's constructor.

The Uize.escapeRegExpLiteral method can be used to escape any string that is to be treated as a literal match - even literals that are to be combined with other regular expression logic to form more complex regular expressions.

NOTES

see also the other useful value transformers

IMPLEMENTATION INFO

this feature was introduced in this module

2.14. Uize.eval

Lets you perform quarantined code evaluation of the specified JavaScript code string, using JavaScript strict mode.

SYNTAX

evalResultANYTYPE = Uize.eval (codeToEvalSTR);

The Uize.eval method imposes JavaScript strict mode on the code being evaluated. If you need to evaluate code in non-strict mode, use the companion Uize.laxEval method. The Uize.eval method returns any result that was produced by the code being evaluated.

For a detailed discussion of quarantining and to see examples, consult the section Quarantined Code Execution.

NOTES

compare to the companion Uize.laxEval static method
compare to the related Uize.quarantine static method

IMPLEMENTATION INFO

this feature was introduced in this module

2.15. Uize.findRecord

Returns the first record in the specified records array whose contents is a superset of the contents of the specified match object. If no matching record can be found, then this method will return the value null.

SYNTAX

recordOBJ = Uize.findRecord (recordsARRAY,matchOBJ);

This method uses the Uize.findRecordNo static method in its implementation, so consult the reference for that method for further details and for an example.

NOTES

this method uses strict matching, so the statement Uize.findRecord ([{index:'0'},{index:'1'}],{index:1}) will return null
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.16. Uize.findRecordNo

Returns an integer, indicating the index in the specified records array of the first record whose contents is a superset of the contents of the specified match object.

SYNTAX

recordNoINT = Uize.findRecordNo (recordsARRAY,matchOBJ);

If no matching record can be found, then this method will return the value -1, unless the optional defaultNoNONNULL parameter is specified.

EXAMPLE

var
  fruits = [
    {
      type:'Apple',
      variety:'Braeburn',
      color:'red'
    },
    {
      type:'Orange',
      variety:'Navel',
      color:'orange'
    },
    {
      type:'Apple',
      variety:'Granny Smith',
      color:'green'
    },
    {
      type:'Apple',
      variety:'Red Delicious',
      color:'red'
    }
  ],
  greenAppleRecordNo = Uize.findRecordNo (fruits,{type:'Apple',variety:'Granny Smith'})
;

In the above example, the variable greenAppleRecordNo will have the value 2.

VARIATION

recordNoINT = Uize.findRecordNo (recordsARRAY,matchOBJ,defaultNoNONNULL);

When the optional defaultNoNONNULL parameter is specified, then the value of this parameter, coerced to a number, will be returned as the result if no match is found. If the value null or undefined is specified for the defaultNoNONNULL parameter, or if its value coerced to a number produces the special value NaN, then it will be treated as -1.

NOTES

this method uses strict matching, so the statement Uize.findRecordNo ([{index:'0'},{index:'1'}],{index:1}) will return -1
see also the related Uize.findRecord and Uize.recordMatches static methods
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.17. Uize.forEach

Iterates over the specified array, arguments object, object, or length range, calling the specified iteration handler for each element or property.

DIFFERENT USAGES

Iterate Over the Elements of An Array

Uize.forEach (sourceARRAY,iterationHandlerSTRorFUNC);

Iterate Over the Arguments of an Arguments Object

Uize.forEach (argumentsOBJ,iterationHandlerSTRorFUNC);

Iterate Over the Properties of an Object

Uize.forEach (sourceOBJ,iterationHandlerSTRorFUNC);

Iterate Over the Integers in a Zero-based Value Range

Uize.forEach (rangeLengthINT,iterationHandlerSTRorFUNC);

Provide a Context for the Iteration Handler

Uize.forEach (sourceARRAYorOBJorINT,iterationHandlerSTRorFUNC,contextANYTYPE);

Iterate Even Over Unassigned Elements of an Array

Uize.forEach (
  sourceARRAYorOBJorINT,
  iterationHandlerSTRorFUNC,
  contextANYTYPE,
  allArrayElementsBOOL
);

2.17.1. Iterate Over the Elements of An Array

In its most basic usage, the Uize.forEach method can be used to iterate over the elements of an array, performing an action for each element.

SYNTAX

Uize.forEach (sourceARRAY,iterationHandlerSTRorFUNC);

EXAMPLE

var fruits = ['apple','banana','grape','melon','peach','watermelon'];

function createFruitWidget (fruit) {
  // create a widget for the fruit
}

Uize.forEach (fruits,createFruitWidget);

2.17.2. Iterate Over the Arguments of an Arguments Object

The arguments of a function's arguments object can be iterated over by specifying a reference to the arguments object using the argumentsOBJ parameter.

SYNTAX

Uize.forEach (argumentsOBJ,iterationHandlerSTRorFUNC);

EXAMPLE

function multiplyAll () {
  var result = 1;
  Uize.forEach (arguments,function (arg) {result *= arg});
  return result;
}

In the above example, we are implementing a multiplyAll function that is variadic in nature and will return a result that is the product of all of the arguments passed to it. We are using the Uize.forEach method to iterate over all arguments of the arguments object, modifying the result upon each iteration by multiplying it by the argument for each iteration.

2.17.3. Iterate Over the Properties of an Object

All the properties of an object can be iterated over, in the order in which the properties were defined on the object, by specifying the object using the sourceOBJ parameter.

SYNTAX

Uize.forEach (sourceOBJ,iterationHandlerSTRorFUNC);

EXAMPLE

function uppserCaseKeys (obj) {
  Uize.forEach (
    obj,
    function (value,key,source) {
      delete source [key];
      source [key.toUpperCase ()] = value;
    }
  );
}

In the above example, we are implementing an uppserCaseKeys function that iterates over all the properties of an object and uppercases the keys (property names) of all the properties. It doesn't matter that we are deleting and adding properties during iterations, as it turns out, because the keys to use for the iteration are gathered at the beginning of the iteration process, so new properties that are added with uppercased keys will not be encountered during iteration.

2.17.4. Iterate Over the Integers in a Zero-based Value Range

The integers in a zero-based value range can be iterated over by specifying the length of the zero-based integer range using the rangeLengthINT parameter.

SYNTAX

Uize.forEach (rangeLengthINT,iterationHandlerSTRorFUNC);

The value of the rangeLengthINT parameter should be the value of the last integer in the range plus 1. So, for example, to iterate over the integers 0, 1, 2, and 3, the value 4 should be specified for the rangeLengthINT parameter.

Essentially, the statement Uize.forEach (4,myIterationHandler) would be equivalent to the statement Uize.forEach ([0,1,2,3],myIterationHandler). And, more generally, the statement Uize.forEach (n,myIterationHandler) would be equivalent to the statement Uize.forEach ([0,1,2,...,n - 1],myIterationHandler).

EXAMPLE

function factorial (n) {
  var result = 1;
  Uize.forEach (n,function (i) {result *= (i + 1)});
  return result;
}

Naturally, the above example would not produce the most efficient implementation of an n-factorial function, since it involves a function call for each iteration - it is provided merely as illustration. This variation of the Uize.forEach is offered primarily as a convenience in cases where an iteration handler function is already to be used inside a regular JavaScript for loop, so using the Uize.forEach method in such cases will only occur one additional function call and will neaten up one's code a bit.

2.17.5. Provide a Context for the Iteration Handler

An iteration handler can be provided a context on which to be called by specifying the optional contextANYTYPE parameter.

SYNTAX

Uize.forEach (sourceARRAYorOBJorINT,iterationHandlerSTRorFUNC,contextANYTYPE);

EXAMPLE

Uize.forEach (listItems,listWidget.addItem,listWidget);

In the above example, the listItems variable is an array of data objects for items in a list. The Uize.forEach method is being used to iterate over the list, calling the function listWidget.addItem with listWidget as the context for each call, so that we are effectively calling the addItem method of the listItem instance.

Note that we can't just supply listWidget.addItem as the iteration handler without supplying a context, since the expression listWidget.addItem simply dereferences the addItem property on the listWidget object and returns a function.

2.17.6. Iterate Even Over Unassigned Elements of an Array

The Uize.forEach method can be forced to iterate over all elements of an array, including unassigned elements, by specify the value true for the optional allArrayElementsBOOL parameter.

Like the forEach method of JavaScript's built-in Array object, the Uize.forEach method will skip over unassigned array elements by default. This behavior can be problematic in certain situations.

EXAMPLE

// create a sparsely populated array, with a length of 5
var sourceArray = new Array (5);
sourceArray [2] = 'apple';
sourceArray [4] = 'pear';

var valuesSeenA = [];
Uize.forEach (sourceArray,function (value) {valuesSeenA.push (value)});
alert (valuesSeenA);  // alerts "apple,pear"

var valuesSeenB = [];
Uize.forEach (sourceArray,function (value) {valuesSeenB.push (value)},0,true);
alert (valuesSeenB);  // alerts "undefined,undefined,apple,undefined,pear"

2.17.7. Parameters

2.17.7.1. sourceARRAYorOBJorINT

An array containing elements over which to iterate, a function arguments object containing arguments over which to iterate, an object containing properties over which to iterate, or a positive integer specifying a zero-based integer range over which to iterate.

2.17.7.2. iterationHandlerSTRorFUNC

A string or function, specifying code that should be executed for handling each iteration.

2.17.7.2.1. Function Iteration Handler

If a function is specified for the iteration handler, the function should expect to receive three arguments - value, key, and source.

The value argument is the value for an array element or object property, the key argument is the array index or object property name, and the source argument is the value specified for the sourceARRAYorOBJorINT parameter when calling the Uize.forEach method.

EXAMPLE

var fruits = ['apple','banana','grape','melon','peach','watermelon'];
Uize.forEach (
  fruits,
  function (value,key,source) {source [key] = value.toUpperCase ()}
);

After the above code has been executed, all the elements of the fruits array will be uppercased, to form...

['APPLE','BANANA','GRAPE','MELON','PEACH','WATERMELON']
2.17.7.2.2. String Iteration Handler

If a string is specified for the iteration handler, the string expression must expect the variables value, key, and source to be reserved words in its scope.

A string iteration handler will be composed into a function by the Uize.forEach method, and values will be supplied for the predefined value, key, and source arguments of the generated function. The value argument is the value for an array element or object property, the key argument is the array index or object property name, and the source argument is the value specified for the sourceARRAYorOBJorINT parameter when calling the Uize.forEach method.

EXAMPLE

var fruits = ['apple','banana','grape','melon','peach','watermelon'];
Uize.forEach (fruits,'source [key] = value.toUpperCase ()');

After the above code has been executed, all the elements of the fruits array will be uppercased, to form...

['APPLE','BANANA','GRAPE','MELON','PEACH','WATERMELON']

2.17.7.3. contextANYTYPE

A value of any type (but typically an object instance), specifying the context on which to call the iteration handler.

By default, the iteration handler specified by the iterationHandlerSTRorFUNC parameter is not called on any context. If you need the iteration handler to be a method call on an object instance, then you will need to use the contextANYTYPE paramter to provide a context for the iteration handler.

2.17.7.4. allArrayElementsBOOL

A boolean, specifying whether or not the Uize.forEach method should iterate even over unassigned elements of a source array.

Like the forEach method of JavaScript's built-in Array object, the Uize.forEach method will skip over unassigned array elements by default. In order to force the method to iterate over all elements, including unassigned elements, specify the value true for the optional allArrayElementsBOOL parameter.

NOTES

this parameter is not applicable when an object or number value is specified for the sourceARRAYorOBJorINT parameter

2.17.8. Key Benefits

While regular JavaScript for loops are still worth using in the majority of cases, there are a number of benefits to using the Uize.forEach method for iterating...

2.17.8.1. Produces More Concise Code

Using the Uize.forEach method can lead to more concise and readable code.

In cases where one is iterating over the elements of an array or the properties of an object and calling a function to handle each iteration, using the Uize.forEach method will produce cleaner code without sacrificing much performance.

INSTEAD OF...

for (var fruitNo = -1; fruitNo < fruits.length; fruitNo++) {
  createFruitWidget (fruits [fruitNo]);
}

USE...

Uize.forEach (fruits,createFruitWidget);

2.17.8.2. Supports Iterating Over Object Properties

The Uize.forEach method supports iterating over the properties of an object, simply by specifying an object as the source.

INSTEAD OF...

for (var fruitId in fruitsById) {
  createFruitWidget (fruitsById [fruitId]);
}

USE...

Uize.forEach (fruitsById,createFruitWidget);

2.17.8.3. Supports Concise String Iteration Handler

In cases smaller and more concise code is desirable and performance isn't critical, a string iteration handler can be used in the Uize.forEach method.

INSTEAD OF...

Uize.forEach (fruitsById,function (value,key) {console.log (key + ': ' + value)});

USE...

Uize.forEach (fruitsById,"console.log (key + ': ' + value)");

2.17.8.4. Uses JavaScript's Built-in, When Possible

Later versions of JavaScript support a built-in forEach instance method for the Array object.

In order to provide the best possible performance, the Uize.forEach method uses the Array object's forEach method whenever possible, which is under the following circumstances...

the version of JavaScript being used supports the forEach method
the value specified for the sourceARRAYorOBJorINT parameter is an array
the value true is not specified for the optional allArrayElementsBOOL parameter (because the Array object's built in forEach method skips unassigned array elements)

2.17.8.5. Enforces Optimized For Loop

Using the Uize.forEach method enforces use of a more performant approach to iterating over an array.

This helps in a small way to offset the performance cost of calling an iteration handler function on every iteration. A classic mistake that is made when writing for loops to iterate over arrays is to dereference the array's length property on every iteration in the loop test expression. Furthermore, most times that people write array iteration loops they don't take advantage of the ability to roll the loop test and counting expression together into a single expression.

WORSE PERFORMANCE

for (var fruitNo = 0; fruitNo < fruits.length; fruitNo++) {
  // do stuff
}

BETTER PERFORMANCE

for (var fruitNo = -1, fruitsLength = fruits.length; ++fruitNo < fruitsLength;) {
  // do stuff
}

Using the Uize.forEach method enforces use of the more performant approach to iterating over an array, which helps in a small way to offset the performance cost of calling an iteration handler function on every iteration.

2.17.8.6. Supports Iterating Over Unassigned Array Elements

The Uize.forEach method supports iterating over all elements of an array, including unassigned elements, by specifying the value true for the optional allArrayElementsBOOL parameter.

For more info, refer to the usage Iterate Even Over Unassigned Elements of an Array.

2.17.8.7. Supports Iterating for a Specified Number of Iterations

As a convenience, the Uize.forEach method supports specifying a number value for the sourceARRAYorOBJorINT parameter, in which case the method iterates for the specified number of times.

When a number is specified for the sourceARRAYorOBJorINT parameter, the iteration index will be used for both the value and key arguments of the iteration handler, and the iteration index will start at 0. Furthermore, since the value of the sourceARRAYorOBJorINT parameter is always provided as the value of the iteration handler's source argument, the handler will receive the number value for the source.

EXAMPLE

var results = [];
Uize.forEach (
  5,
  function (value,key,source) {results.push ({value:value,key:key,source:source})}
);

After the above code has been executed, the results array will have the following contents...

[
  {value:0,key:0,source:5},
  {value:1,key:1,source:5},
  {value:2,key:2,source:5},
  {value:3,key:3,source:5},
  {value:4,key:4,source:5}
]

Admittedly not a particularly practical or compelling example, but it illustrates the behavior.

2.17.9. Some Limitations

The Uize.forEach is intended for a common and very simple use case, and for this use case it provides a convenient and concise form for expressing iteration.

As soon as one strays from the very narrow use case that this method is geared towards, one finds oneself needing to use regular JavaScript loops. The most notable limitations of the Uize.forEach method are as follows...

iterates over every element - can't skip elements, or go back and repeat elements
iterates forwards - can't iterate backwards
iteration can't be stopped - there is no break facility available
iteration handler shouldn't modify the number or order of elements in an array
every iteration involves a function call - sometimes this performance cost may be prohibitive

NOTES

compare to the Uize.map static method
see also the other iterator methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.18. Uize.getClass

Resolves the specified value to a class, or returns the value undefined if the specified value is null or undefined.

SYNTAX

classOBJ = Uize.getClass (valueANYTYPE);

The Uize.getClass method resolves a value to a class using the following steps...

1.  if the specified value is null or undefined, then the value undefined is returned
2.  else, if the specified value is a function reference, then the function reference is returned
3.  else, the value of the value's constructor property is returned

The Uize.getClass method can be used to resolve either an instance of a class, or a class itself, to a class.

EXAMPLES

// when called with null or undefined

  Uize.getClass (null);                 // returns undefined
  Uize.getClass (undefined);            // returns undefined

// when called with JavaScript primitives

  Uize.getClass (42);                   // returns Number
  Uize.getClass (NaN);                  // returns Number
  Uize.getClass (Infinity);             // returns Number
  Uize.getClass (true);                 // returns Boolean
  Uize.getClass ('foo');                // returns String

// when called with instances of JavaScript objects

  Uize.getClass (new Object ());        // returns Object
  Uize.getClass (new Number (42));      // returns Number
  Uize.getClass (new Boolean (true));   // returns Boolean
  Uize.getClass (new String ('foo'));   // returns String
  Uize.getClass (new RegExp ('\\d+'));  // returns RegExp

// when called with implicitly created instances of JavaScript objects

  Uize.getClass ({foo:'bar'});          // returns Object
  Uize.getClass (['foo','bar']);        // returns Array
  Uize.getClass (/\d+/);                // returns RegExp

// when called with instances of Uize.Class subclasses

  Uize.getClass (Uize.Widget.Bar ());   // returns Uize.Widget.Bar
  Uize.getClass (new Uize.Fade);        // returns Uize.Fade

// when called with object constructors or Uize.Class subclasses

  Uize.getClass (Object);               // returns Object
  Uize.getClass (Number);               // returns Number
  Uize.getClass (Boolean);              // returns Boolean
  Uize.getClass (String);               // returns String
  Uize.getClass (Uize.Widget.Bar);      // returns Uize.Widget.Bar

IMPLEMENTATION INFO

this feature was introduced in this module

2.19. Uize.getGuid

Returns a string value, being an ID that is globally unique in the current window context.

SYNTAX

guidSTR = Uize.getGuid ();

When an instance of a Uize.Class subclass is created, its instanceId instance property is set to a value returned by this method. This method may also be useful in the implementations of subclasses, in situations where it is necessary to stash something in a context shared by different modules of code that need to be able to interoperate without conflicts.

IMPLEMENTATION INFO

this feature was introduced in this module

2.20. Uize.getModuleByName

Returns an object reference, being a reference to the module of the specified name, or returns the value undefined if no such module is defined.

SYNTAX

moduleOBJ = Uize.getModuleByName (moduleNameSTR);

EXAMPLE

alert (Uize.Widget == Uize.getModuleByName ('Uize.Widget');  // displays the text "true"

In the above example, sssuming that the Uize.Widget module is loaded at the time that the code is executed, the alert statement will display the text "true".

2.20.1. Graceful Failure

The Uize.getModuleByName method is designed to always fail silently when a specified module is not defined.

Take the example of a module with the name MyNamespace.MyClass.MySubclass. Such a module may not be defined because either MyNamespace, MyNamespace.MyClass, or MyNamespace.MyClass.MySubclass is not defined. Now, normally when you try to dereference MyNamespace.MyClass.MySubclass and MyNamespace is not defined, you'll get a runtime error. The Uize.getModuleByName method handles this and makes it always safe to resolve modules names to modules. In cases where a module path is not defined at some level, the method will simply return the value undefined.

VARIATION

modulesByNameOBJ = Uize.getModuleByName ('*');

When the special value '*' (wildcard character) is specified for the moduleNameSTR parameter, then the Uize.getModuleByName method returns an object that serves as a lookup table for all the modules that have been built, where each property's name is the name of a module and each property's value is a reference to the module.

Module name to module reference mappings are added to the object in the order in which the modules are built. Therefore, if you write a for...in loop to iterate through the properties of the object, then you can build up an array of the names of the modules that have been built, in the correct dependency order. And if you execute such code in a Web page, then you can build up a list of all the modules that were built for that page. If the page only loads in a few modules using script tags that are in the page's initial HTML, then the list resulting from executing your code will give an indication of how many additional modules were loaded in dynamically by the module loader mechanism. The list of all the modules built on a page can be used as the basis for creating a JavaScript library file (see JavaScript Libraries).

EXAMPLE

var
  modulesByName = Uize.getModuleByName ('*'),
  modulesBuilt = []
;
for (var moduleName in modulesByName) {
  modulesBuilt.push (moduleName)
}

After the above code has been executed, the modulesBuilt array will contain the names of all the modules that have been built, listed in the order in which they were built.

NOTES

see also the other module mechanism methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.21. Uize.getPathToLibrary

Returns a string, representing the relative path from the current document to the folder containing the specified JavaScript module.

SYNTAX

pathToModuleSTR = Uize.getPathToLibrary (moduleFilenameSTR);

Whereas the Uize.pathToResources static property specifies the relative path to the folder containing the "Uize.js" JavaScript module, this method can be used to find the relative path to a different JavaScript module that is being sourced into the document. This can be useful when the JavaScript module implementing a Uize.Class subclass does not reside in the same folder alongside the "Uize.js" file.

This method is useful in the implementation of Uize.Class subclasses that may wish to, in their implementation, make use of image and other support resources located inside the folder that contains the class's JavaScript module. By using this method, a subclass' implementation does not need to know whether or not the document using it is being loaded through HTTP or from the local file system and does not need to impose extra requirements on developers regarding where its JavaScript module is located in relation to documents using it.

VARIATION

pathToModuleSTR = Uize.getPathToLibrary (moduleFilenameSTR,moduleTokenSTR);

When the optional moduleTokenSTR parameter is specified, then the value returned by this method will be the value of the src property for the script tag that sources in the module specified by the moduleFilenameSTR parameter, but with the module filename replaced by the substitution token specified by the moduleTokenSTR parameter. Consider the following example...

EXAMPLE

<script type="text/javascript" src="../js/Uize.js?bld=123"></script>

<script type="text/javascript">
  alert (Uize.getPathToLibrary ('Uize.js','[MODULE]'));  // alerts "../js/[MODULE]?bld=123"
</script>

In the above example, the script tag that sources in the "Uize.js" module has the value "../js/Uize.js?bld=123" specified for its src attribute. By specifying the value '[MODULE]' for the optional moduleTokenSTR parameter in the Uize.getPathToLibrary method call, the text "Uize.js" is replaced with the text "[MODULE]", and the value returned by the Uize.getPathToLibrary method is '../js/[MODULE]?bld=123'.

NOTES

see also the Uize.pathToResources static property
see also the other module mechanism methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.22. Uize.global

Returns a reference to the global object.

SYNTAX

globalOBJ = Uize.global ();

The Uize.global method should be used in situations where you need to access or assign properties on the global object, or to call methods on the global object, and where you need that code to be able to run inside a browser as well as other environments like WSH (Windows Script Host) or NodeJS.

In cases where you need to work with properties of the global object inside a browser, you would typically just reference the window object. However, in non-browser environments where you might run your JavaScript code, the window object is not applicable and usually not defined. To be entirely safe, use the Uize.global method - it will return the window object when you're running the code in a browser, and in other environments it will return their equivalent of the global object.

EXAMPLES

// assign a value to a global property
Uize.global ().myGlobalProperty = 'foo';

// access a global property
alert (Uize.global ().myGlobalProperty);

// delete a global property
delete Uize.global ().myGlobalProperty;

If you are going to be calling the Uize.global method multiple times inside some code to access or assign values to global properties, you can create a local variable that is a reference to the global object. So, the above example could be re-written as...

var _global = Uize.global ();

// assign a value to a global property
_global.myGlobalProperty = 'foo';

// access a global property
alert (_global.myGlobalProperty);

// delete a global property
delete _global.myGlobalProperty;

2.22.1. Defeating Scope Chain Overrides

The Uize.global method can be useful in situations where you need to defeat an override of some identifier from the scope chain of the local scope in order to force access of the global version.

If one defines a global identifier but then is executing code from within a deep local scope, and if the identifier is overridden somewhere in the scope chain of the local scope, then a way to force access to that identifier in the global scope is to use the Uize.global method. Consider the following example...

EXAMPLE

var foo = 'global scope';

function MyObject () {
  var foo = 'local scope';

  this.alertLocalScopeFoo = function () {
    alert (foo);
  };

  this.alertGlobalScopeFoo = function () {
    alert (Uize.global ().foo);
  };
}

var myObjectInstance = new MyObject ();

myObjectInstance.alertLocalScopeFoo ();   // alerts "local scope"
myObjectInstance.alertGlobalScopeFoo ();  // alerts "global scope"

In the above example, we have a global variable named foo. Inside the constructor of MyObject, we also have a local variable named foo. Now, for any function that is defined within the constructor's scope, the local foo variable will override the foo variable from the global scope.

So, for the alertLocalScopeFoo method that is being defined, when it tries to access the foo variable simply by its name, it gets the version from the local scope. So, in order for the alertGlobalScopeFoo method to actually access the foo from the global scope, it can use the Uize.global method to get a reference to the global object and then dereference foo as a property on that object.

IMPLEMENTATION INFO

this feature was introduced in this module

2.23. Uize.inRange

Returns a boolean, indicating whether or not the specified value lies within the specified lower and upper limits.

SYNTAX

inRangeBOOL = Uize.inRange (valueANYTYPE,lowerLimitANYTYPE,upperLimitANYTYPE);

It is acceptable for the value of the lowerLimitANYTYPE parameter to be greater than the value of the upperLimitANYTYPE parameter, and the value of the valueANYTYPE parameter will still be constrained within the specified range - even if the lower and upper limits are swapped. So, for example, the statement Uize.inRange (percent,0,100) would be equivalent to Uize.inRange (percent,100,0).

EXAMPLES

// number constraining
Uize.inRange (-50,0,100);     // returns false
Uize.inRange (-50,100,0);     // returns false
Uize.inRange (0,0,100);       // returns true
Uize.inRange (50,0,100);      // returns true
Uize.inRange (100,0,100);     // returns true
Uize.inRange (150,0,100);     // returns false

// inRange testing with value types that are coerced to number
Uize.inRange (                // returns false
  Uize.Class ({value:-50}),  // coerced to -50
  Uize.Class ({value:0}),    // coerced to 0
  Uize.Class ({value:1000})  // coerced to 100
);

// inRange testing with strings values
Uize.inRange ('a','b','y');   // returns false
Uize.inRange ('a','m','y');   // returns false
Uize.inRange ('z','b','y');   // returns false

// in Range testing with dates
Uize.inRange (                // returns false
  new Date ('01/01/1999'),
  new Date ('01/01/2000'),
  new Date ('01/01/2010')
);
Uize.inRange (                // returns true
  new Date ('01/01/2005'),
  new Date ('01/01/2000'),
  new Date ('01/01/2010')
);
Uize.inRange (                // returns false
  new Date ('01/01/2011'),
  new Date ('01/01/2000'),
  new Date ('01/01/2010')
);

2.23.1. Support for Different Value Types

Because the Uize.inRange method uses JavaScript's less than and greater than operators, values specified for the value being tested and the value range's boundaries can be of any type that can be compared using these operators.

That means that the Uize.inRange automatically supports testing number types values, string type values, Date object instances, and instances of any object type that implements the valueOf intrinsic method, such as instances of Uize.Class subclasses that implement the value interface. So, all the following examples are legitimate usages of the Uize.inRange method.

EXAMPLES

// testing a number against a number range
Uize.inRange (-50,0,100);

// testing a string against a string range
Uize.inRange ('a','b','y');

// testing a date against a date range
Uize.inRange (
  new Date ('01/01/1999'),
  new Date ('01/01/2000'),
  new Date ('01/01/2010')
);

// testing an object against a range expressed using objects
Uize.inRange (
  Uize.Class ({value:-50}),  // coerced to -50
  Uize.Class ({value:0}),    // coerced to 0
  Uize.Class ({value:1000})  // coerced to 100
);

NOTES

see the related Uize.constrain static method
see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.24. Uize.indexIn

Returns an integer, indicating the index in the specified array of the first occurrence of the specified value, or returns a string, indicating the name of first property that has the specified value.

DIFFERENT USAGES

Find a Value in an Array

indexINT = Uize.indexIn (sourceARRAY,valueANYTYPE);

Find a Value in an Array, Scanning Backwards From the End

indexINT = Uize.indexIn (sourceARRAY,valueANYTYPE,fromEndBOOL);

Find a Value in an Array, Using Non-strict Comparison

indexINT = Uize.indexIn (sourceARRAY,valueANYTYPE,fromEndBOOL,strictEqualityBOOL);

Find a Property in an Object Having a Specific Value

keySTR = Uize.indexIn (sourceOBJECT,valueANYTYPE,fromEndBOOL,strictEqualityBOOL);

2.24.1. Find a Value in an Array

In the most typical use case, a value can be found in a source array by specifying the array as the first parameter and the search value as the second parameter.

SYNTAX

indexINT = Uize.indexIn (sourceARRAY,valueANYTYPE);

If the value specified by the valueANYTYPE parameter is found inside the array specified by the sourceARRAY parameter, then the index at which the first occurrence is found will be returned. If the value is not found, then the value -1 will be returned.

EXAMPLES

Uize.indexIn (['a','b','c'],'c');      // returns 2
Uize.indexIn (['a','b'],'c');          // returns -1 (no match)
Uize.indexIn (['a','b','b'],'b');      // returns 1 (first occurrence)
Uize.indexIn ([1,7,42,'42',42],'42');  // returns 3 (first strict match)
Uize.indexIn ([1,7,42],'42');          // returns -1 (no strict match)

2.24.2. Find a Value in an Array, Scanning Backwards From the End

A value can be found in a source array, scanning backwards from the end, by specifing the value true for the optional fromEndBOOL third parameter.

SYNTAX

indexINT = Uize.indexIn (sourceARRAY,valueANYTYPE,fromEndBOOL);

By default, the Uize.indexIn method searches for the specified value by scanning forwards through the array from the beginning. When the value true is specified for the optional fromEndBOOL parameter, then this method will search for the specified value by scanning backwards through the array from the end.

EXAMPLES

Uize.indexIn (['a','b','c'],'c',true);      // returns 2
Uize.indexIn (['a','b'],'c',true);          // returns -1 (no match)
Uize.indexIn (['a','b','b'],'b',true);      // returns 2 (first occurrence, from end)
Uize.indexIn ([1,7,42,'42',42],'42',true);  // returns 3 (first strict match, from end)
Uize.indexIn ([1,7,42],'42',true);          // returns -1 (no strict match)

2.24.3. Find a Value in an Array, Using Non-strict Comparison

A value can be found in a source array, using non-strict comparison, by specifying the value false for the optional strictEqualityBOOL fourth parameter.

SYNTAX

indexINT = Uize.indexIn (sourceARRAY,valueANYTYPE,fromEndBOOL,strictEqualityBOOL);

By default, the Uize.indexIn method tests for a match using strict equality. When the value false is specified for the optional strictEqualityBOOL parameter, then this method will test for a match using loose equality (ie. where the string value '1' would be considered equal to the number value 1).

EXAMPLES

Uize.indexIn ([5,9],'9',false,true);       // returns -1 (no strict match)
Uize.indexIn ([5,9,'9'],'9',false,false);  // returns 1 (first non-strict match)
Uize.indexIn ([5,9,'9'],'9',false,true);   // returns 2 (first strict match)
Uize.indexIn ([5,9,'9'],9,false,true);     // returns 1 (first strict match)
Uize.indexIn ([5,'9',9],'9',true,true);    // returns 1 (first strict match, from end)
Uize.indexIn ([5,'9',9],9,true,true);      // returns 2 (first strict match, from end)
Uize.indexIn ([5,'9',9],'9',true,false);   // returns 2 (first non-strict match, from end)
Uize.indexIn ([5,9,'9'],9,true,false);     // returns 2 (first non-strict match, from end)

2.24.4. Find a Property in an Object Having a Specific Value

The property of an object having a specific value can be found by specifying a sourceOBJECT parameter in place of the sourceARRAY first parameter.

SYNTAX

keySTR = Uize.indexIn (sourceOBJECT,valueANYTYPE,fromEndBOOL,strictEqualityBOOL);

When a sourceOBJECT parameter is specified in place of the typical sourceARRAY parameter, the Uize.indexIn method will iterate through the properties of the specified object to find the property whose value is equal to the value specified by the valueANYTYPE parameter. If a property having the specified value is found, then that property's name is returned. If no property having the specified value is found, then the value -1 is returned.

When a source object is specified, the optional fromEndBOOL and strictEqualityBOOL parameters are supported as they are when a source array is specified. In particular, the fromEndBOOL determines the direction in which the method scans through the properties of the object, where the default forwards order of the properties is determined by the order in which the properties were assigned on the object (this ia a behavior of the JavaScript language).

EXAMPLES

Uize.indexIn (
  {p0:5,p1:9},'9',false,true          // returns -1 (no strict match)
);
Uize.indexIn (
  {p0:5,p1:9,p2:'9'},'9',false,false  // returns 'p1' (first non-strict match)
);
Uize.indexIn (
  {p0:5,p1:9,p2:'9'},'9',false,true   // returns 'p2' (first strict match)
);
Uize.indexIn (
  {p0:5,p1:9,p2:'9'},9,false,true     // returns 'p1' (first strict match)
);
Uize.indexIn (
  {p0:5,p1:'9',p2:9},'9',true,true    // returns 'p1' (first strict match, from end)
);
Uize.indexIn (
  {p0:5,p1:'9',p2:9},9,true,true      // returns 'p2' (first strict match, from end)
);
Uize.indexIn (
  {p0:5,p1:'9',p2:9},'9',true,false   // returns 'p2' (first non-strict match, from end)
);
Uize.indexIn (
  {p0:5,p1:9,p2:'9'},9,true,false     // returns 'p2' (first non-strict match, from end)
);

NOTES

see also the related Uize.isIn static method
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.25. Uize.isArguments

Returns a boolean, indicating whether or not the specified value is a function arguments object.

SYNTAX

isArgumentsBOOL = Uize.isArguments (valueANYTYPE);

A value is considered an arguments object if, and only if, the value is a reference to an instance of JavaScript's built-in Arguments object. Arguments objects are created when calling functions in JavaScript and are referenced within a called function by the special arguments keyword.

While an arguments object is listy in nature (ie. it is an object having a length property whose value is a number), listy objects that are not instances of JavaScript's Arguments object are not considered arguments objects by the Uize.isArguments method. So, for example, the array ['foo','bar'] is not considered an arguments object, nor is the listy object {0:'foo',1:'bar',length:2}.

The Uize.isArguments method is useful when wanting to distinguish between an arguments object and other listy objects in order to conditionalize the behavior for a function.

EXAMPLES

Uize.isArguments ((function () {return arguments}) ('foo','bar'));  // return true
Uize.isArguments ((function () {return arguments}) ());             // return true

Uize.isArguments (['foo','bar']);                                   // return false
Uize.isArguments ({0:'foo',1:'bar',length:2});                      // return false
Uize.isArguments ({foo:'bar'});                                     // return false
Uize.isArguments (function () {});                                  // return false
Uize.isArguments (/foo/gi);                                         // return false
Uize.isArguments ('foo');                                           // return false
Uize.isArguments (true);                                            // return false
Uize.isArguments (42);                                              // return false
Uize.isArguments (undefined);                                       // return false
Uize.isArguments (null);                                            // return false

NOTES

compare to the related Uize.isArray and Uize.isList static methods
see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.26. Uize.isArray

Returns a boolean, indicating whether or not the specified value is an instance of the JavaScript Array class.

SYNTAX

isArrayBOOL = Uize.isArray (valueANYTYPE);

This method is a useful abstraction to deal with the fact that the instanceof Array test fails on arrays that are passed across frames, iframes, or windows. The method returns true if the instanceof Array test passes, or if the specified value is an object and has a property named splice that is a function (the splice method is unique to arrays and its name is unique enough that the likelihood of an object having this property and it being a function is quite low).

NOTES

an object having a property named splice whose value is of type function will be regarded as an array by this method
see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.27. Uize.isBoolean

Returns a boolean, indicating whether or not the specified value is a boolean.

SYNTAX

isBooleanBOOL = Uize.isBoolean (valueANYTYPE);

This method tests if the specified value is a boolean primitive, so this method will return false if the value being tested is an instance of JavaScript's built-in Boolean object.

EXAMPLES

Uize.isBoolean (true);                 // returns true
Uize.isBoolean (false);                // returns true

Uize.isBoolean (new Boolean (true));   // returns false
Uize.isBoolean ('true');               // returns false
Uize.isBoolean (5);                    // returns false
Uize.isBoolean (NaN);                  // returns false
Uize.isBoolean (null);                 // returns false
Uize.isBoolean (undefined);            // returns false
Uize.isBoolean ();                     // returns false
Uize.isBoolean ({foo:'bar'});          // returns false
Uize.isBoolean (['foo','bar']);        // returns false
Uize.isBoolean (Uize.Widget ());       // returns false
Uize.isBoolean (function () {});       // returns false
// etc.

NOTES

see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.28. Uize.isEmpty

Returns a boolean, indicating whether or not the specified object or array is empty.

SYNTAX

isEmptyBOOL = Uize.isEmpty (valueANYTYPE);

The valueANYTYPE parameter can be an Object reference, an Array reference, a Function reference, or any other type. For object type values that are references to Object instances, the Uize.isEmpty method returns true if the object has no keys. For an array type value, Uize.isEmpty returns true if the array has no elements (ie. a length of 0). For any other type of value, Uize.isEmpty returns true if the value is equivalent to false.

EXAMPLES

Uize.isEmpty ({});                   // returns true
Uize.isEmpty ([]);                   // returns true
Uize.isEmpty ('');                   // returns true
Uize.isEmpty (0);                    // returns true
Uize.isEmpty (false);                // returns true
Uize.isEmpty (null);                 // returns true
Uize.isEmpty (undefined);            // returns true
Uize.isEmpty (NaN);                  // returns true

Uize.isEmpty ({blah:0});             // returns false
Uize.isEmpty (['blah']);             // returns false
Uize.isEmpty ('blah');               // returns false
Uize.isEmpty (1);                    // returns false
Uize.isEmpty (true);                 // returns false
Uize.isEmpty (function () {});       // returns false

For object type values that are references to instances of objects other than Object (such as the String, Boolean, and Number objects, or Uize.Class subclasses), the object type value will first be resolved to a value by calling the valueOf Instrinsic Method of the object, and this resolved value will then be evaluated according the rules described above. Consider the following examples...

EXAMPLES

Uize.isEmpty (new String (''));         // returns true
Uize.isEmpty (new Number (0));          // returns true
Uize.isEmpty (new Boolean (false));     // returns true
Uize.isEmpty (Uize.Class ({value:0}));  // returns true

Uize.isEmpty (new String ('blah'));     // returns false
Uize.isEmpty (new Number (0));          // returns false
Uize.isEmpty (new Boolean (true));      // returns false
Uize.isEmpty (Uize.Class ({value:1}));  // returns false

Using Uize.isEmpty (objectOrArray) has better performance than the expression !Uize.totalKeys (objectOrArray), because the latter expression iterates through all the keys of the object or elements of the array to count the total.

NOTES

compare to the Uize.emptyOut static method
see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.29. Uize.isFunction

Returns a boolean, indicating whether or not the specified value is a function.

SYNTAX

isFunctionBOOL = Uize.isFunction (valueANYTYPE);

This method is a useful abstraction to deal with some issues with detecting function type values using the traditional typeof value == 'function' approach in different Web browsers, as listed below...

2.29.1. Regular Expressions Masquerading as Functions

In a number of browsers, instances of JavaScript's built-in RegExp object are reported as type 'function' by the typeof operator.

They do, in fact, behave nominally as functions and can be called as functions using the standard syntax for calling functions. Consider the following example...

EXAMPLE

alert (/(\d+)/ ('Space 1999 was an awesome show') [1]);  // alerts the text "1999"

However, regular expressions do not have the Function object as their constructor - their constructor is the RegExp object. As a result, they do not support the call and apply methods or other features of true functions. If your code is expecting true functions that support all the features of functions, then it is better to use the Uize.isFunction method in testing for function type values.

2.29.2. Functions From Other Windows

In Microsoft Internet Explorer, references to functions defined in another window are not reported as type 'function' by the typeof operator.

Furthermore, references to functions defined in another window will fail in a test of "instanceof Function", because the Function constructor for the function that was defined in the other window is discrete from the Function object belonging to the window in which the test is being performed. This behavior may seem unfortunate in this one sense, but it is important in the sense of not allowing contamination across windows and possible interoperability and security issues. If your code is expecting functions that may originate from a different window, then it is better to use the Uize.isFunction method in testing for function type values, because the Uize.isFunction method handles the aforementioned issues.

NOTES

see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.30. Uize.isIn

Returns a boolean, indicating whether or not the specified value can be found within the specified array (or values of an object's properties).

SYNTAX

isInBOOL = Uize.isIn (sourceARRAYorOBJ,valueANYTYPE);

VARIATION

isInBOOL = Uize.isIn (sourceARRAYorOBJ,valueANYTYPE,strictEqualityBOOL);

By default, this method tests for a match using strict equality. When the value false is specified for the optional strictEqualityBOOL parameter, then this method will test for a match using loose equality (ie. where the string value '1' would be considered equal to the number value 1, or the number value 0 would be considered equal to the boolean value false).

EXAMPLE

Uize.isIn ([0,1,2,3,4,5],'3');               // returns false
Uize.isIn ([0,1,2,3,4,5],'3',false);         // returns true
Uize.isIn ({prop1:'foo',prop2:1},'foo');     // returns true
Uize.isIn ({prop1:'foo',prop2:1},'1');       // returns false
Uize.isIn ({prop1:'foo',prop2:1},'1',false); // returns true (non-strict equality test)

NOTES

see also the related Uize.indexIn static method
see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.31. Uize.isInstance

Returns a boolean, indicating whether or not the specified value is a reference to an instance of a UIZE class.

SYNTAX

isInstanceBOOL = Uize.isInstance (valueANYTYPE);

This method can be useful when implementing methods that may be called on a class as well as on an instance of a class.

NOTES

see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.32. Uize.isList

Returns a boolean, indicating whether or not the specified value is considered a list.

SYNTAX

isListBOOL = Uize.isList (valueANYTYPE);

A list is considered to be a non-null value of type 'object' that has a length property whose value is a number. By this definition, an instance of JavaScript's built-in Array object is considered to be a list. Also by this definition, a NodeList instance as returned by the document.getElementsByTagName method is considered to be a list, since it is a non-null object type value with a number type length property.

The Uize.isList method is useful when implementing methods that are to conditionalize their behavior based upon the type of a parameter, and where an iteration behavior is desired for list type values. If a value is considered to be a list, its list items can be iterated over using a standard JavaScript for loop, using the length property to determine how many items should be iterated over, and indexing into the list using JavaScript's [] (square brackets) notation.

EXAMPLES

alert (Uize.isList (['foo','bar','hello','world']));        // alerts "true"
alert (Uize.isList (document.getElementsByTagName ('a')));  // alerts "true"

alert (Uize.isList ({foo:'bar',hello:'world'}));            // alerts "false"
alert (Uize.isList (42));                                   // alerts "false"
alert (Uize.isList (true));                                 // alerts "false"
alert (Uize.isList ('foo');                                 // alerts "false"
alert (Uize.isList (null);                                  // alerts "false"
alert (Uize.isList (undefined);                             // alerts "false"
alert (Uize.isList (/\d+/));                                // alerts "false"
alert (function () {});                                     // alerts "false"

// an object is only considered a list once it has a length property that is a number
var fooObj = {0:'foo',1:'bar',2:'hello',3:'world'};
alert (Uize.isList (fooObj));                               // alerts "false"
fooObj.length = '4';
alert (Uize.isList (fooObj));                               // alerts "false"
fooObj.length = 4;
alert (Uize.isList (fooObj));                               // alerts "true"

// the arguments variable inside functions is considered to be a list
function fooFunc () {
  alert (Uize.isList (arguments));                         // alerts "true"
}
fooFunc ('foo','bar','hello','world');

NOTES

compare to the Uize.isArray static method
see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.33. Uize.isNaN

Returns a boolean value, indicating whether or not the specified value is the JavaScript special value NaN.

SYNTAX

isNaNBOOL = Uize.isNaN (valueANYTYPE);

2.33.1. There's Something About NaN

JavaScript's built-in isNaN function is odd - and, some might say, less than useful - in its peculiar behavior.

The first thing that the isNaN function does is to coerce the value it's given to a number type, so it will return true when the value being tested is undefined or some other value that, when coerced to a number, produces the value NaN. For example, the isNaN function will produce the result false when given the string value '42' ('42' coerces to the number 42), while it will produce the result true when given the string value 'foo' ('foo' coerces to the number type value NaN). Now, clearly neither of these two string values is the special value NaN, so the isNaN function fails to provide a useful way to test if a value is NaN.

Now, add to this the peculiar fact that testing any value for strict equality against the special value NaN always produces the result false - even if the value being tested is itself NaN - and you have yourself a rather frustrating quandary. Since the expression NaN === NaN produces the result false, you could use the expression value !== value as a way of testing if a value is NaN, but you'd probably want to avoid having that in your code for fear of confusing the hell out of a person reading it later.

The Uize.isNaN method comes to the rescue, providing a useful and semantically sensible way of testing if a value is the JavaScript special value NaN.

EXAMPLES

// using the Uize.isNaN method, you get these results...

Uize.isNaN (NaN);               // returns true

Uize.isNaN (function () {});    // returns false (a function is not NaN)
Uize.isNaN (new Number (NaN));  // returns false (a Number object is not NaN)
Uize.isNaN (new Date ('foo'));  // returns false (a Date object is not NaN)
Uize.isNaN (undefined);         // returns false
Uize.isNaN (null);              // returns false
Uize.isNaN ('foo');             // returns false
Uize.isNaN ('');                // returns false
Uize.isNaN ('42');              // returns false
Uize.isNaN (42);                // returns false
Uize.isNaN (true);              // returns false
Uize.isNaN ({});                // returns false
Uize.isNaN ([]);                // returns false


// in contrast, JavaScript's built-in isNaN function produces these results

isNaN (NaN);                    // returns true (hallelujah!)

isNaN (undefined);              // returns true (undefined coerces to NaN)
isNaN ('foo');                  // returns true ('foo' coerces to NaN)
isNaN ({});                     // returns true ({} coerces to NaN)
isNaN (function () {});         // returns true (a function coerces to NaN)
isNaN (new Number (NaN));       // returns true (new Number (NaN) coerces to NaN)
isNaN (new Date ('foo'));       // returns true (an invalid date coerces to NaN)

isNaN (null);                   // returns false (null coerces to 0)
isNaN ('42');                   // returns false ('42' coerces to 42)
isNaN (true);                   // returns false (true coerces to 1)
isNaN ('');                     // returns false ('' coerces to 0)
isNaN ([]);                     // returns false ([] coerces to '', which coerces to 0)

From the above examples, it should be clear that the Uize.isNaN method is far more useful when trying to test if a specific value is exactly the JavaScript special value NaN, while it's clear that the built-in isNaN function's behavior is of questionable value.

NOTES

compare to the Uize.isNumber static method
see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.34. Uize.isNully

Returns a boolean, indicating whether or not the specified value is null or undefined.

SYNTAX

isNullyBOOL = Uize.isNully (valueANYTYPE);

In JavaScript, the values null and undefined are technically different, but in many instances in your code you may wish to treat them as equivalent, often when you are defaulting arguments of functions or properties of objects. Now, you can test to see if a value is either null or undefined by simply comparing the value to undefined in a loose equality (eg. if (myValue == undefined) {...}), but certain tools like jslint may complain about that, forcing you to do two explicit strict equality checks (as in if (myValue === null || myValue === undefined) {...}). This can be tedious when you have a long deferencing, so the Uize.isNully method can be useful and more concise in such cases.

INSTEAD OF...

if (myObject.subObject.property === null || myObject.subObject.property === undefined) {
  // ...
}

USE...

if (Uize.isNully (myObject.subObject.property)) {
  // ...
}

NOTES

compare to the Uize.isObject static method
see the related Uize.defaultNully static method
see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.35. Uize.isNumber

Returns a boolean, indicating whether or not the specified value is a number.

SYNTAX

isNumberBOOL = Uize.isNumber (valueANYTYPE);

This method is a useful abstraction to deal with the fact that the division of zero by zero in JavaScript yields a special kind of value know as NaN. Unfortunately, in the implementation of this special value, the result chosen for when the typeof operator is applied to it is 'number' (ie. typeof NaN == 'number' produces true). The Uize.isNumber method checks that both the type of the parameter is 'number' and also that the parameter is not NaN.

Also note that this method tests if the specified value is a number primitive, so this method will return false if the value being tested is an instance of JavaScript's built-in Number object.

NOTES

compare to the Uize.isNaN static method
see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.36. Uize.isObject

Returns a boolean, indicating whether or not the specified value is an object.

SYNTAX

isObjectBOOL = Uize.isObject (valueANYTYPE);

Using JavaScript's built-in typeof operator, the type of the value null is reported as being 'object'. This can be less than useful when trying to conditionalize code to operate on object type values by dereferencing properties, as attempting to dereference properties off the value null will produce JavaScript errors. The Uize.isObject method provides a more useful and semantically more intuitive way of testing if a value is a non-null object.

INSTEAD OF...

if (typeof myValue == 'object' && myValue !== null) {
  // ...
}

USE...

if (Uize.isObject (myValue)) {
  // ...
}

Note that because arrays in JavaScript are derived from the language's built-in Object object, array values are reported as being objects by this method.

EXAMPLES

Uize.isObject ({foo:'bar'});          // returns true
Uize.isObject (['foo','bar']);        // returns true
Uize.isObject (new Boolean (false));  // returns true
Uize.isObject (new String ('foo'));   // returns true
Uize.isObject (new Number (5));       // returns true
Uize.isObject (new Date);             // returns true
Uize.isObject (Uize.Widget ());       // returns true

Uize.isObject (null);                 // returns false
Uize.isObject (undefined);            // returns false
Uize.isObject ();                     // returns false
Uize.isObject (5);                    // returns false
Uize.isObject (NaN);                  // returns false
Uize.isObject ('foo');                // returns false
Uize.isObject (true);                 // returns false
Uize.isObject (function () {});       // returns false

NOTES

compare to the Uize.isNully and Uize.isPlainObject static methods
see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.37. Uize.isPlainObject

Returns a boolean, indicating whether or not the specified value is a plain object (an instance of JavaScript's built-in Object object).

SYNTAX

isPlainObjectBOOL = Uize.isPlainObject (valueANYTYPE);

Plain objects are often used as very simple data structures in JavaScript. Sometimes it is desirable to conditionalize the behavior of a function or method, based upon whether an object type value is a plain data structure object or an instance of a custom object (such as an instance of a Date object, or an instance of a Uize.Class subclass). In such cases, the Uize.isPlainObject method provides a convenient way to detect if a value is a reference to a plain object.

EXAMPLES

Uize.isPlainObject ({});                   // returns true
Uize.isPlainObject ({foo:'bar'});          // returns true
Uize.isPlainObject (new Object ());        // returns true

Uize.isPlainObject (['foo','bar']);        // returns false
Uize.isPlainObject (new Boolean (false));  // returns false
Uize.isPlainObject (new String ('foo'));   // returns false
Uize.isPlainObject (new Number (5));       // returns false
Uize.isPlainObject (new Date);             // returns false
Uize.isPlainObject (Uize.Widget ());       // returns false
Uize.isPlainObject (null);                 // returns false
Uize.isPlainObject (undefined);            // returns false
Uize.isPlainObject ();                     // returns false
Uize.isPlainObject (5);                    // returns false
Uize.isPlainObject (NaN);                  // returns false
Uize.isPlainObject ('foo');                // returns false
Uize.isPlainObject (true);                 // returns false
Uize.isPlainObject (function () {});       // returns false

NOTES

compare to the Uize.isObject static method
see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.38. Uize.isPrimitive

Returns a boolean, indicating whether or not the specified value is one of JavaScript's built-in primitive types: string, boolean, or number.

SYNTAX

isPrimitiveBOOL = Uize.isPrimitive (valueANYTYPE);

EXAMPLES

Uize.isPrimitive (true);                 // returns true
Uize.isPrimitive (false);                // returns true
Uize.isPrimitive ('foo');                // returns true
Uize.isPrimitive ('');                   // returns true
Uize.isPrimitive (42);                   // returns true
Uize.isPrimitive (0);                    // returns true

Uize.isPrimitive (new Boolean (true));   // returns false
Uize.isPrimitive (new String (foo));     // returns false
Uize.isPrimitive (new Number (42));      // returns false
Uize.isPrimitive (null);                 // returns false
Uize.isPrimitive (undefined);            // returns false
Uize.isPrimitive ();                     // returns false
Uize.isPrimitive ({foo:'bar'});          // returns false
Uize.isPrimitive (['foo','bar']);        // returns false
Uize.isPrimitive (Uize.Widget ());       // returns false
Uize.isPrimitive (function () {});       // returns false
// etc.

NOTES

see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.39. Uize.isRegExp

Returns a boolean, indicating whether or not the specified value is a regular expression (ie. an instance of JavaScript's built-in RegExp object).

SYNTAX

isRegExpBOOL = Uize.isRegExp (valueANYTYPE);

EXAMPLES

Uize.isRegExp (/^\d+$/);                // returns true
Uize.isRegExp (new RegExp ('^\\d+$'));  // returns true

Uize.isRegExp (true);                   // returns false
Uize.isRegExp ('foo');                  // returns false
Uize.isRegExp (42);                     // returns false
Uize.isRegExp (new Boolean (true));     // returns false
Uize.isRegExp (new String (foo));       // returns false
Uize.isRegExp (new Number (42));        // returns false
Uize.isRegExp (null);                   // returns false
Uize.isRegExp (undefined);              // returns false
Uize.isRegExp ();                       // returns false
Uize.isRegExp ({foo:'bar'});            // returns false
Uize.isRegExp (['foo','bar']);          // returns false
Uize.isRegExp (Uize.Widget ());         // returns false
Uize.isRegExp (function () {});         // returns false
// etc.

NOTES

see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.40. Uize.isSameAs

Returns a boolean, indicating whether or not the specified value is the same as another value in a strict equality test, but also supporting comparison of the JavaScript special value NaN.

SYNTAX

isSameAsBOOL = Uize.isSameAs (valueANYTYPE,otherValueANYTYPE);

EXAMPLES

Uize.isSameAs ('foo','foo');          // returns true
Uize.isSameAs ('','');                // returns true
Uize.isSameAs (42,42);                // returns true
Uize.isSameAs (Infinity,Infinity);    // returns true
Uize.isSameAs (NaN,NaN);              // returns true
Uize.isSameAs (false,false);          // returns true
Uize.isSameAs (null,null);            // returns true
Uize.isSameAs (undefined,undefined);  // returns true

Uize.isSameAs (null,undefined);       // returns false
Uize.isSameAs (null,NaN);             // returns false
Uize.isSameAs ('',0);                 // returns false
Uize.isSameAs (1,true);               // returns false
Uize.isSameAs ('true',true);          // returns false
Uize.isSameAs ('foo','');             // returns false
Uize.isSameAs ('null',null);          // returns false
Uize.isSameAs ('42',42);              // returns false
Uize.isSameAs ({},{});                // returns false (different object references)
Uize.isSameAs ([],[]);                // returns false (different array references)

2.40.1. NaN is the Same as NaN

The Uize.isSameAs method is most useful in its support for comparing two values that may be the JavaScript special value NaN.

The special value NaN is never considered to be equal to itself in a strict equality test. So, for example, the expression NaN === NaN produces the result false. The Uize.isSameAs method comes to the rescue and provides special handling in order to ensure that if the two values being compared are both NaN, then the method will return true.

EXAMPLE

var
  valueA = NaN,
  valueB = NaN
;
alert (valueA === valueB);              // alerts "false"
alert (Uize.isSameAs (valueA,valueB));  // alerts "true"

NOTES

see also the related Uize.isNaN static method
see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.41. Uize.isString

Returns a boolean, indicating whether or not the specified value is a string.

SYNTAX

isStringBOOL = Uize.isString (valueANYTYPE);

This method tests if the specified value is a string primitive, so this method will return false if the value being tested is an instance of JavaScript's built-in String object.

EXAMPLES

Uize.isString ('foo');                // returns true
Uize.isString ('');                   // returns true

Uize.isString (new String ('foo'));   // returns false
Uize.isString (5);                    // returns false
Uize.isString (NaN);                  // returns false
Uize.isString (true);                 // returns false
Uize.isString (null);                 // returns false
Uize.isString (undefined);            // returns false
Uize.isString ();                     // returns false
Uize.isString ({foo:'bar'});          // returns false
Uize.isString (['foo','bar']);        // returns false
Uize.isString (Uize.Widget ());       // returns false
Uize.isString (function () {});       // returns false
// etc.

NOTES

see also the other value testing methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.42. Uize.keys

Returns an array, representing the keys (property names) of the specified object.

SYNTAX

keysARRAY = Uize.keys (objectOBJ);

EXAMPLE

var
  personRecord = {
    firstName:'John',
    lastName:'Wilkey',
    addressStreet:'1 Shiny House Way',
    addressCity:'Richville',
    addressState:'CA',
    addressZip:'91234'
  },
  myKeys = Uize.keys (personRecord)
;

After the above code has executed, the myKeys variable will have the value ['firstName', 'lastName', 'addressStreet', 'addressCity', 'addressState', 'addressZip'].

NOTES

when the value of objectOBJ parameter is null or undefined, an empty array will be returned
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.43. Uize.laxEval

Lets you perform quarantined code evaluation of the specified JavaScript code string, but not in JavaScript strict mode.

SYNTAX

evalResultANYTYPE = Uize.laxEval (codeToEvalSTR);

The Uize.laxEval method evaluates the specified code string in non-strict mode. If you would prefer to evaluate code in JavaScript strict mode, use the companion Uize.eval method. The Uize.laxEval method returns any result that was produced by the code being evaluated.

For a detailed discussion of quarantining and to see examples, consult the section Quarantined Code Execution.

NOTES

compare to the companion Uize.eval static method
compare to the related Uize.quarantine static method

IMPLEMENTATION INFO

this feature was introduced in this module

2.44. Uize.lookup

Returns a lookup object, where each key is a value from the specified values array.

DIFFERENT USAGES

Create a Lookup From a Values Array

lookupOBJ = Uize.lookup (valuesARRAY);

Create a Lookup Object With a Custom Lookup Value

lookupOBJ = Uize.lookup (valuesARRAY,lookupValueANYTYPE);

Create a Safe Lookup Object From a Values Array

safeLookupOBJ = Uize.lookup (valuesARRAY,lookupValueANYTYPE,safeBOOL);

Add More Entries to a Lookup Object

lookupOBJ = Uize.lookup (valuesARRAY,lookupValueANYTYPE,targetLookupOBJ);

Create an Empty Safe Lookup Object

emptyLookupOBJ = Uize.lookup (null,1,true);

2.44.1. Create a Lookup From a Values Array

In the most common usage, a lookup object can be created from a values array by specifying just the valuesARRAY parameter.

SYNTAX

lookupOBJ = Uize.lookup (valuesARRAY);

EXAMPLE

var
  fruits = ['apple','peach','pear','banana','orange','mango'],
  fruitsLookup = Uize.lookup (fruits)
;

After the above code is executed, the value of the fruitsLookup variable will be an object with the contents...

{apple:true,peach:true,pear:true,banana:true,orange:true,mango:true}

2.44.2. Create a Lookup Object With a Custom Lookup Value

In cases where the default lookup value true is not desirable, a different lookup value can be specified using the optional lookupValueANYTYPE second parameter.

SYNTAX

lookupOBJ = Uize.lookup (valuesARRAY,lookupValueANYTYPE);

EXAMPLE

var
  fruits = ['apple','peach','pear','banana','orange','mango'],
  foodsLookup = Uize.lookup (fruits,'fruit')
;

In the above example, the value 'fruit' is being specified for the optional lookupValueANYTYPE parameter. After the above code is executed, the value of the foodsLookup variable will be an object with the contents...

{apple:'fruit',peach:'fruit',pear:'fruit',banana:'fruit',orange:'fruit',mango:'fruit'}

Using a custom lookup value can be useful when you're populating a lookup from multiple different values arrays and you want to be able to track which values array a lookup entry came from. For a good illustration of this technique, see the example for the Add More Entries to a Lookup Object use case.

2.44.3. Create a Safe Lookup Object From a Values Array

A safe lookup object can be created from a values array by specifying the value true for the optional safeBOOL third parameter.

SYNTAX

safeLookupOBJ = Uize.lookup (valuesARRAY,lookupValueANYTYPE,safeBOOL);

EXAMPLE

var
  values = ['foo','bar'],
  unsafeLookup = Uize.lookup (values),
  safeLookup = Uize.lookup (values,true,true)
;
if (unsafeLookup ['valueOf']) alert ('unsafe');
if (!safeLookup ['valueOf']) alert ('safe');

In the above example, the unsafeLookup lookup object created from the values array tests truthy for a 'valueOf' entry. This is because the lookup object is an instance of JavaScript's built-in Object object, and this base object has a valueOf instance method as part of its prototype. In contrast, the safeLookup lookup object tests falsy for a 'valueOf' entry, because the Uize.lookup method adds an explicit undefined value for the 'valueOf' entry (and other Object prototype properties) when the value true is specified for the safeBOOL parameter.

2.44.4. Add More Entries to a Lookup Object

By specifying an existing lookup object for the optional targetLookupOBJ third parameter, more entries can be added to the existing lookup.

SYNTAX

lookupOBJ = Uize.lookup (valuesARRAY,lookupValueANYTYPE,targetLookupOBJ);

EXAMPLE

var
  fruits = ['apple','apricot','orange','peach','pear','watermelon'],
  vegetables = ['beet','broccoli','cauliflower','onion','potato','squash'],
  grains = ['barley','maize','oats','quinoa','rice','sorghum','wheat']
  foodLookup = Uize.lookup (fruits,'fruit')
;
Uize.lookup (vegetables,'vegetable',foodLookup); // stitch in keys for vegetables
Uize.lookup (grains,'grain',foodLookup);         // stitch in keys for grains

alert (foodLookup ['apricot']);   // alerts "fruit"
alert (foodLookup ['broccoli']);  // alerts "vegetable"
alert (foodLookup ['quinoa']);    // alerts "grain"

In the above example, a food lookup object is created initially from the fruits array. Then, entries are added to the foodLookup lookup object by specifying it as the target in two additional calls to the Uize.lookup method: one to stirch in lookup entries for the vegetables values array, and the other to stitch in entries for the grains values array. Also note that different lookup values are being used in each case, allowing the foodLookup lookup object to be used to look up the food type from the food name.

2.44.5. Create an Empty Safe Lookup Object

An empty safe lookup object can be created by specifying the value null for the valuesARRAY parameter, the value 1 for the lookupValueANYTYPE second parameter, and the value true for the safeBOOL third parameter.

SYNTAX

emptyLookupOBJ = Uize.lookup (null,1,true);

By specifying the value null for the valuesARRAY parameter, the resulting lookup object will have no lookup entries. Since the resulting lookup will have no entries, the value specified for the lookupValueANYTYPE second parameter is arbitrary, since this value won't be used - the value 1 is nice and concise.

2.44.6. A Real World Example

Creating a lookup object is useful when repeatedly checking to see if values are in a defined values set.

Looping through that defined values set array for each of the lookups would result in poor performance if the set of values to scan through is large, and if the lookup is being performed frequently.

Let's consider an example...

function getValuesInMasterList (values,masterList) {
  var result = [];
  for (var valueNo = -1; ++valueNo < values.length;) {
    var value = values [valueNo];
    if (Uize.isIn (masterList,value)) result.push (value);
  }
  return result;
}

In the above example, a getValuesInMasterList function is being defined. This function accepts two parameters: an array of values, and a master list of values. The function returns an array, containing all the values from the values array that are present in the master list of values. The way it's implemented, on each iteration of the loop through the values array the Uize.isIn static method is being used to determined if the current value is in the master list array. This provides less than optimal performance, since the complexity is O(n2).

Using the Uize.lookup static method, a more efficient solution can be fashioned, as follows...

function getValuesInMasterList (values,masterList) {
  var
    result = [],
    masterListLookup = Uize.lookup (masterList)
  ;
  for (var valueNo = -1; ++valueNo < values.length;) {
    var value = values [valueNo];
    if (masterListLookup [value]) result.push (value);
  }
  return result;
}

In the improved version, a lookup object (aka hash table) is created before the loop. Then, in the loop, all that is needed to see if a value being inspected is in the master list is to do a simple dereference into the lookup object, using the value as the key / property name. Here the complexity is O(n), since indexing into the lookup object is constant time.

NOTES

see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.45. Uize.map

Iterates through the specified array (or object), executing the specified mapper expression or function for each element (or object property), and packages the results into an array (or object).

SYNTAX

mappedARRAYorOBJ = Uize.map (sourceARRAYorOBJorINT,mapperSTRorFUNC);

The Uize.map method is very vertatile and can be used to accomplish a wide array of different tasks. Sure, you could do all the things you could do with Uize.map by writing your own loops. This method serves as a convenience, making certain operations more concise in application code.

The example below, which takes a source array of strings and produces a new array of those strings uppercased, illustrates the difference between writing your own iterator and using the Uize.map method.

INSTEAD OF...

var newArray = [];
for (var elementNo = 0; elementNo < sourceArray.length; elementNo++) {
  newArray.push (sourceArray [elementNo].toUpperCase ());
}

USE...

var newArray = Uize.map (sourceArray,'value.toUpperCase ()');

OR USING A FUNCTION...

var newArray = Uize.map (
  sourceArray,function (value) {return value.toUpperCase ()}
);

Another example below - which generates an array seeded with the values 0 to 99 - further illustrates the convenience of the Uize.map method...

INSTEAD OF...

var newArray = [];
for (var elementNo = 0; elementNo < 100; elementNo++) {
  newArray.push (elementNo);
}

USE...

var newArray = Uize.map (100,'key');

OR USING A FUNCTION...

var newArray = Uize.map (100,function (value,key) {return key});

2.45.1. Key Benefits

The Uize.map static method provides some key improvements over the Array object's map method in JavaScript 1.6 (which is not supported in all browsers)...

can operate on objects as well as arrays
supports a more concise mapper expression string, as well as supporting a function
can optionally modify the source array or object
allows easy creation of a fresh source array for mapping, by specifying an array length
lets you specify an explicit target, where mapped values should be written to

VARIATION

mappedARRAYorOBJ = Uize.map (
  sourceARRAYorOBJorINT,
  mapperSTRorFUNC,
  targetARRAYorOBJorBOOL
);

By default, the Uize.map method maps values of the source array or object and packages the result into a new array or object. Specifying the optional targetARRAYorOBJorBOOL parameter allows us to explicitly specify a target for the operation, into which the mapped values will be packaged.

2.45.2. Parameters

2.45.2.1. sourceARRAYorOBJorINT

Lets you specify the source array or object, or the length of a fresh array, with which the Uize.map method should map new values.

VALUES

When an array is specified, then the Uize.map method will iterate through the elements of the array.
When an object is specified, then the Uize.map method will iterate through the properties of the object.
When a positive integer is specified, then the Uize.map method will create a fresh array of the length specified by this parameter and then iterate through that array. This is a convenient facility for seeding arrays of some desired length with automatically generated values.

2.45.2.2. mapperSTRorFUNC

Lets you specify a mapper expression or function, for mapping the value of the current element of the source array or the current property of the source object to a new value.

VALUES

When a string value is specified, then the JavaScript expression specified in the string will be compiled to a mapper function that will then be used for each iteration. An expression specified for this parameter must be a complete JavaScript expression (it may not be arbitrary, multi-statement chunks of code) following the same requirements of any expression that you might place on the right-hand side of an assignment statement. Within the context of your expression, the identifiers this, key, and value are defined, where this is a reference to the source array or object, key is the index of the current element of the source array or the name of the current property of the source object, and where value is the value of the current element of the source array or the current property of the source object.
When a function reference is specified, then the specified function will be called during each iteration. The function you specify should expect to receive two parameters: value and key. If you don't care about the key, then you can omit the second parameter and only have one parameter declared in your function's argument list. The mapper function is called as an instance method on the source array or object, so the this keyword can be used to access the source array or object for querying the values of other elements or properties.

2.45.2.3. targetARRAYorOBJorBOOL

Lets you specify where the result of the mapper should be packaged.

You can provide your own target array or object, you can specify to use the source array or object, or you can specify that the result should not be packaged (ie. discarded).

VALUES

true - When the boolean value true is specified (the default value for the targetARRAYorOBJorBOOL parameter if it is omitted), then the Uize.map method will package the result from the mapper into a new array or object.
false - When the boolean value false is specified (not the same as not specifying a value), then the Uize.map method will package the result from the mapper into the source array or object specified by the sourceARRAYorOBJorINT parameter (ie. won't use a different target).
null - When the special value null is specified (not the same as not specifying a value), then the Uize.map method will not package the result from the mapper into an array or object. This is useful if you just want to use this method as an iterator, without the memory expense of building an array or object.
object or array - When an object or array is explicitly specified, then the Uize.map method will package the result from the mapper into that array or object. This is convenient if you already have an array or object into which you wish to package the mapped values, or if you want to repeatedly map multiple source arrays or objects into a common array or object so that the mapped values are merged together. Incidentally, specifying the array or object value of the sourceARRAYorOBJorINT parameter as the value for the targetARRAYorOBJorBOOL parameter has the same effect as specifying the value false for this parameter (ie. use the source as the target, don't use a different target).

2.45.3. More Examples

Following are a bunch of examples, demonstrating just a sampling of what's possible using the Uize.map method...

2.45.3.1. Coerce all elements of an array to being numbers, modifying the source array...

Uize.map (array,'+value',false);

2.45.3.2. Coerce all elements of an array to being strings, modifying the source array...

Uize.map (array,'value + ""',false);

2.45.3.3. Default all empty string properties of an object to some value, modifying the source object...

Uize.map (surveyQuestions,'value || "--- no answer provided ---"',false);

2.45.3.4. Return an array of all the elements in the source array uppercased...

var uppercased = Uize.map (array,'value.toUpperCase ()');

2.45.3.5. Add a prefix to all the string elements of an array, modifying the source array...

Uize.map (array,'"prefix_" + value',false);

2.45.3.6. Create a cheap (ie. not deep) copy of an object...

var copyOfFoo = Uize.map (foo,'value');

2.45.3.7. Seed an array of 100 elements with the value range 0 to 99...

var range0to99 = Uize.map (100,'key');

2.45.3.8. Seed an array of 100 elements with the value range 1 to 100...

var range1to100 = Uize.map (100,'key + 1');

2.45.3.9. Create an array of the square roots of 0 to 99...

var squaresOf0to99 = Uize.map (100,'Math.sqrt (key)');

2.45.3.10. Create an array of the square roots of the values in the source array...

var squaresOfArray = Uize.map (array,Math.sqrt);

2.45.3.11. Create an array of all the capital letters of the alphabet...

var capLetters = Uize.map (26,'String.fromCharCode (65 + key)');

2.45.3.12. Create a fresh array of 10 elements that are the first ten powers of 2...

var powersOf2 = Uize.map (10,'Math.pow (2,key)');

2.45.3.13. Creates an array of the first 30 numbers in the Fibonacci series...

var fibonacci = Uize.map (30,'key > 1 ? this [key - 2] + this [key - 1] : key');

2.45.3.14. Smooth an array of values by averaging against adjacent neighbors...

var smoothed = Uize.map (
  array,
  'key && key < this.length - 1 ? (this [key-1] + value + this [key+1]) / 3 : value'
);

2.45.3.15. Output elements of a log array to the Firebug console on separate lines...

Uize.map (logArray,'console.log (value)');

2.45.3.16. Output elements of a log array to the Firebug console on separate lines, with line numbers...

Uize.map (logArray,'console.log (key + ": " + value)');

2.45.3.17. Get a style properties object from a pure number coords object...

var coordsStyleProperties = Uize.map (coords,'value + "px"');

// EXAMPLE
// this... {left:0,top:50,width:100,height:175}
// produces this... {left:'0px',top:'50px',width:'100px',height:'175px'}

2.45.3.18. Get the length of the longest string in an array of strings....

var maxStringLength = Uize.max (Uize.map (stringsArray,'value.length'));

NOTES

compare to the Uize.forEach static method
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.46. Uize.max

Returns the maximum value from the specified array or object.

SYNTAX

var maxValueNUM = Uize.max (valuesARRAYorOBJ);

When an object is specified for the valuesARRAYorOBJ parameter, then the maximum property value in the object will be returned.

EXAMPLE

var
  employeeSalaries = {
    'John Anderson':80000,
    'Peter Hendriks':56000,
    'Jacob Previn':75000,
    'Scarlet Sjedsondorf':63000
  },
  maxEmployeeSalary = Uize.max (employeeSalaries)
;

In the above example, the variable maxEmployeeSalary will be left with the value 80000.

NOTES

if any of the values are not a number, then this method will return the value NaN
see the companion Uize.min static method
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.47. Uize.meldKeysValues

Returns an object that is created by melding together the specified keys array and values array.

SYNTAX

resultOBJ = Uize.meldKeysValues (keysARRAY,valuesARRAY);

The Uize.meldKeysValues method iterates through the elements of the keysARRAY and valuesARRAY arrays in lock step, assigning properties to the resulting object using an element from the keys array as property name and an element from the values array as property value.

If you obtained a keys array from an object using the Uize.keys method, and if you also obtained a values array from that same object using the Uize.values method, then you could use the Uize.meldKeysValues method with those keys and values arrays to recreate the original object.

EXAMPLE

var
  foodInfoKeys = ['apple','banana','beet','corn','potato','rice']
  foodInfoValues = ['fruit','fruit','vegetable','grain','vegetable','grain'],
  foodInfo = Uize.meldKeysValues (foodInfoKeys,foodInfoValues)
;

In the above example, keys from the foodInfoKeys array are being melded with values from the foodInfoValues array to form a value for the foodInfo object. After this code has executed, the foodInfo object will have the following contents...

{
  apple:'fruit',
  banana:'fruit',
  beet:'vegetable',
  corn:'grain',
  onion:'vegetable',
  rice:'grain'
}

2.47.1. Surplus Keys or Values Ignored

If the lengths of the keysARRAY or valuesARRAY arrays differ, then the surplus keys or values will be ignored.

2.47.1.1. Surplus Keys

If more keys are specified in keysARRAY than there are values in valuesARRAY, then the surplus keys will be ignored.

EXAMPLE

var object = Uize.meldKeysValues (['foo','hello'],['bar']);

After the above code has been executed, the object variable will have the value {foo:'bar'} - the surplus 'hello' key is ignored.

2.47.1.2. Surplus Values

If more values are specified in valuesARRAY than there are keys in keysARRAY, then the surplus values will be ignored.

EXAMPLE

var object = Uize.meldKeysValues (['foo'],['bar','world']);

After the above code has been executed, the object variable will have the value {foo:'bar'} - the surplus 'world' value is ignored.

NOTES

see the related Uize.keys and Uize.values static methods
compare to the Uize.pairUp static method
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.48. Uize.merge

Merges the contents of multiple source objects together into a fresh object.

SYNTAX

freshOBJ = Uize.merge (source1OBJ,source2OBJ,source3OBJ,...);

EXAMPLE

var result = Uize.merge (
  {foo:{bar:{hello:'world'}}},
  {foo:{bar:{boo:'yah'}}},
  null,
  {foo:{baz:'qux'},voo:'doo'}
);

RESULT

{
  foo:{
    bar:{
      hello:'world',
      boo:'yah'
    },
    baz:'qux'
  },
  voo:'doo'
}

2.48.1. Same Merging Behavior as the Uize.mergeInto Method

The Uize.merge method behaves in exactly the same manner as the Uize.mergeInto method, except that the first argument is not the target object for the merge but just another source.

Because the Uize.merge method always creates a fresh object, the target object is not specified and all the arguments for the method are source objects to merge together to form the fresh object returned by the method. The Uize.mergeInto method is documented thoroughly, and because both the Uize.merge and Uize.mergeInto methods perform the merge operation according to the same rules, you should refer to the reference for the Uize.mergeInto method for full details on how different situations are handled.

NOTES

see the companion Uize.mergeInto static method
compare to the related Uize.copy and Uize.copyInto static methods
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.49. Uize.mergeInto

Merges the contents of one or more source objects into the specified target object, and returns the target object as the result.

DIFFERENT USAGES

Merge the Contents of a Source Object Into a Target Object

targetOBJ = Uize.mergeInto (targetOBJ,sourceOBJ);

Merge Multiple Source Objects Into a Target Object

targetOBJ = Uize.mergeInto (targetOBJ,source1OBJ,source2OBJ,...,sourceNOBJ);

2.49.1. Merge the Contents of a Source Object Into a Target Object

In the most simple use case, the Uize.mergeInto method can be used to merge the contents of a single source object into a target object.

SYNTAX

targetOBJ = Uize.mergeInto (targetOBJ,sourceOBJ);

The contents of the source object is merged into the target object according to the Uize.mergeInto method's merging rules.

EXAMPLE

var
  targetObject = {
    foo:'bar',
    anArray:[0,1,2],
    junk:{
      hey:'there',
      moreJunk:{
        simple:'simon'
      }
    }
  },
  sourceObject = {
    foo:'BAR',
    anArray:['a','b','c'],
    junk:{
      boo:'yah',
      moreJunk:{
        peter:'pan',
        evenMoreJunk:{
          silly:'sausage'
        }
      }
    }
  }
;
Uize.mergeInto (targetObject,sourceObject);

RESULT

{
  foo:'BAR',
  anArray:['a','b','c'],
  junk:{
    hey:'there',
    moreJunk:{
      simple:'simon',
      peter:'pan',
      evenMoreJunk:{
        silly:'sausage'
      }
    },
    boo:'yah'
  }
}

2.49.2. Merge Multiple Source Objects Into a Target Object

As a convenience, the contents of multiple source objects can be merged into a target object by specifying an arbitrary number of source objects after the targetOBJ first parameter.

SYNTAX

targetOBJ = Uize.mergeInto (targetOBJ,source1OBJ,source2OBJ,...,sourceNOBJ);

When multiple source objects are specified, the contents of the source objects are merged into the target object in the order in which they are specified (ie. left to right in the arguments list). The contents of source objects are merged into the target object according to the Uize.mergeInto method's merging rules.

EXAMPLE

var
  targetObject = {
    foo:'bar',
    anArray:[0,1,2],
    junk:{
      hey:'there',
      moreJunk:{
        simple:'simon'
      }
    }
  },
  sourceObject1 = {
    foo:'BAR',
    anArray:['a','b','c'],
    junk:{
      boo:'yah',
      moreJunk:{
        peter:'pan',
        evenMoreJunk:{
          silly:'sausage'
        }
      }
    }
  },
  sourceObject2 = {
    hello:'world',
    anArray:['A','B','C'],
    junk:{
      yo:'wassup'
    }
  },
  sourceObject3 = {
    foo:'BAR!!!',
    junk:{
      moreJunk:{
        evenMoreJunk:{
          bite:'me'
        }
      }
    }
  }
;
Uize.mergeInto (targetObject,sourceObject1,sourceObject2,sourceObject3);

RESULT

{
  foo:'BAR!!!',
  anArray:['A','B','C'],
  hello:'world',
  junk:{
    hey:'there',
    moreJunk:{
      simple:'simon',
      peter:'pan',
      evenMoreJunk:{
        silly:'sausage',
        bite:'me'
      },
    },
    boo:'yah',
    yo:'wassup'
  }
}

2.49.3. Merging Rules

The Uize.mergeInto method merges the contents of source objects into a target object according to the following set of rules...

2.49.3.1. Merging is Recursive

The contents of a source object is merged into the contents of the target object recursively.

EXAMPLE

var result = Uize.mergeInto (
  {foo:{bar:{hello:'world'}}},
  {foo:{bar:{boo:'yah'}}}
);

RESULT

{foo:{bar:{hello:'world',boo:'yah'}}}

2.49.3.2. Only Plain Objects Are Recursed

Only the contents of plain objects are recursed, and non-plain objects are copied by reference.

EXAMPLE

function CustomObject (value) {this.value = value}

var
  customObject1 = new CustomObject (5),
  customObject2 = new CustomObject (42)
;
customObject1.foo = 'bar';
customObject2.hello = 'world';

var result = Uize.mergeInto (
  {prop:customObject1},
  {prop:customObject2}
);

In the above example, a constructor is created for a custom object called CustomObject. Then, we create two different instances of this object. To each instance, we add extra properties.

Now, when we use the Uize.mergeInto method to merge a source object into a target object, where the value of a prop property in the source object is customObject2 and the value of that same property in the target object is customObject1, the value of the prop property in the target object is simply overwritten with a reference to the customObject2 value contained in the source object - the contents of customObject2 are not merged into customObject1.

In other words, the merge process does not recurse into the properties of the CustomObject instances (or any non-plain objects, for that matter). The Uize.mergeInto method considers custom objects to be values rather than nodes of the object tree.

2.49.3.3. Missing Nodes Copied By Reference

When the target object being recursed is missing a node, at any level of its structure, that is present in the source object, then the node from the source object is copied by reference - it is not cloned.

EXAMPLE

var
  targetObject = {foo:'bar'},
  sourceObject = {aMissingNode:{hello:'world'}}
;
Uize.mergeInto (targetObject,sourceObject);

alert (targetObject.aMissingNode === sourceObject.aMissingNode);  // alerts "true"

In the above example, the sourceObject object contains the property aMissingNode, whose value is a plain object and represent a node in the object structure that is not present in the targetObject object. When the source object is merged into the target object, this missing node is copied by reference - it is not cloned into the target object. Therefore, the expression target.aMissingNode is identical in a strict equality to sourceObject.aMissingNode.

This same rule applies if the target object contains the property that is contained in the source object, but the value of the property in the target object is not a plain object.

EXAMPLE

var
  targetObject = {someProperty:'foo'},
  sourceObject = {someProperty:{hello:'world'}}
;
Uize.mergeInto (targetObject,sourceObject);

alert (targetObject.someProperty === sourceObject.someProperty);  // alerts "true"

In the above example, the sourceObject object contains the property someProperty, which is also present in the targetObject object. However, the value of this property in the target object is a string, so this value is overwritten with a reference to the object value of the property obtained from the source object. Therefore, the expression target.someProperty is identical in a strict equality to sourceObject.someProperty.

2.49.3.4. Null or Undefined Sources Are Ignored

As with the related Uize.copyInto method, specifying the values null or undefined for source object parameters results in those parameters simply being ignored - they contain nothing to merge into the target object.

EXAMPLE

Uize.mergeInto (
  {foo:'bar',junk:{hello:'world'}},
  null,
  {foo:'BAR'},
  undefined,
  {junk:{simple:'simon'}}
);

RESULT

{foo:'BAR',junk:{hello:'world',simple:'simon'}}

NOTES

see the companion Uize.merge static method
compare to the related Uize.copy and Uize.copyInto static methods
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.50. Uize.min

Returns the minimum value from the specified array or object.

SYNTAX

var minValueNUM = Uize.min (valuesARRAYorOBJ);

When an object is specified for the valuesARRAYorOBJ parameter, then the minimum property value in the object will be returned.

EXAMPLE

var
  employeeSalaries = {
    'John Anderson':80000,
    'Peter Hendriks':56000,
    'Jacob Previn':75000,
    'Scarlet Sjedsondorf':63000
  },
  minEmployeeSalary = Uize.min (employeeSalaries)
;

In the above example, the variable minEmployeeSalary will be left with the value 56000.

NOTES

if any of the values are not a number, then this method will return the value NaN
see the companion Uize.max static method
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.51. Uize.module

Lets you declare a module in the UIZE JavaScript Framework.

DIFFERENT USAGES

Declare a Module by Specifying a Module Definition Object

Uize.module (moduleDefinitionOBJ);

Declare a Namespace Module by Specifying Just the Namespace as a String

Uize.module (namespaceSTR);

2.51.1. Declare a Module by Specifying a Module Definition Object

In the most typical use case, a module can be defined by specifying the various properties of the module using a moduleDefinitionOBJ object.

SYNTAX

Uize.module (moduleDefinitionOBJ);

2.51.1.1. moduleDefinitionOBJ

The value specified for the moduleDefinitionOBJ argument should be an object of the following form...

SYNTAX

{
  name:moduleNameSTR,           // omit for anonymous modules
  superclass:superclassNameSTR, // omit for package modules, or if host is superclass
  required:modulesSTRorARRAY,   // omit when only host and superclass are required
  builder:builderFUNC           // omit for library modules and namespace modules
}

2.51.2. Declare a Namespace Module by Specifying Just the Namespace as a String

In the special case of defining a namespace module, a short form allows us to specify just the namespace using a namespaceSTR argument in place of the regular moduleDefinitionOBJ argument.

SYNTAX

Uize.module (namespaceSTR);

INSTEAD OF...

Uize.module ({name:'MyCompanyName.MySectionNamespace'});

USE...

Uize.module ('MyCompanyName.MySectionNamespace');

For an in-depth discussion of modules, consult the guide JavaScript Modules.

NOTES

see also the Uize.moduleLoader static method and the Uize.moduleUrlTemplate static property
see also the other module mechanism methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.52. Uize.moduleLoader

Loads the specified JavaScript module (specified by its module name) and calls the specified callback function once the module has been loaded.

SYNTAX

Uize.moduleLoader (moduleNameSTR,callbackFUNC);

The callback specified by the callbackFUNC parameter is called with a single parameter that represents the code of the module specified by the moduleNameSTR parameter, unless the module loader loads modules by adding script tags to the page (in which case the callback is called with no parameters).

EXAMPLE

Uize.moduleLoader = function (_moduleToLoad,_callback) {
  m._commObject.request ({
    url:[m.get ('env').service + 'getjs',{filename:_moduleToLoad + '.js'}],
    returnType:'json',
    requestMethod:'GET',
    callback:function (_responseObject) {
      _callback (_responseObject.moduleCode);
    }
  });
};

For an in-depth discussion of modules, consult the guide JavaScript Modules.

NOTES

see the related Uize.moduleUrlResolver static method and the Uize.moduleUrlTemplate static property
see also the other module mechanism methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.53. Uize.modulePathResolver

IMPLEMENTATION INFO

this feature was introduced in this module

2.54. Uize.moduleUrlResolver

Returns a string, representing the URL path from where the specified JavaScript module (specified by its module name) can be loaded.

SYNTAX

moduleUrlSTR = Uize.moduleUrlResolver (moduleNameSTR);

By overriding this static method, you have the flexibility to have different types of modules load from different locations. A classic example would be loading modules of the UIZE JavaScript Framework from a shared CDN (Content Delivery Network) location, while loading modules that are in your own Web site's namespace from the same machine that serves the pages. Consider the following example...

EXAMPLE

Uize.moduleUrlResolver = function (_moduleName) {
  var _modulePath = Uize.modulePathResolver (_moduleName);
  return (
    moduleName.indexOf ('MyDomain.') == 0
      ? '/js/' + _modulePath + '.js'
      : 'http://www.some-cdn.com/uize-js/' + _modulePath + '.js'
  );
};

In the above example, a custom module URL resolver is being specified. It looks at the module name, determines if the module name is in the namespace for the Web site (MyDomain in this example), and returns a root relative URL. Otherwise, assuming that all other modules are part of the UIZE JavaScript Framework and are stored on a CDN, it returns a URL for where the module would be located on that CDN Web site.

The module URL returned by your function will be used by the built-in Uize.moduleLoader module loader function. If you override the built-in module loader by specifying your own value for the Uize.moduleLoader static method, then the Uize.moduleUrlResolver static method will only be applicable if your custom module loader uses this method. Similarly, the built-in Uize.moduleUrlResolver implementation uses the Uize.moduleUrlTemplate static property. So, if you supply your own custom module URL resolver by overriding the Uize.moduleUrlResolver static method, then it is your choice as to whether or not you use the value of the Uize.moduleUrlTemplate property.

For an in-depth discussion of modules, consult the guide JavaScript Modules.

NOTES

see the related Uize.moduleLoader static method and the Uize.moduleUrlTemplate static property
see also the other module mechanism methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.55. Uize.noNew

Returns a function that is an object constructor that will construct an object using the specified constructor function, with JavaScript's new operator being optional when creating instances of the object.

SYNTAX

objectConstructorFUNC = Uize.noNew (constructorFunctionFUNC);

Normally, when creating instances of objects in JavaScript, the new operator must be used in conjunction with the constructor function, as in the statement var date = new Date (). The Uize.noNew method can be used to wrap any existing object constructor function, to create an object constructor where JavaScript's new operator will be optional when creating an instance of the object by calling the constructor.

EXAMPLE

// define the Food object
var Food = Uize.noNew (
  function (name,type) {
    this.name = name;
    this.type = type;
  }
);

// create an instance of Food using the new operator
var apple = new Food ('apple','fruit');
alert (apple.type);  // alerts the text "fruit"

// create an instance of Food without using the new operator
var rice = Food ('rice','grain');
alert (rice.type);  // alerts the text "grain"

In the above example, the Food object is being defined by using the Uize.noNew method to wrap a constructor function. Then, one instance of this object is created using the new operator, while another instance is created without using new. Both instances are fully fledged Food object instances and behave in exactly the same way.

2.55.1. Properties Aren't Transferred

When wrapping a constructor function using the Uize.noNew method, static and instance methods and properties on the wrapped constructor function are not transferred to the wrapper function.

The Uize.noNew method is not intended to be used to wrap constructor functions after the fact, but is intended to be used to wrap a constructor function before static and instance methods and properties are assigned.

INCORRECT

// define Food object
function Food (name,type) {
  this.name = name;
  this.type = type;
}

// define instance methods
Food.prototype.isFruit = function () {return this.type == 'fruit'};
Food.prototype.isGrain = function () {return this.type == 'grain'};

// define static methods
Food.isFruit = function (food) {return food && food.isFruit ()};
Food.isGrain = function (food) {return food && food.isGrain ()};

// wrap Food constructor to make new operator optional -- TOO LATE!!!
Food = Uize.noNew (Food);

In the above example, the Food object is defined and then instance and static methods are defined for it. The Food object is then replaced with a wrapper of itself that is created using the Uize.noNew method. Now, the Uize.noNew method does not transfer properties of the constructor function that is wrapped, so the new Food object lacks the instance and static methods - not the desired effect. The solution is to first wrap the constructor function using Uize.noNew, after which the additional features can be defined for the object, as shown below...

CORRECT

// define Food object, already wrapped to make new operator optional
var Food = Uize.noNew (
  function (name,type) {
    this.name = name;
    this.type = type;
  }
);

// define instance methods
Food.prototype.isFruit = function () {return this.type == 'fruit'};
Food.prototype.isGrain = function () {return this.type == 'grain'};

// define static methods
Food.isFruit = function (food) {return food && food.isFruit ()};
Food.isGrain = function (food) {return food && food.isGrain ()};

IMPLEMENTATION INFO

this feature was introduced in this module

2.56. Uize.nop

A dummy function that performs no operation and returns no value (which is effectively the same as returning the value undefined).

SYNTAX

resultUNDEF = Uize.nop ();

The Uize.nop method is named after the NOP (No Operation Performed) assembly language instruction. This method can be provided as a callback to methods that require a callback function and may fail if one is not provided, but where you don't need anything to be executed in the callback. You could always provide your own empty anonymous function, but Uize.nop is provided for your convenience and it can be shared across all instances where an empty function needs to be provided.

EXAMPLE

serviceRequest ({
  serviceParams:{
    // service params here
  },
  callback:Uize.nop
});

NOTES

see the related Uize.returnFalse static method
see also the other dummy functions

IMPLEMENTATION INFO

this feature was introduced in this module

2.57. Uize.now

Returns an integer, representing the current time in milliseconds since 1970 (POSIX time).

SYNTAX

nowMsINT = Uize.now ();

The Uize.now method is optimized to use the Date.now static method that is supported by JavaScript's built-in Date object in newer versions of the language. If this method is not available, then the Uize.now method falls back to using the less performant +new Date approach, which involves construction of a Date object instance each time.

The Uize.now method can be useful when capturing start and end times in order to measure the duration of operations. Consider the following example...

EXAMPLE

var start = Uize.now ();

// ... ... ... ... ... ... ... ... ... ... ...
// do some stuff that may take a bunch of time
// ... ... ... ... ... ... ... ... ... ... ...

var duration = Uize.now () - start;

Using the above template, the value of the duration variable will indicate how long it took to perform the operations in the block between assigning the value for the start variable and the value for the duration variable.

IMPLEMENTATION INFO

this feature was introduced in this module

2.58. Uize.package

Lets you conveniently create a JavaScript package with a specified set of statics (static methods and/or static properties) in a single statement.

SYNTAX

packageFUNC = Uize.package (staticsOBJ);

The Uize.package method provides a more concise way of defining and returning a package function inside a module's builder function.

INSTEAD OF...

builder:function () {
  'use strict';

  var _package = function () {};

  _package.staticMethod1 = function () {
    // implementation
  };

  _package.staticMethod2 = function () {
    // implementation
  };

  return _package;
}

USE...

builder:function () {
  'use strict';

  return Uize.package ({
    staticMethod1:function () {
      // implementation
    },

    staticMethod2:function () {
      // implementation
    }
  });
}

For a more in-depth discussion of package modules, consult the JavaScript Modules guide.

NOTES

see also the other module mechanism methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.59. Uize.pairUp

Returns an object, that is the specified key and value, paired up together in the same object.

SYNTAX

keyValueOBJ = Uize.pairUp (keySTRorNUM,valueANYTYPE);

EXAMPLE

Uize.pairUp ('foo','bar');  // returns the object {foo:'bar'}
Uize.pairUp (0,'zero');     // returns the object {0:'zero'}
Uize.pairUp (1,true);       // returns the object {1:true}

VARIATION 1

keyValueOBJ = Uize.pairUp (
  key1STRorNUM,value1ANYTYPE,
  key2STRorNUM,value2ANYTYPE,
  ...,
  keyNSTRorNUM,valueNANYTYPE
);

When an arbitrary number of arguments are specified for the Uize.pairUp method, then the method will pair up all the arguments as key/value pairs to form a single object, where all the even index arguments are treated as the keys, and where all the odd index arguments are treated as the values. For example, the statement Uize.pairUp ('foo','bar','hello','world') would return the object {foo:'bar',hello:'world'}.

VARIATION 2

keyValueOBJ = Uize.pairUp (keyAndValuePairsARRAY);

When a keyAndValuePairsARRAY parameter is specified when calling the Uize.pairUp method, then the Uize.pairUp method operates on the array in the same way as it would an arbitrary number of arguments. For example, the statement Uize.pairUp (['foo','bar','hello','world']) would return the object {foo:'bar',hello:'world'}. Therefore, if you have an array that represents a set of key / value pairs, you can call the Uize.pairUp method to combine the keys and values together to form an object without having to resort to using the apply method in order to use the arbitrary arguments variation of the Uize.pairUp method.

INSTEAD OF...

Uize.pairUp.apply (0,myKeyValuePairsArray);

USE...

Uize.pairUp (myKeyValuePairsArray);

2.59.1. Why This Method is Useful

The Uize.pairUp method is particularly useful when an object needs to be created from a key/value pair, where the key name is either dynamically generated in an expression or is supplied via a parameter.

Using the Uize.pairUp method can collapse three statements into a single statement, as follows...

INSTEAD OF

var object = {};
object [key] = value;
doSomethingWithAnObject (object);

USE...

doSomethingWithAnObject (Uize.pairUp (key,value));

Let's consider a real world example...

EXAMPLE

function fadeNodeBorderColor (node,edge,startColor,endColor) {
  var styleProperty = 'border' + edge + 'Color';
  Uize.Fx.fadeStyle (
    node,
    Uize.pairUp (styleProperty,startColor),
    Uize.pairUp (styleProperty,endColor),
    1000
  );
}

In the above example, a function is being defined that will fade the border color of the specified edge of the specified node, from the specified start color to the specified end color. The value of the edge property needs to determine which style property needs to be faded.

Now, we're using the Uize.Fx.fadeStyle static method of the Uize.Fx module to perform the border color animation. This method can fade values for one or more style properties, and the start and end values for the style properties are specified in style property objects. Here we need to create start and end style objects where the style property to be faded is dynamically generated using the edge parameter. As you will see from the code, the Uize.pairUp method does this for us nicely.

NOTES

see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.60. Uize.push

Pushes / appends the elements from the specified source list onto the end of the specified target list, and returns the target list as the result.

SYNTAX

targetListARRAYorOBJ = Uize.push (targetListARRAYorOBJ,sourceListARRAYorOBJ);

While the elements from a source list object can be appended at the end of a target array with an expression like targetArray.push.apply (targetArray,sourceList), appending the elements from a source list object at the end of a target list object is even a little more cumbersome with ugly expressions like Array.prototype.push.apply (targetList,sourceList) or [].push.apply (targetList,sourceList) (if you're OK with creating an empty array for immediate garbage collection).

Expressions like this are hard to remember when you need to conjure them up, and they're equally unpleasant to make sense of when you see them in your code. The Uize.push method provides a more semantically elegant way to push the elements of a source list onto the end of a target list, allowing both the source and target to be list objects like array instances, arguments objects, or any object with a length property whose value is a number - basically, any value that would produce the result true when passed to the Uize.isList static method.

EXAMPLE 1

Uize.push (allOfTheNodes,document.getElementsByTagName ('div'));

In the above example, the elements from the HTMLCollection object returned by the document.getElementById method are being pushed onto the end of the allOfTheNodes array.

EXAMPLE 2

var
  registeredFruits = [],
  fruitRegistered = {}
;

function registerFruits () {
  Uize.push (registeredFruits,arguments);
  Uize.lookup (arguments,1,fruitRegistered);
}

registerFruits ('apple','pear','peach');
registerFruits ('banana','orange','mango');

alert (registeredFruits);       // alerts "apple,pear,peach,banana,orange,mango"
alert (fruitRegistered.apple);  // alerts "1"
alert (fruitRegistered.mango);  // alerts "1"

In the above example, the registerFruits variadic function allows any number of fruits to be registered by specifying the names of the fruits using an arbitrarily long arguments list. The function uses the Uize.push method to push the contents of the arguments list object onto the end of the registeredFruits array. It also uses the Uize.lookup method to add entries for the fruits being added to the fruitRegistered lookup object, by specifying the fruitRegistered object as the target for the lookup creation operation.

NOTES

see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.61. Uize.quarantine

Returns a function, being a quarantined version of the supplied function.

SYNTAX

quarantinedFunctionFUNC = Uize.quarantine (sourceFunctionFUNC);

For a detail discussion on this method and to see examples, consult the section Quarantined Nested Functions. For a more general discussion on quarantining, consult the section Quarantined Code Execution.

NOTES

compare to the related Uize.eval and Uize.laxEval static methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.62. Uize.recordMatches

Returns a boolean, indicating whether or not the specified record's contents is a superset of the contents of the specified match object.

SYNTAX

isMatchBOOL = Uize.recordMatches (recordOBJ,matchOBJ);

EXAMPLE

Uize.recordMatches (
  {
    firstName:'Jack',
    lastName:'Lerchner',
    department:'engineering',
    jobTitle:'UI Engineer',
    status:'contract'
  }
  {jobTitle:'UI Engineer',status:'fulltime'}
);

In the above example, the expression would produce the result false, because the value of the status property in the matchOBJ parameter does not match the value for that property in the recordOBJ parameter.

NOTES

this method uses strict matching, so the statement Uize.recordMatches ({index:'1'},{index:1}) will return false
see also the related Uize.findRecord and Uize.findRecordNo static methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.63. Uize.require

Ensures that all of the specified modules are loaded before calling the specified callback function, loading required modules as necessary.

The Uize.require method can be used to load required modules, as necessary, before executing code that depends on those modules being loaded.

DIFFERENT USAGES

Require a Single Module

Uize.require (moduleNameSTR,callbackFUNC);

Require Multiple Modules

Uize.require (moduleNamesARRAY,callbackFUNC);

Require Modules With No Callback

Uize.require (moduleNameSTRorModuleNamesARRAY);

2.63.1. Require a Single Module

In the most basic usage, a single module can be required by specifying the name of the module as a string for the moduleNameSTR parameter.

SYNTAX

Uize.require (moduleNameSTR,callbackFUNC);

EXAMPLE 1

Uize.require (
  'Uize.Widget.Bar.Slider',
  function (Slider) {
    var mySlider = Slider ({
      minValue:-50,
      maxValue:50,
      value:0
    });
  }
);

In the above example, the Uize.Widget.Bar.Slider widget class module is being required. Once the Uize.Widget.Bar.Slider module is loaded, the Uize.require method will call the callback specified by the callbackFUNC parameter, passing a reference to Uize.Widget.Bar.Slider module as the callback function's first argument. In this example, we have named the argument Slider. You can name this argument anything you like, as long as it's a valid JavaScript identifier. If we wanted to reinforce that this argument is a reference to the Uize.Widget.Bar.Slider module, we could name the argument something like Uize_Widget_Bar_Slider or UizeWidgetBarSlider (depending on whether or not we like using underscores in variable names).

EXAMPLE 2

Uize.require (
  'Uize.Widget.Bar.Slider',
  function () {
    var mySlider = Uize.Widget.Bar.Slider ({
      minValue:-50,
      maxValue:50,
      value:0
    });
  }
);

In the above example, we are also requiring the Uize.Widget.Bar.Slider module. In this case, however, instead of using the reference to the module that would be passed to the callback function, we are simply ignoring this argument and referencing the Uize.Widget.Bar.Slider module by its name in the global scope. This is also supported.

2.63.2. Require Multiple Modules

In cases where you need to require more than one module, a list of module names can be specified as a string array for the moduleNamesARRAY parameter.

SYNTAX

Uize.require (moduleNamesARRAY,callbackFUNC);

EXAMPLE

Uize.require (
  [
    'Uize.Widget.Bar.Slider',
    'Uize.Data.Csv',
    'Uize.Color'
  ],
  function (
    Uize_Widget_Bar_Slider,
    Uize_Data_Csv,
    Uize_Color
  ) {
    // reference the Uize.Widget.Bar.Slider module by Uize_Widget_Bar_Slider
    // reference the Uize.Data.Csv module by Uize_Data_Csv
    // reference the Uize.Color module by Uize_Color
  }
);

In the above example, the three modules Uize.Widget.Bar.Slider, Uize.Data.Csv, and Uize.Color are being required. Once all of these modules are loaded, references to the modules are passed as arguments to the callback function, in the order in which the modules are specified in the moduleNamesARRAY parameter. The arguments can be named anything you like, but it helps to name them so as to clearly indicate the modules to which they are references. As with the using the Uize.require method to require a single module, the module references that would be passed as arguments to the callback function can simply be ignored in favor of referencing the modules using their names in the global scope.

2.63.3. Require Modules With No Callback

In an uncommon usage, one or more modules can be required without specifying any callback function to be called once the modules are loaded.

SYNTAX

Uize.require (moduleNameSTRorModuleNamesARRAY);

With this usage, the Uize.require method can be used simply to initiate loading of modules.

EXAMPLE

Uize.require ([
  'Uize.Widget.Bar.Slider',
  'Uize.Data.Csv',
  'Uize.Color'
]);

In the above example, the three modules Uize.Widget.Bar.Slider, Uize.Data.Csv, and Uize.Color are being required without specifying any code that should be executed once the modules are loaded.

2.63.4. The callbackFUNC Parameter

The callbackFUNC parameter of the Uize.require method lets you specify a callback function that should be executed once all the required modules are loaded.

When the Uize.require method calls the specified callback function, it passes references to the required modules as arguments, in the order in which the modules are specified in the first parameter of the Uize.require method. Consider the following example...

EXAMPLE

Uize.require (
  [
    'MyNamespace.MyModule1',
    'MyNamespace.MyModule2'
  ],
  function (
    MyNamespace_MyModule1,
    MyNamespace_MyModule2
  ) {
    // reference the MyNamespace.MyModule1 module by MyNamespace_MyModule1
    // reference the MyNamespace.MyModule2 module by MyNamespace_MyModule2
  }
);

In the above example, the modules MyNamespace.MyModule1 and MyNamespace.MyModule2 are being required. Once these modules are loaded, references to the modules are passed as arguments to the callback function. The arguments can be named anything you like, but it helps to name them so as to clearly indicate the modules to which they are references. Here, for example, we have chosen to name the first argument MyNamespace_MyModule1, since it will be a reference to the MyNamespace.MyModule1 module.

2.63.5. Requiring Nothing

In cases where one specifies an empty array for the moduleNamesARRAY parameter, the callback function specified by the callbackFUNC parameter will be executed immediately, and the callback will receive no arguments.

EXAMPLE

Uize.require (
  [],
  function () {
    // code here is executed immediately, because no modules need to be loaded
  }
);

One would not deliberately write code as shown in the above example, but situations like this may arise where a list of modules that is to be required is being determined programmatically, and where in some situations a programmatically determined list may be empty. Rather than having to implement a check for such cases along with appropriate protection / conditional branching, the Uize.require method does the logical thing and calls the specified callback function immediately, since all requirements (none, in this case) are already satisfied. An empty list indicates that the callback code is not contingent upon anything, so it is executed straight away.

2.63.6. Equivalent to Anonymous Modules

While more concise and convenient, the Uize.require method is roughly equivalent to using anonymous modules.

INSTEAD OF...

Uize.module ({
  required:[
    'MyNamespace.MyModule1',
    'MyNamespace.MyModule2'
  ],
  builder:function () {
    // code here can rely on MyNamespace.MyModule1 and MyNamespace.MyModule2 being loaded
  }
});

USE...

Uize.require (
  [
    'MyNamespace.MyModule1',
    'MyNamespace.MyModule2'
  ],
  function () {
    // code here can rely on MyNamespace.MyModule1 and MyNamespace.MyModule2 being loaded
  }
);

In addition to being a little bit cleaner and more concise, as well as a bit more semantically elegant, the Uize.require method also supports passing references to required modules in the callbackFUNC parameter.

For an in-depth discussion of modules, consult the guide JavaScript Modules.

NOTES

see also the other module mechanism methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.64. Uize.resolveMatcher

Resolves the specified matcher to a function that can be passed two arguments, value and key, and that returns a value derived from one or both of those inputs.

SYNTAX

matcherFUNC = Uize.resolveMatcher (matcherANYTYPE);

The Uize.resolveMatcher method is intended to be used in the implementation of other methods that want to allow a matcher to be specified in several different forms (such as an expression string, for example), but always want to use the matcher as a function. Examples of such methods include the various methods of the Uize.Data.Matches module, such as the Uize.Data.Matches.remove method whose second argument is a matcher. The Uize.resolveMatcher method allows such methods to be versatile in how they let matchers be specified.

EXAMPLE

function findMatches (array,matcher) {
  matcher = Uize.resolveMatcher (matcher);
  var matches = [];
  for (var elementNo = -1; ++elementNo < array.length;) {
    var elementValue = array [elementNo];
    if (matcher (elementValue)) {
      matches.push (elementValue);
    }
  }
  return matches;
}

In the above example, we are implementing a simple function to find the elements in an array that match a specified matcher and return those matches in a new array. The second argument of the function is a matcher. To allow users of the function to specify a matcher using an expression string short form, we resolve the value of the matcher argument using the Uize.resolveMatcher method and re-assign the resolved value to the matcher argument. Once resolved, we can now count on the matcher being a function and we can call it in the loop that iterates over the source array. Now a caller can call this function with statements like...

findMatches (possibleNumbers,'typeof value == "number"');
findMatches (possibleIdentifiers,/^[_\$a-zA-Z][_\$a-zA-Z0-9]*$/);

2.64.1. How Different Matcher Types are Resolved

The Uize.resolveMatcher method supports numerous different ways of specifying a matcher.

2.64.1.1. When a Function Type Matcher is Specified

When a function is specified for the matcherANYTYPE parameter, that function is simply returned.

The Uize.resolveMatcher method is used to resolve a value that could be one of several different types to something that's guaranteed to be a function. In the case where the matcher is already a function, it is considered to already be resolved and is returned as is.

2.64.1.2. When a String Type Matcher is Specified

When a string value is specified for the matcherANYTYPE parameter, a function is produced using the specified string matcher expression as the function's body, and accepting the two arguments value and key.

For example, the matcher expression string 'typeof value == "number"' would be resolved to the function function (value,key) {return typeof value == 'number'}. In another example, the matcher expression string '/name/i.test (key) && /^c/i.test (value)' would be resolved to the function function (value,key) {return /name/i.test (key) && /^c/i.test (value)}.

The Uize.resolveMatcher method imposes the argument names value and key for the two arguments of the function that it produces from a matcher exprression string, so such an expression must use these reserved variable names to access the value and optional key that will be passed in by the caller of the resolved matcher.

2.64.1.3. When a Regular Expression Matcher is Specified

When a regular expression is specified for the matcherANYTYPE parameter, a function is produced using the regular expression to test the value of its first argument for a match, returning a boolean value.

EXAMPLE

var isValidIdentifier = Uize.resolveMatcher (/^[_\$a-zA-Z][_\$a-zA-Z0-9]*$/);

alert (isValidIdentifier (''));         // alerts "false"
alert (isValidIdentifier ('fooVar'));   // alerts "true"
alert (isValidIdentifier ('$foo'));     // alerts "true"
alert (isValidIdentifier ('3rdVar'));   // alerts "false"
alert (isValidIdentifier ('_4thVar'));  // alerts "true"

2.64.1.4. When a Nully Matcher is Specified

When a nully value (ie. the value null or undefined) is specified for the matcherANYTYPE parameter, a function is produced that always returns the value true.

This behavior is useful for methods that want to offer an optional matcher and wish no filtering (ie. always matching) to be performed when the optional argument is not specified, or if the values null or undefined are explicitly specified.

2.64.1.5. When a Boolean Type Matcher is Specified

When a boolean value is specified for the matcherANYTYPE parameter, a function is produced that simply returns that boolean value, regardless of the argument values.

This behavior can be useful in situations where you wish to force the matching result to be always true or false. In such cases, specifying simply a boolean value for the matcher is a convenient shorthand.

NOTES

see also the related Uize.resolveTransformer static method

IMPLEMENTATION INFO

this feature was introduced in this module

2.65. Uize.resolveModuleDefinition

Resolves the specified module definition object by defaulting its properties and expanding them as necessary, returning the resolved definition object.

SYNTAX

moduleDefinitionOBJ = Uize.resolveModuleDefinition (moduleDefinitionOBJ);

The Uize.resolveModuleDefinition method is not intended for use in general application development but is intended for specialized build processes, such as dependency tracing performed during the creation of JavaScript packages.

For an in-depth discussion of modules, consult the guide JavaScript Modules.

NOTES

see also the other module mechanism methods

IMPLEMENTATION INFO

this feature was introduced in this module

2.66. Uize.resolveTransformer

Resolves the specified transformer to a function that can be passed two arguments, value and key, and that returns a value derived from one or both of those inputs.

SYNTAX

transformerFUNC = Uize.resolveTransformer (transformerANYTYPE);

The Uize.resolveTransformer method is intended to be used in the implementation of other methods that want to allow a transformer to be specified in several different forms (such as an expression string, for example), but always want to use the transformer as a function. An example of one such method is the Uize.map method, whose second argument is a mapper transformer. The Uize.resolveTransformer method allows such methods to be versatile in how they let transformers be specified.

EXAMPLE

function simpleArrayMap (array,mapper) {
  mapper = Uize.resolveTransformer (mapper);
  var result = [];
  for (var elementNo = array.length; --elementNo >= 0;) {
    result [elementNo] = mapper (array [elementNo]);
  }
  return result;
}

In the above example, we are implementing a simple array mapper function. The second argument of the function is a mapper. To allow users of the function to specify a mapper using an expression string short form, we resolve the value of the mapper argument using the Uize.resolveTransformer method and re-assign the resolved value to the mapper argument. Once resolved, we can now count on the mapper being a function and we can call it in the loop that processes the source array. Now a caller can call this function with a statement like simpleArrayMap (fruits,'value.toLowerCase ()').

2.66.1. How Different Transformer Types are Resolved

The Uize.resolveTransformer method supports numerous different ways of specifying a transformer.

2.66.1.1. When a Function Type Transformer is Specified

When a function is specified for the transformerANYTYPE parameter, that function is simply returned.

The Uize.resolveTransformer method is used to resolve a value that could be one of several different types to something that's guaranteed to be a function. In the case where the transformer is already a function, it is considered to already be resolved and is returned as is.

2.66.1.2. When a String Type Transformer is Specified

When a string value is specified for the transformerANYTYPE parameter, a function is produced using the specified string transformer expression as the function's body, and accepting the two arguments value and key.

For example, the transformer expression string 'key + ": " + value' would be resolved to the function function (value,key) {return key + ': ' + value}. In another example, the transformer expression string 'value * value' would be resolved to the function function (value,key) {return value * value}.

The Uize.resolveTransformer method imposes the argument names value and key for the two arguments of the function that it produces from a transformer exprression string, so such an expression must use these reserved variable names to access the value and optional key that will be passed in by the caller of the resolved transformer.

EXAMPLE

var squared = Uize.resolveTransformer ('value * value');

alert (squared (3));  // alerts the text "9"

2.66.1.3. When a Regular Expression Transformer is Specified

When a regular expression is specified for the transformerANYTYPE parameter, a function is produced using the regular expression to test the value of its first argument for a match, returning a boolean value.

Because regular expression transformers are resolved to functions that always return true or false values, they are most suited to and most commonly used as value matchers.

EXAMPLE

var isValidIdentifier = Uize.resolveTransformer (/^[_\$a-zA-Z][_\$a-zA-Z0-9]*$/);

alert (isValidIdentifier (''));         // alerts "false"
alert (isValidIdentifier ('fooVar'));   // alerts "true"
alert (isValidIdentifier ('$foo'));     // alerts "true"
alert (isValidIdentifier ('3rdVar'));   // alerts "false"
alert (isValidIdentifier ('_4thVar'));  // alerts "true"

2.66.1.4. When an Array Type Transformer is Specified

.

2.66.1.5. When an Object Type Transformer is Specified

When an object is specified for the transformerANYTYPE parameter, a function is produced using the object as a lookup for remapping the input value, but leaving the input value unchanged if it is not found in the lookup.

EXAMPLE

var whatFoodType = Uize.resolveTransformer ({
  apple:'fruit',
  banana:'fruit',
  beet:'vegetable',
  corn:'grain',
  onion:'vegetable',
  rice:'grain'
});

alert (whatFoodType ('apple'));   // alerts "fruit"
alert (whatFoodType ('onion'));   // alerts "vegetable"
alert (whatFoodType ('rice'));    // alerts "grain"
alert (whatFoodType ('burger'));  // alerts "burger"

2.66.1.6. When a Nully Transformer is Specified

When a nully value (ie. the value null or undefined) is specified for the transformerANYTYPE parameter, a function is produced that simply returns the value of its first argument unmodified.

This behavior is useful for methods that want to offer an optional transformer and wish no transformation to be performed when the optional argument is not specified, or if the values null or undefined are explicitly specified.

2.66.1.7. When a Boolean Type Transformer is Specified

When a boolean value is specified for the transformerANYTYPE parameter, a function is produced that simply returns that boolean value, regardless of the input value.

This behavior is most suited to methods that resolve matchers, and the Uize.resolveMatcher method takes advantage of this behavior because it uses the Uize.resolveTransformer method in its implementation. In cases where a transformer is serving the purpose of a matcher, the values true or false can be provided to defeat the effect of the matcher to either match all elements or no elements.

2.66.1.8. When a Number Type Transformer is Specified

When a number value is specified for the transformerANYTYPE parameter, a function is produced that simply returns that number value, regardless of the input value.

NOTES

see also the related Uize.resolveMatcher static method

IMPLEMENTATION INFO

this feature was introduced in this module

2.67. Uize.returnFalse

A dummy function that always returns the boolean value false, and that can be useful as an event handler or in other situations.

SYNTAX

falseBOOL = Uize.returnFalse ();

This method can be assigned to event handlers to cancel their default action, as in the following example...

EXAMPLE

myNode.onclick = Uize.returnFalse;

If we wish to cancel the default action for many nodes in a page, then using this static method allows us to share a single function - by reference - across all these nodes.

NOTES

see the companion Uize.returnTrue static method
see the related Uize.nop static method
see also the other dummy functions

IMPLEMENTATION INFO

this feature was introduced in this module

2.68. Uize.returnTrue

A dummy function that always returns the boolean value true, and that can be useful as an event handler or in other situations.

SYNTAX

trueBOOL = Uize.returnTrue ();

This method can be assigned to event handlers to enable their default action, as in the following example...

EXAMPLE

myNode.onclick = Uize.returnTrue;

If we wish to enable the default action for many nodes in a page, then using this static method allows us to share a single function - by reference - across all these nodes.

NOTES

see the companion Uize.returnFalse static method
see also the other dummy functions

IMPLEMENTATION INFO

this feature was introduced in this module

2.69. Uize.returnX

A dummy function that accepts a single argument x and returns the value of that argument unchanged.

SYNTAX

xANYTYPE = Uize.returnX (xANYTYPE);

NOTES

see also the other dummy functions

IMPLEMENTATION INFO

this feature was introduced in this module

2.70. Uize.reverseLookup

Returns a reverse lookup object, where each key is a value from the specified source object, and where the value for each key is the associated key from the specified source.

DIFFERENT USAGES

Create a Reverse Lookup From an Object

reverseLookupOBJ = Uize.reverseLookup (hashOBJ);

Create a Reverse Lookup From a Values Array

reverseLookupOBJ = Uize.reverseLookup (valuesARRAY);

Create a Safe Reverse Lookup Object

reverseLookupOBJ = Uize.reverseLookup (hashOBJorValuesARRAY,safeBOOL);

Add More Entries to a Reverse Lookup Object

targetOBJ = Uize.reverseLookup (hashOBJorValuesARRAY,targetOBJ);

Create a Bi-directional Lookup

reverseLookupOBJ = Uize.reverseLookup (lookupOBJ,lookupOBJ);

2.70.1. Create a Reverse Lookup From an Object

In the most typical usage of the Uize.reverseLookup method, a reverse lookup object can be created from an object.

SYNTAX

reverseLookupOBJ = Uize.reverseLookup (hashOBJ);

EXAMPLE

var
  entitiesNamesToCodes = {quot:34,amp:38,lt:60,gt:62,nbsp:160,copy:169,reg:174},
  entitiesCodesToNames = Uize.reverseLookup (entitiesNamesToCodes)
;

After the above code is executed, the value of the entitiesCodesToNames variable will be an object with the contents...

{34:'quot',38:'amp',60:'lt',62:'gt',160:'nbsp',169:'copy',174:'reg'}

By creating a reverse lookup, this code can lookup up an entity's character code from its name, or its name from its character code.

2.70.2. Create a Reverse Lookup From a Values Array

The Uize.reverseLookup method can also be used to create a reverse lookup object for an array.

SYNTAX

reverseLookupOBJ = Uize.reverseLookup (valuesARRAY);

When a valuesARRAY parameter is specified in place of the hashOBJ parameter, a reverse lookup object is generated where each of the values in the array is a key in the object, and the value corresponding to each key is the index of the value in the array.

EXAMPLE

var
  frontRunnerLineup = [
    'John Backsberg',
    'Adrian Gullipeg',
    'Sasha Djenduriba',
    'Clark Holstrom',
    'Michael Anderson',
    'Henry Pratt',
    'Jacob Zimbalist',
    'Steven P. McLoughlan',
    'Chris Gates',
    'Richard Crumb'
  ],
  frontRunnerLineupReverseLookup = Uize.reverseLookup (frontRunnerLineup)
;

After the above code is executed, the value of the frontRunnerLineupReverseLookup variable will be an object with the contents...

{
  'John Backsberg':0,
  'Adrian Gullipeg':1,
  'Sasha Djenduriba':2,
  'Clark Holstrom':3,
  'Michael Anderson':4,
  'Henry Pratt':5,
  'Jacob Zimbalist':6,
  'Steven P. McLoughlan':7,
  'Chris Gates':8,
  'Richard Crumb':9
}

Now the code can look up a front-runner from the front-runner lineup using an index, or the code can determine if a particular person is in the front-runner lineup and what their finishing place is using the generated reverse lookup.

2.70.3. Create a Safe Reverse Lookup Object

By specifying the value true for the optional safeBOOL parameter, a "safe" lookup object can be created.

SYNTAX

reverseLookupOBJ = Uize.reverseLookup (hashOBJorValuesARRAY,safeBOOL);

By default, the Uize.reverseLookup method creates a lookup object using a simple JavaScript Object instance. However, JavaScript's built-in Object object defines certain properties on its prototype, such as valueOf, so indexing into a lookup object for valueOf will return a truthy result. Specifying the value true for the safeBOOL parameter avoids this issue.

EXAMPLE

var
  entitiesNamesToCodes = {quot:34,amp:38,lt:60,gt:62,nbsp:160,copy:169,reg:174},
  entitiesCodesToNames = Uize.reverseLookup (entitiesNamesToCodes),
  entitiesCodesToNamesSafe = Uize.reverseLookup (entitiesNamesToCodes,true)
;

if (entitiesCodesToNames ['valueOf']) {
  alert ('valueOf appears to be an HTML entity char code');
}

if (entitiesCodesToNamesSafe ['valueOf']) {
  alert ('you will not see this alert statement');
}

In the above example, the entitiesCodesToNames reverse lookup is not safe, so looking up the entity name using the bogus entity code "valueOf" will produce a function result - the valueOf Intrinsic Method for JavaScript's built-in Object object. In contrast, the entitiesCodesToNamesSafe reverse lookup is created with the safe option, so looking up "valueOf" will produce the result undefined.

It is often not essential to create safe lookups, since one may know that the keys being used to index into a lookup object will never be the names of methods of the Object object, and not creating safe lookups is a little more efficient.

2.70.4. Add More Entries to a Reverse Lookup Object

By specifying an existing reverse lookup object for the optional targetOBJ second parameter, more entries can be added to the existing reverse lookup.

SYNTAX

targetOBJ = Uize.reverseLookup (hashOBJorValuesARRAY,targetOBJ);

EXAMPLE

var entitiesCodesToNames = Uize.reverseLookup ({quot:34,amp:38,lt:60,gt:62});
Uize.reverseLookup ({nbsp:160,copy:169,reg:174},entitiesCodesToNames);

alert (entitiesCodesToNames [38]);   // alerts "amp"
alert (entitiesCodesToNames [169]);  // alerts "copy"

In the above example, the second call to the Uize.reverseLookup method is adding more entries to the reverse lookup object that was created in the first call to the method. This is done by supplying that reverse lookup object, which is assigned to the entitiesCodesToNames variable, as the second argument. When calling the Uize.reverseLookup method the second time, the result is ignored. This is because the method modifies the target, so we don't care about its return value.

2.70.5. Create a Bi-directional Lookup

By specifying the source hash object as also the target for the reverse lookup creation, a bi-directional lookup object can be created.

SYNTAX

reverseLookupOBJ = Uize.reverseLookup (lookupOBJ,lookupOBJ);

EXAMPLE

var entitiesBiDiLookup = {quot:34, amp:38, lt:60, gt:62, nbsp:160, copy:169, reg:174};
Uize.reverseLookup (entitiesBiDiLookup,entitiesBiDiLookup);

alert (entitiesBiDiLookup ['amp']);  // alerts "38"
alert (entitiesBiDiLookup [38]);     // alerts "amp"

2.70.5.1. Key / Value Collisions

When creating bi-directional lookup objects, be sure that there are no collisions between keys and values, or your bi-directional lookup will not work correctly.

EXAMPLE

var foodsLookup = {apple:'fruit',banana:'fruit',corn:'grain',rice:'grain'};
Uize.reverseLookup (foodsLookup,foodsLookup);

alert (foodsLookup ['apple']);  // alerts "fuit"
alert (foodsLookup ['grain']);  // alerts "rice"

In the above example, creating a bi-directional lookup object from the foodsLookup object is not particularly useful, because multiple properties of the source object share the same value. So, when you do a lookup for 'grain' you get only the value 'rice', even though there's more than one grain in the source lookup object.

NOTES

see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.71. Uize.since

Returns an integer, representing the amount of time (in milliseconds) that has elapsed since the specified date.

SYNTAX

elapsedMsINT = Uize.since (dateOBJorINT);

The value provided for the dateOBJorINT parameter can be either a reference to an instance of JavaScript's built-in Date object, or an integer representing milliseconds since 1970 (POSIX time). The Uize.since method provides a semantically elegant way of dealing with the timing of processes in JavaScript and is provided merely as syntactic sugar.

INSTEAD OF...

var start = Uize.now ();

// ... ... ... ... ... ... ... ... ... ... ...
// do some stuff that may take a bunch of time
// ... ... ... ... ... ... ... ... ... ... ...

var duration = Uize.now () - start;

USE...

var start = Uize.now ();

// ... ... ... ... ... ... ... ... ... ... ...
// do some stuff that may take a bunch of time
// ... ... ... ... ... ... ... ... ... ... ...

var duration = Uize.since (start);

NOTES

see the companion Uize.now static method

IMPLEMENTATION INFO

this feature was introduced in this module

2.72. Uize.substituteInto

Lets you substitute one or more specified substitution values into a specified source string.

SYNTAX

resultSTR = Uize.substituteInto (
  sourceANYTYPE,         // a string, or other type that will be coerced to a string
  substitutionsANYTYPE,  // an object, array, or simple type substitution value
  tokenNamingSTR         // optional, specifies a custom token naming scheme
);

2.72.1. Parameters

2.72.1.1. sourceANYTYPE

The value of the sourceANYTYPE parameter should be a string containing substitution tokens that the substitution values specified in the substitutionsOBJorARRAY parameter will be substituted into.

If the value of the sourceANYTYPE parameter is not a string, then it will be coerced to a string by invoking the value type's valueOf Intrinsic Method. For each of the values to substitute, the sourceANYTYPE string should contain a token of the form [#propertyName] (unless a custom token naming scheme is specified using the optional tokenNamingSTR parameter). Each substitution token for a substitution will be replaced with the substitution value.

2.72.1.2. substitutionsANYTYPE

An object, array, or simple type value, specifying one or more substitution values that should be substituted into the source string specified by the sourceANYTYPE parameter.

object - When the value of the substitutionsANYTYPE parameter is an object, then each property of the object will be a substitution, where a property's value is the substition value, and where a property's name is a key that will be used in forming the substitution's token name.
array - When the value of the substitutionsANYTYPE parameter is an array, then each element of the aray will be a substitution, where an element's value is the substition value, and where an element's index is a key that will be used in forming the substitution's token name.
simple type - When the value of the substitutionsANYTYPE parameter is a simple type value (string, boolean, or number), then a substitutions array is formed using that simple type substitution as its single element.

EXAMPLES

Uize.substituteInto ('My name is [#name]',{name:'Eric'});
Uize.substituteInto ('My name is [#0]',['Eric']);
Uize.substituteInto ('My name is [#0]','Eric');

All of the above statements would produce the result 'My name is Eric'.

2.72.1.3. tokenNamingSTR

The optional tokenNamingSTR parameter allows a custom token naming scheme to be specified, rather than the default [#KEY] format.

This facility provides a lot of flexibility in how tokens are formatted inside localized strings. The value specified for the tokenNamingSTR parameter should be a string containing the text 'KEY' somewhere inside it, where that segment will be replaced with the name for a given key. So, for example, a value of '[KEY]' for the tokenNamingSTR parameter would produce the token name '[firstName]' for the substitution key 'firstName'.

EXAMPLES

Uize.substituteInto ('My name is [#name]',{name:'Eric'});
Uize.substituteInto ('My name is [#name]',{name:'Eric'},'[#KEY]');
Uize.substituteInto ('My name is [name]',{name:'Eric'},'[KEY]');
Uize.substituteInto ('My name is {name}',{name:'Eric'},'{KEY}');
Uize.substituteInto ('My name is <%name%>',{name:'Eric'},'<%KEY%>');
Uize.substituteInto ('My name is ##name##',{name:'Eric'},'##KEY##');
Uize.substituteInto ('My name is [[name]]',{name:'Eric'},'[[KEY]]');

All of the above statements would produce the result 'My name is Eric'.

VARIATION

resultSTR = Uize.substituteInto (sourceANYTYPE,substitutionsOBJorARRAY);

When the optional tokenNamingSTR parameter is omitted, then its value will be defaulted to '[#KEY]'.

2.72.2. Examples

2.72.2.1. Example: Two Substitutions

In the example below, two substitutions are being performed.

EXAMPLE

Uize.substituteInto (
  ''My name is [#name], and I am a [#occupation].',
  {name:'Eric',occupation:'viking'}
);

RESULT

'My name is Eric, and I am a viking.'

2.72.2.2. Example: One Substitution, Used Multiple Times

If there are multiple tokens for the same substitution value, then that value will be substituted multiple times.

EXAMPLE

Uize.substituteInto (
  'An [#fruit]. Oh, an [#fruit]!! Please, give me an [#fruit].',
  {fruit:'apple'}
);

RESULT

'An apple. Oh, an apple!! Please, give me an apple.'

2.72.2.3. Example: No Token for a Substitution Value

If there are no substitution tokens for a substitution value, then that value will not be substituted.

EXAMPLE

Uize.substituteInto (
  'An orange. Oh, an orange!! Please, give me an orange.',
  {fruit:'apple'}
);

RESULT

'An orange. Oh, an orange!! Please, give me an orange.'

2.72.2.4. Example: Tokens With No Substitution Value

Substitution tokens for which there are no properties will be left in the string (they will not be blanked out).

EXAMPLE

Uize.substituteInto (
  'An [#fruit]. Oh, an [#fruit]!! Please, give me an [#fruit].',
  {vegetable:'artichoke'}
);

RESULT

'An [#fruit]. Oh, an [#fruit]!! Please, give me an [#fruit].'

2.72.2.5. Example: Custom Token Naming

The optional tokenNamingSTR parameter allows a custom token naming format to be specified.

EXAMPLE

Uize.substituteInto (
  'Welcome, {firstName} of {state}, {country}',
  {firstName:'Chris',state:'California',country:'USA'},
  '{KEY}'
);

RESULT

'Welcome, Chris of California, USA'

In the above example, the value '{KEY}' is being specified for the Uize.substituteInto method's optional tokenNamingSTR parameter. This means that the key for each substitution will be enclosed with curly braces to form its token name.

2.72.2.6. Example: Bare Tokens

The optional tokenNamingSTR parameter can be used to specify a "bare token" format for token naming, where the substitution tokens are the substitution keys.

EXAMPLE

Uize.substituteInto (
  'Welcome, firstName of state, country',
  {firstName:'Chris',state:'California',country:'USA'},
  'KEY'
);

RESULT

'Welcome, Chris of California, USA'

2.72.2.7. Example: Mixed Type Substitution Values

Substitution values can be of any type, and any value that is not a string will be coerced to a string.

EXAMPLE

Uize.substituteInto (
  '[#month]/[#date]/[#year] FLIGHTS: [#flights]',
  {
    month:9,
    date:11,
    year:Uize.Class ({value:2001}),
    flights:['AA11','UA175','AA77','UA93']
  }
);

RESULT

'9/11/2001 FLIGHTS: AA11,UA175,AA77,UA93'

2.72.2.8. Example: Specifying Substitutions Using an Array

When substitutions are specified using an array, then each substitution's index in the substitutions array is used as the key when forming its token name.

EXAMPLE

Uize.substituteInto ('Welcome, [#0] of [#1], [#2]',['Chris','California','USA']);

RESULT

'Welcome, Chris of California, USA'

2.72.2.9. Example: Substitution Values Containing Tokens

Substitution values that contain tokens are not further substituted into.

EXAMPLE

Uize.substituteInto ('[#token1][#token2]',{token1:'[#token2]foo',token2:'bar'});

RESULT

'[#token2]foobar'

In the above example, the value for the token1 substitution is '[#token2]foo', which contains a token for the token2 substitution. But, the values of substitutions are not further substituted into - for good reason, since this could result in some odd and unexpected behaviors in some cases.

2.72.2.10. Example: Tokens and Substitutions are Case-sensitive

Substitution tokens are case-sensitive.

EXAMPLE

Uize.substituteInto (
  'This is a case of comparing [#fruit] to [#FRUIT].',
  {fruit:'apples',FRUIT:'oranges'}
);

RESULT

'This is a case of comparing apples to oranges.'

In the above example, the token [#fruit] is distinct from the token [#FRUIT]. Our substitution values object in this case has a value for both the fruit and FRUIT properties, so the method call returns the value 'This is a case of comparing apples to oranges.'.

2.72.2.11. Example: Tokens and Substitutions are Space-sensitive

Substitution tokens are space-sensitive.

EXAMPLE

Uize.substituteInto (
  'This is a case of comparing [#fruit] to [# fruit ].',
  {fruit:'apples',' fruit ':'oranges'}
);

RESULT

'This is a case of comparing apples to oranges.'

In the above example, the token [#fruit] is distinct from the token [# fruit ]. Our substitution values object in this case has a value for both the fruit and ' fruit ' properties, so the method call returns the value 'This is a case of comparing apples to oranges.'.

2.72.2.12. Example: A Single Simply Type Substitution

When a simple type value (string, number, or boolean) is specified in place of a substitutions object or array, then a substitutions array is formed using that simple type substitution as its single element.

EXAMPLE

Uize.substituteInto ('My name is [#0].','Eric');

RESULT

'My name is Eric.'

2.72.2.13. Example: Source is Not a String

When the source value to substitute into is not a string (eg. an object, array, number, boolean, etc.), then this value will be coerced to a string.

EXAMPLE

Uize.substituteInto (Uize.Class ({value:'My name is [#name].'}),{name:'Eric'});

RESULT

'My name is Eric.'

In the above example, the value to substitute into is an instance of a Uize.Class subclass. Fortunately, the Uize.Class base class implements a valueOf Intrinsic Method that returns the value of the value state property. Therefore, coercing the source to a string produces the value 'My name is [#name].', which is then substituted into without any trouble.

NOTES

token names are case-sensitive
token names are space-sensitive (ie. padding around key names is not ignored)

IMPLEMENTATION INFO

this feature was introduced in this module

2.73. Uize.toNumber

Returns a number, that is the specified value coerced to a number type value, with optional defaulting if the value can't be successfully coerced to a number.

DIFFERENT USAGES

Coerce a Value to a Number

valueNUMBER = Uize.toNumber (valueANYTYPE);

Coerce a Value to a Number, With Defaulting

valueNUMBER = Uize.toNumber (valueANYTYPE,defaultANYTYPE);

2.73.1. How a Value is Coerced to Number

The Uize.toNumber method coerces a value to a number using the following steps...

1.  if the value is a function, then the function is called and the value is replaced with the value returned by the function
2.  next, if the value is an object, then the object's valueOf intrinsic method is called and the value is replaced by the value returned by the valueOf intrinsic method
3.  next, if the value is undefined, null, '' (an empty string), or not a primitive type value like a string, number, or boolean, then it is replaced with the special value NaN
4.  next, the value is coerced to a number using the "+" operator
5.  next, if the coerced value is the special value NaN, and if an optional default value is specified, then the value is replaced with the default value

The above steps for coercing a value to number has the following side effects / implications...

2.73.1.1. Empty String is Coerced to NaN

Coercing the value '' (an empty string) to a number will produce the result NaN.

EXAMPLE

Uize.toNumber ('');  // returns NaN

2.73.1.2. The Values null and undefined Are Coerced to NaN

Coercing the values null or undefined to a number will produce the result NaN

EXAMPLE

Uize.toNumber (null);       // returns NaN
Uize.toNumber (undefined);  // returns NaN

2.73.1.3. Arrays Are Coerced to NaN

Coercing an array to a number always produces the result NaN.

This is because the valueOf intrinsic method of JavaScript's built-in Array object always returns a reference to the array on which it is called.

EXAMPLE

Uize.toNumber ([]);   // returns NaN
Uize.toNumber ([1]);  // returns NaN

2.73.1.4. Some Objects Are Coerced to NaN

Unless an object deliberately implements the valueOf intrinsic method, or the object is an instance of a Uize.Class subclass, coercing an object to a number will produce the result NaN.

This is because the implementation of the valueOf intrinsic method in JavaScript's built-in Object object simply returns a reference to the object on which it is called. The Uize.toNumber method only coerces an object to a number successfully if the valueOf intrinsic method for the object returns a primitive type value, such as a string, number, or boolean.

EXAMPLE

// these objects can be successfully coerced to a number

Uize.toNumber (new Number (5));                    // returns 5
Uize.toNumber (new String ('5'));                  // returns 5
Uize.toNumber (new Boolean (true));                // returns 1
Uize.toNumber (Uize.Class ({value:5}));            // returns 5
Uize.toNumber (Uize.Class ({value:'5'}));          // returns 5
Uize.toNumber (Uize.Class ({value:true}));         // returns 1
Uize.toNumber ({valueOf:function () {return 5}});  // returns 5


// these objects will be coerced to NaN

Uize.toNumber ({});                                // returns NaN
Uize.toNumber ({foo:'bar'});                       // returns NaN
Uize.toNumber (new XMLHttpRequest);                // returns NaN
Uize.toNumber (/\d+/);                             // returns NaN

2.73.1.5. Key Distinctions When Compared With Simple Coercion

A cheap way to coerce a value to a number in JavaScript is to subtract zero from it, which results in JavaScript performing the steps necessary to produce a number type value.

Besides its convenient defaulting ability, the Uize.toNumber method behaves differently to simple coercion in a number of key ways...

The Uize.toNumber method coerces '' (an empty string) to NaN, whereas simple coercion turns an empty string into 0. So, the statement Uize.toNumber ('') produces the value NaN while the statement '' - 0 produces the value 0. For the purpose of coercing a value to a number with defaulting, it makes more sense to treat an empty string as no value specified, rather than as the value 0 specified.
The Uize.toNumber method coerces null to NaN, whereas simple coercion turns null into 0. So, the statement Uize.toNumber (null) produces the value NaN while the statement null - 0 produces the value 0. For the purpose of coercing a value to a number with defaulting, it makes more sense to treat the value null as no value specified, rather than as the value 0 specified.
The Uize.toNumber method will attempt to coerce a function to a number by calling it and using its result, whereas simple coercion produces the value NaN. So, the statement Uize.toNumber (function () {return 5}) produces the value 5 while the statement (function () {return 5}) - 0 produces the value NaN.

2.73.1.6. Using the Uize.toNumber Method

There are two main situations where the Uize.toNumber method comes in handy.

2.73.1.6.1. Normalizing Method Parameters

The Uize.toNumber method can be used to "normalize" method parameter values that need to be number type.

EXAMPLE

function repeatStr (string,times) {
  times = Uize.toNumber (times,1);
  var result = '';
  for (var repeatNo = -1; ++repeatNo < times;) {
    result += string;
  }
  return result;
}

In the above example, a repeatStr function is being implemented that will take a specified string and create a new string by repeating the string the specified number of times. The number of repetitions, which needs to be a number, is specified by the times parameter of the function.

Now, if the developer of the function wants to provide flexibility in how the number of repetitions is specified, the Uize.toNumber method can be used to coerce the value of this parameter to a number before it is used internally by the function's implementation. In this example, we're also specifying a default of 1, in case the parameter is not specified or if the value specified cannot be coerced to a number without producing the value NaN.

Now, using the repeatStr function, as implemented above, we would see the following results...

RESULTS

repeatStr ('Foo',2);                       // returns "FooFoo"
repeatStr ('Foo','2');                     // returns "FooFoo"
repeatStr ('Foo',Uize.Class ({value:2}));  // returns "FooFoo"
repeatStr ('Foo',function () {return 2});  // returns "FooFoo"
repeatStr ('Foo',true);                    // returns "Foo"
repeatStr ('Foo',false);                   // returns ""

repeatStr ('Foo');                         // returns "Foo"
repeatStr ('Foo',NaN);                     // returns "Foo"
repeatStr ('Foo','bar');                   // returns "Foo"
repeatStr ('Foo',null);                    // returns "Foo"
repeatStr ('Foo',undefined);               // returns "Foo"
2.73.1.6.2. Conforming State Properties

The Uize.toNumber method can be specified as a conformer for a state property of a Uize.Class subclass.

EXAMPLE

var Rectangle = Uize.Class.subclass ();

Rectangle.stateProperties ({
  width:{
    conformer:Uize.toNumber,
    value:0
  },
  height:{
    conformer:Uize.toNumber,
    value:0
  }
});

In the above example, a Rectangle class is being defined that has two state properties: width and height. For the convenience of users of the class, the Uize.toNumber method is set as the conformer for both the width and height properties. This means that the user of the class can set the values for these properties using values that are other than number type, and the developer of the class can write the rest of the class' code with confidence that internally the values for the properties will always be number type.

So, given the above implementation of the Rectangle class, we would see the following results...

RESULTS

var rect = Rectangle ({width:'5',height:'10'});

myInstance.get ('width');                          // returns 5
myInstance.get ('height');                         // returns 10

myInstance.set ('width',true);
myInstance.get ('width');                          // returns 1

myInstance.set ('height',function () {return 7});
myInstance.get ('height');                         // returns 7

myInstance.set ('width',Uize.Class ({value:12}));
myInstance.get ('width');                          // returns 12

2.73.2. Coerce a Value to a Number

A value of any type can be coerced to a number by calling the Uize.toNumber method and passing the value that is to be coerced to a number as the single parameter.

SYNTAX

valueNUMBER = Uize.toNumber (valueANYTYPE);

EXAMPLES

// values that can be coerced successfully to a number

Uize.toNumber (5);                                              // returns 5
Uize.toNumber (Infinity);                                       // returns Infinity
Uize.toNumber (true);                                           // returns 1
Uize.toNumber (false);                                          // returns 0
Uize.toNumber ('-1.234');                                       // returns -1.234
Uize.toNumber ('Infinity');                                     // returns Infinity
Uize.toNumber ('0xff');                                         // returns 255
Uize.toNumber (function () {return 5});                         // returns 5
Uize.toNumber (function () {return '5'});                       // returns 5
Uize.toNumber (Uize.Class ({value:5}));                         // returns 5
Uize.toNumber (Uize.Class ({value:'5'}));                       // returns 5
Uize.toNumber (new Number (5));                                 // returns 5
Uize.toNumber (new String ('5'));                               // returns 5
Uize.toNumber (new Boolean (true));                             // returns 1
Uize.toNumber (function () {return Uize.Class ({value:5})});    // returns 5
Uize.toNumber (function () {return Uize.Class ({value:'5'})});  // returns 5


// values that cannot be coerced to a number

Uize.toNumber ('foo');                                          // returns NaN
Uize.toNumber (NaN);                                            // returns NaN
Uize.toNumber ({});                                             // returns NaN
Uize.toNumber ([1]);                                            // returns NaN
Uize.toNumber (/\d+/);                                          // returns NaN
Uize.toNumber (undefined);                                      // returns NaN
Uize.toNumber (null);                                           // returns NaN
Uize.toNumber ('');                                             // returns NaN
Uize.toNumber (Uize.Class ({value:Uize.Class ({value:5})}));    // returns NaN
Uize.toNumber (Uize.Class ({value:function () {return 5}}));    // returns NaN
Uize.toNumber (function () {return function () {return 5}});    // returns NaN

2.73.3. Coerce a Value to a Number, With Defaulting

A value of any type can be coerced to a number, with defaulting if the value can't be successfully coerced to a number, by specifing a default value using the optional defaultANYTYPE second parameter.

SYNTAX

valueNUMBER = Uize.toNumber (valueANYTYPE,defaultANYTYPE);

EXAMPLES

// values that can be coerced successfully to a number

Uize.toNumber (5,99);                                              // returns 5
Uize.toNumber (Infinity,99);                                       // returns Infinity
Uize.toNumber (true,99);                                           // returns 1
Uize.toNumber (false,99);                                          // returns 0
Uize.toNumber ('-1.234',99);                                       // returns -1.234
Uize.toNumber ('Infinity',99);                                     // returns Infinity
Uize.toNumber ('0xff',99);                                         // returns 255
Uize.toNumber (function () {return 5},99);                         // returns 5
Uize.toNumber (function () {return '5'},99);                       // returns 5
Uize.toNumber (Uize.Class ({value:5}),99);                         // returns 5
Uize.toNumber (Uize.Class ({value:'5'}),99);                       // returns 5
Uize.toNumber (new Number (5),99);                                 // returns 5
Uize.toNumber (new String ('5'),99);                               // returns 5
Uize.toNumber (new Boolean (true),99);                             // returns 1
Uize.toNumber (function () {return Uize.Class ({value:5})},99);    // returns 5
Uize.toNumber (function () {return Uize.Class ({value:'5'})},99);  // returns 5

// values that cannot be coerced to a number

Uize.toNumber ('foo',99);                                          // returns 99
Uize.toNumber (NaN,99);                                            // returns 99
Uize.toNumber ({},99);                                             // returns 99
Uize.toNumber ([1],99);                                            // returns 99
Uize.toNumber (/\d+/,99);                                          // returns 99
Uize.toNumber (undefined,99);                                      // returns 99
Uize.toNumber (null,99);                                           // returns 99
Uize.toNumber ('',99);                                             // returns 99
Uize.toNumber (Uize.Class ({value:Uize.Class ({value:5})}),99);    // returns 99
Uize.toNumber (Uize.Class ({value:function () {return 5}}),99);    // returns 99
Uize.toNumber (function () {return function () {return 5}},99);    // returns 99

NOTES

see also the other useful value transformers

IMPLEMENTATION INFO

this feature was introduced in this module

2.74. Uize.totalKeys

Returns an integer, representing the total number of keys in the specified object.

SYNTAX

totalKeysINT = Uize.totalKeys (objectOBJ);

Using the Uize.totalKeys method to determine the number of keys an object has is more efficient than using the expression Uize.keys (myObject).length, because the Uize.totalKeys method doesn't populate an array. Furthermore, to determine if an object is empty, you could use the expression !Uize.totalKeys (myObject), but it would be more efficient to use the convenient Uize.isEmpty static method.

NOTES

when the value of objectOBJ parameter is null or undefined, the value 0 will be returned
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

2.75. Uize.values

Returns an array, representing the property values of the specified object.

SYNTAX

valuesARRAY = Uize.values (objectOBJ);

EXAMPLE

var
  personRecord = {
    firstName:'John',
    lastName:'Wilkey',
    addressStreet:'1 Shiny House Way',
    addressCity:'Richville',
    addressState:'CA',
    addressZip:'91234'
  },
  myValues = Uize.keys (personRecord)
;

After the above code has executed, the myValues variable will have the value ['John', 'Wilkey', '1 Shiny House Way', 'Richville', 'CA', '91234'].

VARIATION

valuesARRAY = Uize.values (objectARRAY);

When an objectARRAY parameter is specified in place of an objectOBJ parameter, then the value of the objectARRAY parameter will be returned as the result. This behavior makes this method useful for canonicalizing what could be an object or an array to an array of values.

NOTES

when the value of objectOBJ parameter is null or undefined, an empty array will be returned
see also the other basic data utilities

IMPLEMENTATION INFO

this feature was introduced in this module

3. Static Properties

3.1. Uize.moduleName

IMPLEMENTATION INFO

this feature was introduced in this module

3.2. Uize.moduleUrlTemplate

A string, representing a template to be used when generating URLs for loading JavaScript modules dynamically.

EXAMPLE

Uize.moduleUrlTemplate = 'http://www.somedomain.com/js/[#modulePath]';

For an in-depth discussion of modules, consult the guide JavaScript Modules.

NOTES

see also the Uize.module and Uize.moduleLoader static methods
this static property is not inherited by subclasses

IMPLEMENTATION INFO

this feature was introduced in this module

3.3. Uize.pathToResources

A string, representing the relative path from the current document to the folder containing the Uize module's JavaScript library.

This property is useful in the implementation of Uize.Class subclasses that are to reside in the same folder alongside the Uize module's JavaScript file and that may wish to, in their implementation, make use of image and other support resources located inside that folder.

By using this property, a subclass' implementation does not need to know whether or not the document using it is being loaded through HTTP or from the local file system and does not need to impose extra requirements on developers regarding where its JavaScript library is located in relation to documents using it.

NOTES

this static property is not inherited by subclasses

IMPLEMENTATION INFO

this feature was introduced in this module