// 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. part of $LIBRARYNAME; class _ChildrenElementList extends ListBase implements NodeListWrapper { // Raw Element. final Element _element; final HtmlCollection _childElements; _ChildrenElementList._wrap(Element element) : _childElements = element._children, _element = element; bool contains(Object element) => _childElements.contains(element); bool get isEmpty { return _element._firstElementChild == null; } int get length { return _childElements.length; } Element operator [](int index) { return _childElements[index]; } void operator []=(int index, Element value) { _element._replaceChild(value, _childElements[index]); } set length(int newLength) { // TODO(jacobr): remove children when length is reduced. throw new UnsupportedError('Cannot resize element lists'); } Element add(Element value) { _element.append(value); return value; } Iterator get iterator => toList().iterator; void addAll(Iterable iterable) { if (iterable is _ChildNodeListLazy) { iterable = new List.from(iterable); } for (Element element in iterable) { _element.append(element); } } void sort([int compare(Element a, Element b)]) { throw new UnsupportedError('Cannot sort element lists'); } void shuffle([Random random]) { throw new UnsupportedError('Cannot shuffle element lists'); } void removeWhere(bool test(Element element)) { _filter(test, false); } void retainWhere(bool test(Element element)) { _filter(test, true); } void _filter(bool test(Element element), bool retainMatching) { var removed; if (retainMatching) { removed = _element.children.where((e) => !test(e)); } else { removed = _element.children.where(test); } for (var e in removed) e.remove(); } void fillRange(int start, int end, [Element fillValue]) { throw new UnimplementedError(); } void replaceRange(int start, int end, Iterable iterable) { throw new UnimplementedError(); } void removeRange(int start, int end) { throw new UnimplementedError(); } void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { throw new UnimplementedError(); } bool remove(Object object) { if (object is Element) { Element element = object; if (identical(element.parentNode, _element)) { _element._removeChild(element); return true; } } return false; } void insert(int index, Element element) { if (index < 0 || index > length) { throw new RangeError.range(index, 0, length); } if (index == length) { _element.append(element); } else { _element.insertBefore(element, this[index]); } } void setAll(int index, Iterable iterable) { throw new UnimplementedError(); } void clear() { _element._clearChildren(); } Element removeAt(int index) { final result = this[index]; if (result != null) { _element._removeChild(result); } return result; } Element removeLast() { final result = this.last; if (result != null) { _element._removeChild(result); } return result; } Element get first { Element result = _element._firstElementChild; if (result == null) throw new StateError("No elements"); return result; } Element get last { Element result = _element._lastElementChild; if (result == null) throw new StateError("No elements"); return result; } Element get single { if (length > 1) throw new StateError("More than one element"); return first; } List get rawList => _childElements; } /** * An immutable list containing HTML elements. This list contains some * additional methods when compared to regular lists for ease of CSS * manipulation on a group of elements. */ abstract class ElementList extends ListBase { /** * The union of all CSS classes applied to the elements in this list. * * This set makes it easy to add, remove or toggle (add if not present, remove * if present) the classes applied to a collection of elements. * * htmlList.classes.add('selected'); * htmlList.classes.toggle('isOnline'); * htmlList.classes.remove('selected'); */ CssClassSet get classes; /** Replace the classes with `value` for every element in this list. */ set classes(Iterable value); /** * Access the union of all [CssStyleDeclaration]s that are associated with an * [ElementList]. * * Grouping the style objects all together provides easy editing of specific * properties of a collection of elements. Setting a specific property value * will set that property in all [Element]s in the [ElementList]. Getting a * specific property value will return the value of the property of the first * element in the [ElementList]. */ CssStyleDeclarationBase get style; /** * Access dimensions and position of the Elements in this list. * * Setting the height or width properties will set the height or width * property for all elements in the list. This returns a rectangle with the * dimensions actually available for content * in this element, in pixels, regardless of this element's box-sizing * property. Getting the height or width returns the height or width of the * first Element in this list. * * Unlike [getBoundingClientRect], the dimensions of this rectangle * will return the same numerical height if the element is hidden or not. */ @Experimental() CssRect get contentEdge; /** * Access dimensions and position of the first Element's content + padding box * in this list. * * This returns a rectangle with the dimensions actually available for content * in this element, in pixels, regardless of this element's box-sizing * property. Unlike [getBoundingClientRect], the dimensions of this rectangle * will return the same numerical height if the element is hidden or not. This * can be used to retrieve jQuery's `innerHeight` value for an element. This * is also a rectangle equalling the dimensions of clientHeight and * clientWidth. */ @Experimental() CssRect get paddingEdge; /** * Access dimensions and position of the first Element's content + padding + * border box in this list. * * This returns a rectangle with the dimensions actually available for content * in this element, in pixels, regardless of this element's box-sizing * property. Unlike [getBoundingClientRect], the dimensions of this rectangle * will return the same numerical height if the element is hidden or not. This * can be used to retrieve jQuery's `outerHeight` value for an element. */ @Experimental() CssRect get borderEdge; /** * Access dimensions and position of the first Element's content + padding + * border + margin box in this list. * * This returns a rectangle with the dimensions actually available for content * in this element, in pixels, regardless of this element's box-sizing * property. Unlike [getBoundingClientRect], the dimensions of this rectangle * will return the same numerical height if the element is hidden or not. This * can be used to retrieve jQuery's `outerHeight` value for an element. */ @Experimental() CssRect get marginEdge; $!STREAM_GETTER_SIGNATURES } // Wrapper over an immutable NodeList to make it implement ElementList. // // Clients are {`Document`, `DocumentFragment`}.`querySelectorAll` which are // declared to return `ElementList`. This provides all the static analysis // benefit so there is no need for this class have a constrained type parameter. // class _FrozenElementList extends ListBase implements ElementList, NodeListWrapper { final List _nodeList; _FrozenElementList._wrap(this._nodeList); int get length => _nodeList.length; E operator [](int index) => _nodeList[index]; void operator []=(int index, E value) { throw new UnsupportedError('Cannot modify list'); } set length(int newLength) { throw new UnsupportedError('Cannot modify list'); } void sort([Comparator compare]) { throw new UnsupportedError('Cannot sort list'); } void shuffle([Random random]) { throw new UnsupportedError('Cannot shuffle list'); } E get first => _nodeList.first; E get last => _nodeList.last; E get single => _nodeList.single; CssClassSet get classes => new _MultiElementCssClassSet(this); CssStyleDeclarationBase get style => new _CssStyleDeclarationSet(this); set classes(Iterable value) { // TODO(sra): This might be faster for Sets: // // new _MultiElementCssClassSet(this).writeClasses(value) // // as the code below converts the Iterable[value] to a string multiple // times. Maybe compute the string and set className here. forEach((e) => e.classes = value); } CssRect get contentEdge => new _ContentCssListRect(this); CssRect get paddingEdge => this.first.paddingEdge; CssRect get borderEdge => this.first.borderEdge; CssRect get marginEdge => this.first.marginEdge; List get rawList => _nodeList; $!ELEMENT_STREAM_GETTERS } @DocsEditable() $(ANNOTATIONS)$(NATIVESPEC)class $CLASSNAME$EXTENDS$IMPLEMENTS { /** * Creates an HTML element from a valid fragment of HTML. * * var element = new Element.html('
content
'); * * The HTML fragment should contain only one single root element, any * leading or trailing text nodes will be removed. * * The HTML fragment is parsed as if it occurred within the context of a * `` tag, this means that special elements such as `` which * must be parsed within the scope of a `` element will be dropped. Use * [createFragment] to parse contextual HTML fragments. * * Unless a validator is provided this will perform the default validation * and remove all scriptable elements and attributes. * * See also: * * * [NodeValidator] * */ factory Element.html(String html, {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) { var fragment = document.body.createFragment(html, validator: validator, treeSanitizer: treeSanitizer); return fragment.nodes.where((e) => e is Element).single; } /** * Custom element creation constructor. * * This constructor is used by the DOM when a custom element has been * created. It can only be invoked by subclasses of Element from * that classes created constructor. * * class CustomElement extends Element { * factory CustomElement() => new Element.tag('x-custom'); * * CustomElement.created() : super.created() { * // Perform any element initialization. * } * } * document.registerElement('x-custom', CustomElement); */ Element.created() : super._created(); /** * Creates the HTML element specified by the tag name. * * This is similar to [Document.createElement]. * [tag] should be a valid HTML tag name. If [tag] is an unknown tag then * this will create an [UnknownElement]. * * var divElement = new Element.tag('div'); * print(divElement is DivElement); // 'true' * var myElement = new Element.tag('unknownTag'); * print(myElement is UnknownElement); // 'true' * * For standard elements it is better to use the element type constructors: * * var element = new DivElement(); * * It is better to use e.g `new CanvasElement()` because the type of the * expression is `CanvasElement`, whereas the type of `Element.tag` is the * less specific `Element`. * * See also: * * * [isTagSupported] */ factory $CLASSNAME.tag(String tag, [String typeExtention]) => _$(CLASSNAME)FactoryProvider.createElement_tag(tag, typeExtention); /// Creates a new `` element. /// /// This is equivalent to calling `new Element.tag('a')`. factory Element.a() => new AnchorElement(); /// Creates a new `
` element. /// /// This is equivalent to calling `new Element.tag('article')`. factory Element.article() => new Element.tag('article'); /// Creates a new `