| Index: lib/web_components.dart
|
| diff --git a/lib/web_components.dart b/lib/web_components.dart
|
| deleted file mode 100644
|
| index e346b33973ec2f5bf715b70e7103dbf07758cc1e..0000000000000000000000000000000000000000
|
| --- a/lib/web_components.dart
|
| +++ /dev/null
|
| @@ -1,583 +0,0 @@
|
| -// 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.
|
| -
|
| -/**
|
| - * This library exposes the types in [watcher], [safe_html], [templating] and
|
| - * the [WebComponent] base class. See this article for more information about
|
| - * this library: <http://www.dartlang.org/articles/dart-web-components/>.
|
| - */
|
| -library web_components;
|
| -
|
| -export 'watcher.dart';
|
| -export 'safe_html.dart';
|
| -export 'templating.dart';
|
| -
|
| -import 'dart:html';
|
| -
|
| -// Imported for the doc comment
|
| -import 'watcher.dart' as watcher;
|
| -import 'safe_html.dart' as safe_html;
|
| -import 'templating.dart' as templating;
|
| -
|
| -/**
|
| - * The base class for all Dart web components. In addition to the [Element]
|
| - * interface, it also provides lifecycle methods:
|
| - * - [created]
|
| - * - [inserted]
|
| - * - [attributeChanged]
|
| - * - [removed]
|
| - */
|
| -abstract class WebComponent implements Element {
|
| - /** The web component element wrapped by this class. */
|
| - final Element _element;
|
| - List _shadowRoots;
|
| -
|
| - /**
|
| - * Default constructor for web components. This contructor is only provided
|
| - * for tooling, and is *not* currently supported.
|
| - * Use [WebComponent.forElement] instead.
|
| - */
|
| - WebComponent() : _element = null {
|
| - throw new UnsupportedError(
|
| - 'Directly constructing web components is not currently supported. '
|
| - 'You need to use the WebComponent.forElement constructor to associate '
|
| - 'a component with its DOM element. If you run "bin/dwc.dart" on your '
|
| - 'component, the compiler will create the approriate construction '
|
| - 'logic.');
|
| - }
|
| -
|
| - /**
|
| - * Temporary constructor until components extend [Element]. Attaches this
|
| - * component to the provided [element]. The element must not already have a
|
| - * component associated with it.
|
| - */
|
| - WebComponent.forElement(Element element) : _element = element {
|
| - if (element == null || _element.xtag != null) {
|
| - throw new ArgumentError(
|
| - 'element must be provided and not have its xtag property set');
|
| - }
|
| - _element.xtag = this;
|
| - }
|
| -
|
| - /**
|
| - * **Note**: This is an implementation helper and should not need to be called
|
| - * from your code.
|
| - *
|
| - * Creates the [ShadowRoot] backing this component.
|
| - */
|
| - createShadowRoot() {
|
| - if (_realShadowRoot) {
|
| - return new ShadowRoot(_element);
|
| - }
|
| - if (_shadowRoots == null) _shadowRoots = [];
|
| - _shadowRoots.add(new Element.html('<div class="shadowroot"></div>'));
|
| - return _shadowRoots.last;
|
| - }
|
| -
|
| - /**
|
| - * Invoked when this component gets created.
|
| - * Note that [root] will be a [ShadowRoot] if the browser supports Shadow DOM.
|
| - */
|
| - void created() {}
|
| -
|
| - /** Invoked when this component gets inserted in the DOM tree. */
|
| - void inserted() {}
|
| -
|
| - /** Invoked when this component is removed from the DOM tree. */
|
| - void removed() {}
|
| -
|
| - // TODO(jmesserly): how do we implement this efficiently?
|
| - // See https://github.com/dart-lang/dart-web-components/issues/37
|
| - /** Invoked when any attribute of the component is modified. */
|
| - void attributeChanged(
|
| - String name, String oldValue, String newValue) {}
|
| -
|
| - /**
|
| - * **Note**: This is an implementation helper and should not need to be called
|
| - * from your code.
|
| - *
|
| - * If [ShadowRoot.supported] or [useShadowDom] is false, this distributes
|
| - * children to the insertion points of the emulated ShadowRoot.
|
| - * This is an implementation helper and should not need to be called from your
|
| - * code.
|
| - *
|
| - * This is an implementation of [composition][1] and [rendering][2] from the
|
| - * Shadow DOM spec. Currently the algorithm will replace children of this
|
| - * component with the DOM as it should be rendered.
|
| - *
|
| - * Note that because we're always expanding to the render tree, and nodes are
|
| - * expanded in a bottom up fashion, [reprojection][3] is handled naturally.
|
| - *
|
| - * [1]: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#composition
|
| - * [2]: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#rendering-shadow-trees
|
| - * [3]: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#reprojection
|
| - */
|
| - void composeChildren() {
|
| - if (_realShadowRoot) return;
|
| -
|
| - if (_shadowRoots.length == 0) {
|
| - // TODO(jmesserly): this is a limitation of our codegen approach.
|
| - // We could keep the _shadowRoots around and clone(true) them, but then
|
| - // bindings wouldn't be properly associated.
|
| - throw new StateError('Distribution algorithm requires at least one shadow'
|
| - ' root and can only be run once.');
|
| - }
|
| -
|
| - var treeStack = _shadowRoots;
|
| -
|
| - // Let TREE be the youngest tree in the HOST's tree stack
|
| - var tree = treeStack.removeLast();
|
| - var youngestRoot = tree;
|
| - // Let POOL be the list of nodes
|
| - var pool = new List.from(nodes);
|
| -
|
| - // Note: reprojection logic is skipped here because composeChildren is
|
| - // run on each component in bottom up fashion.
|
| -
|
| - var shadowInsertionPoints = [];
|
| - var shadowInsertionTrees = [];
|
| -
|
| - while (true) {
|
| - // Run the distribution algorithm, supplying POOL and TREE as input
|
| - pool = _distributeNodes(tree, pool);
|
| -
|
| - // Let POINT be the first encountered active shadow insertion point in
|
| - // TREE, in tree order
|
| - var point = tree.query('shadow');
|
| - if (point != null) {
|
| - if (treeStack.length > 0) {
|
| - // Find the next older tree, relative to TREE in the HOST's tree stack
|
| - // Set TREE to be this older tree
|
| - tree = treeStack.removeLast();
|
| - // Assign TREE to the POINT
|
| -
|
| - // Note: we defer the actual tree replace operation until the end, so
|
| - // we can run _distributeNodes on this tree. This simplifies the query
|
| - // for content nodes in tree order.
|
| - shadowInsertionPoints.add(point);
|
| - shadowInsertionTrees.add(tree);
|
| -
|
| - // Continue to repeat
|
| - } else {
|
| - // If we've hit a built-in element, just use a content selector.
|
| - // This matches the behavior of built-in HTML elements.
|
| - // Since <content> can be implemented simply, we just inline it.
|
| - _distribute(point, pool);
|
| -
|
| - // If there is no older tree, stop.
|
| - break;
|
| - }
|
| - } else {
|
| - // If POINT exists: ... Otherwise, stop
|
| - break;
|
| - }
|
| - }
|
| -
|
| - // Handle shadow tree assignments that we deferred earlier.
|
| - for (int i = 0; i < shadowInsertionPoints.length; i++) {
|
| - var point = shadowInsertionPoints[i];
|
| - var tree = shadowInsertionTrees[i];
|
| - // Note: defensive copy is a workaround for http://dartbug.com/6684
|
| - _distribute(point, new List.from(tree.nodes));
|
| - }
|
| -
|
| - // Replace our child nodes with the ones in the youngest root.
|
| - nodes.clear();
|
| - // Note: defensive copy is a workaround for http://dartbug.com/6684
|
| - nodes.addAll(new List.from(youngestRoot.nodes));
|
| - }
|
| -
|
| -
|
| - /**
|
| - * This is an implementation of the [distribution algorithm][1] from the
|
| - * Shadow DOM spec.
|
| - *
|
| - * [1]: http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#dfn-distribution-algorithm
|
| - */
|
| - List<Node> _distributeNodes(Element tree, List<Node> pool) {
|
| - // Repeat for each active insertion point in TREE, in tree order:
|
| - for (var insertionPoint in tree.queryAll('content')) {
|
| - if (!_isActive(insertionPoint)) continue;
|
| - // Let POINT be the current insertion point.
|
| -
|
| - // TODO(jmesserly): validate selector, as specified here:
|
| - // http://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#matching-insertion-points
|
| - var select = insertionPoint.attributes['select'];
|
| - if (select == null || select == '') select = '*';
|
| -
|
| - // Repeat for each node in POOL:
|
| - // 1. Let NODE be the current node
|
| - // 2. If the NODE matches POINT's matching criteria:
|
| - // 1. Distribute the NODE to POINT
|
| - // 2. Remove NODE from the POOL
|
| -
|
| - var matching = [];
|
| - var notMatching = [];
|
| - for (var node in pool) {
|
| - (_matches(node, select) ? matching : notMatching).add(node);
|
| - }
|
| -
|
| - if (matching.length == 0) {
|
| - // When an insertion point or a shadow insertion point has nothing
|
| - // assigned or distributed to them, the fallback content must be used
|
| - // instead when rendering. The fallback content is all descendants of
|
| - // the element that represents the insertion point.
|
| - matching = insertionPoint.nodes;
|
| - }
|
| -
|
| - _distribute(insertionPoint, matching);
|
| -
|
| - pool = notMatching;
|
| - }
|
| -
|
| - return pool;
|
| - }
|
| -
|
| - static bool _matches(Node node, String selector) {
|
| - if (node is Text) return selector == '*';
|
| - // TODO(jmesserly): cannot use matchesSelector because of dartbug.com/4401
|
| - //return (node as Element).matchesSelector(selector);
|
| - return (node.parent as Element).queryAll(selector).some((n) => n == node);
|
| - }
|
| -
|
| - static bool _isInsertionPoint(Element node) =>
|
| - node.tagName == 'CONTENT' || node.tagName == 'SHADOW';
|
| -
|
| - /**
|
| - * An insertion point is "active" if it is not the child of another insertion
|
| - * point. A child of an insertion point is "fallback" content and should not
|
| - * be considered during the distribution algorithm.
|
| - */
|
| - static bool _isActive(Element node) {
|
| - assert(_isInsertionPoint(node));
|
| - for (node = node.parent; node != null; node = node.parent) {
|
| - if (_isInsertionPoint(node)) return false;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - /** Distribute the [nodes] in place of an existing [insertionPoint]. */
|
| - static void _distribute(Element insertionPoint, List<Node> nodes) {
|
| - assert(_isInsertionPoint(insertionPoint));
|
| - for (var node in nodes) {
|
| - insertionPoint.parent.insertBefore(node, insertionPoint);
|
| - }
|
| - insertionPoint.remove();
|
| - }
|
| -
|
| - // TODO(jmesserly): this forwarding is temporary until Dart supports
|
| - // subclassing Elements.
|
| - // TODO(jmesserly): we were missing the setter for title, are other things
|
| - // missing setters?
|
| -
|
| - List<Node> get nodes => _element.nodes;
|
| -
|
| - set nodes(Collection<Node> value) { _element.nodes = value; }
|
| -
|
| - /**
|
| - * Replaces this node with another node.
|
| - */
|
| - Node replaceWith(Node otherNode) { _element.replaceWith(otherNode); }
|
| -
|
| - /**
|
| - * Removes this node from the DOM.
|
| - */
|
| - void remove() => _element.remove();
|
| -
|
| - Node get nextNode => _element.nextNode;
|
| -
|
| - Document get document => _element.document;
|
| -
|
| - Node get previousNode => _element.previousNode;
|
| -
|
| - String get text => _element.text;
|
| -
|
| - set text(String v) { _element.text = v; }
|
| -
|
| - bool contains(Node other) => _element.contains(other);
|
| -
|
| - bool hasChildNodes() => _element.hasChildNodes();
|
| -
|
| - Node insertBefore(Node newChild, Node refChild) =>
|
| - _element.insertBefore(newChild, refChild);
|
| -
|
| - Map<String, String> get attributes => _element.attributes;
|
| - set attributes(Map<String, String> value) {
|
| - _element.attributes = value;
|
| - }
|
| -
|
| - List<Element> get elements => _element.elements;
|
| -
|
| - set elements(Collection<Element> value) {
|
| - _element.elements = value;
|
| - }
|
| -
|
| - List<Element> get children => _element.children;
|
| -
|
| - set children(Collection<Element> value) {
|
| - _element.children = value;
|
| - }
|
| -
|
| - Set<String> get classes => _element.classes;
|
| -
|
| - set classes(Collection<String> value) {
|
| - _element.classes = value;
|
| - }
|
| -
|
| - Map<String, String> get dataAttributes => _element.dataAttributes;
|
| - set dataAttributes(Map<String, String> value) {
|
| - _element.dataAttributes = value;
|
| - }
|
| -
|
| - Map<String, String> getNamespacedAttributes(String namespace) =>
|
| - _element.getNamespacedAttributes(namespace);
|
| -
|
| - Future<CSSStyleDeclaration> get computedStyle => _element.computedStyle;
|
| -
|
| - Future<CSSStyleDeclaration> getComputedStyle(String pseudoElement)
|
| - => _element.getComputedStyle(pseudoElement);
|
| -
|
| - Element clone(bool deep) => _element.clone(deep);
|
| -
|
| - Element get parent => _element.parent;
|
| -
|
| - ElementEvents get on => _element.on;
|
| -
|
| - String get contentEditable => _element.contentEditable;
|
| -
|
| - String get dir => _element.dir;
|
| -
|
| - bool get draggable => _element.draggable;
|
| -
|
| - bool get hidden => _element.hidden;
|
| -
|
| - String get id => _element.id;
|
| -
|
| - String get innerHTML => _element.innerHtml;
|
| -
|
| - void set innerHTML(String v) {
|
| - _element.innerHtml = v;
|
| - }
|
| -
|
| - String get innerHtml => _element.innerHtml;
|
| - void set innerHtml(String v) {
|
| - _element.innerHtml = v;
|
| - }
|
| -
|
| - bool get isContentEditable => _element.isContentEditable;
|
| -
|
| - String get lang => _element.lang;
|
| -
|
| - String get outerHtml => _element.outerHtml;
|
| -
|
| - bool get spellcheck => _element.spellcheck;
|
| -
|
| - int get tabIndex => _element.tabIndex;
|
| -
|
| - String get title => _element.title;
|
| -
|
| - set title(String value) { _element.title = value; }
|
| -
|
| - bool get translate => _element.translate;
|
| -
|
| - String get webkitdropzone => _element.webkitdropzone;
|
| -
|
| - void click() { _element.click(); }
|
| -
|
| - Element insertAdjacentElement(String where, Element element) =>
|
| - _element.insertAdjacentElement(where, element);
|
| -
|
| - void insertAdjacentHtml(String where, String html) {
|
| - _element.insertAdjacentHtml(where, html);
|
| - }
|
| -
|
| - void insertAdjacentText(String where, String text) {
|
| - _element.insertAdjacentText(where, text);
|
| - }
|
| -
|
| - Map<String, String> get dataset => _element.dataset;
|
| -
|
| - Element get nextElementSibling => _element.nextElementSibling;
|
| -
|
| - Element get offsetParent => _element.offsetParent;
|
| -
|
| - Element get previousElementSibling => _element.previousElementSibling;
|
| -
|
| - CSSStyleDeclaration get style => _element.style;
|
| -
|
| - String get tagName => _element.tagName;
|
| -
|
| - void blur() { _element.blur(); }
|
| -
|
| - void focus() { _element.focus(); }
|
| -
|
| - void scrollByLines(int lines) {
|
| - _element.scrollByLines(lines);
|
| - }
|
| -
|
| - void scrollByPages(int pages) {
|
| - _element.scrollByPages(pages);
|
| - }
|
| -
|
| - void scrollIntoView([bool centerIfNeeded]) {
|
| - if (centerIfNeeded == null) {
|
| - _element.scrollIntoView();
|
| - } else {
|
| - _element.scrollIntoView(centerIfNeeded);
|
| - }
|
| - }
|
| -
|
| - bool matchesSelector(String selectors) => _element.matchesSelector(selectors);
|
| -
|
| - void webkitRequestFullScreen(int flags) {
|
| - _element.webkitRequestFullScreen(flags);
|
| - }
|
| -
|
| - void webkitRequestFullscreen() { _element.webkitRequestFullscreen(); }
|
| -
|
| - void webkitRequestPointerLock() { _element.webkitRequestPointerLock(); }
|
| -
|
| - Element query(String selectors) => _element.query(selectors);
|
| -
|
| - List<Element> queryAll(String selectors) => _element.queryAll(selectors);
|
| -
|
| - HTMLCollection get $dom_children => _element.$dom_children;
|
| -
|
| - int get $dom_childElementCount => _element.$dom_childElementCount;
|
| -
|
| - String get $dom_className => _element.$dom_className;
|
| - set $dom_className(String value) { _element.$dom_className = value; }
|
| -
|
| - int get clientHeight => _element.clientHeight;
|
| -
|
| - int get clientLeft => _element.clientLeft;
|
| -
|
| - int get clientTop => _element.clientTop;
|
| -
|
| - int get clientWidth => _element.clientWidth;
|
| -
|
| - int get childElementCount => _element.childElementCount;
|
| -
|
| - Element get firstElementChild => _element.firstElementChild;
|
| -
|
| - Element get lastElementChild => _element.lastElementChild;
|
| -
|
| - Element get $dom_firstElementChild => _element.$dom_firstElementChild;
|
| -
|
| - Element get $dom_lastElementChild => _element.$dom_lastElementChild;
|
| -
|
| - int get offsetHeight => _element.offsetHeight;
|
| -
|
| - int get offsetLeft => _element.offsetLeft;
|
| -
|
| - int get offsetTop => _element.offsetTop;
|
| -
|
| - int get offsetWidth => _element.offsetWidth;
|
| -
|
| - int get scrollHeight => _element.scrollHeight;
|
| -
|
| - int get scrollLeft => _element.scrollLeft;
|
| -
|
| - int get scrollTop => _element.scrollTop;
|
| -
|
| - set scrollLeft(int value) { _element.scrollLeft = value; }
|
| -
|
| - set scrollTop(int value) { _element.scrollTop = value; }
|
| -
|
| - int get scrollWidth => _element.scrollWidth;
|
| -
|
| - String $dom_getAttribute(String name) =>
|
| - _element.$dom_getAttribute(name);
|
| -
|
| - String $dom_getAttributeNS(String namespaceUri, String localName) =>
|
| - _element.$dom_getAttributeNS(namespaceUri, localName);
|
| -
|
| - String $dom_setAttributeNS(
|
| - String namespaceUri, String localName, String value) {
|
| - _element.$dom_setAttributeNS(namespaceUri, localName, value);
|
| - }
|
| -
|
| - bool $dom_hasAttributeNS(String namespaceUri, String localName) =>
|
| - _element.$dom_hasAttributeNS(namespaceUri, localName);
|
| -
|
| - void $dom_removeAttributeNS(String namespaceUri, String localName) =>
|
| - _element.$dom_removeAttributeNS(namespaceUri, localName);
|
| -
|
| - ClientRect getBoundingClientRect() => _element.getBoundingClientRect();
|
| -
|
| - List<ClientRect> getClientRects() => _element.getClientRects();
|
| -
|
| - List<Node> $dom_getElementsByClassName(String name) =>
|
| - _element.$dom_getElementsByClassName(name);
|
| -
|
| - List<Node> $dom_getElementsByTagName(String name) =>
|
| - _element.$dom_getElementsByTagName(name);
|
| -
|
| - bool $dom_hasAttribute(String name) =>
|
| - _element.$dom_hasAttribute(name);
|
| -
|
| - Element $dom_querySelector(String selectors) =>
|
| - _element.$dom_querySelector(selectors);
|
| -
|
| - List<Node> $dom_querySelectorAll(String selectors) =>
|
| - _element.$dom_querySelectorAll(selectors);
|
| -
|
| - void $dom_removeAttribute(String name) =>
|
| - _element.$dom_removeAttribute(name);
|
| -
|
| - void $dom_setAttribute(String name, String value) =>
|
| - _element.$dom_setAttribute(name, value);
|
| -
|
| - NamedNodeMap get $dom_attributes => _element.$dom_attributes;
|
| -
|
| - List<Node> get $dom_childNodes => _element.$dom_childNodes;
|
| -
|
| - Node get $dom_firstChild => _element.$dom_firstChild;
|
| -
|
| - Node get $dom_lastChild => _element.$dom_lastChild;
|
| -
|
| - String get $dom_localName => _element.$dom_localName;
|
| -
|
| - String get $dom_namespaceUri => _element.$dom_namespaceUri;
|
| -
|
| - int get nodeType => _element.nodeType;
|
| -
|
| - void $dom_addEventListener(String type, EventListener listener,
|
| - [bool useCapture]) {
|
| - _element.$dom_addEventListener(type, listener, useCapture);
|
| - }
|
| -
|
| - Node $dom_appendChild(Node newChild) => _element.$dom_appendChild(newChild);
|
| -
|
| - bool $dom_dispatchEvent(Event event) => _element.$dom_dispatchEvent(event);
|
| -
|
| - Node $dom_removeChild(Node oldChild) => _element.$dom_removeChild(oldChild);
|
| -
|
| - void $dom_removeEventListener(String type, EventListener listener,
|
| - [bool useCapture]) {
|
| - _element.$dom_removeEventListener(type, listener, useCapture);
|
| - }
|
| -
|
| - Node $dom_replaceChild(Node newChild, Node oldChild) =>
|
| - _element.$dom_replaceChild(newChild, oldChild);
|
| -
|
| - get xtag => _element.xtag;
|
| -
|
| - set xtag(value) { _element.xtag = value; }
|
| -
|
| - void append(Element e) => _element.append(e);
|
| -
|
| - void appendText(String text) => _element.appendText(text);
|
| -
|
| - void appendHtml(String html) => _element.appendHtml(html);
|
| -}
|
| -
|
| -/**
|
| - * Set this to true to use native Shadow DOM if it is supported.
|
| - * Note that this will change behavior of [WebComponent] APIs for tree
|
| - * traversal.
|
| - */
|
| -bool useShadowDom = false;
|
| -
|
| -bool get _realShadowRoot => useShadowDom && ShadowRoot.supported;
|
|
|