diff --git a/client/html/html.dart b/client/html/html.dart
index 77b3aff5621..9c018152e81 100644
--- a/client/html/html.dart
+++ b/client/html/html.dart
@@ -549,6 +549,7 @@
#source('src/BodyElement.dart');
#source('src/BodyElementWrappingImplementation.dart');
#source('src/CssClassSet.dart');
+#source('src/DataAttributeMap.dart');
#source('src/DocumentFragment.dart');
#source('src/DocumentFragmentWrappingImplementation.dart');
#source('src/DocumentWrappingImplementation.dart');
diff --git a/client/html/src/DataAttributeMap.dart b/client/html/src/DataAttributeMap.dart
new file mode 100644
index 00000000000..e678de7de41
--- /dev/null
+++ b/client/html/src/DataAttributeMap.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/**
+ * Provides a Map abstraction on top of data-* attributes, similar to the
+ * dataSet in the old DOM.
+ */
+class _DataAttributeMap implements Map {
+
+ final Map _attributes;
+
+ _DataAttributeMap(this._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) => _attributes.containsKey(_attr(key));
+
+ String operator [](String key) => _attributes[_attr(key)];
+
+ void operator []=(String key, String value) {
+ _attributes[_attr(key)] = value;
+ }
+
+ String putIfAbsent(String key, String ifAbsent()) {
+ if (!containsKey(key)) {
+ return this[key] = ifAbsent();
+ }
+ return this[key];
+ }
+
+ String remove(String key) => _attributes.remove(_attr(key));
+
+ void clear() {
+ // Needs to operate on a snapshot since we are mutatiting the collection.
+ for (String key in getKeys()) {
+ remove(key);
+ }
+ }
+
+ void forEach(void f(String key, String value)) {
+ _attributes.forEach((String key, String value) {
+ if (_matches(key)) {
+ f(_strip(key), value);
+ }
+ });
+ }
+
+ Collection getKeys() {
+ final keys = new List();
+ _attributes.forEach((String key, String value) {
+ if (_matches(key)) {
+ keys.add(_strip(key));
+ }
+ });
+ return keys;
+ }
+
+ Collection getValues() {
+ final values = new List();
+ _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.substringToEnd(5);
+}
+
diff --git a/client/html/src/Element.dart b/client/html/src/Element.dart
index b375e14fd1f..c176912becb 100644
--- a/client/html/src/Element.dart
+++ b/client/html/src/Element.dart
@@ -84,6 +84,9 @@ interface Element extends Node /*, common.NodeSelector, common.ElementTraversal
// TODO: The type of value should be Collection. See http://b/5392897
void set classes(value);
+ Map get dataAttributes();
+ void set dataAttributes(Map value);
+
int get clientHeight();
int get clientLeft();
diff --git a/client/html/src/ElementWrappingImplementation.dart b/client/html/src/ElementWrappingImplementation.dart
index a9876fe5afe..697815a9c94 100644
--- a/client/html/src/ElementWrappingImplementation.dart
+++ b/client/html/src/ElementWrappingImplementation.dart
@@ -402,6 +402,7 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement
ElementWrappingImplementation._wrap(ptr) : super._wrap(ptr);
_CssClassSet _cssClassSet;
+ _DataAttributeMap _dataAttributes;
Map get attributes() {
return new ElementAttributeMap._wrap(_ptr);
@@ -422,6 +423,21 @@ class ElementWrappingImplementation extends NodeWrappingImplementation implement
classSet.addAll(value);
}
+ Map get dataAttributes() {
+ if (_dataAttributes === null) {
+ _dataAttributes = new _DataAttributeMap(attributes);
+ }
+ return _dataAttributes;
+ }
+
+ void set dataAttributes(Map value) {
+ Map dataAttributes = this.dataAttributes;
+ dataAttributes.clear();
+ for (String key in value.getKeys()) {
+ dataAttributes[key] = value[key];
+ }
+ }
+
int get clientHeight() => _ptr.clientHeight;
int get clientLeft() => _ptr.clientLeft;