blob: 72fc1dd6055b649257da67ef8a677033aa66120c [file] [log] [blame]
// Copyright (c) 2016, 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.
import 'dart:async';
import 'dart:html';
HtmlElement element(CustomElement e) => e.element;
class CustomElement {
static Expando reverseElements = new Expando();
static CustomElement reverse(HtmlElement element) => reverseElements[element];
static List<CustomElement> toBeAttached = <CustomElement>[];
static void drainAttached() {
// Send 'attached' to elements that have been attached to the document.
bool fired = false;
var connectedElements = toBeAttached
.where((CustomElement element) => element.element.isConnected)
.toList();
for (CustomElement element in connectedElements) {
toBeAttached.remove(element);
element.attached();
fired = true;
}
if (toBeAttached.isEmpty) {
return; // Done.
}
if (fired) {
// The 'attached' events above may have scheduled microtasks that will
// will add more CustomElements to be document, e.g. 'render'.
scheduleMicrotask(() => drainAttached());
}
while (!toBeAttached.isEmpty) {
// Either this element will never be attached or it will be attached
// after a turn of the outer event loop. Fire 'attached' in case it is
// the latter, since firing it out of order is preferable to not firing
// it at all.
CustomElement element = toBeAttached.removeLast();
print("Warning: created but not in document: $element");
element.attached();
}
}
final HtmlElement element;
CustomElement.created(String elementClass)
: element = document.createElement("shadow") {
reverseElements[element] = this;
element.classes = [elementClass];
if (toBeAttached.isEmpty) {
scheduleMicrotask(() => drainAttached());
}
toBeAttached.add(this);
}
void attached() {}
void detached() {}
Element get parent => element.parent;
List<Element> get children => element.children;
set children(List<Element> c) => element.children = c;
CssClassSet get classes => element.classes;
set classes(dynamic c) => element.classes = c;
String get title => element.title;
set title(String t) => element.title = t;
String get text => element.text;
set text(String t) => element.text = t;
CssStyleDeclaration get style => element.style;
ElementStream<MouseEvent> get onClick => element.onClick;
Rectangle getBoundingClientRect() => element.getBoundingClientRect();
List<Node> getElementsByClassName(String c) =>
element.getElementsByClassName(c);
void scrollIntoView() => element.scrollIntoView();
}