1640b1cc by Michael Richards

Merge branch 'master' into utilize-adapter-read-when-subscribing

Conflicts:
	README.md
2 parents 3246edc1 d5ccb916
Showing 1 changed file with 70 additions and 56 deletions
...@@ -6,32 +6,35 @@ Rivets.js is a declarative data binding facility that plays well with existing f ...@@ -6,32 +6,35 @@ Rivets.js is a declarative data binding facility that plays well with existing f
6 6
7 Describe your UI in plain HTML using data attributes: 7 Describe your UI in plain HTML using data attributes:
8 8
9 <div id='auction'> 9 ```html
10 <h1 data-text='auction.title'></h1> 10 <div id='auction'>
11 <img data-src='auction.image_url'> 11 <h1 data-text='auction.title'></h1>
12 <span data-text='auction.timeRemaining | time'></span> 12 <img data-src='auction.image_url'>
13 13 <span data-text='auction.timeRemaining | time'></span>
14 <div class='alert-box' data-show='auction.endingSoon'> 14
15 <p>Hurry up! This auction is ending soon.</p> 15 <div class='alert-box' data-show='auction.endingSoon'>
16 </div> 16 <p>Hurry up! This auction is ending soon.</p>
17 17 </div>
18 <dl> 18
19 <dt>Highest Bid:</dt> 19 <dl>
20 <dd data-text='auction.bid | currency'></dd> 20 <dt>Highest Bid:</dt>
21 <dt>Bidder:</dt> 21 <dd data-text='auction.bid | currency'></dd>
22 <dd data-text='auction.bidder'></dd> 22 <dt>Bidder:</dt>
23 </dl> 23 <dd data-text='auction.bidder'></dd>
24 24 </dl>
25 <dl> 25
26 <dt>Bids Left:</dt> 26 <dl>
27 <dd data-text='user.bidCount'></dd> 27 <dt>Bids Left:</dt>
28 </dl> 28 <dd data-text='user.bidCount'></dd>
29 </div> 29 </dl>
30 </div>
31 ```
30 32
31 Then tell Rivets.js what model(s) to bind to it: 33 Then tell Rivets.js what model(s) to bind to it:
32 34
33 rivets.bind($('#auction'), {auction: auction, user: currentUser}); 35 ```javascript
34 36 rivets.bind($('#auction'), {auction: auction, user: currentUser});
37 ```
35 ## Configure 38 ## Configure
36 39
37 Use `rivets.configure` to configure Rivets.js for your app (or you can set configuration options manually on `rivets.config`). 40 Use `rivets.configure` to configure Rivets.js for your app (or you can set configuration options manually on `rivets.config`).
...@@ -40,37 +43,42 @@ Use `rivets.configure` to configure Rivets.js for your app (or you can set confi ...@@ -40,37 +43,42 @@ Use `rivets.configure` to configure Rivets.js for your app (or you can set confi
40 43
41 Rivets.js is model interface-agnostic, meaning it can work with any event-driven model by way of defining an adapter. This is the only required configuration as it's what Rivet.js uses to observe and interact with your model objects. An adapter is just an object that responds to `subscribe`, `unsubscribe`, `read` and `publish`. Here is a sample configuration with an adapter for using Rivets.js with Backbone.js. 44 Rivets.js is model interface-agnostic, meaning it can work with any event-driven model by way of defining an adapter. This is the only required configuration as it's what Rivet.js uses to observe and interact with your model objects. An adapter is just an object that responds to `subscribe`, `unsubscribe`, `read` and `publish`. Here is a sample configuration with an adapter for using Rivets.js with Backbone.js.
42 45
43 rivets.configure({ 46 ```javascript
44 adapter: { 47 rivets.configure({
45 subscribe: function(obj, keypath, callback) { 48 adapter: {
46 obj.on('change:' + keypath, callback); 49 subscribe: function(obj, keypath, callback) {
47 }, 50 obj.on('change:' + keypath, callback);
48 unsubscribe: function(obj, keypath, callback) { 51 },
49 obj.off('change:' + keypath, callback); 52 unsubscribe: function(obj, keypath, callback) {
50 }, 53 obj.off('change:' + keypath, callback);
51 read: function(obj, keypath) { 54 },
52 return obj.get(keypath); 55 read: function(obj, keypath) {
53 }, 56 return obj.get(keypath);
54 publish: function(obj, keypath, value) { 57 },
55 obj.set(keypath, value); 58 publish: function(obj, keypath, value) {
56 } 59 obj.set(keypath, value);
57 } 60 }
58 }); 61 }
59 62 });
63 ```
60 64
61 #### Prefix and data preloading 65 #### Prefix and data preloading
62 66
63 To prevent data attribute collision, you can set the `prefix` option to something like 'rv' or 'bind' so that data attributes are prefixed like `data-rv-text`. 67 To prevent data attribute collision, you can set the `prefix` option to something like 'rv' or 'bind' so that data attributes are prefixed like `data-rv-text`.
64 68
65 rivets.configure({ 69 ```javascript
66 prefix: 'rv' 70 rivets.configure({
67 }); 71 prefix: 'rv'
72 });
73 ```
68 74
69 Set the `preloadData` option to `false` if you don't want your bindings to be bootstrapped with the current model values on bind. This option is set to `true` by default. 75 Set the `preloadData` option to `false` if you don't want your bindings to be bootstrapped with the current model values on bind. This option is set to `true` by default.
70 76
71 rivets.configure({ 77 ```javascript
72 preloadData: false 78 rivets.configure({
73 }); 79 preloadData: false
80 });
81 ```
74 82
75 ## Extend 83 ## Extend
76 84
...@@ -82,13 +90,17 @@ Rivets.js is easily extended by adding your own custom *binding routines* and *f ...@@ -82,13 +90,17 @@ Rivets.js is easily extended by adding your own custom *binding routines* and *f
82 90
83 Let's say we wanted a `data-color` binding that sets the element's colour, here's what the routine function for that binding might look like: 91 Let's say we wanted a `data-color` binding that sets the element's colour, here's what the routine function for that binding might look like:
84 92
85 rivets.routines.color = function(el, value) { 93 ```javascript
86 el.style.color = value; 94 rivets.routines.color = function(el, value) {
87 }; 95 el.style.color = value;
96 };
97 ```
88 98
89 With that routine defined, the following binding will update the element's color when `model.color` changes: 99 With that routine defined, the following binding will update the element's color when `model.color` changes:
90 100
91 <span data-color="model.color">COLOR</span> 101 ```html
102 <span data-color="model.color">COLOR</span>
103 ```
92 104
93 Available bindings out-of-the-box: 105 Available bindings out-of-the-box:
94 106
...@@ -110,7 +122,7 @@ Available bindings out-of-the-box: ...@@ -110,7 +122,7 @@ Available bindings out-of-the-box:
110 122
111 *Formatters* are simple one-way functions that mutate the incoming value of a binding. You can use them to format dates, numbers, currencies, etc. and because they work in a similar fashion to the Unix pipeline, the output of each feeds directly as input to the next one, so you can stack as many of them together as you like. 123 *Formatters* are simple one-way functions that mutate the incoming value of a binding. You can use them to format dates, numbers, currencies, etc. and because they work in a similar fashion to the Unix pipeline, the output of each feeds directly as input to the next one, so you can stack as many of them together as you like.
112 124
113 ``` 125 ```javascript
114 rivets.formatters.money = function(value){ 126 rivets.formatters.money = function(value){
115 return accounting.formatMoney(value); 127 return accounting.formatMoney(value);
116 }; 128 };
...@@ -120,7 +132,7 @@ rivets.formatters.date = function(value){ ...@@ -120,7 +132,7 @@ rivets.formatters.date = function(value){
120 }; 132 };
121 ``` 133 ```
122 134
123 ``` 135 ```html
124 <span data-text="event.startDate | date"></span> 136 <span data-text="event.startDate | date"></span>
125 ``` 137 ```
126 138
...@@ -140,13 +152,15 @@ Just use `model:property` instead of `model.property` inside your binding declar ...@@ -140,13 +152,15 @@ Just use `model:property` instead of `model.property` inside your binding declar
140 152
141 Computed properties are functions that get re-evaluated when one or more dependent properties change. Declaring computed properties in Rivets.js is simple, just separate the function from it's dependencies with a *<*. The following `data-text` binding will get re-evaluated with `event.duration()` when either the event's `start` or `end` attribute changes. 153 Computed properties are functions that get re-evaluated when one or more dependent properties change. Declaring computed properties in Rivets.js is simple, just separate the function from it's dependencies with a *<*. The following `data-text` binding will get re-evaluated with `event.duration()` when either the event's `start` or `end` attribute changes.
142 154
143 <span data-text="event:duration < start end"></span> 155 ```html
156 <span data-text="event:duration < start end"></span>
157 ```
144 158
145 #### Iteration Binding 159 #### Iteration Binding
146 160
147 Use the `data-each-[item]` binding to have Rivets.js automatically loop over items in an array and append bound instances of that element. Within that element you can bind to the iterated item as well as any contexts that are available in the parent view. 161 Use the `data-each-[item]` binding to have Rivets.js automatically loop over items in an array and append bound instances of that element. Within that element you can bind to the iterated item as well as any contexts that are available in the parent view.
148 162
149 ``` 163 ```html
150 <ul> 164 <ul>
151 <li data-each-todo="list.todos"> 165 <li data-each-todo="list.todos">
152 <input type="checkbox" data-checked="todo.done"> 166 <input type="checkbox" data-checked="todo.done">
...@@ -157,7 +171,7 @@ Use the `data-each-[item]` binding to have Rivets.js automatically loop over ite ...@@ -157,7 +171,7 @@ Use the `data-each-[item]` binding to have Rivets.js automatically loop over ite
157 171
158 If the array you're binding to contains non-model objects (they don't conform to your adapter), you can still iterate over them, just make sure to use the adapter bypass syntax — in doing so, the iteration binding will still update when the array changes, however the individual items will not since they'd be bypassing the `adapter.subscribe`. 172 If the array you're binding to contains non-model objects (they don't conform to your adapter), you can still iterate over them, just make sure to use the adapter bypass syntax — in doing so, the iteration binding will still update when the array changes, however the individual items will not since they'd be bypassing the `adapter.subscribe`.
159 173
160 ``` 174 ```html
161 <ul> 175 <ul>
162 <li data-each-link="item.links"> 176 <li data-each-link="item.links">
163 <a data-href="link:url" data-text="link:title"></span> 177 <a data-href="link:url" data-text="link:title"></span>
...@@ -167,7 +181,7 @@ If the array you're binding to contains non-model objects (they don't conform to ...@@ -167,7 +181,7 @@ If the array you're binding to contains non-model objects (they don't conform to
167 181
168 Also note that you may bind to the iterated item directly on the parent element. 182 Also note that you may bind to the iterated item directly on the parent element.
169 183
170 ``` 184 ```html
171 <ul> 185 <ul>
172 <li data-each-tag="item.tags" data-text="tag:name"></li> 186 <li data-each-tag="item.tags" data-text="tag:name"></li>
173 </ul> 187 </ul>
......