4093da62 by Michael Richards

Separate the full documentation from the README.

1 parent 84e325a6
Showing 1 changed file with 10 additions and 181 deletions
...@@ -4,194 +4,23 @@ Rivets.js is a declarative data binding facility that plays well with existing f ...@@ -4,194 +4,23 @@ Rivets.js is a declarative data binding facility that plays well with existing f
4 4
5 --- 5 ---
6 6
7 Describe your UI in plain HTML using data attributes: 7 Rivets.js keeps your UI and model data in sync for you, so you can spend less time manually tying into the DOM and more time on your actual data and application logic.
8 8
9 ```html 9 Out-of-the-box it’s got:
10 <div id='auction'>
11 <h1 data-text='auction.title'></h1>
12 <img data-src='auction.image_url'>
13 <span data-text='auction.timeRemaining | time'></span>
14 10
15 <div class='alert-box' data-show='auction.endingSoon'> 11 - **One-way** and **two-way** binding to/from DOM elements.
16 <p>Hurry up! This auction is ending soon.</p> 12 - **Computed properties** with dependent attributes.
17 </div> 13 - **Formatters** to allow mutatating values through piping.
14 - **A powerful custom bindings API** for building your own binding routines.
15 - **Easy debugging** and manual bidirectional syncing of bindings.
18 16
19 <dl> 17 ## Getting Started and Documentation
20 <dt>Highest Bid:</dt>
21 <dd data-text='auction.bid | currency'></dd>
22 <dt>Bidder:</dt>
23 <dd data-text='auction.bidder'></dd>
24 </dl>
25 18
26 <dl> 19 All documentation for Rivets.js is available on the [homepage](http://rivetsjs.com). See [#configure](http://rivetsjs.com#configure) to learn how to properly configure Rivets.js for your app.
27 <dt>Bids Left:</dt>
28 <dd data-text='user.bidCount'></dd>
29 </dl>
30 </div>
31 ```
32
33 Then tell Rivets.js what model(s) to bind to it:
34
35 ```javascript
36 rivets.bind($('#auction'), {auction: auction, user: currentUser});
37 ```
38 ## Configure
39
40 Use `rivets.configure` to configure Rivets.js for your app (or you can set configuration options manually on `rivets.config`).
41
42 #### Adapter
43
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.
45
46 ```javascript
47 rivets.configure({
48 adapter: {
49 subscribe: function(obj, keypath, callback) {
50 obj.on('change:' + keypath, callback);
51 },
52 unsubscribe: function(obj, keypath, callback) {
53 obj.off('change:' + keypath, callback);
54 },
55 read: function(obj, keypath) {
56 return obj.get(keypath);
57 },
58 publish: function(obj, keypath, value) {
59 obj.set(keypath, value);
60 }
61 }
62 });
63 ```
64
65 #### Prefix and data preloading
66
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`.
68
69 ```javascript
70 rivets.configure({
71 prefix: 'rv'
72 });
73 ```
74
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.
76
77 ```javascript
78 rivets.configure({
79 preloadData: false
80 });
81 ```
82
83 ## Extend
84
85 Rivets.js is easily extended by adding your own custom *binding routines* and *formatters*. Rivets.js comes bundled with a few commonly used bindings, but users are encouraged to add their own that are specific to the needs of their application.
86
87 #### Binding Routines
88
89 *Binding routines* are the functions that run when an observed attribute changes. Their sole concern is to describe what happens to the element when a new value comes in. All binding routines are publicly available on the `rivets.routines` object.
90
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:
92
93 ```javascript
94 rivets.routines.color = function(el, value) {
95 el.style.color = value;
96 };
97 ```
98
99 With that routine defined, the following binding will update the element's color when `model.color` changes:
100
101 ```html
102 <span data-color="model.color">COLOR</span>
103 ```
104
105 Available bindings out-of-the-box:
106
107 - data-text
108 - data-html
109 - data-value
110 - data-show
111 - data-hide
112 - data-enabled
113 - data-disabled
114 - data-checked
115 - data-unchecked
116 - data-*[attribute]*
117 - data-class-*[class]*
118 - data-on-*[event]*
119 - data-each-*[item]*
120
121 #### Formatters
122
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.
124
125 ```javascript
126 rivets.formatters.money = function(value){
127 return accounting.formatMoney(value);
128 };
129
130 rivets.formatters.date = function(value){
131 return moment(value).format('MMM DD, YYYY');
132 };
133 ```
134
135 ```html
136 <span data-text="event.startDate | date"></span>
137 ```
138
139 ## Usage Notes
140
141 #### Rivets.View and Rivets.Binding
142
143 The `rivets.bind` function returns a bound `Rivets.View` instance that you should hold on to for later. You may want to unbind it's listeners with `view.unbind()` and/or rebuild it's bindings with `view.build()`. You can also access the individual `Rivets.Binding` instances inside the view through `view.bindings` — this is useful for debugging purposes or if you want to unbind or manually set the value for certain bindings.
144
145 #### Adapter Bypass
146
147 If your model object encapsulates it's attributes (e.g. `model.attributes` for Backbone.js models) and your adapter conforms to that object specifically, you can still utilize properties defined outside of that object — such as functions or other static values defined on the object root.
148
149 Just use `model:property` instead of `model.property` inside your binding declaration and Rivets.js will bypass the adapter completely and access that property as it's defined on the object root. This obviously won't sync any changes, but that is by design in this case as these properties should be mostly static and used in conjunction with other "dynamic" properties.
150
151 #### Computed Properties
152
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.
154
155 ```html
156 <span data-text="event:duration < .start .end"></span>
157 ```
158
159 The prepended `.` is a shorthand syntax for specifying dependencies that are on the same object as the target, so that the above declaration is effectively the same as `event:duration < event.start event.end`.
160
161 #### Iteration Binding
162
163 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.
164
165 ```html
166 <ul>
167 <li data-each-todo="list.todos">
168 <input type="checkbox" data-checked="todo.done">
169 <span data-text="todo.summary"></span>
170 </li>
171 <ul>
172 ```
173
174 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`.
175
176 ```html
177 <ul>
178 <li data-each-link="item.links">
179 <a data-href="link:url" data-text="link:title"></span>
180 </li>
181 </ul>
182 ```
183
184 Also note that you may bind to the iterated item directly on the parent element.
185
186 ```html
187 <ul>
188 <li data-each-tag="item.tags" data-text="tag:name"></li>
189 </ul>
190 ```
191 20
192 ## Building and Testing 21 ## Building and Testing
193 22
194 Make sure to run `npm install` so that you have all the development dependencies. To have the test suite run as part of the build process, you'll also need to have [PhantomJS](http://phantomjs.org) installed. 23 Make sure to run npm install so that you have all the development dependencies. To have the test suite run as part of the build process, you'll also need to have PhantomJS installed.
195 24
196 #### Building 25 #### Building
197 26
......