Skip to content

jtlc and JXL Reference

MaxMotovilov edited this page Sep 17, 2010 · 9 revisions

jtlc and JXL: Reference

dojox.jtlc.compile()

var compiled_template = dojox.jtlc.compile( template, language, options );

Accepts template as its first argument and the language description (such as an instance of dojo.jtlc.JXL) as its second argument. Returns the compiled evaluator function for the template or throws an exception in case of errors.

The third, optional argument of this function is used to inject properties directly into the compiler state (the language object serves as its prototype and is not modified during compilation). This is a mechanism provided for the benefit of derived languages (e.g. CHT uses it to collect localizable strings from the template) and is of no interest for the JXL.

dojox.jtlc.JXL()

var jxl = new dojox.jtlc.JXL( settings );

Instantiates language description for JXL that can be customized by providing an optional property bag as an argument. The following are the settings recognized by the JXL:

elideNulls
When true, null values are not placed into array or dictionary sinks but are thrown away instead (with their corresponding keys in case of a dictionary).
failOnDuplicateKeys
When true, an attempt to insert a duplicate key into the dictionary sink results in an exception.
singletonQuery.failOnNoResults
Set to true to verify that queries in singleton contexts produce at least one result or throw an exception otherwise.
singletonQuery.failOnManyResults
Set to true to verify that queries in singleton contexts produce no more than one result or throw an exception otherwise.
queryLanguage
By default this option is set to dojox.json.query. You may substitute a query language compiler with compatible API.
replaceLanguage
By defualt this option is set to dojo.replace. You may substitute a formatting function of your own with compatible API.

Note that default settings always favor performance over other concerns; turning on additional checking in the code is likely to make it somewhat more complex and, as a result, slower.

JXL literals

In JXL a literal is any value that is not an object with compile() method defined.

Object literals

{ key0 : input0 [ ,keyN : inputN ] }

Object literals are sinks producing dictionaries (anonymous Javascript objects). By default, all inputs of an object literal are evaluated in singleton mode and the resulting values inserted into the resulting dictionary with literal key values. In order to populate a dictionary with keys generated from an input sequence, use the setkey primitive within a sub-template enclosed in many. In this case the key associated with this sub-template within the literal will be ignored and the computed value will be used instead.

Array literals

[ input0 [ ,inputN ] ]

Array literals are sinks producing anonymous Javascript arrays. By default, each input of an array literal is evaluated in an iterative context of its own. In order to evaluate a singleton sub-template and put its value into an array, enclose the sub-template within one.

Note that array literals themselves are not generators and should not appear in an iterative context even though they establish an iterative context of their own inside the brackets. In order to use the value produced by an array literal as a generator, enclose it in from.

String literals

String literals may appear in place of a sub-template anywhere in JXL. They are interpreted differently depending on the context: in the context of a singleton, the string is taken to be an inline expression as if it were enclosed in an expr tag. In an iterative context, the string is assumed to be a query without additional parameters, which is to say, an equivalent of query( "string", current() ).

Numeric and boolean literals

Numeric and boolean literals are always interpreted as if they were enclosed in quote, consequently, they may not appear in an iterative context.

Functions

Values with the type of function are treated as if they were enclosed in bind.

JXL tags

In order to simplify construction of JXL trees, all JXL tag definitions consist of a creator function and a constructor function. Their relationship can be expressed as:

function creator( args )
{
  return new constructor( args );
}

Creator functions for JXL tags are defined in the namespace dojox.jtlc.tags, the following text will assume

var t = dojox.jtlc.tags;

for the sake of brevity. The users of the library do not access constructor functions directly, only the creator functions; if extending an existing tag is desired, the constructor functions can also be found within this namespace with the same names except for the prepended underscore character.

acc

t.acc( initial_value )

Ensures that the value of its argument (usually a constant) is stored in a local variable (accumulator). Usually used as part of an aggregation construct such as t.expr( '$1+=(some expression)', input, t.acc(0) ). It is not an error to use acc in an iterative context but the tag will have no effect as the accumulator will be overwritten by the next iteration.

arg

t.arg( index )

Returns one of the arguments passed into the evaluator of the template. While current defaults to iterating over t.arg(0), the two are not equivalent: arg is not by itself a generator and should be enclosed in from to work as one. The argument of arg should be a numeric value.

bind

t.bind( function_value, input0 ... inputN )

Evaluates all of the input arguments, then applies the function to them. In the iterative context the function is called once for every iteration with input0 treated as the generator and the rest of the arguments evaluated only once (in singleton contexts of their own). If no input arguments are provided, bind assumes that the function is applied to current input.

current

t.current()

In a singleton context, returns value of the current input. Current input defaults to the value of t.arg(0) but may be temporarily reset to different objects in a sub-template enclosed in primitives such as each, group and setkey. In an iterative context, t.current() serves as a generator of values from current input and may cause a runtime error if current input is not an array.

defined

t.defined( input )

Serves as a filter passing only the defined values (i.e. values whose typeof is not equal to 'undefined') from the input, potentially reducing the length of the resulting sequence. Should not be used outside of iterative contexts.

each

t.each( input0 ... inputN )

Performs nested iterations by evaluating its first argument in iterative mode with current input set to each of the values generated by the second argument in turn and so on. Thus the rightmost argument forms the outermost iteration and the leftmost argument forms the innermost iteration. This primitive can only be used
in iterative contexts and evaluates every one of its arguments in an iterative context of its own.

Note that each does not nest sinks, only the iterations. In fact, its usual application is flattening hierarchies formed by nested arrays passed into the template.

When given only one argument, each will evaluate it against every value generated from current input.

expr

t.expr( expression, input0 ... inputN )

Evaluates its input arguments (a maximum of 10 is supported), then evaluates the inline expression (a string constant), substituting values of the arguments for placeholder symbols $, $0 through $9 and $#:

$0$9
Values of input0 through input9.
$
In singleton context, equivalent to $0. In an iterative context, current value generated by input0.
$#
Sequence number of current iteration in an iterative context. Not defined in singleton contexts.

If the expression contains no placeholder strings and begins with an identifier, expr assumes the latter to be a property reference relative to the current input and prepends $. to it.

If no input arguments are provided, the expression is evaluated as if t.current() was supplied as input0. Note that expr is entirely similar to bind except that bind refers to a function outside of the template’s evaluator and expr injects Javascript code directly into the evaluator’s body. In particular, arguments input1 through inputN are evaluated only once even when expr itself is in iterative context.

from

t.from( input )

Evaluates the input argument as a singleton and generates values from the resulting array or property values from the resulting dictionary. Applying from to t.current() has no effect because current already serves as a generator in iterative contexts.

group

t.group( keys, body, input )

Provides SQL-like grouping capability by evaluating its body repeatedly over subsequences formed from input. The subsequences are established by evaluating the keys — which should be either a single sub-template or an array of subtemplates, typically inline expressions — over each element of the sequence and comparing the results. The longest contiguous subsequence of generated values where keys are equal forms a group. The body is then evaluated with current input set to the entire group.

The group primitive can be used only in iterative contexts; it generates values returned by the body: one value per group.

Note that for the grouping to work properly the input sequence should already be ordered in respect to the keys, so usually group is applied to the
results produced by a query. However, the user is left free to group sorted sequences originating elsewhere.

If the input argument is omitted, current input is assumed.

keys

t.keys( input )

Generates keys from the input: property names if the value of input is a dictionary (i.e. a non-array object), indices if it is an array. If input is omitted, current input is used. Cannot be used outside of an iterative context.

last

t.last( input )

Serves as a special type of sink, returning only the last value generated by input. Usually used for aggregation purposes. If input is omitted, current input is used.

many

t.many( input )

Evaluates its input in an iterative context established for that purpose; if many appears within an externally established iterative context it does not modify the behavior of its input in any way and simply passes on all the values it may return.

one

t.one( input )

Evaluates its input in a singleton context of its own when used within an externally established iterative context, effectively working as a generator that returns a single value.

query

t.query( query_text, input0 ... inputN )

Executes a query over specified inputs; each of the arguments input0inputN is evaluated as a singleton. By default, the @query_text is pre-compiled with dojox.json.query(); changing the queryLanguage setting allows the user to use another query language implementation with a compatible API.

In iterative contexts, query works as a generator returning individual matches. In singleton contexts query assumes that one and only one result should be produced, which is returned on its own. If there are no matches, the result will have an “undefined” value; if there is more than one match only the first one will be used. This default behavior may be modified with the settings singletonQuery.failOnNoResults and singletonQuery.failOnManyResults.

Using query without input arguments applies the query to current input (treated as a single value).

quote

t.quote( value )

Returns value as is (i.e. the jtlc does not get a chance to try and compile it), whether it it is a Javascript object, an array or a string.

replace

t.replace( format_string, input )

Formats and returns its input by performing substitutions specified by the format_string which should be a string value.

By default, replace uses dojo.replace(); user can change this behavior with the replaceLanguage setting.

If the input argument is omitted, replace works with current input.

setkey

t.setkey( body, input )

Changes the key (property name) under which the computed values will be stored in a dictionary sink. The input argument is evaluated first, then body is evaluated as a singleton with current input set to the value obtained by evaluating the input; usually, the body consists of a replace possibly in combination with expr. The result returned by evaluating the body is used as the key, the value returned by the input is passed on.

The setkey primitive can be used both within singletons and iterative contexts, but makes little sense in the former. Without the input argument, setkey operates on current input.