Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1119)

Unified Diff: client/dom/templates/html/frog/impl_Element.darttemplate

Issue 9403004: Wrapperless dart:html generator (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Final version to check in. changes generator script but doesn't check in an active version of the … Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: client/dom/templates/html/frog/impl_Element.darttemplate
diff --git a/client/dom/templates/html/frog/impl_Element.darttemplate b/client/dom/templates/html/frog/impl_Element.darttemplate
new file mode 100644
index 0000000000000000000000000000000000000000..1345ffc5bb96b74c277543a22b48f86403eab46e
--- /dev/null
+++ b/client/dom/templates/html/frog/impl_Element.darttemplate
@@ -0,0 +1,464 @@
+// Copyright (c) 2012, 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.
+
+// TODO(jacobr): use Lists.dart to remove some of the duplicated functionality.
+class _ChildrenElementList implements ElementList {
+ // Raw Element.
+ final _ElementJs _element;
+ final _HTMLCollectionJs _childElements;
+
+ _ChildrenElementList._wrap(_ElementJs element)
+ : _childElements = element._children,
+ _element = element;
+
+ List<Element> _toList() {
+ final output = new List(_childElements.length);
+ for (int i = 0, len = _childElements.length; i < len; i++) {
+ output[i] = _childElements[i];
+ }
+ return output;
+ }
+
+ _ElementJs get first() {
+ return _element._firstElementChild;
+ }
+
+ void forEach(void f(Element element)) {
+ for (_ElementJs element in _childElements) {
+ f(element);
+ }
+ }
+
+ Collection<Element> filter(bool f(Element element)) {
+ List<Element> output = <Element>[];
+ forEach((Element element) {
+ if (f(element)) {
+ output.add(element);
+ }
+ });
+ return output;
+ }
+
+ bool every(bool f(Element element)) {
+ for(Element element in this) {
+ if (!f(element)) {
+ return false;
+ }
+ };
+ return true;
+ }
+
+ bool some(bool f(Element element)) {
+ for(Element element in this) {
+ if (f(element)) {
+ return true;
+ }
+ };
+ return false;
+ }
+
+ bool isEmpty() {
+ return _element._firstElementChild !== null;
+ }
+
+ int get length() {
+ return _childElements.length;
+ }
+
+ _ElementJs operator [](int index) {
+ return _childElements[index];
+ }
+
+ void operator []=(int index, _ElementJs value) {
+ _element._replaceChild(value, _childElements.item(index));
+ }
+
+ void set length(int newLength) {
+ // TODO(jacobr): remove children when length is reduced.
+ throw const UnsupportedOperationException('');
+ }
+
+ Element add(_ElementJs value) {
+ _element._appendChild(value);
+ return value;
+ }
+
+ Element addLast(_ElementJs value) => add(value);
+
+ Iterator<Element> iterator() => _toList().iterator();
+
+ void addAll(Collection<_ElementJs> collection) {
+ for (_ElementJs element in collection) {
+ _element._appendChild(element);
+ }
+ }
+
+ void sort(int compare(Element a, Element b)) {
+ throw const UnsupportedOperationException('TODO(jacobr): should we impl?');
+ }
+
+ void copyFrom(List<Object> src, int srcStart, int dstStart, int count) {
+ throw 'Not impl yet. todo(jacobr)';
+ }
+
+ void setRange(int start, int length, List from, [int startFrom = 0]) {
+ throw const NotImplementedException();
+ }
+
+ void removeRange(int start, int length) {
+ throw const NotImplementedException();
+ }
+
+ void insertRange(int start, int length, [initialValue = null]) {
+ throw const NotImplementedException();
+ }
+
+ List getRange(int start, int length) {
+ throw const NotImplementedException();
+ }
+
+ int indexOf(Element element, [int start = 0]) {
+ return _Lists.indexOf(this, element, start, this.length);
+ }
+
+ int lastIndexOf(Element element, [int start = null]) {
+ if (start === null) start = length - 1;
+ return _Lists.lastIndexOf(this, element, start);
+ }
+
+ void clear() {
+ // It is unclear if we want to keep non element nodes?
+ _element.text = '';
+ }
+
+ Element removeLast() {
+ final last = this.last();
+ if (last != null) {
+ _element._removeChild(last);
+ }
+ return last;
+ }
+
+ Element last() {
+ return _element.lastElementChild;
+ }
+}
+
+class ElementAttributeMap implements Map<String, String> {
+
+ final _ElementJs _element;
+
+ ElementAttributeMap._wrap(this._element);
+
+ bool containsValue(String value) {
+ final attributes = _element.attributes;
+ for (int i = 0, len = attributes.length; i < len; i++) {
+ if(value == attributes.item(i).value) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool containsKey(String key) {
+ return _element._hasAttribute(key);
+ }
+
+ String operator [](String key) {
+ return _element._getAttribute(key);
+ }
+
+ void operator []=(String key, String value) {
+ _element._setAttribute(key, value);
+ }
+
+ String putIfAbsent(String key, String ifAbsent()) {
+ if (!containsKey(key)) {
+ this[key] = ifAbsent();
+ }
+ }
+
+ String remove(String key) {
+ _element._removeAttribute(key);
+ }
+
+ void clear() {
+ final attributes = _element._attributes;
+ for (int i = attributes.length - 1; i >= 0; i--) {
+ remove(attributes.item(i).name);
+ }
+ }
+
+ void forEach(void f(String key, String value)) {
+ final attributes = _element.attributes;
+ for (int i = 0, len = attributes.length; i < len; i++) {
+ final item = attributes.item(i);
+ f(item.name, item.value);
+ }
+ }
+
+ Collection<String> getKeys() {
+ // TODO(jacobr): generate a lazy collection instead.
+ final attributes = _element.attributes;
+ final keys = new List<String>(attributes.length);
+ for (int i = 0, len = attributes.length; i < len; i++) {
+ keys[i] = attributes.item(i).name;
+ }
+ return keys;
+ }
+
+ Collection<String> getValues() {
+ // TODO(jacobr): generate a lazy collection instead.
+ final attributes = _element.attributes;
+ final values = new List<String>(attributes.length);
+ for (int i = 0, len = attributes.length; i < len; i++) {
+ values[i] = attributes.item(i).value;
+ }
+ return values;
+ }
+
+ /**
+ * The number of {key, value} pairs in the map.
+ */
+ int get length() {
+ return _element._attributes.length;
+ }
+
+ /**
+ * Returns true if there is no {key, value} pair in the map.
+ */
+ bool isEmpty() {
+ return length == 0;
+ }
+}
+
+class _SimpleClientRect implements ClientRect {
+ final num left;
+ final num top;
+ final num width;
+ final num height;
+ num get right() => left + width;
+ num get bottom() => top + height;
+
+ const _SimpleClientRect(this.left, this.top, this.width, this.height);
+
+ bool operator ==(ClientRect other) {
+ return other !== null && left == other.left && top == other.top
+ && width == other.width && height == other.height;
+ }
+
+ String toString() => "($left, $top, $width, $height)";
+}
+
+// TODO(jacobr): we cannot currently be lazy about calculating the client
+// rects as we must perform all measurement queries at a safe point to avoid
+// triggering unneeded layouts.
+/**
+ * All your element measurement needs in one place
+ * @domName none
+ */
+class _ElementRectImpl implements ElementRect {
+ final ClientRect client;
+ final ClientRect offset;
+ final ClientRect scroll;
+
+ // TODO(jacobr): should we move these outside of ElementRect to avoid the
+ // overhead of computing them every time even though they are rarely used.
+ final _ClientRectJs _boundingClientRect;
+ final _ClientRectListJs _clientRects;
+
+ _ElementRectImpl(_ElementJs element) :
+ client = new _SimpleClientRect(element._clientLeft,
+ element._clientTop,
+ element._clientWidth,
+ element._clientHeight),
+ offset = new _SimpleClientRect(element._offsetLeft,
+ element._offsetTop,
+ element._offsetWidth,
+ element._offsetHeight),
+ scroll = new _SimpleClientRect(element._scrollLeft,
+ element._scrollTop,
+ element._scrollWidth,
+ element._scrollHeight),
+ _boundingClientRect = element.getBoundingClientRect(),
+ _clientRects = element.getClientRects();
+
+ _ClientRectJs get bounding() => _boundingClientRect;
+
+ // TODO(jacobr): cleanup.
+ List<ClientRect> get clientRects() {
+ final out = new List(_clientRects.length);
+ for (num i = 0; i < _clientRects.length; i++) {
+ out[i] = _clientRects.item(i);
+ }
+ return out;
+ }
+}
+
+final _START_TAG_REGEXP = const RegExp('<(\\w+)');
+
+class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+
+ static final _CUSTOM_PARENT_TAG_MAP = const {
+ 'body' : 'html',
+ 'head' : 'html',
+ 'caption' : 'table',
+ 'td': 'tr',
+ 'tbody': 'table',
+ 'colgroup': 'table',
+ 'col' : 'colgroup',
+ 'tr' : 'tbody',
+ 'tbody' : 'table',
+ 'tfoot' : 'table',
+ 'thead' : 'table',
+ 'track' : 'audio',
+ };
+
+ /** @domName Document.createElement */
+ factory Element.html(String html) {
+ // TODO(jacobr): this method can be made more robust and performant.
+ // 1) Cache the dummy parent elements required to use innerHTML rather than
+ // creating them every call.
+ // 2) Verify that the html does not contain leading or trailing text nodes.
+ // 3) Verify that the html does not contain both <head> and <body> tags.
+ // 4) Detatch the created element from its dummy parent.
+ String parentTag = 'div';
+ String tag;
+ final match = _START_TAG_REGEXP.firstMatch(html);
+ if (match !== null) {
+ tag = match.group(1).toLowerCase();
+ if (_CUSTOM_PARENT_TAG_MAP.containsKey(tag)) {
+ parentTag = _CUSTOM_PARENT_TAG_MAP[tag];
+ }
+ }
+ _ElementJs temp = _document._createElement(parentTag);
+ temp.innerHTML = html;
+
+ if (temp._childElementCount == 1) {
+ return temp._firstElementChild;
+ } else if (parentTag == 'html' && temp._childElementCount == 2) {
+ // Work around for edge case in WebKit and possibly other browsers where
+ // both body and head elements are created even though the inner html
+ // only contains a head or body element.
+ return temp.elements[tag == 'head' ? 0 : 1];
+ } else {
+ throw new IllegalArgumentException('HTML had ${temp._childElementCount} ' +
+ 'top level elements but 1 expected');
+ }
+ }
+
+ /** @domName Document.createElement */
+ factory Element.tag(String tag) {
+ return _document._createElement(tag);
+ }
+
+ // TODO(jacobr): caching these may hurt performance.
+ ElementAttributeMap _elementAttributeMap;
+ _CssClassSet _cssClassSet;
+ _DataAttributeMap _dataAttributes;
+
+ // TODO(jacobr): remove these methods and let them be generated automatically
+ // once dart supports defining fields with the same name in an interface and
+ // its parent interface.
+ String get title() native "return this.parentNode.title;";
+ void set title(String value) native "this.parentNode.title = value;";
+
+ /**
+ * @domName Element.hasAttribute, Element.getAttribute, Element.setAttribute,
+ * Element.removeAttribute
+ */
+ Map<String, String> get attributes() {
+ if (_elementAttributeMap === null) {
+ _elementAttributeMap = new ElementAttributeMap._wrap(this);
+ }
+ return _elementAttributeMap;
+ }
+
+ void set attributes(Map<String, String> value) {
+ Map<String, String> attributes = this.attributes;
+ attributes.clear();
+ for (String key in value.getKeys()) {
+ attributes[key] = value[key];
+ }
+ }
+
+ void set elements(Collection<Element> value) {
+ final elements = this.elements;
+ elements.clear();
+ elements.addAll(value);
+ }
+
+ /**
+ * @domName childElementCount, firstElementChild, lastElementChild,
+ * children, Node.nodes.add
+ */
+ ElementList get elements() => new _ChildrenElementList._wrap(this);
+
+ /** @domName querySelector, Document.getElementById */
+ Element query(String selectors) native "return this.querySelector(selectors);";
+
+ /**
+ * @domName querySelectorAll, getElementsByClassName, getElementsByTagName,
+ * getElementsByTagNameNS
+ */
+ ElementList queryAll(String selectors) native "return this.querySelectorAll(selectors);";
+
+ /** @domName className, classList */
+ Set<String> get classes() {
+ if (_cssClassSet === null) {
+ _cssClassSet = new _CssClassSet(this);
+ }
+ return _cssClassSet;
+ }
+
+ void set classes(Collection<String> value) {
+ _CssClassSet classSet = classes;
+ classSet.clear();
+ classSet.addAll(value);
+ }
+
+ Map<String, String> get dataAttributes() {
+ if (_dataAttributes === null) {
+ _dataAttributes = new _DataAttributeMap(attributes);
+ }
+ return _dataAttributes;
+ }
+
+ void set dataAttributes(Map<String, String> value) {
+ Map<String, String> dataAttributes = this.dataAttributes;
+ dataAttributes.clear();
+ for (String key in value.getKeys()) {
+ dataAttributes[key] = value[key];
+ }
+ }
+
+ bool matchesSelector(String selectors) native "return this.webkitMatchesSelector(selectors)";
+
+ /**
+ * @domName getClientRects, getBoundingClientRect, clientHeight, clientWidth,
+ * clientTop, clientLeft, offsetHeight, offsetWidth, offsetTop, offsetLeft,
+ * scrollHeight, scrollWidth, scrollTop, scrollLeft
+ */
+ Future<ElementRect> get rect() {
+ return _createMeasurementFuture(
+ () => new _ElementRectImpl(this),
+ new Completer<ElementRect>());
+ }
+
+ /** @domName Window.getComputedStyle */
+ Future<CSSStyleDeclaration> get computedStyle() {
+ // TODO(jacobr): last param should be null, see b/5045788
+ return getComputedStyle('');
+ }
+
+ /** @domName Window.getComputedStyle */
+ Future<CSSStyleDeclaration> getComputedStyle(String pseudoElement) {
+ return _createMeasurementFuture(() =>
+ _window._getComputedStyle(this, pseudoElement),
+ new Completer<CSSStyleDeclaration>());
+ }
+
+ _ElementJs clone(bool deep) native;
+$!MEMBERS
+}
« no previous file with comments | « client/dom/templates/html/frog/impl_Document.darttemplate ('k') | client/dom/templates/html/frog/impl_Event.darttemplate » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698