paxi.js is an experimental, minimalist companion to [fixi.js](https://github.com/bigskysoftware/fixi)
that swaps HTML into the DOM by *morphing* instead of replacing: preserving existing nodes,
focus, scroll position, and form state wherever the old and new trees align.
Part of the [fixi project](https://fixiproject.org).
When paired with fixi, paxi registers itself as the `morph` swap strategy, so you can write
`fx-swap="morph"` and get id-keyed reconciliation out of the box. It also works stand-alone
via the `window.morph(target, html)` global.
Here is an example:
```html
...
```
The response HTML replaces the contents of `#profile`, but the `` keeps its focus,
caret, and any in-progress value because its `id` matches a node in the incoming markup.
## Minimalism
paxi is to [idiomorph](https://github.com/bigskysoftware/idiomorph) what fixi is to htmx:
a smaller, less ambitious take on the same idea. No configuration, no callbacks, no
head-merging, no id-set inference - just a single recursive diff that keeps id-keyed
nodes stable as the tree around them changes.
As such, it does *not* include many features found in idiomorph or morphdom:
* head merging / stylesheet reconciliation
* `beforeNodeMorphed` / `afterNodeMorphed` callbacks
* `outerHTML` vs `innerHTML` modes
* id-set propagation across ancestors
* pluggable node matchers
A hard constraint on the project is that the *unminified, uncompressed* size stays under
2KB.
## Installing
Drop `paxi.js` in a script tag after (or before) `fixi.js`:
```html
```
Or install via npm:
```
npm install @bigskysoftware/paxi-js
```
## API
### `window.morph(target, html)`
Morph `target` (an `Element`) toward the first element parsed from `html` (a string). The
target is updated in place when the root node names match; otherwise it is replaced.
```js
morph(document.getElementById("panel"), "
new contents
")
```
### `fx-swap="morph"`
When loaded alongside fixi, paxi registers a config hook that intercepts `fx-swap="morph"`
and wires it to `morph(cfg.target, cfg.text)`.
## Modus Operandi
paxi walks the old and new trees in lockstep:
1. If node type or name differ, the old node is replaced - but any id-keyed descendant of
the incoming node whose id matches a node in the old tree is first rescued into place.
2. For text and comment nodes, the value is updated when it differs.
3. For elements, attributes are synced (extras removed, missing added, values updated).
4. Children are reconciled positionally, except that id-keyed children in the incoming
tree pull their original counterparts forward when they exist.
## LICENCE
```
Zero-Clause BSD
=============
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE
FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
```