| Index: sdk/lib/html/dart2js/html_dart2js.dart
|
| diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
|
| index 107961528981c75dd7f9ad625c29bfcb507a9ebc..2096f94d785ae7016c021d36afe0a89337b4dc90 100644
|
| --- a/sdk/lib/html/dart2js/html_dart2js.dart
|
| +++ b/sdk/lib/html/dart2js/html_dart2js.dart
|
| @@ -7386,18 +7386,27 @@ abstract class Element extends Node implements ElementTraversal native "Element"
|
| void onCreated() {}
|
|
|
| // Hooks to support custom WebComponents.
|
| +
|
| + @Creates('Null') // Set from Dart code; does not instantiate a native type.
|
| + Element _xtag;
|
| +
|
| /**
|
| * Experimental support for [web components][wc]. This field stores a
|
| * reference to the component implementation. It was inspired by Mozilla's
|
| * [x-tags][] project. Please note: in the future it may be possible to
|
| * `extend Element` from your class, in which case this field will be
|
| - * deprecated and will simply return this [Element] object.
|
| + * deprecated.
|
| + *
|
| + * If xtag has not been set, it will simply return `this` [Element].
|
| *
|
| * [wc]: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html
|
| * [x-tags]: http://x-tags.org/
|
| */
|
| - @Creates('Null') // Set from Dart code; does not instantiate a native type.
|
| - var xtag;
|
| + Element get xtag => _xtag != null ? _xtag : this;
|
| +
|
| + void set xtag(Element value) {
|
| + _xtag = value;
|
| + }
|
|
|
| /**
|
| * Scrolls this element into view.
|
| @@ -7621,7 +7630,7 @@ abstract class Element extends Node implements ElementTraversal native "Element"
|
| self._attributeBindings = new Map<String, StreamSubscription>();
|
| }
|
|
|
| - self.attributes.remove(name);
|
| + self.xtag.attributes.remove(name);
|
|
|
| var changed;
|
| if (name.endsWith('?')) {
|
| @@ -7629,16 +7638,16 @@ abstract class Element extends Node implements ElementTraversal native "Element"
|
|
|
| changed = (value) {
|
| if (_templateBooleanConversion(value)) {
|
| - self.attributes[name] = '';
|
| + self.xtag.attributes[name] = '';
|
| } else {
|
| - self.attributes.remove(name);
|
| + self.xtag.attributes.remove(name);
|
| }
|
| };
|
| } else {
|
| changed = (value) {
|
| // TODO(jmesserly): escape value if needed to protect against XSS.
|
| // See https://github.com/toolkitchen/mdv/issues/58
|
| - self.attributes[name] = value == null ? '' : '$value';
|
| + self.xtag.attributes[name] = value == null ? '' : '$value';
|
| };
|
| }
|
|
|
| @@ -26479,7 +26488,7 @@ void _parseAndBind(Node node, String name, String text, model,
|
| return newValue.toString();
|
| };
|
|
|
| - node.bind(name, replacementBinding, 'value');
|
| + _nodeOrCustom(node).bind(name, replacementBinding, 'value');
|
| }
|
|
|
| void _bindOrDelegate(node, name, model, String path,
|
| @@ -26493,9 +26502,17 @@ void _bindOrDelegate(node, name, model, String path,
|
| }
|
| }
|
|
|
| - node.bind(name, model, path);
|
| + _nodeOrCustom(node).bind(name, model, path);
|
| }
|
|
|
| +/**
|
| + * Gets the [node]'s custom [Element.xtag] if present, otherwise returns
|
| + * the node. This is used so nodes can override [Node.bind], [Node.unbind],
|
| + * and [Node.unbindAll] like InputElement does.
|
| + */
|
| +// TODO(jmesserly): remove this when we can extend Element for real.
|
| +_nodeOrCustom(node) => node is Element ? node.xtag : node;
|
| +
|
| class _BindingToken {
|
| final String value;
|
| final bool isBinding;
|
| @@ -26555,7 +26572,7 @@ void _addTemplateInstanceRecord(fragment, model) {
|
| }
|
|
|
| void _removeAllBindingsRecursively(Node node) {
|
| - node.unbindAll();
|
| + _nodeOrCustom(node).unbindAll();
|
| for (var c = node.$dom_firstChild; c != null; c = c.nextNode) {
|
| _removeAllBindingsRecursively(c);
|
| }
|
|
|