API Reference
rx
Namespace
This contains the core reactive programming primitives. These are the core data structures:
ObsCell
: observable cell base classSrcCell
: a source cell, one that can be directly mutatedDepCell
: a dependent cell, one whose value is some function of another observable cell
ObsArray
: observable array base classSrcArray
: a source array, one that can be directly mutatedDepArray
: a dependent array, one whose value is some transformation of another observable array
ObsMap
: observable object (map) base classSrcMap
: a source object, one that can be directly mutatedDepMap
: a dependent object, one whose value is some transformation of another observable object
Ev
: an event node; serves as a pub-sub node for events of a certain type
Free functions
cell(value)
: return aSrcCell
initialized to the given value (optional; defaults toundefined
)array(value[, diff])
: return aSrcArray
initialized to the given array (optional; defaults to[]
) and the givendiff
function for computing/propagating the minimal set of change events (defaults torx.basicDiff()
).bind(fn)
: given a 0-ary function, return aDepCell
whose value is bound to the result of evaluating that function. The function is immediately evaluated once, and each time it's evaluated, for any accesses of observables, theDepCell
subscribes to the corresponding events, which may subsequently trigger future re-evaluations.snap(fn)
: evaluate the given 0-ary function while insulating it from the enclosing bind. This will be evaluated just once and prevents subscriptions to any observables contained therein.asyncBind(init, fn)
: create an asynchronous bind. The givenfn
is expected to callthis.record(f)
up to at most one time at some point during its potentially asynchronous duration before callingthis.done(result)
. The call tothis.record(f)
evaluatesf
while recording the implicit subscriptions triggered by accesses to observables. (You can calldone
from withinrecord
but the result won't be set on this cell until afterrecord
finishes.) The cell's initial value isinit
.lagBind(lag, init, fn)
: same asbind
but waits a 500ms delay after a dependency changes (or after initialization) before theDepCell
refreshes. For the first 500ms, the cell's value isinit
; you can set this to e.g.noSub(fn)
if you want to immediately populate it with the result of evaluating your givenfn
.postLagBind(init, fn)
: immediately evaluatesfn
, which is expected to return a{val, ms}
, wherems
indicates how long to wait before publishingval
as the new value of thisDepCell
. Until the first published value, the cell is initialized toinit
.reactify(obj, spec)
: mutates an object to replace the specified fields with ES5 getters/setters powered by an observable cell/array, and returns the object.spec
is a mapping from field name to{type, val}
, wheretype
is'array'
or'cell'
andval
is an optional initial value.autoReactify(obj)
: mutates an object toreactify
all fields (specifyingarray
for arrays andcell
for everything else), and returns the objectflatten(xs)
: given an array of either arrays, observable arrays, observable cells, or other elements, flatten them into one dependent array, which will be able to react to changes in any of the observables. It furthermore strips outundefined
/null
elements (for convenient conditionals in the array).onDispose(callback)
: add a (0-ary) cleanup listener, which gets fired whenever the current (enclosing) bind is removed or refreshed. This is useful for proper resource disposal, such as closing a connection or removing an interval timer.skipFirst(f)
: wrap a 1-ary function such that the first invocation is simply dropped. This is useful for subscribing an event listener but suppressing the initial invocation at subscription time.autoSub(ev, listener)
: Subscribes a listener to an event but such that if this is called from within abind
context, the listener will be properly cleaned up (unsubscribed) on context disposal. Returns the subscription ID.concat(arrays...)
: returns a dependent array that is the result of concatenating multipleObsArray
s (efficiently maintained).cellToArray(cell[, diff])
: given anObsCell
of an array, return aDepArray
that issues the minimal set of change events by diffing the contents of the array to determine what has changed. Similar in mechanism toSrcArray.update
.diff
is an optional diff function (seeSrcArray.update
documentation) and defaults torx.basicDiff()
.basicDiff([key])
: returns a diff function that takes two arrays and uses the given key function, which defaults torx.smartUidify
, to efficiently hash-compare elements between the two arrays. Used byrx.cellToArray
.smartUidify(x)
: returns a unique identifier for the given object. If the item is a scalar, then return its JSON string. If the item is an object/array/etc., create a unique ID for it, insert it (this is a standard "hashing hack" for JS) as a non-enumerable property__rxUid
, and return it (or just return any already-existing__rxUid
). I.e., this implements reference equality. Used byrx.basicDiff
.lift(x[, spec])
: convert an objectx
containing regular non-observable fields to one with observable fields instead.spec
is a mapping from field name to either'cell'
,'array'
, or'map'
, based on what kind of observable data structure we want. By default this is supplied byrx.liftSpec
.liftSpec(x)
: given an objectx
, return a spec forrx.lift
where any field that is an array is to be stored in anrx.array
, and otherwise in anrx.cell
.transaction(f)
: run the given function in a transaction, during which updates to observables will not emit change events to their subscribers. Only once the transaction ends will all events be fired (at which time the state of the source cells will no longer be in flux, and thus a consistent view of the universe can always be maintained).
ObsCell
members
get()
: return current value of the cellonSet
: the event that is fired after the value of the cell is changed. The event data is an array of two elements,[oldVal, newVal]
.
SrcCell
members
set(x)
: set value of cell tox
and return old value ofx
- inherits
ObsCell
DepCell
members
- inherits
ObsCell
disconnect
: unsubscribes this cell from its dependencies and recursively disconnects all nested binds; useful for manual disposal ofbind
s
ObsArray
members
at(i)
: return element ati
all()
: return array copy of all elementsraw()
: return raw array of all elements; this is unsafe since mutations will violate the encapsulated invariants, but serves as a performance escape hatch aroundall()
length()
: return size of the arraymap(fn)
: returnDepArray
of given function mapped over this arrayonChange
: the event that is fired after any part of the array is changed. The event data is an array of three elements:[index, added, removed]
, whereindex
is the index where the change occurred,added
is the sub-array of elements that were added, andremoved
is the sub-array of elements that were removed.indexed()
: return aDepArray
that mirrors this array, but whosemap
method passes in the index as well. The mapper function takes(x,i)
wherex
is the current element andi
is a cell whose value always reflects the index of the current element.
SrcArray
members
SrcArray([xs[, diff]])
: constructor that initializes the content array toxs
(note: keeps a reference and does not create a copy) and the diff function forupdate
todiff
(defaults torx.basicDiff()
).splice(index, count, additions...)
: replacecount
elements starting atindex
withadditions
insert(x, i)
: insert valuex
at indexi
remove(x)
: find and remove first occurrence ofx
removeAt(i)
: remove element at indexi
push(x)
: appendx
to the end of the arrayput(i, x)
: replace elementi
with valuex
replace(xs)
: replace entire array with raw arrayxs
update(xs[, diff])
: replace entire array with raw arrayxs
, but apply thediff
algorithm to determine the minimal set of changes for which to emit events. This enables flexible updating of the array, representing arbtirary transformations, while at the same time minimizing the downstream recomputation necessary (particularly DOM manipulations).- inherits
ObsArray
DepArray
members
- inherits
ObsArray
ObsMap
members
get(k)
: return value associated with keyk
all()
: return raw object copyonAdd
: the event that is fired after an element is added. The event data is[key, newVal]
.onRemove
: the event that is fired after an element is removed. The event data is[key, oldVal]
.onChange
: the event that is fired after a key's value is changed. The event data is[key, oldVal, newVal]
.
SrcMap
members
put(k, v)
: associate valuev
with keyk
and return any prior value associated withk
remove(k)
: remove the entry associated at keyk
update(map)
: update the currentSrcMap
's contents to those of the given JS objectmap
, triggering any necessaryremove
s andput
s- inherits
ObsMap
DepMap
members
- inherits
ObsMap
Ev
members
sub(listener)
: subscribes a listener function for events from this event node and returns a unique ID for this subscription, which can be used as the handle by which to unsubscribe later. The listener takes a single argument, whose type depends on the event, and is called every time an event is fired on this event node.pub(data)
: publish an event, described by the data indata
.data
is what will be passed to all the subscribed listeners.unsub(subscriptionId)
: detaches a listener from this event.
rx.rxt
Namespace
This contains the template DSL constructs. Main thing here is the tag function, which is what constructs a DOM element.
Free functions
mktag(tag)
: returns a tag function of the given tag name. The various tags likediv
andh2
are simply aliases; e.g.,div = mktag('div')
. Tag functions themselves take(attrs, contents)
, both optional, whereattrs
is a JavaScript object of HTML attributes and/or special attributes andcontents
is an array (ObsArray
or regularArray
) of child nodes (either raw elements,RawHtml
, or jQuery objects) and/or strings (for text nodes). You can also pass in a singular such node without the array. The function returns an instance of the specified element wrapped in a jQuery object. See alsospecialAttrs
below for more on special attributes.importTags([dest])
: populate the global namespace (or thedest
object if given) with the tag symbols, so you don't need haverxt
all over your templates. Useful for quickly throwing something together.rawHtml(html)
: returns aRawHtml
wrapper for strings that tags won't escape when rendering; example:div {}, [rawHtml('<span>hello</span>')]
rxt.cast(...)
: two forms:rxt.cast(opts, types)
: convenience utility for use in preparing arguments for a component.opts
is the arguments object mapping, andtypes
is an object mapping fields ofopts
to eithercell
orarray
.cast
returns a copy ofopts
but with the fields casted based on the specified desiredtypes
(yielding observable cells and arrays).rxt.cast(data, type)
: lift the given datum to the given type; acts as identity function if data is already of the proper type
rxt.cssify(props)
: (deprecated: set thestyle
property directly to a JSON object instead of using this so as to usejQuery.css
, which is smarter about interpreting the given values) convenience utility for programmatically constructing strings suitable for use as astyle
attribute. Takes an object mapping camelCase versions of style property names and values that are either strings (which are put in verbatim), numbers (which are written as pixels), ornull
/undefined
(which omits that property altogether).rxt.smushClasses(classes)
: convenience utility for programmatically constructing strings suitable for use as aclass
attribute. Takes an array of strings orundefined
s (useful for conditionally including a class), and filters out thenull
/undefined
.- Tags:
p
,br
,ul
,li
,span
,anchor
,div
,input
,select
,option
,label
,button
,fieldset
,legend
,section
,header
,footer
,strong
,h1
,h2
,h3
,h4
,h5
,h6
,h7
jQuery plug-in
rx(property)
: lazily create (or take the cached instance) of a cell whose value is maintained to reflect the desired property on the element.property
can be'checked'
,'focused'
, or'val'
. Returns the cell.
Special attributes
Special attributes are handled differently from normal. The built-in
special attributes are primarily events like click
:
button {click: -> console.log('hello')}, 'Hello'
Special attributes are really just a convenient short-hand for running the handler functions after constructing object. The above example is equivalent to:
$button = button 'Hello'
$button.click -> console.log('hello')
The built-in special attributes available include:
init
: which is a 0-ary function that is run immediately upon instantiation of the element.style
: automatically transforms the given value withcssify
if it's not a stringclass
: automatically transforms the given value withsmushClasses
if it's not a stringevents like
click
,focus
,mouseleave
,keyup
,load
, etc.,: these are available for all jQuery events. The handlers are similar to those you would pass to a jQuery event method—they take a jQuery event and return false to stop propagation—but the context is the jQuery-wrapped element instead of the raw element. The full list:blur
change
click
dblclick
error
focus
focusin
focusout
hover
keydown
keypress
keyup
load
mousedown
mouseenter
mouseleave
mousemove
mouseout
mouseover
mouseup
ready
resize
scroll
select
submit
toggle
unload
specialAttrs
: an object mapping special attribute names to the functions
that handle them. When an element specifies a special attribute, this
handler function is invoked. The handler function takes (element, value,
attrs, contents)
, where:
element
is the element being operated onvalue
is the value of this special attribute forelement
attrs
is the full map of attributes forelement
contents
is the content/children forelement
(which can be a string,RawHtml
, array,ObsCell
, orObsArray
)
So for instance, we can create a special attribute drag
that just
forwards to the jQuery [jdragdrop]
plug-in:
rxt.specialAttrs.drag = (elt, fn, attrs, contents) -> elt.drag(fn)
and then use it like so in your templates:
div {class: 'block', drag: -> $(this).css('top', e.offsetY)}