// 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. class _ChildrenNodeList implements NodeList { // Raw node. final _node; final _childNodes; _ChildrenNodeList._wrap(var node) : _childNodes = node.childNodes, _node = node; List _toList() { final output = new List(_childNodes.length); for (int i = 0, len = _childNodes.length; i < len; i++) { output[i] = LevelDom.wrapNode(_childNodes[i]); } return output; } Node get first() { return LevelDom.wrapNode(_node.firstChild); } void forEach(void f(Node element)) { for (var node in _childNodes) { f(LevelDom.wrapNode(node)); } } Collection filter(bool f(Node element)) { List output = new List(); forEach((Node element) { if (f(element)) { output.add(element); } }); return output; } bool every(bool f(Node element)) { for(Node element in this) { if (!f(element)) { return false; } }; return true; } bool some(bool f(Node element)) { for(Node element in this) { if (f(element)) { return true; } }; return false; } bool isEmpty() { return _node.hasChildNodes(); } int get length() { return _childNodes.length; } Node operator [](int index) { return LevelDom.wrapNode(_childNodes[index]); } void operator []=(int index, Node value) { _childNodes[index] = LevelDom.unwrap(value); } void set length(int newLength) { throw new UnsupportedOperationException(''); } Node add(Node value) { _node.appendChild(LevelDom.unwrap(value)); return value; } Node addLast(Node value) { _node.appendChild(LevelDom.unwrap(value)); return value; } Iterator iterator() { return _toList().iterator(); } void addAll(Collection collection) { for (Node node in collection) { _node.appendChild(LevelDom.unwrap(node)); } } void sort(int compare(Node a, Node b)) { throw const UnsupportedOperationException('TODO(jacobr): should we impl?'); } void copyFrom(List 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(Node element, [int start = 0]) { return _Lists.indexOf(this, element, start, this.length); } int lastIndexOf(Node element, [int start = null]) { if (start === null) start = length - 1; return _Lists.lastIndexOf(this, element, start); } void clear() { _node.textContent = ''; } Node removeLast() { final last = this.last(); if (last != null) { _node.removeChild(LevelDom.unwrap(last)); } return last; } Node last() { return LevelDom.wrapNode(_node.lastChild); } } class NodeWrappingImplementation extends EventTargetWrappingImplementation implements Node { NodeList _nodes; NodeWrappingImplementation._wrap(ptr) : super._wrap(ptr); void set nodes(Collection value) { // Copy list first since we don't want liveness during iteration. List copy = new List.from(value); nodes.clear(); nodes.addAll(copy); } NodeList get nodes() { if (_nodes === null) { _nodes = new _ChildrenNodeList._wrap(_ptr); } return _nodes; } Node get nextNode() => LevelDom.wrapNode(_ptr.nextSibling); Document get document() => LevelDom.wrapDocument(_ptr.ownerDocument); Node get parent() => LevelDom.wrapNode(_ptr.parentNode); Node get previousNode() => LevelDom.wrapNode(_ptr.previousSibling); String get text() => _ptr.textContent; void set text(String value) { _ptr.textContent = value; } // New methods implemented. Node replaceWith(Node otherNode) { try { _ptr.parentNode.replaceChild(LevelDom.unwrap(otherNode), _ptr); } catch(var e) { // TODO(jacobr): what should we return on failure? } return this; } Node remove() { // TODO(jacobr): should we throw an exception if parent is already null? if (_ptr.parentNode !== null) { _ptr.parentNode.removeChild(_ptr); } return this; } bool contains(Node otherNode) { // TODO: Feature detect and use built in. while (otherNode != null && otherNode != this) { otherNode = otherNode.parent; } return otherNode == this; } // TODO(jacobr): remove when/if List supports a method similar to // insertBefore or we switch NodeList to implement LinkedList rather than // array. Node insertBefore(Node newChild, Node refChild) { return LevelDom.wrapNode(_ptr.insertBefore( LevelDom.unwrap(newChild), LevelDom.unwrap(refChild))); } Node clone(bool deep) { return LevelDom.wrapNode(_ptr.cloneNode(deep)); } }