A minimalistic two-way binding system. View twine on GitHub.
Bindings are defined with strings of JavaScript directly on a DOM node. This means you're already familiar with the binding syntax, and you have access to all the properties inside your binding definition that the underlying object does.
For input elements, the initial value of a binding will be read from the DOM if it's not already defined:
Every binding is evaluated relative to a context. All this means is that when you write data-bind="key"
, you're accessing the key
property of the current context. Any value can be used as a context, so most of the time you'll use a plain ol' JavaScript object.
The context for this page is stored on window
, so you can access it in the console if you want. Since it's just an object, it's easy to encode:
In this demonstration, the context was defined and initialized with:
var context = {}; Twine.reset(context).bind().refresh();
The context is shown in the sidebar for reference as you peruse.
It is also possible to create sub-contexts with the define
attribute.
data-define
can be used for context creation or for introducing variables into the current context.
This can be pretty useful for when you want to use data-bind-show
and start in a visible state.
data-context
lets you change the current context for every element nested inside.
data-define-array
lets you define an array of objects one at a time in the context and implicitly reference the correct member in the array.
data-define-array
can also be used with data-context
data-bind-show
adds the class hide
to the node. You can then use CSS like .hide { display: none; }
or similar to hide the node and its children from view.
That color is not longer than 4 characters.
data-bind-class
toggles a node's classes, given an object with class names for keys and booleans for values.
The binding value of checkboxes is a boolean indicating the checked state.
The binding value of radio buttons is the value
attribute of the currently selected button. Make sure to use the same key for every button in the radio group.
State:
Alternatively, you may use data-bind-checked
, which is a one-way binding of the checked
attribute.
The following DOM attributes can be bound to via:
data-bind-placeholder
data-bind-checked
data-bind-disabled
data-bind-href
data-bind-title
data-bind-readOnly
data-bind-draggable
DOM events are available for quick bindings. The default behaviour (think event.preventDefault
) will be prevented, unless either:
event.type === "submit"
<a>
Additionally, the presence of allow-default
attribute will cause the twine system to never prevent default, rending the two exceptions above moot.
The following events are provided:
data-bind-event-click
data-bind-event-dblclick
data-bind-event-mouseenter
data-bind-event-mouseleave
data-bind-event-mouseover
data-bind-event-mouseout
data-bind-event-mousedown
data-bind-event-mouseup
data-bind-event-submit
data-bind-event-dragenter
data-bind-event-dragleave
data-bind-event-dragover
data-bind-event-drop
data-bind-event-drag
data-bind-event-change
data-bind-event-keypress
data-bind-event-keydown
data-bind-event-keyup
data-bind-event-input
data-bind-event-error
data-bind-event-done
data-bind-event-success
data-bind-event-fail
data-bind-event-blur
data-bind-event-focus
data-bind-event-load
Remember how bindings are just JavaScript? The same applies for event handlers.
However, inline mutation is pretty ghetto, so let's define some functions on our context. (these won't appear in the sidebar since JSON.stringify
ignores functions)
Events bound in this way have access to a few named parameters that you can pass in:
this
: the node in questionevent
: the event object that is firedYou pressed key:
inside of input with ID:
Further, as you can see from the example keyPressed
above, this
inside of a function called this way will refer to the current context.