Clean up the Rivets.Binding constructor by passing only the four required argume…
…nts and using an options object.
Showing
4 changed files
with
48 additions
and
39 deletions
... | @@ -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) -> | ... | ... |
-
Please register or sign in to post a comment