# xxdom.js
## What is xxdomjs?

xxdom.js is a lightweight JavaScript library that provides incremental
DOM rendering through declarative directives. It allows developers to
bind JavaScript data to HTML elements using attribute-based directives
(like `xx-for`, `xx-if`, `xx-text`) and mustache-style interpolation
(`{{expression}}`).

The library implements a manual reactivity model where developers
explicitly call `xx()` to trigger DOM updates after data changes,
providing precise control over rendering cycles.


# Jump start

[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/jensh/xxdomjs)

You can play with the code online [on jsfiddle.net](https://jsfiddle.net/jensh/8k93yzat/).

Load `xx.min.js` and you are ready for rendering dynamic content with well known `{{expression}}` syntax.
The expression in-between `{{}}` is pure JavaScript.

```html
<script src="https://4k2.de/xxdomjs/dist/xx.min.js"></script>

Hello {{ world + '!' }} <br>
Today is: {{ (new Date).toDateString() }}.

<script>
	var world="world";
</script>
```

You can bind an "xx-scope" to an HTML element. Additionally to the global JavaScript scope, every expression
placed in one of the children have also access to this xx-scope. This works very much like
local variables in js functions.

```html
<div xx-scope="{ x:'local X'}">
	Access local var x = {{x}}<br>
	Access global var world = {{world}}
</div>
```

Within event handlers the xx-scope of that element can be accessed by
the new property `$scope`. As a side effect, reading the property
`$scope` also schedules a render update.


## xx-text

You can `xx-text` the result of an expression to the elements `el.innerText`.

```html
Hello <span xx-text="world"></span><span xx-text="'!'"></span>
```


## xx-for

Loop over an iterable collection of something and access the items in there on "xx-scope".

```html
<ul>
	<li xx-for="item of things.reverse()">
		The {{item.name}} is
		<span xx-style="{color: (item.color)}" xx-text="item.color"></span>.
	</li>
</ul>
<script>
var things = [
	{ name: 'banana', color: 'blue' },
	{ name: 'fox', color: 'brown'},
	{ name: 'ball', color: 'red' },
];
</script>
```

## xx-if

Yes, we have also an if:
```html
<div xx-scope="{ isCool: true }">
	Criss-Cross <span xx-if="isCool">is cool!</span>
</div>
```


## xx-style, xx-class

xx-style uses the key-value pairs of a js object as "style property" and "value". xx-class use
the keys as the "classname" and its value is an boolean expression for using or not using this "classname".


```html
<div xx-scope="{ isSelected: true, acolor: 'blue' }">
	<div xx-style="{width: '300px', color: acolor}" xx-class="{ selected: isSelected }">
		Criss-Cross
	</div>
</div>
```

## xx-prop

`xx-prop` bind to element properties. `xx-prop` expects an js-object. The
key names of this js-object are the element property names to assign to.

```html
<input xx-prop="{value: aValue}">
```

will do on every value change:

```js
elInput.value = aValue;
```

## xx-attr

`xx-attr` bind to element attributes. `xx-attr` expects an js-object. The
key names of this js-object are the element attribute names to assign to.

```html
<input xx-attr="{hint: aHint}">
```

will do on every value change:

```js
elInput.setAttribute('hint', aHint);
```

## xx-component

Define a new component with `<template xx-component="{name}">` and use it with its name `<{name}></{name}>`:
```html
<abc></abc>
<abc></abc>

<template xx-component="abc">
	<div>The quick brown fox jumps over the lazy dog.</div>
</template>
```


## Re-render

The HTML document will be rendered with Criss-Cross after the "DOMContentLoaded" event.
If the data/your model changes, you can re-render the DOM by calling `xx.render()` or
short just `xx()`. Only changed values will trigger a change on the HTML element. On
`xx-for` loops, the item identity operator ('===') is used to detect additions, deletions,
replacements and kept items. If only the item content changes, its HTML element only gets
an update.

```html
<div> It is: {{ new Date }}</div>
<script>setInterval(xx, 1000);</script>
```

## Exported helpers

### `xx.expr(exStr, el)`

Creates a reusable function that evaluates the JavaScript expression
given in exStr.

Parameters:

 * `exStr` the expression to evaluate, as a string.
 * `e` the element associated with this expression; used only for
   context in console error messages.

Returns:

A function (scope) => result that evaluates `exStr` against the given
`scope` object (i.e., scope's properties are accessible as local
variables within the expression). If `exStr` is empty/falsy, or if it
fails to parse, `null` is returned instead. Runtime errors during
evaluation are logged to the console and cause the function to return
an empty string.


### `xx.attrExpr(el, attrName)`

Like `xx.expr`, but reads the expression from the attribute `attrName`
on element `el` instead of taking it as a direct argument. The
attribute is removed from `el` after being read.

Parameters:

* `el` the DOM element to read the attribute from (and use for error
  context).
* `attrName` the name of the attribute containing the expression
  string.

Returns:

The same kind of evaluator function as `xx.expr`.


## Installation

Use git:
```sh
git clone https://github.com/jensh/xxdomjs.git xxdom
```

Or npm:
```sh
npm install xxdom
```

## Online examples

Here is a [link to all above examples](https://4k2.de/xxdomjs/examples/readme.html) in action.
The other [examples](https://4k2.de/xxdomjs/examples/demo.html) from this repo.

Have fun!

We are interested in your thoughts!

Twitter: [@jens4321](https://twitter.com/jens4321)
