| OLD | NEW |
| 1 part of angular.core.dom; | 1 part of angular.core.dom; |
| 2 | 2 |
| 3 /** | 3 /** |
| 4 * Callback function used to notify of attribute changes. | 4 * Callback function used to notify of attribute changes. |
| 5 */ | 5 */ |
| 6 typedef AttributeChanged(String newValue); | 6 typedef AttributeChanged(String newValue); |
| 7 | 7 |
| 8 /** | 8 /** |
| 9 * Callback function used to notify of text changes. | 9 * Callback function used to notify of text changes. |
| 10 */ | 10 */ |
| 11 abstract class TextChangeListener{ | 11 abstract class TextChangeListener{ |
| 12 call(String text); | 12 call(String text); |
| 13 } | 13 } |
| 14 | 14 |
| 15 | |
| 16 /** | 15 /** |
| 17 * NodeAttrs is a facade for element attributes. The facade is responsible | 16 * NodeAttrs is a facade for element attributes. The facade is responsible |
| 18 * for normalizing attribute names as well as allowing access to the | 17 * for normalizing attribute names as well as allowing access to the |
| 19 * value of the directive. | 18 * value of the directive. |
| 20 */ | 19 */ |
| 21 class NodeAttrs { | 20 class NodeAttrs { |
| 22 final dom.Element element; | 21 final dom.Element element; |
| 23 | 22 |
| 24 Map<String, List<AttributeChanged>> _observers; | 23 Map<String, List<AttributeChanged>> _observers; |
| 25 | 24 |
| 26 NodeAttrs(this.element); | 25 NodeAttrs(this.element); |
| 27 | 26 |
| 28 operator [](String name) => element.attributes[_snakeCase(name, '-')]; | 27 operator [](String attributeName) => |
| 28 element.attributes[snakecase(attributeName, '-')]; |
| 29 | 29 |
| 30 operator []=(String name, String value) { | 30 operator []=(String attributeName, String value) { |
| 31 name = _snakeCase(name, '-'); | 31 var snakeName = snakecase(attributeName, '-'); |
| 32 if (value == null) { | 32 if (value == null) { |
| 33 element.attributes.remove(name); | 33 element.attributes.remove(snakeName); |
| 34 } else { | 34 } else { |
| 35 element.attributes[name] = value; | 35 element.attributes[snakeName] = value; |
| 36 } | 36 } |
| 37 if (_observers != null && _observers.containsKey(name)) { | 37 if (_observers != null && _observers.containsKey(attributeName)) { |
| 38 _observers[name].forEach((fn) => fn(value)); | 38 _observers[attributeName].forEach((fn) => fn(value)); |
| 39 } | 39 } |
| 40 } | 40 } |
| 41 | 41 |
| 42 /** | 42 /** |
| 43 * Observe changes to the attribute by invoking the [AttributeChanged] | 43 * Observe changes to the attribute by invoking the [AttributeChanged] |
| 44 * function. On registration the [AttributeChanged] function gets invoked | 44 * function. On registration the [AttributeChanged] function gets invoked |
| 45 * synchronise with the current value. | 45 * synchronise with the current value. |
| 46 */ | 46 */ |
| 47 observe(String attributeName, AttributeChanged notifyFn) { | 47 observe(String attributeName, AttributeChanged notifyFn) { |
| 48 attributeName = _snakeCase(attributeName, '-'); | |
| 49 if (_observers == null) { | 48 if (_observers == null) { |
| 50 _observers = new Map<String, List<AttributeChanged>>(); | 49 _observers = new Map<String, List<AttributeChanged>>(); |
| 51 } | 50 } |
| 52 if (!_observers.containsKey(attributeName)) { | 51 if (!_observers.containsKey(attributeName)) { |
| 53 _observers[attributeName] = new List<AttributeChanged>(); | 52 _observers[attributeName] = new List<AttributeChanged>(); |
| 54 } | 53 } |
| 55 _observers[attributeName].add(notifyFn); | 54 _observers[attributeName].add(notifyFn); |
| 56 notifyFn(this[attributeName]); | 55 notifyFn(this[attributeName]); |
| 57 } | 56 } |
| 57 |
| 58 void forEach(void f(String k, String v)) { |
| 59 element.attributes.forEach((k, v) => f(camelcase(k), v)); |
| 60 } |
| 61 |
| 62 bool containsKey(String attributeName) => |
| 63 element.attributes.containsKey(snakecase(attributeName, '-')); |
| 64 |
| 65 Iterable<String> get keys => |
| 66 element.attributes.keys.map((name) => camelcase(name)); |
| 58 } | 67 } |
| 59 | 68 |
| 60 /** | 69 /** |
| 61 * TemplateLoader is an asynchronous access to ShadowRoot which is | 70 * TemplateLoader is an asynchronous access to ShadowRoot which is |
| 62 * loaded asynchronously. It allows a Component to be notified when its | 71 * loaded asynchronously. It allows a Component to be notified when its |
| 63 * ShadowRoot is ready. | 72 * ShadowRoot is ready. |
| 64 */ | 73 */ |
| 65 class TemplateLoader { | 74 class TemplateLoader { |
| 66 final async.Future<dom.ShadowRoot> _template; | 75 final async.Future<dom.ShadowRoot> _template; |
| 67 | 76 |
| 68 async.Future<dom.ShadowRoot> get template => _template; | 77 async.Future<dom.ShadowRoot> get template => _template; |
| 69 | 78 |
| 70 TemplateLoader(this._template); | 79 TemplateLoader(this._template); |
| 71 } | 80 } |
| 72 | |
| 73 var _SNAKE_CASE_REGEXP = new RegExp("[A-Z]"); | |
| 74 String _snakeCase(String name, [separator = '_']) { | |
| 75 _snakeReplace(Match match) => | |
| 76 (match.start != 0 ? separator : '') + match.group(0).toLowerCase(); | |
| 77 | |
| 78 return name.replaceAllMapped(_SNAKE_CASE_REGEXP, _snakeReplace); | |
| 79 } | |
| OLD | NEW |