d06e350d by Michael Richards

Namespace everything under Rivets and rewrite the registerBinding function as a new class.

1 parent 77351bb8
1 // Generated by CoffeeScript 1.3.1 1 // Generated by CoffeeScript 1.3.1
2 (function() { 2 (function() {
3 var attributeBinding, bidirectionals, bindings, getInputValue, registerBinding, rivets, stateBinding, 3 var Rivets,
4 __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
4 __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; }; 5 __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; };
5 6
6 registerBinding = function(el, adapter, type, context, keypath) { 7 Rivets = {
7 var bind; 8 Helpers: {}
8 bind = bindings[type] || attributeBinding(type); 9 };
9 bind(el, adapter.read(context, keypath)); 10
10 adapter.subscribe(context, keypath, function(value) { 11 Rivets.Binding = (function() {
11 return bind(el, value); 12
13 Binding.name = 'Binding';
14
15 function Binding(el, adapter, type, context, keypath) {
16 this.el = el;
17 this.adapter = adapter;
18 this.type = type;
19 this.context = context;
20 this.keypath = keypath;
21 this.bind = __bind(this.bind, this);
22
23 this.set = __bind(this.set, this);
24
25 this.routine = Rivets.bindings[this.type] || Rivets.Helpers.attributeBinding(this.type);
26 }
27
28 Binding.prototype.set = function(value) {
29 if (value == null) {
30 value = null;
31 }
32 return this.routine(this.el, value || this.adapter.read(this.context, this.keypath));
33 };
34
35 Binding.prototype.bind = function() {
36 var _ref,
37 _this = this;
38 this.adapter.subscribe(this.context, this.keypath, function(value) {
39 return _this.set(value);
12 }); 40 });
13 if (__indexOf.call(bidirectionals, type) >= 0) { 41 if (_ref = this.type, __indexOf.call(Rivets.bidirectionals, _ref) >= 0) {
14 return el.addEventListener('change', function() { 42 return this.el.addEventListener('change', function(el) {
15 return adapter.publish(context, keypath, getInputValue(this)); 43 return _this.adapter.publish(_this.context, _this.keypath, Rivets.Helpers.getInputValue(el));
16 }); 44 });
17 } 45 }
18 }; 46 };
19 47
20 getInputValue = function(el) { 48 return Binding;
49
50 })();
51
52 Rivets.Helpers.getInputValue = function(el) {
21 switch (el.type) { 53 switch (el.type) {
22 case 'text': 54 case 'text':
23 case 'textarea': 55 case 'textarea':
...@@ -30,7 +62,7 @@ ...@@ -30,7 +62,7 @@
30 } 62 }
31 }; 63 };
32 64
33 attributeBinding = function(attr) { 65 Rivets.Helpers.attributeBinding = function(attr) {
34 return function(el, value) { 66 return function(el, value) {
35 if (value) { 67 if (value) {
36 return el.setAttribute(attr, value); 68 return el.setAttribute(attr, value);
...@@ -40,22 +72,24 @@ ...@@ -40,22 +72,24 @@
40 }; 72 };
41 }; 73 };
42 74
43 stateBinding = function(attr, inverse) { 75 Rivets.Helpers.stateBinding = function(attr, inverse) {
44 if (inverse == null) { 76 if (inverse == null) {
45 inverse = false; 77 inverse = false;
46 } 78 }
47 return function(el, value) { 79 return function(el, value) {
48 return attributeBinding(attr)(el, inverse === !value ? attr : false); 80 var binding;
81 binding = Rivets.Helpers.attributeBinding(attr);
82 return binding(el, inverse === !value ? attr : false);
49 }; 83 };
50 }; 84 };
51 85
52 bindings = { 86 Rivets.bindings = {
53 checked: stateBinding('checked'), 87 checked: Rivets.Helpers.stateBinding('checked'),
54 selected: stateBinding('selected'), 88 selected: Rivets.Helpers.stateBinding('selected'),
55 disabled: stateBinding('disabled'), 89 disabled: Rivets.Helpers.stateBinding('disabled'),
56 unchecked: stateBinding('checked', true), 90 unchecked: Rivets.Helpers.stateBinding('checked', true),
57 unselected: stateBinding('selected', true), 91 unselected: Rivets.Helpers.stateBinding('selected', true),
58 enabled: stateBinding('disabled', true), 92 enabled: Rivets.Helpers.stateBinding('disabled', true),
59 text: function(el, value) { 93 text: function(el, value) {
60 return el.innerText = value || ''; 94 return el.innerText = value || '';
61 }, 95 },
...@@ -73,14 +107,14 @@ ...@@ -73,14 +107,14 @@
73 } 107 }
74 }; 108 };
75 109
76 bidirectionals = ['value', 'checked', 'unchecked', 'selected', 'unselected']; 110 Rivets.bidirectionals = ['value', 'checked', 'unchecked', 'selected', 'unselected'];
77 111
78 rivets = { 112 Rivets["interface"] = {
79 register: function(routine, routineFunction) { 113 register: function(routine, routineFunction) {
80 return bindings[routine] = routineFunction; 114 return Rivets.bindings[routine] = routineFunction;
81 }, 115 },
82 bind: function(el, adapter, contexts) { 116 bind: function(el, adapter, contexts) {
83 var attribute, context, keypath, node, path, type, _i, _len, _ref, _results; 117 var attribute, binding, context, keypath, node, path, type, _i, _len, _ref, _results;
84 if (contexts == null) { 118 if (contexts == null) {
85 contexts = {}; 119 contexts = {};
86 } 120 }
...@@ -99,7 +133,8 @@ ...@@ -99,7 +133,8 @@
99 path = attribute.value.split('.'); 133 path = attribute.value.split('.');
100 context = path.shift(); 134 context = path.shift();
101 keypath = path.join('.'); 135 keypath = path.join('.');
102 _results1.push(registerBinding(node, adapter, type, contexts[context], keypath)); 136 binding = new Rivets.Binding(node, adapter, type, contexts[context], keypath);
137 _results1.push(binding.bind());
103 } else { 138 } else {
104 _results1.push(void 0); 139 _results1.push(void 0);
105 } 140 }
...@@ -112,9 +147,9 @@ ...@@ -112,9 +147,9 @@
112 }; 147 };
113 148
114 if (typeof module !== "undefined" && module !== null) { 149 if (typeof module !== "undefined" && module !== null) {
115 module.exports = rivets; 150 module.exports = Rivets["interface"];
116 } else { 151 } else {
117 this.rivets = rivets; 152 this.rivets = Rivets["interface"];
118 } 153 }
119 154
120 }).call(this); 155 }).call(this);
......
...@@ -3,53 +3,60 @@ ...@@ -3,53 +3,60 @@
3 # author : Michael Richards 3 # author : Michael Richards
4 # license : MIT 4 # license : MIT
5 5
6 # Registers a specific binding routine between a model object and a DOM element. 6 Rivets =
7 # All information for that routine is passed in when calling this function; the 7 Helpers: {}
8 # specific element to bind to, an adapter interface for the model object, the
9 # type of binding, the context object and the keypath at which to subscribe to
10 # on the model object.
11 registerBinding = (el, adapter, type, context, keypath) ->
12 bind = bindings[type] || attributeBinding type
13 bind el, adapter.read context, keypath
14 8
15 adapter.subscribe context, keypath, (value) -> 9 class Rivets.Binding
16 bind el, value 10 constructor: (@el, @adapter, @type, @context, @keypath) ->
11 @routine = Rivets.bindings[@type] || Rivets.Helpers.attributeBinding @type
17 12
18 if type in bidirectionals 13 # Sets a value for this binding. Basically just runs the routine on the
19 el.addEventListener 'change', -> 14 # element with a suplied value.
20 adapter.publish context, keypath, getInputValue this 15 set: (value = null) =>
16 @routine @el, value || @adapter.read @context, @keypath
17
18 # Subscribes to the context object for changes on the specific keypath.
19 # Conditionally also does the inverse and listens to the element for changes
20 # to propogate back to the context object.
21 bind: =>
22 @adapter.subscribe @context, @keypath, (value) => @set value
23
24 if @type in Rivets.bidirectionals
25 @el.addEventListener 'change', (el) =>
26 @adapter.publish @context, @keypath, Rivets.Helpers.getInputValue el
21 27
22 # Returns the current input value for the specified element. 28 # Returns the current input value for the specified element.
23 getInputValue = (el) -> 29 Rivets.Helpers.getInputValue = (el) ->
24 switch el.type 30 switch el.type
25 when 'text', 'textarea', 'password', 'select-one' then el.value 31 when 'text', 'textarea', 'password', 'select-one' then el.value
26 when 'checkbox', 'radio' then el.checked 32 when 'checkbox', 'radio' then el.checked
27 33
28 # Returns an attribute binding routine for the specified attribute. This is what 34 # Returns an attribute binding routine for the specified attribute. This is what
29 # `registerBinding` falls back to when there is no routine for the binding type. 35 # `registerBinding` falls back to when there is no routine for the binding type.
30 attributeBinding = (attr) -> (el, value) -> 36 Rivets.Helpers.attributeBinding = (attr) -> (el, value) ->
31 if value then el.setAttribute attr, value else el.removeAttribute attr 37 if value then el.setAttribute attr, value else el.removeAttribute attr
32 38
33 # Returns a state binding routine for the specified attribute. Can optionally be 39 # Returns a state binding routine for the specified attribute. Can optionally be
34 # negatively evaluated. This is used to build a lot of the core state binding 40 # negatively evaluated. This is used to build a lot of the core state binding
35 # routines. 41 # routines.
36 stateBinding = (attr, inverse = false) -> (el, value) -> 42 Rivets.Helpers.stateBinding = (attr, inverse = false) -> (el, value) ->
37 attributeBinding(attr) el, if inverse is !value then attr else false 43 binding = Rivets.Helpers.attributeBinding(attr)
44 binding el, if inverse is !value then attr else false
38 45
39 # Core binding routines. 46 # Core binding routines.
40 bindings = 47 Rivets.bindings =
41 checked: 48 checked:
42 stateBinding 'checked' 49 Rivets.Helpers.stateBinding 'checked'
43 selected: 50 selected:
44 stateBinding 'selected' 51 Rivets.Helpers.stateBinding 'selected'
45 disabled: 52 disabled:
46 stateBinding 'disabled' 53 Rivets.Helpers.stateBinding 'disabled'
47 unchecked: 54 unchecked:
48 stateBinding 'checked', true 55 Rivets.Helpers.stateBinding 'checked', true
49 unselected: 56 unselected:
50 stateBinding 'selected', true 57 Rivets.Helpers.stateBinding 'selected', true
51 enabled: 58 enabled:
52 stateBinding 'disabled', true 59 Rivets.Helpers.stateBinding 'disabled', true
53 text: (el, value) -> 60 text: (el, value) ->
54 el.innerText = value or '' 61 el.innerText = value or ''
55 html: (el, value) -> 62 html: (el, value) ->
...@@ -63,13 +70,13 @@ bindings = ...@@ -63,13 +70,13 @@ bindings =
63 70
64 # Bindings that should also be observed for changes on the DOM element in order 71 # Bindings that should also be observed for changes on the DOM element in order
65 # to propogate those changes back to the model object. 72 # to propogate those changes back to the model object.
66 bidirectionals = ['value', 'checked', 'unchecked', 'selected', 'unselected'] 73 Rivets.bidirectionals = ['value', 'checked', 'unchecked', 'selected', 'unselected']
67 74
68 # The rivets module exposes `register` and `bind` functions to register new 75 # The rivets module exposes `register` and `bind` functions to register new
69 # binding routines and bind contexts to DOM elements. 76 # binding routines and bind contexts to DOM elements.
70 rivets = 77 Rivets.interface =
71 register: (routine, routineFunction) -> 78 register: (routine, routineFunction) ->
72 bindings[routine] = routineFunction 79 Rivets.bindings[routine] = routineFunction
73 80
74 bind: (el, adapter, contexts = {}) -> 81 bind: (el, adapter, contexts = {}) ->
75 for node in el.getElementsByTagName '*' 82 for node in el.getElementsByTagName '*'
...@@ -79,10 +86,12 @@ rivets = ...@@ -79,10 +86,12 @@ rivets =
79 path = attribute.value.split '.' 86 path = attribute.value.split '.'
80 context = path.shift() 87 context = path.shift()
81 keypath = path.join '.' 88 keypath = path.join '.'
82 registerBinding node, adapter, type, contexts[context], keypath 89
90 binding = new Rivets.Binding node, adapter, type, contexts[context], keypath
91 binding.bind()
83 92
84 # Exports rivets for both CommonJS and the browser. 93 # Exports rivets for both CommonJS and the browser.
85 if module? 94 if module?
86 module.exports = rivets 95 module.exports = Rivets.interface
87 else 96 else
88 @rivets = rivets
...\ No newline at end of file ...\ No newline at end of file
97 @rivets = Rivets.interface
...\ No newline at end of file ...\ No newline at end of file
......