blob: 20ee0b258ed1b7cad1d1b09ba456561ad7629198 [file] [log] [blame]
// Copyright (c) 2014, 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.
library trydart.shadow_root;
import 'dart:html';
import 'selection.dart' show
TrySelection;
import 'html_to_text.dart' show
htmlToText;
const int WALKER_NEXT = 0;
const int WALKER_RETURN = 1;
const int WALKER_SKIP_NODE = 2;
void setShadowRoot(Element node, text) {
if (text is String) {
text = new Text(text);
}
getShadowRoot(node)
..nodes.clear()
..append(text);
}
/* ShadowRoot or Element */ getShadowRoot(Element node) {
if (ShadowRoot.supported) {
ShadowRoot root = node.shadowRoot;
return root != null ? root : node.createShadowRoot();
} else {
Element root = node.querySelector('[try-dart-shadow-root]');
if (root == null) {
root = new SpanElement()
..setAttribute('try-dart-shadow-root', '');
node.append(root);
}
return root;
}
}
String getText(Element node) {
if (ShadowRoot.supported) return node.text;
StringBuffer buffer = new StringBuffer();
htmlToText(
node, buffer, new TrySelection.empty(node), treatRootAsInline: true);
return '$buffer';
}
/// Element.contains(n) doesn't work when n is node(Text) in IE,
/// so this is a brute-force implementation of contains.
bool containsNode(parent, child) {
var p = child;
while (p != null && p != parent) {
p = p.parentNode;
}
return p != null;
}
/// Position [walker] at the last predecessor (that is, child of child of
/// child...) of [node]. The next call to walker.nextNode will return the first
/// node after [node].
void skip(Node node, TreeWalker walker) {
if (walker.nextSibling() != null) {
walker.previousNode();
return;
}
for (Node current = walker.nextNode();
current != null;
current = walker.nextNode()) {
if (!containsNode(node, current)) {
walker.previousNode();
return;
}
}
}
/// Call [f] on each node in [root] in same order as [TreeWalker]. Skip any
/// nodes used to implement shadow root polyfill.
void walkNodes(Node root, int f(Node node)) {
TreeWalker walker = new TreeWalker(root, NodeFilter.SHOW_ALL);
for (Node node = root; node != null; node = walker.nextNode()) {
if (!ShadowRoot.supported &&
node is Element &&
node.getAttribute('try-dart-shadow-root') != null) {
skip(node, walker);
} else {
int action = f(node);
switch (action) {
case WALKER_RETURN:
return;
case WALKER_SKIP_NODE:
skip(node, walker);
break;
case WALKER_NEXT:
break;
default:
throw 'Unexpected action returned from [f]: $action';
}
}
}
}