| Index: lib/dom/templates/html/impl/impl_Element.darttemplate
|
| diff --git a/lib/dom/templates/html/impl/impl_Element.darttemplate b/lib/dom/templates/html/impl/impl_Element.darttemplate
|
| index f7542b2b8a0356aefdfe1a3ddcebec4e97b31067..95d62620845e54de424736e8844427cdcb054050 100644
|
| --- a/lib/dom/templates/html/impl/impl_Element.darttemplate
|
| +++ b/lib/dom/templates/html/impl/impl_Element.darttemplate
|
| @@ -305,11 +305,11 @@ class _ElementList extends _ListWrapper<Element> implements ElementList {
|
| new _ElementList(super.getRange(start, length));
|
| }
|
|
|
| -class ElementAttributeMap implements Map<String, String> {
|
| +class _ElementAttributeMap implements AttributeMap {
|
|
|
| final _ElementImpl _element;
|
|
|
| - ElementAttributeMap._wrap(this._element);
|
| + _ElementAttributeMap(this._element);
|
|
|
| bool containsValue(String value) {
|
| final attributes = _element.$dom_attributes;
|
| @@ -329,8 +329,8 @@ class ElementAttributeMap implements Map<String, String> {
|
| return _element.$dom_getAttribute(key);
|
| }
|
|
|
| - void operator []=(String key, String value) {
|
| - _element.$dom_setAttribute(key, value);
|
| + void operator []=(String key, value) {
|
| + _element.$dom_setAttribute(key, '$value');
|
| }
|
|
|
| String putIfAbsent(String key, String ifAbsent()) {
|
| @@ -393,6 +393,203 @@ class ElementAttributeMap implements Map<String, String> {
|
| }
|
| }
|
|
|
| +/**
|
| + * Provides a Map abstraction on top of data-* attributes, similar to the
|
| + * dataSet in the old DOM.
|
| + */
|
| +class _DataAttributeMap implements AttributeMap {
|
| +
|
| + final Map<String, String> $dom_attributes;
|
| +
|
| + _DataAttributeMap(this.$dom_attributes);
|
| +
|
| + // interface Map
|
| +
|
| + // TODO: Use lazy iterator when it is available on Map.
|
| + bool containsValue(String value) => getValues().some((v) => v == value);
|
| +
|
| + bool containsKey(String key) => $dom_attributes.containsKey(_attr(key));
|
| +
|
| + String operator [](String key) => $dom_attributes[_attr(key)];
|
| +
|
| + void operator []=(String key, value) {
|
| + $dom_attributes[_attr(key)] = '$value';
|
| + }
|
| +
|
| + String putIfAbsent(String key, String ifAbsent()) {
|
| + $dom_attributes.putIfAbsent(_attr(key), ifAbsent);
|
| + }
|
| +
|
| + String remove(String key) => $dom_attributes.remove(_attr(key));
|
| +
|
| + void clear() {
|
| + // Needs to operate on a snapshot since we are mutating the collection.
|
| + for (String key in getKeys()) {
|
| + remove(key);
|
| + }
|
| + }
|
| +
|
| + void forEach(void f(String key, String value)) {
|
| + $dom_attributes.forEach((String key, String value) {
|
| + if (_matches(key)) {
|
| + f(_strip(key), value);
|
| + }
|
| + });
|
| + }
|
| +
|
| + Collection<String> getKeys() {
|
| + final keys = new List<String>();
|
| + $dom_attributes.forEach((String key, String value) {
|
| + if (_matches(key)) {
|
| + keys.add(_strip(key));
|
| + }
|
| + });
|
| + return keys;
|
| + }
|
| +
|
| + Collection<String> getValues() {
|
| + final values = new List<String>();
|
| + $dom_attributes.forEach((String key, String value) {
|
| + if (_matches(key)) {
|
| + values.add(value);
|
| + }
|
| + });
|
| + return values;
|
| + }
|
| +
|
| + int get length() => getKeys().length;
|
| +
|
| + // TODO: Use lazy iterator when it is available on Map.
|
| + bool isEmpty() => length == 0;
|
| +
|
| + // Helpers.
|
| + String _attr(String key) => 'data-$key';
|
| + bool _matches(String key) => key.startsWith('data-');
|
| + String _strip(String key) => key.substring(5);
|
| +}
|
| +
|
| +class _CssClassSet implements Set<String> {
|
| +
|
| + final _ElementImpl _element;
|
| +
|
| + _CssClassSet(this._element);
|
| +
|
| + String toString() => _formatSet(_read());
|
| +
|
| + // interface Iterable - BEGIN
|
| + Iterator<String> iterator() => _read().iterator();
|
| + // interface Iterable - END
|
| +
|
| + // interface Collection - BEGIN
|
| + void forEach(void f(String element)) {
|
| + _read().forEach(f);
|
| + }
|
| +
|
| + Collection map(f(String element)) => _read().map(f);
|
| +
|
| + Collection<String> filter(bool f(String element)) => _read().filter(f);
|
| +
|
| + bool every(bool f(String element)) => _read().every(f);
|
| +
|
| + bool some(bool f(String element)) => _read().some(f);
|
| +
|
| + bool isEmpty() => _read().isEmpty();
|
| +
|
| + int get length() =>_read().length;
|
| +
|
| + // interface Collection - END
|
| +
|
| + // interface Set - BEGIN
|
| + bool contains(String value) => _read().contains(value);
|
| +
|
| + void add(String value) {
|
| + // TODO - figure out if we need to do any validation here
|
| + // or if the browser natively does enough
|
| + _modify((s) => s.add(value));
|
| + }
|
| +
|
| + bool remove(String value) {
|
| + Set<String> s = _read();
|
| + bool result = s.remove(value);
|
| + _write(s);
|
| + return result;
|
| + }
|
| +
|
| + void addAll(Collection<String> collection) {
|
| + // TODO - see comment above about validation
|
| + _modify((s) => s.addAll(collection));
|
| + }
|
| +
|
| + void removeAll(Collection<String> collection) {
|
| + _modify((s) => s.removeAll(collection));
|
| + }
|
| +
|
| + bool isSubsetOf(Collection<String> collection) =>
|
| + _read().isSubsetOf(collection);
|
| +
|
| + bool containsAll(Collection<String> collection) =>
|
| + _read().containsAll(collection);
|
| +
|
| + Set<String> intersection(Collection<String> other) =>
|
| + _read().intersection(other);
|
| +
|
| + void clear() {
|
| + _modify((s) => s.clear());
|
| + }
|
| + // interface Set - END
|
| +
|
| + /**
|
| + * Helper method used to modify the set of css classes on this element.
|
| + *
|
| + * f - callback with:
|
| + * s - a Set of all the css class name currently on this element.
|
| + *
|
| + * After f returns, the modified set is written to the
|
| + * className property of this element.
|
| + */
|
| + void _modify( f(Set<String> s)) {
|
| + Set<String> s = _read();
|
| + f(s);
|
| + _write(s);
|
| + }
|
| +
|
| + /**
|
| + * Read the class names from the Element class property,
|
| + * and put them into a set (duplicates are discarded).
|
| + */
|
| + Set<String> _read() {
|
| + // TODO(mattsh) simplify this once split can take regex.
|
| + Set<String> s = new Set<String>();
|
| + for (String name in _classname().split(' ')) {
|
| + String trimmed = name.trim();
|
| + if (!trimmed.isEmpty()) {
|
| + s.add(trimmed);
|
| + }
|
| + }
|
| + return s;
|
| + }
|
| +
|
| + /**
|
| + * Read the class names as a space-separated string. This is meant to be
|
| + * overridden by subclasses.
|
| + */
|
| + String _classname() => _element.$dom_className;
|
| +
|
| + /**
|
| + * Join all the elements of a set into one string and write
|
| + * back to the element.
|
| + */
|
| + void _write(Set s) {
|
| + _element.$dom_className = _formatSet(s);
|
| + }
|
| +
|
| + String _formatSet(Set<String> s) {
|
| + // TODO(mattsh) should be able to pass Set to String.joins http:/b/5398605
|
| + List list = new List.from(s);
|
| + return Strings.join(list, ' ');
|
| + }
|
| +}
|
| +
|
| class _SimpleClientRect implements ClientRect {
|
| final num left;
|
| final num top;
|
| @@ -458,21 +655,11 @@ class _ElementRectImpl implements ElementRect {
|
|
|
| class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
|
|
|
| - // TODO(jacobr): caching these may hurt performance.
|
| - ElementAttributeMap _elementAttributeMap;
|
| - _CssClassSet _cssClassSet;
|
| - _DataAttributeMap _dataAttributes;
|
| -
|
| /**
|
| * @domName Element.hasAttribute, Element.getAttribute, Element.setAttribute,
|
| * Element.removeAttribute
|
| */
|
| - Map<String, String> get attributes() {
|
| - if (_elementAttributeMap === null) {
|
| - _elementAttributeMap = new ElementAttributeMap._wrap(this);
|
| - }
|
| - return _elementAttributeMap;
|
| - }
|
| + _ElementAttributeMap get attributes() => new _ElementAttributeMap(this);
|
|
|
| void set attributes(Map<String, String> value) {
|
| Map<String, String> attributes = this.attributes;
|
| @@ -493,12 +680,7 @@ class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
|
| ElementList queryAll(String selectors) =>
|
| new _FrozenElementList._wrap($dom_querySelectorAll(selectors));
|
|
|
| - Set<String> get classes() {
|
| - if (_cssClassSet === null) {
|
| - _cssClassSet = new _CssClassSet(this);
|
| - }
|
| - return _cssClassSet;
|
| - }
|
| + _CssClassSet get classes() => new _CssClassSet(this);
|
|
|
| void set classes(Collection<String> value) {
|
| _CssClassSet classSet = classes;
|
| @@ -506,15 +688,11 @@ class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
|
| classSet.addAll(value);
|
| }
|
|
|
| - Map<String, String> get dataAttributes() {
|
| - if (_dataAttributes === null) {
|
| - _dataAttributes = new _DataAttributeMap(attributes);
|
| - }
|
| - return _dataAttributes;
|
| - }
|
| + Map<String, String> get dataAttributes() =>
|
| + new _DataAttributeMap(attributes);
|
|
|
| void set dataAttributes(Map<String, String> value) {
|
| - Map<String, String> dataAttributes = this.dataAttributes;
|
| + final dataAttributes = this.dataAttributes;
|
| dataAttributes.clear();
|
| for (String key in value.getKeys()) {
|
| dataAttributes[key] = value[key];
|
|
|