&#9665; [Expression Language](expression.md)
&nbsp;&nbsp;&nbsp;&nbsp; &#8801; [Table of Contents](README.md#markup)
&nbsp;&nbsp;&nbsp;&nbsp; [Scripting](scripting.md) &#9655;
- - -

# Markup
Seanox aspect-js extends the declarative approach of HTML. In addition to the
expression language, HTML elements get attributes for runtime functions and
View-Module Binding. The renderer is part of the composite implementation. It
monitors the DOM from the BODY element with MutationObserver and reacts
recursively to changes.

## Contents Overview
- [Attributes](#attributes)
  - [composite](#composite)
  - [condition](#condition)
  - [events](#events)
  - [id](#id)
  - [import](#import)
  - [interval](#interval)
  - [iterate](#iterate)
  - [message](#message)
  - [output](#output)
  - [release](#release)
  - [render](#render)
  - [route](#route)
  - [validate](#validate)
- [@-Attributes](#-attributes) 
- [Expression Language](#expression-language)
- [Scripting](#scripting)
- [Customizing](#customizing)
  - [Tag](#tag)
  - [Selector](#selector)
  - [Interceptor](#interceptor)
- [Protection](#protection)

## Attributes
In Seanox aspect-js, the declarative approach is implemented with attributes.
They can be used and combined in all HTML elements starting with the HTML
element `BODY`. Attribute values can be static or dynamic through the expression
language. If an attribute contains an expression, the renderer updates the value
with each render cycle based on the initial expression.

### composite
Marks an element in the markup as a [Composite](composite.md). Composites are
essential components that require an identifier (ID / Composite ID).

```html
<article id="example" composite>
  ...
</article>
```

As a component, composites are composed of various [resources](
    composite.md#resources) (markup, CSS, JS). They can be outsourced to the
module directory based on the Composite ID and are loaded at runtime when used.

Composites are also the basis for [View-Module Binding](
    view-module-binding.md#view-module-binding). It connects HTML elements in
the markup (view) with corresponding JavaScript objects. The view as
presentation and user interface for interactions remains decoupled from the
application module. Application modules provide the data, state and behavior
that are exposed to the view through View-Module Binding. Binding links views
and modules bidirectionally based on the Composite IDs, so manual declaration of
events, interaction or synchronization is not required.

[Routing](routing.md#routing) uses composites as [views](routing.md#view). They
can be path targets in the [view flow](routing.md#view-flow), which controls the
visibility of composites. When routing is active, composites can be marked with
attribute [route](#route) so that routing controls their visibility through
paths and the permission concept.

```html
<article id="example" composite route>
  ...
</article>
```

Details on the use of composites / modular components are described in chapter
[Composites](composite.md) and [View-Module Binding](
    view-module-binding.md#view-module-binding).

### condition
As a condition, the attribute specifies whether an element remains contained in
the DOM. The expression specified as the value must explicitly return `true` to
retain the element. If the return value is different, the element is temporarily
removed from the DOM and can be reinserted later by refreshing the __parent
element__ if the expression returns `true`.

```html
<article condition="{% raw %}{{model.visible}}{% endraw %}">
  ...
</article>
```

When combined with the attribute [interval](#interval), it should be noted that
when the element is removed from the DOM, the associated timer is also
terminated. If the element is added back to the DOM with a later refresh, a new
timer starts, so it is not continued.

```html
<article interval="{% raw %}{{1000}}" condition="{{model.visible}}{% endraw %}">
  ...
</article>
```

The use of the condition attribute in combination with embedded JavaScript is
possible as SCRIPT element with the type `composite/javascript` as Composite
JavaScript, because here the renderer has control over the script execution and
not the browser.

```html
<script type="composite/javascript" condition="{% raw %}{{model.visible}}{% endraw %}">
    ...
</script>
```

Details about using embedded JavaScript are described in chapter [Scripting](
    #scripting).

### events
Binds one or more [events](https://www.w3.org/TR/DOM-Level-3-Events) to an HTML
element. This allows for event-driven synchronization of HTML elements with
corresponding JavaScript objects, validation of synchronized data (see
[validate](#validate)) and event-driven control and refreshing of other HTML
elements (see [render](#render)).

As with all attributes, the expression language can be used here. Runtime
changes have no effect because the attribute value for View-Module Binding is
processed only initially while the HTML element exists in the DOM.

```html
<span id="output1">{% raw %}{{#text1.value}}{% endraw %}</span>
<input id="text1" type="text"
    events="input change" render="#output1"/>
```

The example synchronously refreshes the HTML element _output1_ with the events
_Input_ or _Change_ at the HTML element _text1_. The input value of _text1_ is
output synchronously with _output1_.

```javascript
const model = {
    validate(element, value) {
        return true;
    },
    text1: ""
};
```

```html
<form id="model" composite>
  <input id="text1" type="text"
      validate events="input change"/>
  <input type="submit" value="submit"
      validate events="click"/>
</form>
```

The example combines the attributes `events` and `validate`. The input value
from the composite field _text1_ is transferred to the field of the same name in
the JavaScript object only if the event _Input_ or _Change_ occurs.

### id
The ID (identifier) has a central role in Seanox aspect-js. It is the basis for
[View-Module Binding](view-module-binding.md#view-module-binding) and is used by
[Routing](routing.md#routing) for [views](routing.md#view) in the [view flow](
    routing.md#view-flow) and as a destination for paths.

As with all attributes, the expression language can be used. The attribute is
only read at the beginning. Due to View-Module Binding, changes to an existing
element at runtime have no effect while it exists in the DOM.

### import
Loads the content for the HTML element at runtime and inserts it as inner HTML.
The behavior is similar to the [output](#output) attribute, except that the
import is done once and the import attribute is removed after successful
loading. As value one or more elements are supported as NodeList or Array, as
well as absolute or relative URLs to a remote resource and also the [DataSource
    URL (locator)](datasource.md#locator) for transformed content from the
[DataSource](datasource.md).

The import attribute can be combined with the condition attribute and will then
only be executed if the condition is `true`.

```javascript
const model = {
    publishForm() {
        const form = document.createElement("form");
        const label = document.createElement("label");
        label.textContent = "Input";
        form.appendChild(label);
        const input = document.createElement("input");
        input.value = "123";
        input.type = "text";
        form.appendChild(input);
        const submit = document.createElement("input");
        submit.type = "submit";
        form.appendChild(submit);
        return form;
    },
    publishImg() {
        const img = document.createElement("img");
        img.src = "https://raw.githubusercontent.com/seanox/aspect-js/master/test/resources/smile.png";
        return img;
    }
};
```

```html
<article import="{% raw %}{{model.publishImg()}}{% endraw %}">
  loading image...
</article>
<article import="{% raw %}{{model.publishForm()}}{% endraw %}">
  loading form...
</article>
```

Example of importing a remote resource using the HTTP method GET.

```html
<article import="{% raw %}{{'https://raw.githubusercontent.com/seanox/aspect-js/master/test/resources/import_c.htmlx'}}{% endraw %}">
  loading resource...
</article>

<article import="https://raw.githubusercontent.com/seanox/aspect-js/master/test/resources/import_c.htmlx">
  loading resource...
</article>
```

Example of importing via DataSource-URL. If only one URL is specified, the URI
for data and transformation are derived from it. 

```html
<article import="{% raw %}{{'xml://example/content'}}{% endraw %}">
  loading resource...
</article>

<article import="xml://example/content">
  loading resource...
</article>

<article import="xml://example/content?count(//item)">
    loading resource...
</article>
```

Example of importing a DataSource-URL with a specific data URL (locator) and
transformation URL. As a value, the data URL (locator of the XML file) and the
transformation URL (locator of the XSLT template) are is specified, separated by
a blank character. 

```html
<article import="{% raw %}{{'xml://example/data + xslt://example/style'}}{% endraw %}">
  loading resource...
</article>

<article import="xml://example/data + xslt://example/style">
  loading resource...
</article>

<article import="xml://example/data + xslt">
    loading resource...
</article>
```

If only _xslt_ is specified without a locator, a corresponding XSLT locator with
the same name is derived from the XML locator.

When inserting content from the DataSource, the type of JavaScript blocks is
automatically changed to `composite/javascript` and only executed by the
renderer. This results in JavaScript being executed depending on the enclosing
condition attribute.

### interval
Activates an interval-controlled refresh of the HTML element without the need to
actively trigger the refresh. The interval uses the inner HTML as a template
from which updated content is generated and inserted with each interval cycle.
The attribute expects milliseconds as value, which can also be formulated as
expression, where invalid values cause console output. Processing is concurrent
or asynchronous but not parallel. Processing will start after the specified time
when a previously started JavaScript procedure has finished. Therefore, the
interval should be understood as timely but not exact. The interval starts
refreshing automatically and ends when:
- the element no longer exists in the DOM
- the condition attribute is used that is not true

```html
<span interval="1000">
  ...
</span>

<span interval="{% raw %}{{1000 +500}}{% endraw %}">
  ...
</span>
```

The interval attribute can be used for HTML elements and complex HTML
constructs. For example, the SPAN element is updated every 1000ms. An active
interval reacts dynamically to DOM changes. It starts automatically when the
HTML element is added to the DOM and ends when it is removed from the DOM. This
makes the interval attribute controllable in combination with the condition
attribute.

```html
<span interval="1000" condition="{% raw %}{{model.isVisible()}}{% endraw %}">
  ...
</span>
```

For example, interval and a variable expression can implement a permanent
counter.

```html
{% raw %}{{counter:0}}{% endraw %}
<p interval="1000">
  {% raw %}{{counter:parseInt(counter) +1}}{% endraw %}
  {% raw %}{{counter}}{% endraw %}
</p>
```

It is also possible to use the interval attribute in combination with embedded
JavaScript as a composite JavaScript.

```html
<script type="composite/javascript" interval="1000">
    ...
</script>
```

### iterate
Iterative output is based on lists, enumerations and arrays. If an HTML element
is declared as iterative, the inner HTML is used as a template from which
updated content is generated and inserted as inner HTML with each render cycle.
The attribute value expects a [variable expression](
    expression.md#variable-expression). It creates a meta-object that allows
access to the iteration in the template. The variable expression
`iterate={% raw %}{{tempA:model.list}}{% endraw %}` creates the meta-object
`tempA = {item, index, data}`.

```javascript
const model = {
    months: ["Spring", "Summer", "Autumn", "Winter"]
};
```

```html
<select iterate={% raw %}{{months:model.months}}{% endraw %}>
  <option value="{% raw %}{{months.index}}{% endraw %}">
    {% raw %}{{months.item}}{% endraw %}
  </option>
</select>
```

> __Note__  
> If arrays are used with reactive objects, iterate accesses the arrays
> directly. If the array is a list of values, value changes also change the
> array and trigger re-rendering of the iterate. To change values at runtime
> without triggering re-rendering of the iterate, the array must contain objects
> with the values. Setting the value in the objects does not change the array
> itself and therefore does not trigger re-rendering.
> 
> Alternatively, the length of the array can also be passed to the iterate. It
> then generates a list of values with the index without accessing the elements.
> The index can then be used by the expression within the iterate to access the
> array.

```html
<select iterate={% raw %}{{months:model.months.length}}{% endraw %}>
  <option value="{% raw %}{{months.index}}{% endraw %}">
    {% raw %}{{model.months[months.index]}}{% endraw %}
  </option>
</select>
```

If the value for an iterator is a positive number, a list of values from 0 to
(number -1) is used. If the value is negative, a descending list of values is
used from (number +1) to 0.

### message
Message is an optional part of [Validation](#validate) and is used for text and
error output in case of an unconfirmed validation. This requires a combination
with the attributes [validate](#validate) and [events](#events). 

```html
<form id="model" composite>
  <input id="email" type="text" placeholder="email address"
      pattern="^\w+([\w\.\-]*\w)*@\w+([\w\.\-]*\w{2,})$"
      validate message="Valid e-mail address required"
      events="input change" render="#model"/>
  <input type="submit" value="submit" validate events="click"/>
</form>
```

```html
<form id="model" composite>
  <input id="email" type="text" placeholder="email address"
      pattern="^\w+([\w\.\-]*\w)*@\w+([\w\.\-]*\w{2,})$"
      validate message="{% raw %}{{Messages['model.email.validation.message']}}{% endraw %}"
      events="input change" render="#model"/>
  <input type="submit" value="submit" validate events="click"/>
</form>
```

### output
Sets for the HTML element the value or result of its expression as inner HTML.
The behavior is similar to the [import](#import) attribute, except that the
output is updated with each render cycle. Supported values are text, one or more
elements as NodeList or Array, as well as absolute or relative URLs to a remote
resource and also the [DataSource-URL (locator)](datasource.md#locator) for
transformed content from the [DataSource](datasource.md).

The output attribute can be combined with the condition attribute and will then
only be executed if the condition is `true`.

```javascript
const model = {
    publishForm() {
        const form = document.createElement("form");
        const label = document.createElement("label");
        label.textContent = "Input";
        form.appendChild(label);
        const input = document.createElement("input");
        input.value = "123";
        input.type = "text";
        form.appendChild(input);
        const submit = document.createElement("input");
        submit.type = "submit";
        form.appendChild(submit);
        return form;
    },
    publishImg() {
        const img = document.createElement("img");
        img.src = "https://raw.githubusercontent.com/seanox/aspect-js/master/test/resources/smile.png";
        return img;
    }
};
```

```html
<article output="{% raw %}{{model.publishImg()}}{% endraw %}">
  loading image...
</article>
<article output="{% raw %}{{model.publishForm()}}{% endraw %}">
  loading form...
</article>
```

Example of outputting a remote resource using the HTTP method GET.

```html
<article import="{% raw %}{{'https://raw.githubusercontent.com/seanox/aspect-js/master/test/resources/import_c.htmlx'}}{% endraw %}">
  loading resource...
</article>

<article import="https://raw.githubusercontent.com/seanox/aspect-js/master/test/resources/import_c.htmlx">
  loading resource...
</article>
```

Example of outputting via DataSource-URL. If only one URL is specified, the URI
for data and transformation are derived from it.

```html
<article output="{% raw %}{{'xml://example/content'}}{% endraw %}">
  loading resource...
</article>

<article output="xml://example/content">
  loading resource...
</article>

<article output="xml://example/content?count(//item)">
    loading resource...
</article>
```

Example of outputting a DataSource-URL with a specific data URL (locator) and
transformation URL. As a value, the data URL (locator of the XML file) and the
transformation URL (locator of the XSLT template) are is specified, separated by
a blank character.

```html
<article output="{% raw %}{{'xml://example/data + xslt://example/style'}}{% endraw %}">
  loading resource...
</article>

<article output="xml://example/data + xslt://example/style">
  loading resource...
</article>

<article output="xml://example/data + xslt">
    loading resource...
</article>
```

If only _xslt_ is specified without a locator, a corresponding XSLT locator with
the same name is derived from the XML locator.

When inserting content from the DataSource, the type of JavaScript blocks is
automatically changed to `composite/javascript` and only executed by the
renderer. This results in JavaScript being only executed depending on the
enclosing condition attribute.

### release
Inverse indicator that an HTML element was rendered. The renderer removes this
attribute when an HTML element is rendered. This effect can be used for CSS to
show elements only in rendered state. A corresponding CSS rule is automatically
added to the HEAD when the page is loaded. 

```html
<span release>{% raw %}{{'Show me after rendering.'}}{% endraw %}</span>
```

### render
The attribute requires the combination with the [events](#events) attribute.
Together they define which targets are refreshed by the renderer with which
occurring events. The expected value is one or more space-separated CSS or Query
selectors that define the targets.

```javascript
const model = {
    _status1: 0,
    getStatus1() {
        return ++model._status1;
    },
    _status2: 0,
    getStatus2() {
        return ++model._status2;
    },
    _status3: 0,
    getStatus3() {
        return ++model._status3;
    }
};
```

```html
Target #1:
<span id="outputText1">{% raw %}{{model.status1}}{% endraw %}</span>
Events: Wheel
<input id="text1" type="text"
    events="wheel"
    render="#outputText1, #outputText2, #outputText3"/>

Target #2:
<span id="outputText2">{% raw %}{{model.status2}}{% endraw %}</span>
Events: MouseDown KeyDown
<input id="text1" type="text"
    events="mousedown keydown"
    render="#outputText2, #outputText3"/>

Target #3:
<span id="outputText3">{% raw %}{{model.status3}}{% endraw %}</span>
Events: MouseUp KeyUp
<input id="text1" type="text"
    events="mouseup keyup"
    render="#outputText3"/>

```

The example contains 3 input fields with different events (`events`) and targets
(`render`), each of which represents an incremental text output and reacts to
corresponding events.

__Alternatively, [reactive rendering](reactive.md) can be used, where changes in
the data objects trigger a partial update of the view.__

### route
The route attribute marks a composite as a path-addressable destination and
includes it in path-based control and the internal permission concept of
routing. The attribute can be used in the BODY tag and otherwise only in
combination with the attribute composite.

> __Note__  
> The attribute route is not a core attribute of the renderer. It is added as a
> custom attribute by the [Routing](routing.md#view) and is listed here for
> completeness.

[Learn more](routing.md#view)

### validate
The attribute `validate` requires the attribute `events`. Together they define
and control synchronization between the markup of a composite and the
corresponding JavaScript object. A property with the same name must exist as the
synchronization target.

Validation works in two steps and starts with standard HTML5 validation. If this
does not detect deviations from the expected result or no HTML5 validation is
specified, the JavaScript object validation is used. This requires a
corresponding validate method `boolean validate(element, value)` and an element
embedded in a composite.

Validation directly affects synchronization and the browser default action. It
can use four return states: `true`, `not true`, `text`, `undefined/void`.

#### true
Validation was successful. No error is shown and the browser default action is
used. If possible, the value is synchronized.

#### not true and not undefined/void
The validation failed and an error is shown. The return value indicates that the
default behavior (action) should not be executed by the browser and is thus
blocked. With the strict default behaviour of Seanox aspect-js, the invalid
value is not synchronized with the model.

#### text
The validation has failed with an error message. If the error message is empty,
the message from the message attribute is used as an alternative. With the
strict default behaviour of Seanox aspect-js, the invalid value is not
synchronized with the model.

#### undefined/void
Validation failed and an error is shown. Without a return value, the default
behavior (action) is executed by the browser. This behavior is important for
validating input fields, for example, so that the input reaches the user
interface. With the strict default behaviour of Seanox aspect-js, the invalid
value is not synchronized with the model.

__Validation works strictly by default. This means that the validation must
explicitly be `true` and only then is the input data of the HTML elements
synchronized with the model. This protects against invalid data in the models
which may then be reflected in the view. If attribute `validate` is declared as
`optional`, this behaviour can be specifically deactivated and the input data is
then always synchronized with the model. The effects of validation are then only
optional.__

```html
<form id="model" composite>
  <input id="text1" type="text" placeholder="e-mail address"
      validate="optional" events="input change" render="#model"/>
  model.text1: {% raw %}{{model.text1}}{% endraw %}
  <input type="submit" value="submit" validate events="click"/>
</form>
```

By default, validation message are shown as a native browser toolbox for the
input element. The corresponding message is set via the attribute of the same
name. If custom validation and output need to be implemented, this behavior can
be changed by redirecting the message to an attribute of the input element. For
this purpose, the message, which at this point also includes the return value of
expressions, must begin as follows: `@<attribute>:`.

A general strategy or standard implementation for error output is deliberately
not provided, as this is too strict in most cases and can be implemented
individually as a central solution.

```css
input[type='text']:not([fault]) {
    background:#EEEEFF;
    border-color:#7777AA;
}
input[type='text'][fault=''] {
    background:#EEFFEE;
    border-color:#77AA77;
}
input[type='text'][fault]:not([fault='']) {
    background:#FFEEEE;
    border-color:#AA7777;
}
```

```javascript
const model = {
    validate(element, value) {
        const PATTERN_EMAIL_SIMPLE = /^\w+([\w\.\-]*\w)*@\w+([\w\.\-]*\w{2,})$/;
        const test = PATTERN_EMAIL_SIMPLE.test(value);
        return test || ("Invalid " + element.getAttribute("placeholder"));
    },
    text1: ""
};
```

```html
<form id="model" composite>
  <input id="text1" type="text" placeholder="e-mail address"
      validate message="@fault:Wrong e-mail address"
      events="input change" render="#model"/>
  model.text1: {% raw %}{{model.text1}}{% endraw %}
  <input type="submit" value="submit" validate events="click"/>
</form>
```

In this example, the input field expects an e-mail address. The value is checked
continuously during the input and in case of an invalid value an error message
is written into the attribute `fault`, or in case of a valid value the content
is deleted from the attribute `fault`. Below the input field is the control
output of the corresponding field in the JavaScript object (model). This field
is only synchronized if the validate method return the value `true`.

## @-Attributes
Expressions are resolved only after the page is loaded by the renderer. For some
HTML elements, this can be annoying if the attributes are already interpreted by
the browser. For example, the src attribute for resources such as the img tag.
For these cases @-attributes can be used. These work like templates for
attributes. The renderer will resolve their value and then add the attributes of
the same name to the element. After that, they behave like all other attributes,
including being updated by the renderer if the attributes contain expressions.

```html
<img @src="{% raw %}{{...}}{% endraw %}"/>
```

## Expression Language
The expression language can be used in the markup as free text and in the
attributes of the HTML elements. JavaScript and CSS elements are excluded. The
expression language is not supported here. When used as free text, pure text
(plain text) is always generated as output. The addition of markup, especially
HTML code, is not possible and is only supported with the attributes `output`
and `import`.

```html
<article title="{% raw %}{{model.title}}{% endraw %}">
  {% raw %}{{'Hello World!'}}{% endraw %}
  ...
</article>
```

Details about syntax and usage are described in chapter [Expression Language](
    expression.md).

## Scripting
Embedded scripting has specific runtime behavior. Standard scripts are executed
automatically by the browser and independently of rendering. Markup for
rendering therefore supports the additional script type `composite/javascript`.
It uses normal JavaScript, but the browser does not recognize it as
`text/javascript` and does not execute it directly. The renderer recognizes the
JavaScript code and executes it in every relevant render cycle. This allows
SCRIPT execution to be combined with the `condition` attribute.

```html
<script type="composite/javascript">
    ...
</script>
```

Details about using composite JavaScript including modules are described in
chapter [Scripting](scripting.md).

## Customizing

### Tag
Custom HTML elements (tags) take over the complete rendering on their own
responsibility. The return value determines whether the standard functions of
the renderer are used or not. Only the return value `false` (not void, not
empty) terminates the rendering for a custom HTML elements without using the
standard functions of the renderer.

```javascript
Composite.customize("foo", function(element) {
    ...
});
```

```html
<article>
  <foo/>
</article>
```

### Selector
Selectors work similarly to custom tags. Unlike custom tags, selectors use a CSS
selector to recognize elements. This selector must address the element from the
parent element. Different selectors with different functions can affect one
element.

Selectors are iterated in order of registration and then their callback methods
are executed. The return value of the callback method determines whether the
iteration is terminated or not. Only the return value `false` (not void, not
empty) terminates the iteration over other selectors and the rendering for the
selector is terminated without using the standard functions.

```javascript
Composite.customize("a:not([href])", function(element) {
    ...
});

Composite.customize("a.foo", function(element) {
    ...
});
```

```html
<article>
  <a class="foo"></a>
</article>
```

### Interceptor
Interceptors customize rendering by manipulating elements before rendering. They
can change attributes and/or markup before the renderer processes them. An
interceptor has no effect on the rendering implementation.

```javascript
Composite.customize(function(element) {
    ...
});
```

## Protection
Seanox aspect-js provides markup protection that makes runtime manipulation of
the markup more difficult. On the one hand, hidden markup with a condition is
physically removed from the DOM and on the other hand, the renderer observes
manipulations of attributes at runtime. This observation is based on a filter
with static attributes. Static attributes are read when an element is created in
the DOM and restored when manipulated (deleted/changed).

To configure static attributes, use the method `Composite.customize(...)` and
using the parameter `@ATTRIBUTES-STATICS`. The configuration can be done several
times. The individual static attributes are then merged. All @ parameters are
case insensitive.

```javascript
Composite.customize("@ATTRIBUTES-STATICS", "action name src type");
Composite.customize("@Attributes-Statics", "required");
Composite.customize("@attributes-statics", "method action");
...
```

```html
<form method="POST" action="/service">
  <input type="user" name="user"
  <input type="password" name="password"/>
  <input type="submit"/>
</form>
```



- - -
&#9665; [Expression Language](expression.md)
&nbsp;&nbsp;&nbsp;&nbsp; &#8801; [Table of Contents](README.md#markup)
&nbsp;&nbsp;&nbsp;&nbsp; [Scripting](scripting.md) &#9655;
