UIZE JavaScript Framework

GUIDES General Constructs

1. Introduction

This document describes a number of general constructs that apply across the entire UIZE JavaScript Framework, and can apply in application programming more generally.

2. Value Transformer

A value transformer is code (specified as a value transformer function) that transforms one value to another value.

2.1. Value Transformer Function

A value transformer function is a value transformer specified in the form of a function.

A value transformer function should expect to receive a single parameter, being the value that is to be transformed to a new value. The function should return the transformed value. Consider the following example...

EXAMPLE

function cubed (value) {
  return value * value * value;
}

In the above example, the function cubed transforms its input value to the input value to the power of three (i.e. cubed).

2.1.1. Using a Value Transformer Function

A value transformer function can be supplied as a parameter to any method that supports a value transformer function, such as the Uize.map static method. Consider the following example...

EXAMPLE

function cubed (value) {
  return value * value * value;
}

var myValuesCubed = Uize.map (myValues,cubed);

The Uize.map method accepts a value and key transformer for its first parameter and a source array as its second. It iterates through all the elements of the source array, calling the Value and Key Transformer for each element. With the transformed element values returned by the value and key transformer, the method populates a new array.

In this example we are supplying a value transformer in place of a value and key transformer (see Using a Value Transformer in Place of a Value and Key Transformer), which just means that the additional key / index information for the elements will be ignored. The variable myValuesCubed, in this case, will contain the cubes of all the values in the myValues source array.

2.1.2. Value Parameter Can Be Named Anything

The value input parameter for a value transformer function can be named anything - it does not need to be named value. Consider the following example...

EXAMPLE

function cubed (toCube) {
  return toCube * toCube * toCube;
}

In the above example, our value parameter is named toCube.

2.2. Different Types of Value Transformers

The value transformer construct is deliberately very generic, making it applicable in a number of different contexts and to a wide range of different types of value transformers.

Now, while there are a number of different kinds of value transformers (as outlined below) that are different in spirit and intended use, they all share the basic feature of accepting an input value and then returning that value transformed somehow into a new value. Different types of value transformers can impose different limits on the kinds of input values they accept, and the nature of their transformations can differ radically.

2.2.1. Curve Functions Are Specialized Value Transformers

A Curve Function is a specialized kind of value transformer whose input value is expected to be a floating point number in the range of 0 to 1, and where the returned transformed value should also be a floating point number in the range of 0 to 1.

EXAMPLE

Uize.Fade.Factory.fade (scrollTo,[0,0],[0,200],800,{curve:Uize.Curve.easeInOutPow (4)});

In the above example, the vertical scroll position of a browser window is being animated using the Uize.Fade.Factory.fade method of the Uize.Fade.Factory module. A curve function (which is a value transformer) is being created using the statement Uize.Curve.easeInOutPow (4), and this curve is being supplied to the Uize.Fade.Factory.fade method so that the animation isn't completely linear and lifeless - some non-linearity adds physical realism to the animation. The curve function is being used to bend / distort a 0 to 1 floating point number into a different 0 to 1 floating point number.

2.2.2. Value Matchers Are Specialized Value Transformers

A value matcher is a specialized kind of value transformer that transforms a value to a boolean value.

EXAMPLE

function isOnlyWhitespace (value) {
  return /^\s*$/.test (value);
}

In the above example, the function isOnlyWhitespace returns a boolean value, indicating whether or not the input value is a string containing only whitespace characters (such as spaces and tabs). The fact that it always returns a value true or false makes it a value matcher (by the very definition of a value matcher).

2.2.3. Value Conformers Are Specialized Value Transformers

A value conformer is a specialized kind of value transformer that transforms a value so that it conforms to certain criteria.

EXAMPLE

function limitStringLengthTo100Chars (sourceStr) {
  return sourceStr.length > 100 ? sourceStr.slice (0,100) : sourceStr;
}

In the above example, the limitStringLengthTo100Chars function is a value conformer that conforms a string value so that it can never be more than a hundred characters in length. It does this by using the String object's slice instance method, chopping off any characters beyond the first hundred.

2.3. Using Value Transformers

A value transformer can be used with any of the many methods that support a value transformer.

2.3.1. The Uize.Fade Class

The Uize.Fade class supports a value transformer with its curve state property.

Additionally, any of the factory methods that create instances of the Uize.Fade class will also support value transformers for the curve fade property. Examples of such factory methods are the Uize.Fade.Factory.fade, Uize.Fade.Factory.fadeMethod, Uize.Fade.Factory.fadeProperty, and Uize.Fade.Factory.fadeProperties methods implemented in the Uize.Fade.Factory module, as well as the Uize.Fx.fadeStyle and Uize.Fx.fadeStyleAcrossNodes methods of the Uize.Fx module.

For a more in-depth discussion of curve functions, see the section Curve Functions Are Specialized Value Transformers.

2.3.2. The Uize.Str.Lines.modify Method

The Uize.Str.Lines.modify static method of the Uize.Str.Lines module supports a value transformer for the line modifier that processes each line of a multi-line string.

EXAMPLE

function limitStringLengthTo100Chars (sourceStr) {
  return sourceStr.length > 100 ? sourceStr.slice (0,100) : sourceStr;
}

Uize.Str.Lines.modify (multiLineStr,limitStringLengthTo100Chars);

In the above example, the Uize.Str.Lines.modify method is using the limitStringLengthTo100Chars value transformer to limit the length of all lines in a multi-line string to a maximum of a hundred characters - lines that are longer than a hundred characters in length will be truncated so that the extra characters are discarded.

2.3.3. Using a Value Transformer in Place of a Value and Key Transformer

A value transformer can always be used in place of a value and key transformer.

In such cases, the key that is supplied as the second parameter to the Value Transformer that is only expecting a single parameter will simply be ignored - the transformed value that it returns will only be influenced by the value and not the key.

2.3.3.1. The Uize.map Method

While the Uize.map method expects a value and key transformer, a value transformer can be supplied instead.

To see an example that illustrates this, consult the section Using a Value Transformer Function.

2.3.3.2. The Uize.Array.Sort.sortBy Method

The Uize.Array.Sort.sortBy method of the Uize.Array.Sort module expects a value and key transformer, but a value transformer can be supplied instead. Consider the following example...

EXAMPLE

Uize.Array.Sort.sortBy (dateStrings,function (value) {return +(new Date (value))});

In the above example, the dateStrings variable is a reference to an array containing correctly formatted date strings. The array of date strings is being sorted into chronological order by the Uize.Array.Sort.sortBy method, with a value transformer function specified for the sort value generator that transforms a date string value into a number, representing the date as the number of milliseconds elapsed since January 1st, 1970 (i.e. POSIX time). While the sort value generator will be passed the index / key as the second parameter when it is called for each element of the dateStrings array, the function does not declare or use that second parameter.

2.3.4. Any Type of Value Can Be Transformed

There is no limit to the kinds of values that can be transformed by a value transformer.

While an input value for a Value Transformer is likely to be a simple type value, such as a number or a string, there is no saying that an input value can't also be an array or an object. Consider the following example...

EXAMPLE

function computeArea (value) {
  return value.width * value.height;
}

var
  rects = [
    {width:5,height:10},
    {width:1.4,height:5},
    {width:3,height:4}
  ],
  rectAreas = Uize.map (rects,computeArea)
;

In the above example, the computeArea function defines a value transformer that transforms an input value that is expected to be an object with width and height properties, into an area value that is computed as the product of the width and height properties. This value transformer is then supplied to the Uize.map method, which is used to produce an array containing the areas computed from the rectangle objects inside the rects array. After the above code has been executed, the statement alert (rectAreas) would display the text "50,7,12" in the alert dialog.

3. Value Matcher

A value matcher is code (specified as a value matcher function) that transforms a value to a boolean value.

A value matcher can be considered to be a specialized kind of value transformer, where the input value is always transformed to a result of true or false.

3.1. Applications of Value Matchers

Value matchers can have a variety of different uses - they can be used as validators, they can be supplied to map functions (such as Uize.Str.Lines.removeMatching), they can be used to test values generated in unit tests against expectations, etc.

Among other things, value matchers can be used to match...

integer numbers
odd numbers, or even numbers
values within a specific value range
strings or arrays whose length is in a specific range
empty objects, or non-empty objects
empty arrays, or non-empty arrays
non-null values
instances of specific objects or classes
correctly formatted e-mail addresses
correctly formatted URLs
correctly formatted color values
etc.

3.2. Value Matcher Function

A value matcher function is a value matcher specified in the form of a function.

A value matcher function should expect to receive a single parameter, being the value that is to be transformed to a boolean value. The function should return the transformed boolean value. Consider the following example...

EXAMPLE

function isOnlyWhitespace (value) {
  return /^\s*$/.test (value);
}

In the above example, the function isOnlyWhitespace returns a boolean value, indicating whether or not the input value is a string containing only whitespace characters (such as spaces and tabs).

3.2.1. Using a Value Matcher Function

A value matcher function can be supplied as a parameter to any method that supports a value matcher function, such as the Uize.Str.Lines.removeMatching static method of the Uize.Str.Lines module. Consider the following example...

EXAMPLE

function isOnlyWhitespace (value) {
  return /^\s*$/.test (value);
}

myString = Uize.Str.Lines.removeMatching (myString,isOnlyWhitespace);

The Uize.Str.Lines.removeMatching method accepts a multi-line string (containing zero or more linebreaks) for its first parameter and a matcher function as its second. It iterates through all the lines of the specified multi-line string, calling the Value Matcher Function for each line. Depending on the boolean value that is returned by the matcher, the method will either remove or retain the line.

The variable myString, in this case, will contain only the lines of the source multi-line string that have at least one non-whitespace character - lines containing only whitespace are matched by the isOnlyWhitespace matcher function and are removed by the Uize.Str.Lines.removeMatching method.

3.3. Different Types of Value Matchers

As with the value transformer construct, the value matcher construct is deliberately very generic, making it applicable in a number of different contexts.

3.3.1. Value Validators Are Specialized Value Matchers

A value validator is a specialized kind of value matcher that transforms a value to a boolean value, indicating whether or not the input value is valid according to certain criteria.

A value validator is no more than a value matcher, where the implication of a value not being matched by the matcher is that the value is not valid.

3.4. Using Value Matchers

A value matcher can be used with any of the many methods that support a value matcher.

3.4.1. Methods of the Uize.Str.Lines Module

Some of the static methods of the Uize.Str.Lines module support a value matcher.

3.4.1.1. Uize.Str.Lines.removeMatching

The Uize.Str.Lines.removeMatching static method supports a value matcher to identify which lines of a multi-line string should be removed.

EXAMPLE

myString = Uize.Str.Lines.removeMatching (
  myString,
  function (value) {return /^\s*$/.test (value)
};

In the above example, all lines that are either empty or only contain whitespace characters will be removed from the string specified by the myString variable, and the resulting string will be assigned back to the myString variable.

3.4.1.2. Uize.Str.Lines.retainMatching

The Uize.Str.Lines.retainMatching static method supports a value matcher to identify which lines of a multi-line string should be retained (i.e. not removed).

EXAMPLE

myString = Uize.Str.Lines.retainMatching (
  myString,
  function (value) {return /\S/.test (value)
};

In the above example, all lines that contain at least one non-whitespace character will be retained in the string specified by the myString variable (so, empty lines or lines with only whitespace will be removed), and the resulting string will be assigned back to the myString variable.

4. Value Conformer

A value conformer is code (specified as a value conformer function) that transforms a value so that it conforms to certain criteria.

a value conformer can be considered to be a specialized kind of value transformer, where the input value may be returned as is if it already conforms to the criteria, or it may be transformed in some way to force it into conformance with the criteria.

4.1. Applications of Value Conformers

Value conformers can have a variety of different uses - they can be used as conformers for state properties, or they can be supplied to map functions (such as Uize.map).

Among other things, value conformers can be used to...

conform floating point numbers to integer numbers
constrain numbers to limited value ranges
coerce values to specific allowable types
limit string values to a maximum length
limit string or number values to being within a finite set of allowable values
conform strings to strip out disallowed characters
etc.

4.2. Value Conformer Function

A value conformer function is a value conformer specified in the form of a function.

A value conformer function should expect to receive a single parameter, being the value that is to be conformed. The function should return the conformed value. Consider the following example...

EXAMPLE

function conformToRange0to100 (value) {
  return Uize.constrain (value,0,100);
}

In the above example, the conformToRange0to100 function defines a value conformer that conforms a number value so that it is constrained to the value range of 0 to 100.

4.2.1. Using a Value Conformer Function

A value conformer function can be supplied as a parameter to any method that supports a value transformer function, such as the Uize.map static method. Consider the following example...

EXAMPLE

Uize.map (myNumbersArray,Math.round,false);

In the above example, the Math.round static method of JavaScript's built-in Math object is being used as a value conformer with the Uize.map method in order to conform all the number values in an array to integer values. The third parameter of the Uize.map method specifies the target for the mapped values, where the value false indicates that the values should not be populated into a new array but should replace the values in the source array.

4.2.1.1. Conformers for State Properties

A value conformer function can be specified for the conformer property in the profile of a state property. Consider the following example...

EXAMPLE

function conformToRange0to100 (value) {
  return Uize.constrain (value,0,100);
}

var MyClass = Uize.Class.subclass ();
MyClass.stateProperties ({
  _percentLoaded:{
    name:'percentLoaded',
    conformer:conformToRange0to100,
    value:0
  }
});

In the above example, a percentLoaded state property is being declared for the class MyClass. In order to ensure that the value set for this property doesn't stray outside of the range of 0 to 100, the value conformer function conformToRange0to100 is being specified for the conformer property inside the profile for the percentLoaded state property.

5. Value Validator

A value validator is code (specified as a value validator function) that transforms an input value to a boolean value, indicating whether or not the input value is valid according to certain criteria.

A value validator is no more than a value matcher, where the implication of a value not being matched by the matcher is that the value is not valid.

5.1. Applications of Value Validators

Value validators can have a variety of different uses, but most typically they are used for validating user input for form element widgets.

Among other things, value validators can be used to...

validate that a user entered e-mail address is correctly formatted
validate that a user entered phone number is correctly formatted
validate that a user entered date falls within a valid date range
validate that user entered text does not exceed a maximum allowable length
validate that a user entered string does not contain illegal characters (e.g. a user name that may not contain spaces or special characters)
etc.

5.2. Value Validator Function

A value validator function is a value validator specified in the form of a function.

A value validator function should expect to receive a single parameter, being the value that is to be validated. The function should return a boolean value, indicating whether or not the input value is valid according to the validation criteria. Consider the following example...

EXAMPLE

function validateInRange0to100 (value) {
  return value >= 0 && value <= 100;
}

In the above example, the validateInRange0to100 function defines a value validator that validates that a value is in the range of 0 to 100.

6. Conformers vs. Validators

Conformers and validators are similar in nature, and can be considered to be two sides of the same coin.

Whereas a value validator is a type of value matcher that returns a boolean to indicate whether or not the input value is valid according to certain criteria, a value conformer is a value transformer that will modify the input value as needed in order to ensure that it is valid according to specific constrains (returning it as is when it is already valid). To illustrate this point, let's look at a comparison of a 0 to 100 range conformer versus a 0 to 100 range validator...

0 TO 100 RANGE CONFORMER

function conformToRange0to100 (value) {  // this function is a conformer
  return Uize.constrain (value,0,100);
}

0 TO 100 RANGE VALIDATOR

function validateInRange0to100 (value) {  // this function is a validator
  return value >= 0 && value <= 100;
}

6.1. Not all Validators Have Corresponding Conformers

While there is a simple way of deriving a validator from a conformer, it is not always possible to create a meaningful conformer to pair with a validator.

Take for example a validator that tests whether or not a string is a correctly formatted e-mail address. Such a validator can be implemented without too much difficulty using a regular expression - albeit a rather sophisticated one. On the flip side, how does one meaningfully conform a string value to a correctly formatted e-mail address? An even more extreme illustration of this is with a non-empty validator, where a string value is considered valid as long as it is not empty. How does one then conform a string that is empty to being a string that is not empty? There are too many choices of possible non-empty values.

6.2. Deriving a Validator From a Conformer

While not all validators have corresponding conformers, it is always possible to generate / derive a value validator from a value conformer, according to the following simple principle...

function deriveValidatorFromConformer (conformer) {
  return function (value) {
    return value === conformer (value);
  };
}

Essentially, if you use a specified value conformer to conform a value, and the resulting conformed value is not the same as the original value, then the original value must have been non-conforming (another way of saying not valid). So, for example, the Math.round method of JavaScript's built-in Math object can be considered a conformer that conforms any floating point number value to an integer number value. Therefore, a validator can be produced by using the Math.round method, as follows...

var isInteger = deriveValidatorFromConformer (Math.round);

Similarly, the conformToRange0to100 function defined in the example in the Conformers vs. Validators section could be used to derive the validateInRange0to100 validator function using the statement deriveValidatorFromConformer (conformToRange0to100).