Controls how HTML is going to be inserted into your page. Should be set on an origin element. Can be one of the following keywords:
| ||replace target element with an incoming element (default)|
| ||replaces target's children with an incoming element|
| ||inserts incoming element as a first child of the target|
| ||inserts incoming element as a last child of the target|
| ||inserts incoming element before target|
| ||inserts incoming element after target|
| ||morphs incoming element into target (see lower)|
| ||same as |
| ||just skip that response, sometimes useful for operations with side-effects|
With the exception of
morph-all (see further) and
TwinSpark will try to “settle” all elements with an
New elements with an
id will be inserted with
ts-insert class, which is then
removed. Existing elements will be inserted with an old values in
attibutes (by default this is
height), and then
given new values shortly afterwards.
This makes transitions work: same element changes from old to new values, which triggers transitions.
Morph is a complex algorithm, and it could take tens of ms on complex layouts, but it could be really useful at times.
Main idea is to keep elements with
id in place, only updating their
attributes, so that all the browser state (focus, transitions, animations,
playing state of videos and audios) is kept intact. This makes doing form
validation and various animations easy.
Every new element with an
id attribute is insert with a
ts-insert class. It
is removed after a short timeout, so you can add some transitions on that. Same
with elements being removed, they are given
ts-remove class, so you can
transition to that.
Original idea is from idiomorph.
TwinSpark has a somewhat smaller implementation, see code for details (search
Multiple Children #
If you look how endless scrolling is implemented in HTML, it's usually a long
list of elements inside some other element - so you have to deal with several
elements being appended to a parent. For this and similar use cases there is
Element 1 Element 2
<p class="list2"> <span class="chip">Element 1</span> <span class="chip">Element 2</span> <button class="btn" ts-req="/children" ts-req-selector="children .list" ts-target="sibling .chip:last-of-type" ts-swap="morph">Morph last</button> </p>
Dynamic Form Validation (advanced)#
Form validation is a common task, and TwinSpark allows to consolidate
validation logic on the server. Surprisingly, it could be difficult, but
ts-swap="morph" strategy allows us to just return whole new form
with errors and not mess up with focus.
- Inputs have an
idattribute - so that morphing algorithm can find them reliably.
- POST body contains
<input type="submit">'s value - this way backend distinguish submission and validation.
keyupupdates form on every character input and it feels natural - morph algorithm skips currently focused element so that state is intact.
Solve this problem with odd numbers
Animated Pagination #
Morphing gives you ability to add animations and transitions during HTML replacement. This example uses zero lines of custom JS, just some styles to add transitions.
Morphing Video #
This is a hard problem to solve with other algorithms (notably, morphdom gets
it wrong). HTML structure is changed a lot, and element with an
id is deep (enough) inside that structure, but Youtube video
still plays after change.