Skip to content

Commit

Permalink
Documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
ArnaudBuchholz committed Nov 19, 2022
1 parent d65af84 commit 531e2fa
Showing 1 changed file with 59 additions and 13 deletions.
72 changes: 59 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
[![MIT License](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)


A minimalist one-way binding helper.
A minimalist *(⇡ check the install size)* one-way binding helper.

## Usage

### 1. Inject the punybind helper
### 1. Include the punybind helper

```html
<script src="punybind.js"></script>
<script src="https://cdn.jsdelivr.net/npm/punybind/dist/punybind.js"></script>
```

### 2. Define bindings in the HTML
Expand All @@ -26,7 +26,6 @@ A minimalist one-way binding helper.
<html>
<head>
<title>TODO list</title>
<script src="punybind.js"></script>
</head>
<body>
<h1>{{ title }}</h1>
Expand All @@ -40,8 +39,7 @@ A minimalist one-way binding helper.
</html>
```

Text elements and attribute values can use `{{ }}` syntax.
The special `{{for}}` attribute defines an iteration.
See below for supported syntaxes.

### 3. Bind the section

Expand All @@ -52,35 +50,83 @@ const update = await punybind(document.body)
The `update` asynchronous method exposes the following properties :
* `bindingsCount` (number) : The number of bindings detected
* `model` (object) : The reactive model (see below)
* `done` (function) : Returns a promise being fulfilled when the last update completes (see below).

Upon `update` invocation, the returned [promise is fulfilled](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) when the DOM update is **completed**.

### 4. Update the section by passing a context object

```JavaScript
await update({
title: 'My TODO list',
items: [{
done: false,
done: true,
text: 'Forget about heavy frameworks'
}, {
done: true,
done: false,
text: 'Adopt punybind'
}]
})
```

*Or use the reactive model (see below).*

### 5. Enjoy !

## Supported syntaxes

### Text and attribute binding

Text nodes and attribute values leverage binding using the `{{ expression }}` syntax.

The `expression` is evaluated with the properties of the contextual object.

It is possible to mix static content with computed one but *any* error **clears** the whole value.

### Iterators

Iterators allow the repetition of elements.

An iterator is declared **on** the element to repeat using the special attribute `{{for}}` with the value being either :
* `{{for}}="item of expression"`
* `{{for}}="item, index of expression"`

Where :
* `item` is the contextual property receiving the value of the current iteration (to use in the subsequent bindings),
* `index` is the contextual property receiving the index of the current iteration (0-based),
* `expression` must evaluate to an [iterable object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols).

### Conditionals

Conditionals rule the rendering of elements.

They can form an `if` / `elseif` / `else` chain. Their expression must evaluate to a [truthy value](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) to enable rendering.

To work properly, the attributes must be set **on contiguous sibling elements** :
* `{{if}}="expression"` : must be the first element of the chain,
* `{{elseif}}="expression"` : (optional) is evaluated and rendered only if the previous `if` / `elseif` did not evaluate to a truthy value,
* `{{else}}` : (optional) terminates the chain and is rendered only if the previous `if` / `elseif` did not evaluate to a truthy value.

## Reactive model

```JavaScript
const { model } = await punybind(document.body, {
title: 'Hello World !'
const { model, done } = await punybind(document.body, {
title: 'Hello World !',
items: []
})
console.log(model.title) // Hello World !
model.title = 'It works !' // Triggers update
// The following lines of code trigger updates
model.title = 'My TODO list'
model.items.push({
done: false,
text: 'Adopt punybind'
})
await done() // Wait for the DOM update to be completed
```

## Implementation notes

* This implementation is **not** compliant with [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP).
* For textual values, it is possible to mix static content with computed one but any error clears the whole value.
* The implementation is **not** compliant with [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP).
* **Only** properties coming from the contextual object can be used in evaluated expressions.
* Bound elements are *hidden* under [`template` elements](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template).
* When any error occurs *(inconsistent binding, invalid syntax)*, the binding **silently** fails.

0 comments on commit 531e2fa

Please sign in to comment.