Skip to content

Commit db9895f

Browse files
author
Vlad Balin
committed
Finalized Events chapter
1 parent ba6d5a6 commit db9895f

File tree

10 files changed

+1784
-188
lines changed

10 files changed

+1784
-188
lines changed

docs/chapters/Events.md

Lines changed: 38 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,38 @@
11
# Events
22

3-
Both `Record` and `Collection` uses an efficient synchronous events implementation which is compatible with Backbone 1.1 Events API but is twice faster in average. It comes in form of `Events` mixin and the `Messenger` base class.
4-
5-
An implementation is optimized for the large amount of relatively small subscriptions (5-10 events). Here are the benchmark results (lower is the better).
6-
7-
![performance](./events-performance.jpg)
8-
9-
It is also available separately as part of [MixtureJS](https://github.com/Volicon/MixtureJS) package.
3+
Type-R uses an efficient synchronous events implementation which is backward compatible with Backbone 1.1 Events API but is about twice faster in all major browsers. It comes in form of `Events` mixin and the `Messenger` base class.
104

115
## Events mixin
126

13-
`Events` is a [mixin](11_Mixins.md) giving the object the ability to bind and trigger custom named events. Events do not have to be declared before they are bound, and may take passed arguments.
7+
`Events` is a [mixin](#mixins) giving the object the ability to bind and trigger custom named events. Events do not have to be declared before they are bound, and may take passed arguments.
8+
9+
Both `source` and `listener` mentioned in method signatures must implement Events methods.
1410

1511
```javascript
1612
import { mixins, Events } from 'type-r'
1713

1814
@mixins( Events )
19-
class Messenger {
15+
class EventfulClass {
2016
...
2117
}
2218
```
2319

24-
> `Messenger` abstract base class is included with Type-R, see below.
20+
<aside class="notice">There's the <code>Messenger</code> abstract base class with Events mixed in.</aside>
2521

26-
### trigger(event, arg1, arg2, ... )
22+
### source.trigger(event, arg1, arg2, ... )
2723

2824
Trigger callbacks for the given event, or space-delimited list of events. Subsequent arguments to trigger will be passed along to the event callbacks.
2925

30-
### listenTo(source, event, callback)
26+
### listener.listenTo(source, event, callback)
3127
Tell an object to listen to a particular event on an other object. The advantage of using this form, instead of other.on(event, callback, object), is that listenTo allows the object to keep track of the events, and they can be removed all at once later on. The callback will always be called with object as context.
3228

3329
```javascript
3430
view.listenTo(record, 'change', view.render );
3531
```
3632

37-
### stopListening([source], [event], [callback])
33+
<aside class="success">Subscriptions made with <code>listenTo()</code> will be stopped automatically if an object is properly disposed (<code>dispose()</code> method is called).</aside>
34+
35+
### listener.stopListening([source], [event], [callback])
3836

3937
Tell an object to stop listening to events. Either call stopListening with no arguments to have the object remove all of its registered callbacks ... or be more precise by telling it to remove just the events it's listening to on a specific object, or a specific event, or just a specific callback.
4038

@@ -44,13 +42,13 @@ Tell an object to stop listening to events. Either call stopListening with no ar
4442
view.stopListening(record); // Unsubscribe from all events from the record
4543
```
4644

47-
All Type-R classes execute `this.stopListening()` from their `dispose()` method.
45+
<aside class="notice">Messenger, Record, Collection, and Store execute <code>this.stopListening()</code> from their <code>dispose()</code> method. You don't have to unsubscribe from events explicitly if you are using <code>listenTo()</code> method and disposing your objects properly.</aside>
4846

49-
### listenToOnce(source, event, callback)
47+
### listener.listenToOnce(source, event, callback)
5048

51-
Just like listenTo, but causes the bound callback to fire only once before being removed.
49+
Just like `listenTo()`, but causes the bound callback to fire only once before being automatically removed.
5250

53-
### on(event, callback, [context])
51+
### source.on(event, callback, [context])
5452

5553
Bind a callback function to an object. The callback will be invoked whenever the event is fired. If you have a large number of different events on a page, the convention is to use colons to namespace them: `poll:start`, or `change:selection`. The event string may also be a space-delimited list of several events...
5654

@@ -78,7 +76,9 @@ All event methods also support an event map syntax, as an alternative to positio
7876

7977
To supply a context value for this when the callback is invoked, pass the optional last argument: `record.on('change', this.render, this)` or `record.on({change: this.render}, this)`.
8078

81-
### off([event], [callback], [context])
79+
<aside class="warning">Event subscription with <code>source.on()</code> may create memory leaks if it's not stopped properly with <code>source.off()</code></aside>
80+
81+
### source.off([event], [callback], [context])
8282

8383
Remove a previously bound callback function from an object. If no context is specified, all of the versions of the callback with different contexts will be removed. If no callback is specified, all callbacks for the event will be removed. If no event is specified, callbacks for all events will be removed.
8484

@@ -101,7 +101,7 @@ Remove a previously bound callback function from an object. If no context is spe
101101

102102
Note that calling `record.off()`, for example, will indeed remove all events on the record — including events that Backbone uses for internal bookkeeping.
103103

104-
### once(event, callback, [context])
104+
### source.once(event, callback, [context])
105105
Just like `on()`, but causes the bound callback to fire only once before being removed. Handy for saying "the next time that X happens, do this". When multiple events are passed in using the space separated syntax, the event will fire once for every event you passed in, not once for a combination of all events
106106

107107
## Messenger class
@@ -120,51 +120,43 @@ class MyMessenger extends Messenger {
120120

121121
Messenger implements [Events](#events-mixin) mixin.
122122

123-
### cid
123+
### messenger.cid
124124

125125
Unique run-time only messenger instance id (string).
126126

127-
### initialize()
127+
### `callback` messenger.initialize()
128128

129129
Callback which is called at the end of the constructor.
130130

131-
### dispose()
131+
### messenger.dispose()
132132

133133
Executes `messenger.stopListening()` and `messenger.off()`.
134134

135135
Objects must be disposed to prevent memory leaks caused by subscribing for events from singletons.
136136

137137
## Built-in events
138138

139-
### `event` "change" (record, options)
140-
141-
When a record's attributes have changed. Triggered by both record and collection containing the record.
142-
143-
### `event` "change:attrName" (record, value, options)
144-
145-
When a specific record's attribute has been updated
146-
147-
### `event` "changes" (collection, options)
148-
149-
When collection has changed. Single event triggered when the collection has been changed.
150-
151-
### `event` "reset" (collection, options)
152-
153-
When the collection's entire contents have been reset (`reset()` method was called).
154-
155-
### `event` "update" (collection, options)
139+
All Type-R objects implement Events mixin and use events to notify listeners on changes.
156140

157-
Single event triggered after any number of records have been added or removed from a collection.
141+
Record and Store change events:
158142

159-
### `event` "sort" (collection, options)
143+
Event name | Handler arguments | When triggered
144+
-------|-------------------|------------
145+
change | (record, options) | At the end of any changes.
146+
change:attrName | (record, value, options) | The record's attribute has been changed.
160147

161-
When the collection has been re-sorted.
148+
Collection change events:
162149

163-
### `event` "add" (record, collection, options)
150+
Event name | Handler arguments | When triggered
151+
-------|-------------------|------------
152+
changes | (collection, options) | At the end of any changes.
153+
reset | (collection, options) | `reset()` method was called.
154+
update | (collection, options) | Any records added or removed.
155+
sort | (collection, options) | Order of records is changed.
156+
add | (record, collection, options) | The record is added to a collection.
157+
remove | (record, collection, options) | The record is removed from a collection.
158+
change | (record, options) | The record is changed inside of collection.
164159

165-
When a record is added to a collection.
166160

167-
### `event` "remove" (record, collection, options)
168161

169-
When a record is removed from a collection.
170162

docs/chapters/collection.md

Lines changed: 69 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,7 @@ Initialization function which is called at the end of the constructor.
7373

7474
### collection.createSubset()
7575

76-
## Read and Update
77-
78-
Methods to update the collection. They accept common options:
79-
80-
- `sort : false` - do not sort the collection.
81-
- `parse : true` - parse raw JSON (used to set collection with a data from the server).
76+
## Read and iterate
8277

8378
### collection.get( id )
8479
Get a record from a collection, specified by an `id`, a `cid`, or by passing in a record.
@@ -98,6 +93,59 @@ Like an array, a Collection maintains a length property, counting the number of
9893

9994
Raw access to the JavaScript array of records inside of the collection. Usually you'll want to use `get`, `at`, or the other methods to access record objects, but occasionally a direct reference to the array is desired.
10095

96+
### collection.slice( begin, end )
97+
98+
Return a shallow copy of the `collection.models`, using the same options as native Array#slice.
99+
100+
### collection.indexOf( recordOrId : any ) : number
101+
102+
Return an index of the record in the collection, and -1 if there are no such a record in the collection.
103+
104+
Can take the record itself as an argument, `id`, or `cid` of the record.
105+
106+
### collection.forEach( iteratee : ( val : Record, index ) => void, context? )
107+
108+
Same as `collection.each()`.
109+
110+
### collection.each( iteratee : ( val : Record, index ) => void, context? )
111+
112+
Iterate through the elements of the collection. Similar to `Array.forEach`.
113+
114+
<aside class="notice">Use <code>collection.updateEach( iteratee, index )</code> method to update records in a loop.</aside>
115+
116+
### collection.map( iteratee : ( val : Record, index ) => T, context? )
117+
118+
Map elements of the collection. Similar to `Array.map`, but `undefined` values returned by iteratee are filtered out.
119+
120+
Thus, `collection.map` can be used to map and filter elements in a single pass.
121+
122+
### collection.filter( iteratee : Predicate, context? )
123+
124+
Return filtered array of records matching the predicate.
125+
126+
Predicate is either the iteratee function returning boolean, or an object with attribute values used to match with record's attributes.
127+
128+
### collection.every( iteratee : Predicate, context? ) : boolean
129+
130+
Return `true` if all records match the predicate.
131+
132+
### collection.some( iteratee : Predicate, context? ) : boolean
133+
134+
Return `true` if at least one record match the predicated.
135+
136+
By default there is no comparator for a collection. If you define a comparator, it will be used to maintain the collection in sorted order. This means that as records are added, they are inserted at the correct index in `collection.models`.
137+
138+
Note that Type-R depends on the arity of your comparator function to determine between the two styles, so be careful if your comparator function is bound.
139+
140+
Collections with a comparator will not automatically re-sort if you later change record attributes, so you may wish to call sort after changing record attributes that would affect the order.
141+
142+
## Update
143+
144+
Methods to update the collection. They accept common options:
145+
146+
- `sort : false` - do not sort the collection.
147+
- `parse : true` - parse raw JSON (used to set collection with a data from the server).
148+
101149
### collection.add( records, options? )
102150

103151
Add a record (or an array of records) to the collection. If this is the `Record.Collection`, you may also pass raw attributes objects, and have them be vivified as instances of the `Record`. Returns the added (or preexisting, if duplicate) records.
@@ -165,7 +213,7 @@ Any additional changes made to the collection or its items in event handlers wil
165213

166214
### collection.updateEach( iteratee : ( val : Record, index ) => void, context? )
167215

168-
Similar to the `collection.each`, but wraps the loop in a transaction.
216+
Similar to the `collection.each`, but wraps an iteration in a transaction. The single `changes` event will be emitted for the group of changes to the records made in `updateEach`.
169217

170218
### collection.push( record, options? )
171219

@@ -181,16 +229,6 @@ Add a record at the beginning of a collection. Takes the same options as add.
181229
### collection.shift( options? )
182230
Remove and return the first record from a collection. Takes the same options as remove.
183231

184-
### collection.slice( begin, end )
185-
186-
Return a shallow copy of the `collection.models`, using the same options as native Array#slice.
187-
188-
### collection.indexOf( recordOrId : any ) : number
189-
190-
Return an index of the record in the collection, and -1 if there are no such a record in the collection.
191-
192-
Can take the record itself as an argument, `id`, or `cid` of the record.
193-
194232
## Change events
195233

196234
Object tree formed by nested records is deeply observable by default; changes in every item trigger change events for the collection and all parent elements in sequence.
@@ -215,48 +253,33 @@ Subscribe for events from records. The `hander` is either the collection's metho
215253

216254
When `true` is passed as a handler, the corresponding event will be triggered on the collection.
217255

218-
## Iteration
256+
### `event` "changes" (collection, options)
219257

220-
### collection.forEach( iteratee : ( val : Record, index ) => void, context? )
258+
When collection has changed. Single event triggered when the collection has been changed.
221259

222-
Same as `collection.each()`.
260+
### `event` "reset" (collection, options)
223261

224-
### collection.each( iteratee : ( val : Record, index ) => void, context? )
262+
When the collection's entire contents have been reset (`reset()` method was called).
225263

226-
Iterate through the elements of the collection. Similar to `Array.forEach`.
227-
228-
### collection.updateEach( iteratee : ( val : Record, index ) => void, context? )
229-
230-
Similar to the `collection.each`, but wraps an iteration in a transaction. The single `changes` event will be emitted
231-
for the group of changes to the records made in `updateEach`.
232-
233-
*Use this method if you modify records in a loop*.
234-
235-
### collection.map( iteratee : ( val : Record, index ) => T, context? )
236-
237-
Map elements of the collection. Similar to `Array.map`, but `undefined` values returned by iteratee are filtered out.
238-
239-
Thus, `collection.map` can be used to map and filter elements in a single pass.
264+
### `event` "update" (collection, options)
240265

241-
### collection.filter( iteratee : Predicate, context? )
266+
Single event triggered after any number of records have been added or removed from a collection.
242267

243-
Return filtered array of records matching the predicate.
268+
### `event` "sort" (collection, options)
244269

245-
Predicate is either the iteratee function returning boolean, or an object with attribute values used to match with record's attributes.
270+
When the collection has been re-sorted.
246271

247-
### collection.every( iteratee : Predicate, context? ) : boolean
272+
### `event` "add" (record, collection, options)
248273

249-
Return `true` if all records match the predicate.
274+
When a record is added to a collection.
250275

251-
### collection.some( iteratee : Predicate, context? ) : boolean
276+
### `event` "remove" (record, collection, options)
252277

253-
Return `true` if at least one record match the predicated.
278+
When a record is removed from a collection.
254279

255-
By default there is no comparator for a collection. If you define a comparator, it will be used to maintain the collection in sorted order. This means that as records are added, they are inserted at the correct index in `collection.models`.
280+
### `event` "change" (record, options)
256281

257-
Note that Type-R depends on the arity of your comparator function to determine between the two styles, so be careful if your comparator function is bound.
258-
259-
Collections with a comparator will not automatically re-sort if you later change record attributes, so you may wish to call sort after changing record attributes that would affect the order.
282+
When a record inside of the collection is changed.
260283

261284
## Sorting
262285

docs/images/logo-dark.png

-508 Bytes
Loading

0 commit comments

Comments
 (0)