7a99780e by Michael Richards

Clean up the Rivets.Binding constructor by passing only the four required argume…

…nts and using an options object.
1 parent 237f7d9b
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
3 // author: Michael Richards 3 // author: Michael Richards
4 // license: MIT 4 // license: MIT
5 (function() { 5 (function() {
6 var Rivets, attributeBinding, bidirectionals, bindEvent, eventBinding, getInputValue, rivets, unbindEvent, 6 var Rivets, attributeBinding, bindEvent, eventBinding, getInputValue, rivets, unbindEvent,
7 __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, 7 __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
8 __slice = [].slice, 8 __slice = [].slice,
9 __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; 9 __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
...@@ -18,13 +18,12 @@ ...@@ -18,13 +18,12 @@
18 18
19 Rivets.Binding = (function() { 19 Rivets.Binding = (function() {
20 20
21 function Binding(el, type, bindType, model, keypath, formatters) { 21 function Binding(el, type, model, keypath, options) {
22 this.el = el; 22 this.el = el;
23 this.type = type; 23 this.type = type;
24 this.bindType = bindType;
25 this.model = model; 24 this.model = model;
26 this.keypath = keypath; 25 this.keypath = keypath;
27 this.formatters = formatters != null ? formatters : []; 26 this.options = options != null ? options : {};
28 this.unbind = __bind(this.unbind, this); 27 this.unbind = __bind(this.unbind, this);
29 28
30 this.publish = __bind(this.publish, this); 29 this.publish = __bind(this.publish, this);
...@@ -35,13 +34,16 @@ ...@@ -35,13 +34,16 @@
35 34
36 this.formattedValue = __bind(this.formattedValue, this); 35 this.formattedValue = __bind(this.formattedValue, this);
37 36
38 if (this.bindType === "event") { 37 if (this.options.special === "event") {
39 this.routine = eventBinding(this.type); 38 this.routine = eventBinding(this.type);
40 } else { 39 } else {
41 this.routine = Rivets.routines[this.type] || attributeBinding(this.type); 40 this.routine = Rivets.routines[this.type] || attributeBinding(this.type);
42 } 41 }
42 this.formatters = this.options.formatters || [];
43 } 43 }
44 44
45 Binding.prototype.bidirectionals = ['value', 'checked', 'unchecked'];
46
45 Binding.prototype.formattedValue = function(value) { 47 Binding.prototype.formattedValue = function(value) {
46 var args, formatter, id, _i, _len, _ref, _ref1; 48 var args, formatter, id, _i, _len, _ref, _ref1;
47 _ref = this.formatters; 49 _ref = this.formatters;
...@@ -56,20 +58,24 @@ ...@@ -56,20 +58,24 @@
56 58
57 Binding.prototype.set = function(value) { 59 Binding.prototype.set = function(value) {
58 value = this.formattedValue(value); 60 value = this.formattedValue(value);
59 if (this.bindType === "event") { 61 if (this.options.special === "event") {
60 this.routine(this.el, value, this.currentListener); 62 this.routine(this.el, value, this.currentListener);
61 return this.currentListener = value; 63 return this.currentListener = value;
62 } else { 64 } else {
65 if (value instanceof Function) {
66 value = value();
67 }
63 return this.routine(this.el, value); 68 return this.routine(this.el, value);
64 } 69 }
65 }; 70 };
66 71
67 Binding.prototype.bind = function() { 72 Binding.prototype.bind = function() {
73 var _ref;
68 Rivets.config.adapter.subscribe(this.model, this.keypath, this.set); 74 Rivets.config.adapter.subscribe(this.model, this.keypath, this.set);
69 if (Rivets.config.preloadData) { 75 if (Rivets.config.preloadData) {
70 this.set(Rivets.config.adapter.read(this.model, this.keypath)); 76 this.set(Rivets.config.adapter.read(this.model, this.keypath));
71 } 77 }
72 if (this.bindType === "bidirectional") { 78 if (_ref = this.type, __indexOf.call(this.bidirectionals, _ref) >= 0) {
73 return bindEvent(this.el, 'change', this.publish); 79 return bindEvent(this.el, 'change', this.publish);
74 } 80 }
75 }; 81 };
...@@ -81,8 +87,9 @@ ...@@ -81,8 +87,9 @@
81 }; 87 };
82 88
83 Binding.prototype.unbind = function() { 89 Binding.prototype.unbind = function() {
90 var _ref;
84 Rivets.config.adapter.unsubscribe(this.model, this.keypath, this.set); 91 Rivets.config.adapter.unsubscribe(this.model, this.keypath, this.set);
85 if (this.bindType === "bidirectional") { 92 if (_ref = this.type, __indexOf.call(this.bidirectionals, _ref) >= 0) {
86 return this.el.removeEventListener('change', this.publish); 93 return this.el.removeEventListener('change', this.publish);
87 } 94 }
88 }; 95 };
...@@ -127,13 +134,13 @@ ...@@ -127,13 +134,13 @@
127 bindingRegExp = this.bindingRegExp(); 134 bindingRegExp = this.bindingRegExp();
128 eventRegExp = /^on-/; 135 eventRegExp = /^on-/;
129 parseNode = function(node) { 136 parseNode = function(node) {
130 var attribute, bindType, keypath, model, path, pipe, pipes, type, _i, _len, _ref, _results; 137 var attribute, keypath, model, options, path, pipe, pipes, type, _i, _len, _ref, _results;
131 _ref = node.attributes; 138 _ref = node.attributes;
132 _results = []; 139 _results = [];
133 for (_i = 0, _len = _ref.length; _i < _len; _i++) { 140 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
134 attribute = _ref[_i]; 141 attribute = _ref[_i];
135 if (bindingRegExp.test(attribute.name)) { 142 if (bindingRegExp.test(attribute.name)) {
136 bindType = "attribute"; 143 options = {};
137 type = attribute.name.replace(bindingRegExp, ''); 144 type = attribute.name.replace(bindingRegExp, '');
138 pipes = (function() { 145 pipes = (function() {
139 var _j, _len1, _ref1, _results1; 146 var _j, _len1, _ref1, _results1;
...@@ -145,16 +152,16 @@ ...@@ -145,16 +152,16 @@
145 } 152 }
146 return _results1; 153 return _results1;
147 })(); 154 })();
148 path = pipes.shift().split('.'); 155 path = pipes.shift().split(/(\.|:)/);
156 options.formatters = pipes;
149 model = _this.models[path.shift()]; 157 model = _this.models[path.shift()];
150 keypath = path.join('.'); 158 path.shift();
159 keypath = path.join();
151 if (eventRegExp.test(type)) { 160 if (eventRegExp.test(type)) {
152 type = type.replace(eventRegExp, ''); 161 type = type.replace(eventRegExp, '');
153 bindType = "event"; 162 options.special = "event";
154 } else if (__indexOf.call(bidirectionals, type) >= 0) {
155 bindType = "bidirectional";
156 } 163 }
157 _results.push(_this.bindings.push(new Rivets.Binding(node, type, bindType, model, keypath, pipes))); 164 _results.push(_this.bindings.push(new Rivets.Binding(node, type, model, keypath, options)));
158 } else { 165 } else {
159 _results.push(void 0); 166 _results.push(void 0);
160 } 167 }
...@@ -256,8 +263,6 @@ ...@@ -256,8 +263,6 @@
256 }; 263 };
257 }; 264 };
258 265
259 bidirectionals = ['value', 'checked', 'unchecked'];
260
261 Rivets.routines = { 266 Rivets.routines = {
262 enabled: function(el, value) { 267 enabled: function(el, value) {
263 return el.disabled = !value; 268 return el.disabled = !value;
...@@ -289,7 +294,7 @@ ...@@ -289,7 +294,7 @@
289 return el.innerHTML = value || ''; 294 return el.innerHTML = value || '';
290 }, 295 },
291 value: function(el, value) { 296 value: function(el, value) {
292 return el.value = value; 297 return el.value = value || '';
293 }, 298 },
294 text: function(el, value) { 299 text: function(el, value) {
295 if (el.innerText != null) { 300 if (el.innerText != null) {
......
...@@ -2,4 +2,4 @@ ...@@ -2,4 +2,4 @@
2 // version: 0.2.4 2 // version: 0.2.4
3 // author: Michael Richards 3 // author: Michael Richards
4 // license: MIT 4 // license: MIT
5 (function(){var a,b,c,d,e,f,g,h,i=function(a,b){return function(){return a.apply(b,arguments)}},j=[].slice,k=[].indexOf||function(a){for(var b=0,c=this.length;b<c;b++)if(b in this&&this[b]===a)return b;return-1};a={},String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),a.Binding=function(){function c(c,d,f,g,h,j){this.el=c,this.type=d,this.bindType=f,this.model=g,this.keypath=h,this.formatters=j!=null?j:[],this.unbind=i(this.unbind,this),this.publish=i(this.publish,this),this.bind=i(this.bind,this),this.set=i(this.set,this),this.formattedValue=i(this.formattedValue,this),this.bindType==="event"?this.routine=e(this.type):this.routine=a.routines[this.type]||b(this.type)}return c.prototype.formattedValue=function(b){var c,d,e,f,g,h,i;h=this.formatters;for(f=0,g=h.length;f<g;f++)d=h[f],c=d.split(/\s+/),e=c.shift(),b=(i=a.config.formatters)[e].apply(i,[b].concat(j.call(c)));return b},c.prototype.set=function(a){return a=this.formattedValue(a),this.bindType==="event"?(this.routine(this.el,a,this.currentListener),this.currentListener=a):this.routine(this.el,a)},c.prototype.bind=function(){a.config.adapter.subscribe(this.model,this.keypath,this.set),a.config.preloadData&&this.set(a.config.adapter.read(this.model,this.keypath));if(this.bindType==="bidirectional")return d(this.el,"change",this.publish)},c.prototype.publish=function(b){var c;return c=b.target||b.srcElement,a.config.adapter.publish(this.model,this.keypath,f(c))},c.prototype.unbind=function(){a.config.adapter.unsubscribe(this.model,this.keypath,this.set);if(this.bindType==="bidirectional")return this.el.removeEventListener("change",this.publish)},c}(),a.View=function(){function b(a,b){this.els=a,this.models=b,this.unbind=i(this.unbind,this),this.bind=i(this.bind,this),this.build=i(this.build,this),this.bindingRegExp=i(this.bindingRegExp,this),this.els.jquery||this.els instanceof Array||(this.els=[this.els]),this.build()}return b.prototype.bindingRegExp=function(){var b;return b=a.config.prefix,b?new RegExp("^data-"+b+"-"):/^data-/},b.prototype.build=function(){var b,d,e,f,g,h,i,j,l,m=this;this.bindings=[],b=this.bindingRegExp(),e=/^on-/,g=function(d){var f,g,h,i,j,l,n,o,p,q,r,s;r=d.attributes,s=[];for(p=0,q=r.length;p<q;p++)f=r[p],b.test(f.name)?(g="attribute",o=f.name.replace(b,""),n=function(){var a,b,c,d;c=f.value.split("|"),d=[];for(a=0,b=c.length;a<b;a++)l=c[a],d.push(l.trim());return d}(),j=n.shift().split("."),i=m.models[j.shift()],h=j.join("."),e.test(o)?(o=o.replace(e,""),g="event"):k.call(c,o)>=0&&(g="bidirectional"),s.push(m.bindings.push(new a.Binding(d,o,g,i,h,n)))):s.push(void 0);return s},j=this.els,l=[];for(h=0,i=j.length;h<i;h++)d=j[h],g(d),l.push(function(){var a,b,c,e;c=d.getElementsByTagName("*"),e=[];for(a=0,b=c.length;a<b;a++)f=c[a],e.push(g(f));return e}());return l},b.prototype.bind=function(){var a,b,c,d,e;d=this.bindings,e=[];for(b=0,c=d.length;b<c;b++)a=d[b],e.push(a.bind());return e},b.prototype.unbind=function(){var a,b,c,d,e;d=this.bindings,e=[];for(b=0,c=d.length;b<c;b++)a=d[b],e.push(a.unbind());return e},b}(),d=function(a,b,c){return window.addEventListener?a.addEventListener(b,c):a.attachEvent(b,c)},h=function(a,b,c){return window.removeEventListener?a.removeEventListener(b,c):a.detachEvent(b,c)},f=function(a){switch(a.type){case"text":case"textarea":case"password":case"select-one":case"radio":return a.value;case"checkbox":return a.checked}},e=function(a){return function(b,c,e){c&&d(b,a,c);if(e)return h(b,a,e)}},b=function(a){return function(b,c){return c?b.setAttribute(a,c):b.removeAttribute(a)}},c=["value","checked","unchecked"],a.routines={enabled:function(a,b){return a.disabled=!b},disabled:function(a,b){return a.disabled=!!b},checked:function(a,b){return a.type==="radio"?a.checked=a.value===b:a.checked=!!b},unchecked:function(a,b){return a.type==="radio"?a.checked=a.value!==b:a.checked=!b},show:function(a,b){return a.style.display=b?"":"none"},hide:function(a,b){return a.style.display=b?"none":""},html:function(a,b){return a.innerHTML=b||""},value:function(a,b){return a.value=b},text:function(a,b){return a.innerText!=null?a.innerText=b||"":a.textContent=b||""}},a.config={preloadData:!0},g={routines:a.routines,config:a.config,configure:function(b){var c,d,e;b==null&&(b={}),e=[];for(c in b)d=b[c],e.push(a.config[c]=d);return e},bind:function(b,c){var d;return c==null&&(c={}),d=new a.View(b,c),d.bind(),d}},typeof module!="undefined"&&module!==null?module.exports=g:this.rivets=g}).call(this);
...\ No newline at end of file ...\ No newline at end of file
5 (function(){var a,b,c,d,e,f,g,h=function(a,b){return function(){return a.apply(b,arguments)}},i=[].slice,j=[].indexOf||function(a){for(var b=0,c=this.length;b<c;b++)if(b in this&&this[b]===a)return b;return-1};a={},String.prototype.trim||(String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")}),a.Binding=function(){function f(c,e,f,g,i){this.el=c,this.type=e,this.model=f,this.keypath=g,this.options=i!=null?i:{},this.unbind=h(this.unbind,this),this.publish=h(this.publish,this),this.bind=h(this.bind,this),this.set=h(this.set,this),this.formattedValue=h(this.formattedValue,this),this.options.special==="event"?this.routine=d(this.type):this.routine=a.routines[this.type]||b(this.type),this.formatters=this.options.formatters||[]}return f.prototype.bidirectionals=["value","checked","unchecked"],f.prototype.formattedValue=function(b){var c,d,e,f,g,h,j;h=this.formatters;for(f=0,g=h.length;f<g;f++)d=h[f],c=d.split(/\s+/),e=c.shift(),b=(j=a.config.formatters)[e].apply(j,[b].concat(i.call(c)));return b},f.prototype.set=function(a){return a=this.formattedValue(a),this.options.special==="event"?(this.routine(this.el,a,this.currentListener),this.currentListener=a):(a instanceof Function&&(a=a()),this.routine(this.el,a))},f.prototype.bind=function(){var b;a.config.adapter.subscribe(this.model,this.keypath,this.set),a.config.preloadData&&this.set(a.config.adapter.read(this.model,this.keypath));if(b=this.type,j.call(this.bidirectionals,b)>=0)return c(this.el,"change",this.publish)},f.prototype.publish=function(b){var c;return c=b.target||b.srcElement,a.config.adapter.publish(this.model,this.keypath,e(c))},f.prototype.unbind=function(){var b;a.config.adapter.unsubscribe(this.model,this.keypath,this.set);if(b=this.type,j.call(this.bidirectionals,b)>=0)return this.el.removeEventListener("change",this.publish)},f}(),a.View=function(){function b(a,b){this.els=a,this.models=b,this.unbind=h(this.unbind,this),this.bind=h(this.bind,this),this.build=h(this.build,this),this.bindingRegExp=h(this.bindingRegExp,this),this.els.jquery||this.els instanceof Array||(this.els=[this.els]),this.build()}return b.prototype.bindingRegExp=function(){var b;return b=a.config.prefix,b?new RegExp("^data-"+b+"-"):/^data-/},b.prototype.build=function(){var b,c,d,e,f,g,h,i,j,k=this;this.bindings=[],b=this.bindingRegExp(),d=/^on-/,f=function(c){var e,f,g,h,i,j,l,m,n,o,p,q;p=c.attributes,q=[];for(n=0,o=p.length;n<o;n++)e=p[n],b.test(e.name)?(h={},m=e.name.replace(b,""),l=function(){var a,b,c,d;c=e.value.split("|"),d=[];for(a=0,b=c.length;a<b;a++)j=c[a],d.push(j.trim());return d}(),i=l.shift().split(/(\.|:)/),h.formatters=l,g=k.models[i.shift()],i.shift(),f=i.join(),d.test(m)&&(m=m.replace(d,""),h.special="event"),q.push(k.bindings.push(new a.Binding(c,m,g,f,h)))):q.push(void 0);return q},i=this.els,j=[];for(g=0,h=i.length;g<h;g++)c=i[g],f(c),j.push(function(){var a,b,d,g;d=c.getElementsByTagName("*"),g=[];for(a=0,b=d.length;a<b;a++)e=d[a],g.push(f(e));return g}());return j},b.prototype.bind=function(){var a,b,c,d,e;d=this.bindings,e=[];for(b=0,c=d.length;b<c;b++)a=d[b],e.push(a.bind());return e},b.prototype.unbind=function(){var a,b,c,d,e;d=this.bindings,e=[];for(b=0,c=d.length;b<c;b++)a=d[b],e.push(a.unbind());return e},b}(),c=function(a,b,c){return window.addEventListener?a.addEventListener(b,c):a.attachEvent(b,c)},g=function(a,b,c){return window.removeEventListener?a.removeEventListener(b,c):a.detachEvent(b,c)},e=function(a){switch(a.type){case"text":case"textarea":case"password":case"select-one":case"radio":return a.value;case"checkbox":return a.checked}},d=function(a){return function(b,d,e){d&&c(b,a,d);if(e)return g(b,a,e)}},b=function(a){return function(b,c){return c?b.setAttribute(a,c):b.removeAttribute(a)}},a.routines={enabled:function(a,b){return a.disabled=!b},disabled:function(a,b){return a.disabled=!!b},checked:function(a,b){return a.type==="radio"?a.checked=a.value===b:a.checked=!!b},unchecked:function(a,b){return a.type==="radio"?a.checked=a.value!==b:a.checked=!b},show:function(a,b){return a.style.display=b?"":"none"},hide:function(a,b){return a.style.display=b?"none":""},html:function(a,b){return a.innerHTML=b||""},value:function(a,b){return a.value=b||""},text:function(a,b){return a.innerText!=null?a.innerText=b||"":a.textContent=b||""}},a.config={preloadData:!0},f={routines:a.routines,config:a.config,configure:function(b){var c,d,e;b==null&&(b={}),e=[];for(c in b)d=b[c],e.push(a.config[c]=d);return e},bind:function(b,c){var d;return c==null&&(c={}),d=new a.View(b,c),d.bind(),d}},typeof module!="undefined"&&module!==null?module.exports=f:this.rivets=f}).call(this);
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -40,7 +40,7 @@ describe('Rivets.Binding', function() { ...@@ -40,7 +40,7 @@ describe('Rivets.Binding', function() {
40 40
41 describe('on an event binding', function() { 41 describe('on an event binding', function() {
42 beforeEach(function() { 42 beforeEach(function() {
43 binding.bindType = 'event'; 43 binding.options.special = 'event';
44 }); 44 });
45 45
46 it('performs the binding routine with the supplied function and current listener', function() { 46 it('performs the binding routine with the supplied function and current listener', function() {
......
...@@ -12,14 +12,20 @@ unless String::trim then String::trim = -> @replace /^\s+|\s+$/g, "" ...@@ -12,14 +12,20 @@ unless String::trim then String::trim = -> @replace /^\s+|\s+$/g, ""
12 # A single binding between a model attribute and a DOM element. 12 # A single binding between a model attribute and a DOM element.
13 class Rivets.Binding 13 class Rivets.Binding
14 # All information about the binding is passed into the constructor; the DOM 14 # All information about the binding is passed into the constructor; the DOM
15 # element, the routine identifier, the model object and the keypath at which 15 # element, the type of binding, the model object and the keypath at which
16 # to listen for changes. 16 # to listen for changes.
17 constructor: (@el, @type, @bindType, @model, @keypath, @formatters = []) -> 17 constructor: (@el, @type, @model, @keypath, @options = {}) ->
18 if @bindType is "event" 18 if @options.special is "event"
19 @routine = eventBinding @type 19 @routine = eventBinding @type
20 else 20 else
21 @routine = Rivets.routines[@type] || attributeBinding @type 21 @routine = Rivets.routines[@type] || attributeBinding @type
22 22
23 @formatters = @options.formatters || []
24
25 # Bindings that should also observe the DOM element for changes in order to
26 # propagate those changes back to the model object.
27 bidirectionals: ['value', 'checked', 'unchecked']
28
23 # Applies all the current formatters to the supplied value and returns the 29 # Applies all the current formatters to the supplied value and returns the
24 # formatted value. 30 # formatted value.
25 formattedValue: (value) => 31 formattedValue: (value) =>
...@@ -35,10 +41,11 @@ class Rivets.Binding ...@@ -35,10 +41,11 @@ class Rivets.Binding
35 set: (value) => 41 set: (value) =>
36 value = @formattedValue value 42 value = @formattedValue value
37 43
38 if @bindType is "event" 44 if @options.special is "event"
39 @routine @el, value, @currentListener 45 @routine @el, value, @currentListener
40 @currentListener = value 46 @currentListener = value
41 else 47 else
48 value = value() if value instanceof Function
42 @routine @el, value 49 @routine @el, value
43 50
44 # Subscribes to the model for changes at the specified keypath. Bi-directional 51 # Subscribes to the model for changes at the specified keypath. Bi-directional
...@@ -50,7 +57,7 @@ class Rivets.Binding ...@@ -50,7 +57,7 @@ class Rivets.Binding
50 if Rivets.config.preloadData 57 if Rivets.config.preloadData
51 @set Rivets.config.adapter.read @model, @keypath 58 @set Rivets.config.adapter.read @model, @keypath
52 59
53 if @bindType is "bidirectional" 60 if @type in @bidirectionals
54 bindEvent @el, 'change', @publish 61 bindEvent @el, 'change', @publish
55 62
56 # Publishes the value currently set on the input element back to the model. 63 # Publishes the value currently set on the input element back to the model.
...@@ -62,7 +69,7 @@ class Rivets.Binding ...@@ -62,7 +69,7 @@ class Rivets.Binding
62 unbind: => 69 unbind: =>
63 Rivets.config.adapter.unsubscribe @model, @keypath, @set 70 Rivets.config.adapter.unsubscribe @model, @keypath, @set
64 71
65 if @bindType is "bidirectional" 72 if @type in @bidirectionals
66 @el.removeEventListener 'change', @publish 73 @el.removeEventListener 'change', @publish
67 74
68 # A collection of bindings built from a set of parent elements. 75 # A collection of bindings built from a set of parent elements.
...@@ -87,20 +94,21 @@ class Rivets.View ...@@ -87,20 +94,21 @@ class Rivets.View
87 parseNode = (node) => 94 parseNode = (node) =>
88 for attribute in node.attributes 95 for attribute in node.attributes
89 if bindingRegExp.test attribute.name 96 if bindingRegExp.test attribute.name
90 bindType = "attribute" 97 options = {}
98
91 type = attribute.name.replace bindingRegExp, '' 99 type = attribute.name.replace bindingRegExp, ''
92 pipes = (pipe.trim() for pipe in attribute.value.split '|') 100 pipes = (pipe.trim() for pipe in attribute.value.split '|')
93 path = pipes.shift().split '.' 101 path = pipes.shift().split(/(\.|:)/)
102 options.formatters = pipes
94 model = @models[path.shift()] 103 model = @models[path.shift()]
95 keypath = path.join '.' 104 path.shift()
105 keypath = path.join()
96 106
97 if eventRegExp.test type 107 if eventRegExp.test type
98 type = type.replace eventRegExp, '' 108 type = type.replace eventRegExp, ''
99 bindType = "event" 109 options.special = "event"
100 else if type in bidirectionals
101 bindType = "bidirectional"
102 110
103 @bindings.push new Rivets.Binding node, type, bindType, model, keypath, pipes 111 @bindings.push new Rivets.Binding node, type, model, keypath, options
104 112
105 for el in @els 113 for el in @els
106 parseNode el 114 parseNode el
...@@ -137,7 +145,7 @@ getInputValue = (el) -> ...@@ -137,7 +145,7 @@ getInputValue = (el) ->
137 when 'text', 'textarea', 'password', 'select-one', 'radio' then el.value 145 when 'text', 'textarea', 'password', 'select-one', 'radio' then el.value
138 when 'checkbox' then el.checked 146 when 'checkbox' then el.checked
139 147
140 # Returns an element binding routine for the specified attribute. 148 # Returns an event binding routine for the specified event.
141 eventBinding = (event) -> (el, bind, unbind) -> 149 eventBinding = (event) -> (el, bind, unbind) ->
142 bindEvent el, event, bind if bind 150 bindEvent el, event, bind if bind
143 unbindEvent el, event, unbind if unbind 151 unbindEvent el, event, unbind if unbind
...@@ -147,10 +155,6 @@ eventBinding = (event) -> (el, bind, unbind) -> ...@@ -147,10 +155,6 @@ eventBinding = (event) -> (el, bind, unbind) ->
147 attributeBinding = (attr) -> (el, value) -> 155 attributeBinding = (attr) -> (el, value) ->
148 if value then el.setAttribute attr, value else el.removeAttribute attr 156 if value then el.setAttribute attr, value else el.removeAttribute attr
149 157
150 # Bindings that should also be observed for changes on the DOM element in order
151 # to propagate those changes back to the model object.
152 bidirectionals = ['value', 'checked', 'unchecked']
153
154 # Core binding routines. 158 # Core binding routines.
155 Rivets.routines = 159 Rivets.routines =
156 enabled: (el, value) -> 160 enabled: (el, value) ->
......