TwinSpark was heavily influenced by Intercooler and the main reasons for existing are following:
See at Github.
This document has tests embedded in examples, to run them, press:
To simplify inner logic you have one limitation - you can only return single element from the server. If you return more, they will be ignored. How to deal with that and why it is so - read on.
Usually requests are triggered on natural interrupts: submit on forms and clicks elsewhere, but sometimes you want more, like triggering on being seen or hovered:
If you need to do some custom things around your request, you can use
ts-req-after. Those use same
ts-action, so it's pretty
flexible. One additional thing is that if last (or the only) command of
ts-req-before returns falsy value (
an empty string, or a zero) - this stops that request.
Sometimes collecting the data you need to send in templates is really
annoying: you'll have to teach lower-level components/partials/etc some
knowledge about higher levels. That is something TwinSpark can prevent: when
you send a request, it iterates through element parents and searches for
ts-data attributes, parses their content as query string or JSON
and merges it into a single object. Note how values with same keys are aggregated
into an array (like normal query string or form data). You can override that by
specifying key with null or empty string (see demo source).
Often you don't want to replace clicked element, but some other part of the
page, like if you hit "Refresh" and need to update big part of the page. This
can be done with
ts-target attribute, which takes a CSS
I'm waiting... Do it!
Interestingly, this seems like the most common pattern - when a button needs
to update an element around itself. Add modifier
element.closest(selector) method will be used to
find a parent. This will help a lot to minimize amount of ids.
Wanna read text behind me? Do it!
URLs are a fundament of the Web. Changing URLs in line with activity makes your app reloadable, browseable with backward/forward button and overall a good citizen of the Web.
It's really irritating when you click a link and nothing happens for some time. Luckily
TwinSpark makes it really easy: it adds class
ts-active to an element, enhanced with
Sometimes you don't need to go to server to do something. Closing popup or hiding an element can be done without network round trip.
Hey! I'm here!
Remove with timeout
animate(no Safari here)
Doing something when element is almost visible makes it possible to implement lazy loading and various analytical events
You'll probably see this text after around 5 seconds or so. Click "Reset" to see loader again.
This sentence will log some message when it becomes invisible (moves out of browser viewport, and, actually, on load as well).
TwinSpark usually deals with single element being target (
and single element being replacement (
ts-req-selector) - this is
much more controlled behavior than multiple elements. But 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 a modifier
This is a thing which is not immediately obvious, but is one of the reasons why TwinSpark appeared. It is an important optimization. Our use case for it was following: page renders for an anonymous user (for efficient caching on CDN) and then status of wishlisted products is checked. It's a pattern we use often and we really wanted it to be a first-class feature.
Also waiting here.
It is useful to do something when node is removed (especially if that's some child or even non-related node triggering that removal). It's possible, but not recommended to use often since performance characteristics of the code are not well understood.
When this paragraph is removed by clicking button, it will resurrect itself.
Autocomplete is interesting because it executes many things at once. Just look at the source, the interesting part is trigger modifiers - it does something only if user typed something (rather than just navigated field with cursor keys) and then stopped for 200 ms.
Filtering on ecommerce sites is a complex task. On one side you want it to be crawlable by Google, on the other if a user selected two filters one by one you'd like to see products, filtered by both. Naïve implementation will filter only one of them if a pause between clicks was short enough. It seems like the best way is form, full of links (so that Google/no-js envs can still use it), which toggle checkboxes when JS is enabled and auto-submit form.