| // Copyright (c) 2013, 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. |
| |
| /** |
| * Custom DOM elements. |
| * |
| * This library provides access to the Polymer project's |
| * [Custom Elements] |
| * (http://www.polymer-project.org/platform/custom-elements.html) |
| * API, which lets you define your own elements. With custom elements, you |
| * associate code with custom tag names, and then use those custom tag names |
| * as you would any standard tag. For more information, see the |
| * [Polymer.dart homepage](https://www.dartlang.org/polymer-dart/) and its |
| * [custom element example] |
| * (https://www.dartlang.org/polymer-dart/#custom-elements). |
| */ |
| library custom_element; |
| |
| import 'dart:html'; |
| import 'dart:async'; |
| |
| /** |
| * *Deprecated* -- do not use. Extend [HtmlElement] and use |
| * [document.register] instead. If running on a browser without native |
| * document.register, you can add the polyfill script to your page: |
| * |
| * <script src="packages/custom_element/custom-elements.debug.js"></script> |
| * |
| * You can also use "custom-elements.min.js" for the minified version. |
| */ |
| // This is only used by Dart Web UI. |
| class CustomElement implements Element { |
| /** The web component element wrapped by this class. */ |
| Element _host; |
| List _shadowRoots; |
| |
| /** |
| * Shadow roots generated by dwc for each custom element, indexed by the |
| * custom element tag name. |
| */ |
| Map<String, dynamic> _generatedRoots = {}; |
| |
| /** |
| * Temporary property until components extend [Element]. An element can |
| * only be associated with one host, and it is an error to use a web component |
| * without an associated host element. |
| */ |
| Element get host { |
| if (_host == null) throw new StateError('host element has not been set.'); |
| return _host; |
| } |
| |
| set host(Element value) { |
| if (value == null) { |
| throw new ArgumentError('host must not be null.'); |
| } |
| // TODO(jmesserly): xtag used to return "null" if unset, now it checks for |
| // "this". Temporarily allow both. |
| var xtag = value.xtag; |
| if (xtag != null && xtag != value) { |
| throw new ArgumentError('host must not have its xtag property set.'); |
| } |
| if (_host != null) { |
| throw new StateError('host can only be set once.'); |
| } |
| |
| value.xtag = this; |
| _host = value; |
| } |
| |
| /** |
| * **Note**: This is an implementation helper and should not need to be called |
| * from your code. |
| * |
| * Creates the [ShadowRoot] backing this component. |
| */ |
| createShadowRoot([String componentName]) { |
| var root = host.createShadowRoot(); |
| if (componentName != null) { |
| _generatedRoots[componentName] = root; |
| } |
| return root; |
| } |
| |
| getShadowRoot(String componentName) => _generatedRoots[componentName]; |
| |
| /** |
| * Invoked when this component gets created. |
| * Note that [root] will be a [ShadowRoot] if the browser supports Shadow DOM. |
| */ |
| void created() {} |
| // Added for analyzer warnings |
| @deprecated |
| void createdCallback() {} |
| |
| /** Invoked when this component gets inserted in the DOM tree. */ |
| void inserted() {} |
| @deprecated |
| void enteredView() {} |
| |
| /** Invoked when this component is removed from the DOM tree. */ |
| void removed() {} |
| @deprecated |
| void leftView() {} |
| |
| /** Invoked when any attribute of the component is modified. */ |
| void attributeChanged(String name, String oldValue, String newValue) => |
| host.attributeChanged(name, oldValue, newValue); |
| |
| // TODO(efortuna): Update these when we decide what to do with these |
| // properties. |
| @deprecated |
| String getAttribute(String name) => |
| host.getAttribute(name); |
| |
| @deprecated |
| String getAttributeNS(String namespaceUri, String localName) => |
| host.getAttributeNS(namespaceUri, localName); |
| |
| @deprecated |
| void setAttributeNS( |
| String namespaceUri, String localName, String value) { |
| host.setAttributeNS(namespaceUri, localName, value); |
| } |
| |
| @deprecated |
| void setAttribute(String name, String value) => |
| host.setAttribute(name, value); |
| |
| @deprecated |
| List<Node> get childNodes => host.childNodes; |
| |
| // 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 => host.nodes; |
| |
| set nodes(Iterable<Node> value) { host.nodes = value; } |
| |
| /** |
| * Replaces this node with another node. |
| */ |
| Node replaceWith(Node otherNode) => host.replaceWith(otherNode); |
| |
| /** |
| * Removes this node from the DOM. |
| */ |
| void remove() => host.remove(); |
| |
| Node get nextNode => host.nextNode; |
| |
| String get nodeName => host.nodeName; |
| |
| Document get ownerDocument => host.ownerDocument; |
| |
| Node get previousNode => host.previousNode; |
| |
| String get text => host.text; |
| |
| set text(String v) { host.text = v; } |
| |
| bool contains(Node other) => host.contains(other); |
| |
| bool hasChildNodes() => host.hasChildNodes(); |
| |
| Node insertBefore(Node newChild, Node refChild) => |
| host.insertBefore(newChild, refChild); |
| |
| Node insertAllBefore(Iterable<Node> newChild, Node refChild) => |
| host.insertAllBefore(newChild, refChild); |
| |
| Map<String, String> get attributes => host.attributes; |
| set attributes(Map<String, String> value) { |
| host.attributes = value; |
| } |
| |
| List<Element> get elements => host.children; |
| |
| set elements(List<Element> value) { |
| host.children = value; |
| } |
| |
| String get baseUri => host.baseUri; |
| |
| List<Element> get children => host.children; |
| |
| set children(List<Element> value) { |
| host.children = value; |
| } |
| |
| Set<String> get classes => host.classes; |
| |
| set classes(Iterable<String> value) { |
| host.classes = value; |
| } |
| |
| CssRect get contentEdge => host.contentEdge; |
| CssRect get paddingEdge => host.paddingEdge; |
| CssRect get borderEdge => host.borderEdge; |
| CssRect get marginEdge => host.marginEdge; |
| Point get documentOffset => host.documentOffset; |
| Point offsetTo(Element parent) => host.offsetTo(parent); |
| |
| Map<String, String> getNamespacedAttributes(String namespace) => |
| host.getNamespacedAttributes(namespace); |
| |
| CssStyleDeclaration getComputedStyle([String pseudoElement]) |
| => host.getComputedStyle(pseudoElement); |
| |
| Element clone(bool deep) => host.clone(deep); |
| |
| Element get parent => host.parent; |
| |
| Node get parentNode => host.parentNode; |
| |
| String get nodeValue => host.nodeValue; |
| |
| Events get on => host.on; |
| |
| String get contentEditable => host.contentEditable; |
| set contentEditable(String v) { host.contentEditable = v; } |
| |
| String get dir => host.dir; |
| set dir(String v) { host.dir = v; } |
| |
| bool get draggable => host.draggable; |
| set draggable(bool v) { host.draggable = v; } |
| |
| bool get hidden => host.hidden; |
| set hidden(bool v) { host.hidden = v; } |
| |
| String get id => host.id; |
| set id(String v) { host.id = v; } |
| |
| String get innerHtml => host.innerHtml; |
| void set innerHtml(String v) { |
| host.innerHtml = v; |
| } |
| |
| void setInnerHtml(String html, |
| {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) { |
| host.setInnerHtml(html, validator: validator, treeSanitizer: treeSanitizer); |
| } |
| |
| DocumentFragment createFragment(String html, |
| {NodeValidator validator, NodeTreeSanitizer treeSanitizer}) => |
| host.createFragment(html, |
| validator: validator, treeSanitizer: treeSanitizer); |
| |
| bool get isContentEditable => host.isContentEditable; |
| |
| String get lang => host.lang; |
| set lang(String v) { host.lang = v; } |
| |
| String get outerHtml => host.outerHtml; |
| |
| bool get spellcheck => host.spellcheck; |
| set spellcheck(bool v) { host.spellcheck = v; } |
| |
| int get tabIndex => host.tabIndex; |
| set tabIndex(int i) { host.tabIndex = i; } |
| |
| String get title => host.title; |
| |
| set title(String value) { host.title = value; } |
| |
| bool get translate => host.translate; |
| set translate(bool v) { host.translate = v; } |
| |
| String get dropzone => host.dropzone; |
| set dropzone(String v) { host.dropzone = v; } |
| |
| void click() { host.click(); } |
| |
| List<Node> getDestinationInsertionPoints() => |
| host.getDestinationInsertionPoints(); |
| |
| Element insertAdjacentElement(String where, Element element) => |
| host.insertAdjacentElement(where, element); |
| |
| void insertAdjacentHtml(String where, String html) { |
| host.insertAdjacentHtml(where, html); |
| } |
| |
| void insertAdjacentText(String where, String text) { |
| host.insertAdjacentText(where, text); |
| } |
| |
| Map<String, String> get dataset => host.dataset; |
| |
| set dataset(Map<String, String> value) { |
| host.dataset = value; |
| } |
| |
| Element get nextElementSibling => host.nextElementSibling; |
| |
| Element get offsetParent => host.offsetParent; |
| |
| Element get previousElementSibling => host.previousElementSibling; |
| |
| CssStyleDeclaration get style => host.style; |
| |
| String get tagName => host.tagName; |
| |
| // Note: we are not polyfilling the shadow root here. This will be fixed when |
| // we migrate to the JS Shadow DOM polyfills. You can still use getShadowRoot |
| // to retrieve a node that behaves as the shadow root when Shadow DOM is not |
| // enabled. |
| ShadowRoot get shadowRoot => host.shadowRoot; |
| |
| void blur() { host.blur(); } |
| |
| void focus() { host.focus(); } |
| |
| void scrollByLines(int lines) { |
| host.scrollByLines(lines); |
| } |
| |
| void scrollByPages(int pages) { |
| host.scrollByPages(pages); |
| } |
| |
| void scrollIntoView([ScrollAlignment alignment]) { |
| host.scrollIntoView(alignment); |
| } |
| |
| bool matches(String selectors) => host.matches(selectors); |
| |
| bool matchesWithAncestors(String selectors) => |
| host.matchesWithAncestors(selectors); |
| |
| @deprecated |
| void requestFullScreen(int flags) { requestFullscreen(); } |
| |
| void requestFullscreen() { host.requestFullscreen(); } |
| |
| void requestPointerLock() { host.requestPointerLock(); } |
| |
| Element querySelector(String selectors) => host.querySelector(selectors); |
| |
| ElementList querySelectorAll(String selectors) => |
| host.querySelectorAll(selectors); |
| |
| @deprecated |
| Element query(String selectors) => host.querySelector(selectors); |
| |
| @deprecated |
| ElementList queryAll(String selectors) => host.querySelectorAll(selectors); |
| |
| String get className => host.className; |
| set className(String value) { host.className = value; } |
| |
| @deprecated |
| int get clientHeight => client.height; |
| |
| @deprecated |
| int get clientLeft => client.left; |
| |
| @deprecated |
| int get clientTop => client.top; |
| |
| @deprecated |
| int get clientWidth => client.width; |
| |
| Rectangle get client => host.client; |
| |
| @deprecated |
| int get offsetHeight => offset.height; |
| |
| @deprecated |
| int get offsetLeft => offset.left; |
| |
| @deprecated |
| int get offsetTop => offset.top; |
| |
| @deprecated |
| int get offsetWidth => offset.width; |
| |
| Rectangle get offset => host.offset; |
| |
| int get scrollHeight => host.scrollHeight; |
| |
| int get scrollLeft => host.scrollLeft; |
| |
| int get scrollTop => host.scrollTop; |
| |
| set scrollLeft(int value) { host.scrollLeft = value; } |
| |
| set scrollTop(int value) { host.scrollTop = value; } |
| |
| int get scrollWidth => host.scrollWidth; |
| |
| Rectangle getBoundingClientRect() => host.getBoundingClientRect(); |
| |
| List<Rectangle> getClientRects() => host.getClientRects(); |
| |
| List<Node> getElementsByClassName(String name) => |
| host.getElementsByClassName(name); |
| |
| Node get firstChild => host.firstChild; |
| |
| Node get lastChild => host.lastChild; |
| |
| String get localName => host.localName; |
| |
| String get namespaceUri => host.namespaceUri; |
| |
| int get nodeType => host.nodeType; |
| |
| void addEventListener(String type, EventListener listener, |
| [bool useCapture]) { |
| host.addEventListener(type, listener, useCapture); |
| } |
| |
| bool dispatchEvent(Event event) => host.dispatchEvent(event); |
| |
| void removeEventListener(String type, EventListener listener, |
| [bool useCapture]) { |
| host.removeEventListener(type, listener, useCapture); |
| } |
| |
| get xtag => host.xtag; |
| |
| set xtag(value) { host.xtag = value; } |
| |
| Node append(Node e) => host.append(e); |
| |
| void appendText(String text) => host.appendText(text); |
| |
| void appendHtml(String html) => host.appendHtml(html); |
| |
| Animation animate(List<Map> keyframes, [num duration]) => |
| host.animate(keyframes, duration); |
| |
| // TODO(jmesserly): rename "created" to "onCreated". |
| void onCreated() => created(); |
| |
| Stream<Event> get onAbort => host.onAbort; |
| Stream<Event> get onBeforeCopy => host.onBeforeCopy; |
| Stream<Event> get onBeforeCut => host.onBeforeCut; |
| Stream<Event> get onBeforePaste => host.onBeforePaste; |
| Stream<Event> get onBlur => host.onBlur; |
| Stream<Event> get onChange => host.onChange; |
| Stream<MouseEvent> get onClick => host.onClick; |
| Stream<MouseEvent> get onContextMenu => host.onContextMenu; |
| Stream<Event> get onCopy => host.onCopy; |
| Stream<Event> get onCut => host.onCut; |
| Stream<Event> get onDoubleClick => host.onDoubleClick; |
| Stream<MouseEvent> get onDrag => host.onDrag; |
| Stream<MouseEvent> get onDragEnd => host.onDragEnd; |
| Stream<MouseEvent> get onDragEnter => host.onDragEnter; |
| Stream<MouseEvent> get onDragLeave => host.onDragLeave; |
| Stream<MouseEvent> get onDragOver => host.onDragOver; |
| Stream<MouseEvent> get onDragStart => host.onDragStart; |
| Stream<MouseEvent> get onDrop => host.onDrop; |
| Stream<Event> get onError => host.onError; |
| Stream<Event> get onFocus => host.onFocus; |
| Stream<Event> get onInput => host.onInput; |
| Stream<Event> get onInvalid => host.onInvalid; |
| Stream<KeyboardEvent> get onKeyDown => host.onKeyDown; |
| Stream<KeyboardEvent> get onKeyPress => host.onKeyPress; |
| Stream<KeyboardEvent> get onKeyUp => host.onKeyUp; |
| Stream<Event> get onLoad => host.onLoad; |
| Stream<MouseEvent> get onMouseDown => host.onMouseDown; |
| Stream<MouseEvent> get onMouseEnter => host.onMouseEnter; |
| Stream<MouseEvent> get onMouseLeave => host.onMouseLeave; |
| Stream<MouseEvent> get onMouseMove => host.onMouseMove; |
| Stream<Event> get onFullscreenChange => host.onFullscreenChange; |
| Stream<Event> get onFullscreenError => host.onFullscreenError; |
| Stream<Event> get onPaste => host.onPaste; |
| Stream<Event> get onReset => host.onReset; |
| Stream<Event> get onResize => host.onResize; |
| Stream<Event> get onScroll => host.onScroll; |
| Stream<Event> get onSearch => host.onSearch; |
| Stream<Event> get onSelect => host.onSelect; |
| Stream<Event> get onSelectStart => host.onSelectStart; |
| Stream<Event> get onSubmit => host.onSubmit; |
| Stream<MouseEvent> get onMouseOut => host.onMouseOut; |
| Stream<MouseEvent> get onMouseOver => host.onMouseOver; |
| Stream<MouseEvent> get onMouseUp => host.onMouseUp; |
| Stream<TouchEvent> get onTouchCancel => host.onTouchCancel; |
| Stream<TouchEvent> get onTouchEnd => host.onTouchEnd; |
| Stream<TouchEvent> get onTouchEnter => host.onTouchEnter; |
| Stream<TouchEvent> get onTouchLeave => host.onTouchLeave; |
| Stream<TouchEvent> get onTouchMove => host.onTouchMove; |
| Stream<TouchEvent> get onTouchStart => host.onTouchStart; |
| Stream<TransitionEvent> get onTransitionEnd => host.onTransitionEnd; |
| |
| // TODO(sigmund): do the normal forwarding when dartbug.com/7919 is fixed. |
| Stream<WheelEvent> get onMouseWheel { |
| throw new UnsupportedError('onMouseWheel is not supported'); |
| } |
| } |