Implement wildcard attribute bindings so that it's possible to bind to any arbitrary attribute.
Showing
3 changed files
with
27 additions
and
35 deletions
... | @@ -24,7 +24,7 @@ No contrived example here yet, but the `rivets` module is simple. It exposes a s | ... | @@ -24,7 +24,7 @@ No contrived example here yet, but the `rivets` module is simple. It exposes a s |
24 | - **data-unchecked**: two-way inverse binding that sets the node's checked state. | 24 | - **data-unchecked**: two-way inverse binding that sets the node's checked state. |
25 | - **data-selected**: two-way binding that sets the node's selected state. | 25 | - **data-selected**: two-way binding that sets the node's selected state. |
26 | - **data-unselected**: two-way inverse binding that sets the node's checked state. | 26 | - **data-unselected**: two-way inverse binding that sets the node's checked state. |
27 | - **data-[attribute]**: one-way binding that sets the node's attribute value (currently only for a few select attributes). | 27 | - **data-[attribute]**: one-way binding that sets the node's attribute value. |
28 | 28 | ||
29 | ## Adapters | 29 | ## Adapters |
30 | 30 | ... | ... |
... | @@ -3,11 +3,13 @@ | ... | @@ -3,11 +3,13 @@ |
3 | var __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; }; | 3 | var __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; }; |
4 | 4 | ||
5 | window.rivets = (function() { | 5 | window.rivets = (function() { |
6 | var attr, bidirectionalBindings, bindableAttributes, bindings, getInputValue, registerBinding, setAttribute, _fn, _i, _len; | 6 | var attributeBinding, bidirectionalBindings, bindings, getInputValue, registerBinding, setAttribute; |
7 | registerBinding = function(el, adapter, type, context, keypath) { | 7 | registerBinding = function(el, adapter, type, context, keypath) { |
8 | bindings[type](el, adapter.read(context, keypath)); | 8 | var bind; |
9 | bind = bindings[type] || attributeBinding(type); | ||
10 | bind(el, adapter.read(context, keypath)); | ||
9 | adapter.subscribe(context, keypath, function(value) { | 11 | adapter.subscribe(context, keypath, function(value) { |
10 | return bindings[type](el, value); | 12 | return bind(el, value); |
11 | }); | 13 | }); |
12 | if (__indexOf.call(bidirectionalBindings, type) >= 0) { | 14 | if (__indexOf.call(bidirectionalBindings, type) >= 0) { |
13 | return $(el).bind('change', function() { | 15 | return $(el).bind('change', function() { |
... | @@ -76,42 +78,35 @@ | ... | @@ -76,42 +78,35 @@ |
76 | return $(el).val(value); | 78 | return $(el).val(value); |
77 | } | 79 | } |
78 | }; | 80 | }; |
79 | bidirectionalBindings = ['value', 'checked', 'unchecked', 'selected', 'unselected']; | 81 | attributeBinding = function(attr) { |
80 | bindableAttributes = ['id', 'class', 'name', 'src', 'href', 'alt', 'title', 'placeholder']; | 82 | return function(el, value) { |
81 | _fn = function(attr) { | ||
82 | return bindings[attr] = function(el, value) { | ||
83 | return setAttribute(el, attr, value); | 83 | return setAttribute(el, attr, value); |
84 | }; | 84 | }; |
85 | }; | 85 | }; |
86 | for (_i = 0, _len = bindableAttributes.length; _i < _len; _i++) { | 86 | bidirectionalBindings = ['value', 'checked', 'unchecked', 'selected', 'unselected']; |
87 | attr = bindableAttributes[_i]; | ||
88 | _fn(attr); | ||
89 | } | ||
90 | return { | 87 | return { |
91 | bind: function(el, adapter, contexts) { | 88 | bind: function(el, adapter, contexts) { |
92 | if (contexts == null) { | 89 | if (contexts == null) { |
93 | contexts = {}; | 90 | contexts = {}; |
94 | } | 91 | } |
95 | return $(el).add($('*', el)).each(function() { | 92 | return $(el).add($('*', el)).each(function() { |
96 | var nodeMap, target, _j, _ref, _results; | 93 | var nodeMap, target, _i, _ref, _results; |
97 | target = this; | 94 | target = this; |
98 | nodeMap = target.attributes; | 95 | nodeMap = target.attributes; |
99 | if (nodeMap.length > 0) { | 96 | if (nodeMap.length > 0) { |
100 | return (function() { | 97 | return (function() { |
101 | _results = []; | 98 | _results = []; |
102 | for (var _j = 0, _ref = nodeMap.length - 1; 0 <= _ref ? _j <= _ref : _j >= _ref; 0 <= _ref ? _j++ : _j--){ _results.push(_j); } | 99 | for (var _i = 0, _ref = nodeMap.length - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; 0 <= _ref ? _i++ : _i--){ _results.push(_i); } |
103 | return _results; | 100 | return _results; |
104 | }).apply(this).forEach(function(n) { | 101 | }).apply(this).forEach(function(n) { |
105 | var context, keypath, node, path, type; | 102 | var context, keypath, node, path, type; |
106 | node = nodeMap[n]; | 103 | node = nodeMap[n]; |
107 | if (/^data-/.test(node.name)) { | 104 | if (/^data-/.test(node.name)) { |
108 | type = node.name.replace('data-', ''); | 105 | type = node.name.replace('data-', ''); |
109 | if (type in bindings) { | 106 | path = node.value.split('.'); |
110 | path = node.value.split('.'); | 107 | context = path.shift(); |
111 | context = path.shift(); | 108 | keypath = path.join('.'); |
112 | keypath = path.join('.'); | 109 | return registerBinding($(target), adapter, type, contexts[context], keypath); |
113 | return registerBinding($(target), adapter, type, contexts[context], keypath); | ||
114 | } | ||
115 | } | 110 | } |
116 | }); | 111 | }); |
117 | } | 112 | } | ... | ... |
... | @@ -5,14 +5,15 @@ | ... | @@ -5,14 +5,15 @@ |
5 | 5 | ||
6 | window.rivets = do -> | 6 | window.rivets = do -> |
7 | registerBinding = (el, adapter, type, context, keypath) -> | 7 | registerBinding = (el, adapter, type, context, keypath) -> |
8 | bindings[type] el, adapter.read(context, keypath) | 8 | bind = bindings[type] || attributeBinding type |
9 | bind el, adapter.read context, keypath | ||
9 | 10 | ||
10 | adapter.subscribe context, keypath, (value) -> | 11 | adapter.subscribe context, keypath, (value) -> |
11 | bindings[type] el, value | 12 | bind el, value |
12 | 13 | ||
13 | if type in bidirectionalBindings | 14 | if type in bidirectionalBindings |
14 | $(el).bind 'change', -> | 15 | $(el).bind 'change', -> |
15 | adapter.publish context, keypath, getInputValue(this) | 16 | adapter.publish context, keypath, getInputValue this |
16 | 17 | ||
17 | setAttribute = (el, attr, value, mirrored=false) -> | 18 | setAttribute = (el, attr, value, mirrored=false) -> |
18 | if value | 19 | if value |
... | @@ -47,13 +48,11 @@ window.rivets = do -> | ... | @@ -47,13 +48,11 @@ window.rivets = do -> |
47 | value: (el, value) -> | 48 | value: (el, value) -> |
48 | $(el).val value | 49 | $(el).val value |
49 | 50 | ||
50 | bidirectionalBindings = ['value', 'checked', 'unchecked', 'selected', 'unselected'] | 51 | attributeBinding = (attr) -> |
51 | bindableAttributes = ['id', 'class', 'name', 'src', 'href', 'alt', 'title', 'placeholder'] | 52 | (el, value) -> |
53 | setAttribute el, attr, value | ||
52 | 54 | ||
53 | for attr in bindableAttributes | 55 | bidirectionalBindings = ['value', 'checked', 'unchecked', 'selected', 'unselected'] |
54 | do (attr) -> | ||
55 | bindings[attr] = (el, value) -> | ||
56 | setAttribute el, attr, value | ||
57 | 56 | ||
58 | bind: (el, adapter, contexts={}) -> | 57 | bind: (el, adapter, contexts={}) -> |
59 | $(el).add($('*', el)).each -> | 58 | $(el).add($('*', el)).each -> |
... | @@ -66,9 +65,7 @@ window.rivets = do -> | ... | @@ -66,9 +65,7 @@ window.rivets = do -> |
66 | 65 | ||
67 | if /^data-/.test node.name | 66 | if /^data-/.test node.name |
68 | type = node.name.replace 'data-', '' | 67 | type = node.name.replace 'data-', '' |
69 | 68 | path = node.value.split '.' | |
70 | if type of bindings | 69 | context = path.shift() |
71 | path = node.value.split '.' | 70 | keypath = path.join '.' |
72 | context = path.shift() | 71 | registerBinding $(target), adapter, type, contexts[context], keypath |
73 | keypath = path.join '.' | ||
74 | registerBinding $(target), adapter, type, contexts[context], keypath | ... | ... |
-
Please register or sign in to post a comment