Handlers - xokomola/origami GitHub Wiki

Handlers

Origami node handlers are functions embedded in a Mu data structure. They can be embedded in three different places insde the data structure.

  • Element handlers
  • Attribute handlers
  • Inline handlers

A handler implements a piece of templating logic which takes a node (the element node in which the handler is contained) and optionally some data.

When data is "applied" to a Mu data structure using o:apply the Mu data structure will be output and each handler will receive the data together with the node it's defined in.

Let's look at the different forms a handler can take (the function body is left out):

function($node, $data) { ... }

This is the most common form (arity 2). When a Mu element is "invoked" it will first evaluate all attribute handlers and then the element handler. The element handler will see the evaluated attributes.

Inline handlers are part of the element content and will be evaluated when encountered.

function() { ... }

This handler will take no arguments (arity 0).

function($node) { ... }

This handler will receive the containing element node (arity 1).

A handler form may also provide data arguments which results in the following other form. The extra data is prepended to the data provided from the outside using o:apply.

[function($node, $data) { ... }, $extra-data]

Although it is accepted it's serves no purpose to use arity 0 or 1 functions with this form as these do not get the data including the provided extra data.

Note that in this form the extra data is optional so the following form is also allowed (and is identical to the first form). I prefer this form when defining inline handlers but that is a matter of taste.

[function($node,$data) { ... }]

And by extension the following are then also valid forms.

[function($node) { ... }]
[function() { ... }]

Handler argument adapters

The earlier forms do not allow functions with different arguments than the current element node and data (arity 0, 1 or 2).

Some functions may need different arguments. For these situations you can use the following form which specifies a second function as a way to adapt the default arguments to an argument list that match your function's signature.

[
    function($a,$b,$c) { $a + $b + $c }, 
    function($node,$data) { [1,2,3] }
]

Such a handler is always a two-item array where both items are functions. The second function must be an arity 2 function (as it always receives the default arguments of $node and $data) and it must produce an array which will be used as the arguments for the handler function (similar to the second argument of fn:apply).

The advantage of these handler argument adapters is that you can use regular functions to be used as a handler in a Mu data structure.

For example:

let $template :=
    ['p', 
        [
            concat#3, 
            function($node,$data) { 
                [$data[1], ' and ', $data[2]]
            }
        ]
    ]
return
    o:xml(o:apply($template, ('apples','bananas')))

returns

<p>apples and bananas</p>