GUIDES General Constructs
- Contents
- 1. Introduction
- 2. Value Transformer
- 3. Value Matcher
- 4. Value Conformer
- 5. Value Validator
- 6. Conformers vs. Validators
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)
.