In batman.js, you need observable data structures everywhere.
Batman.Set is the observable, array-like enumerable that the framework uses internally, and you can use it too! Besides
Batman.Set, batman.js provides some other classes to help you get things done:
indexedBy) groups a Set’s items by a property value
indexedByUnique) looks up items by unique value
sortedBy) returns a sorted proxy of the Set
- Binary set operations create unions, intersections and complements of sets.
Batman.Set implements the set pattern. It is a collection of distinct objects, meaning that there can be no duplicates (unlike an array). Features of
- Enumeration (
- Guaranteed unique contents (a
Batman.Setwon’t allow duplicates, even if you call
- Sorting and searching, with internal caching
- Extensible with CoffeeScript
extendfor making custom sets
You can create a
Batman.Set by passing n items to the constructor:
You can add and remove with the
remove functions, which also take any number of items:
1 2 3
If you try to add the same (
===) item twice, it won’t be added:
1 2 3
If you try to remove an item that isn’t in the set, nothing will happen:
1 2 3
Calling these functions inside an accessor function will cause the accessor to track the
forEach(and any other
Batman.Enumablefunction, since they call
forEachunder the hood)
getting these accessors:
For example, all these accessors will be recalculated when
1 2 3 4 5 6 7 8 9 10 11
Besides automatic source tracking in accessors, you can observe these properties with
A set notifies its subscribers by firing:
itemsWereAddedwhen items are added to the set
itemsWereRemovedwhen items are removed from the set
Each event is fired with the items that were added and removed.
You can handle these events with
1 2 3 4 5
The event may be fired with the internally-determined indexes of the items. This is used internally by batman.js but isn’t implemented in all cases.
These functions cause items to be added or removed:
Under the hood, batman.js depends on these events to keep
data-foreach bindings up to date.
Set indexes are batman.js’s way of searching sets. Batman.js caches these indexes and updates them whenever items are added or removed from the base
Batman.Set. This way, you can be sure than any indexes you use will be automatically updated when the set is changed.
1 2 3 4 5
Batman.SetIndex groups the base
Batman.Set by a property of its members. For example, we can group
Then, to get vegetables of a certain color, you
get the color from the set index:
1 2 3
Batman.SetIndex::get is an example of the “default accessor as
The resulting set is just like any other
Batman.Set, so you can observe it, pass it to view bindings, etc.
get a value that doesn’t exist, you get an empty
Batman.Set. However, if a matching item is added to the base set, the index will be updated and the derived set will have the matching item added to it. For example, the
yellow vegetables set is empty at first:
But if you add a vegetable with
it will be immediately added to the derived set:
Batman.UniqueSetIndex doesn’t return a set of matching items, it returns the first matching item. This is useful when you know that the values of a property will be unique (For example, batman.js uses
MyModel.get('loaded.indexedBy.id') to update records from JSON by ID).
For example, our
vegetables all have unique names:
indexedByUnique in an accessor makes the
Batman.UniqueSetIndex a source for that accessor. So when the unique set index’s value changes, the accessor will be recalculated.
This can be demonstrated by extending our
vegetables example a little bit. Imagine a garden which should know what vegetables are growing in it. Since it’s essentially a group of vegetables, let’s extend
In our app, we want to display red/green for which vegetables are in a garden. For example,
1 2 3
Now, a Garden will return
hasTomato as soon as a tomato is added:
1 2 3 4 5 6 7
Batman.SetSort behaves just like a
Batman.Set, except that its members are ordered by a given property. If an item is added to the base set, it is also added to the set sort (in its proper place, of course).
Given these vegetables:
1 2 3 4 5
We can easily sort them by name:
1 2 3
They can also be sorted in reverse order:
Or, to sort descending by an accessor:
You don’t have to worry about calling
sortedBy repeatedly. Under the hood, batman.js caches them on their base sets, so it doesn’t recalculate the indexes and sorts every time.
Union, Intersection, Complement
Batman.BinarySetOperations are objects that track two sets and contain the resulting elements from their operations. There are three implemented subclasses of
Batman.SetUnioncontains all members from both sets, without duplicates.
Batman.SetIntersectioncontains members which are present in the first set and present in the second set.
Batman.SetComplementcontains members which are in the first set but not present in the second set.
Take note: constructors for binary set operations will fail if either argument is
null, so be sure to check for that when you’re building them!