1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-01 09:24:20 -04:00
denoland-deno/js/dom_util.ts

86 lines
2.1 KiB
TypeScript
Raw Normal View History

2019-05-27 09:20:34 -04:00
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
// Utility functions for DOM nodes
import * as domTypes from "./dom_types.ts";
2019-05-27 09:20:34 -04:00
export function isNode(nodeImpl: domTypes.EventTarget | null): boolean {
return Boolean(nodeImpl && "nodeType" in nodeImpl);
}
export function isShadowRoot(nodeImpl: domTypes.EventTarget | null): boolean {
return Boolean(
nodeImpl &&
2019-07-16 00:19:26 -04:00
nodeImpl[domTypes.eventTargetNodeType] ===
domTypes.NodeType.DOCUMENT_FRAGMENT_NODE &&
nodeImpl[domTypes.eventTargetHost] != null
2019-05-27 09:20:34 -04:00
);
}
export function isSlotable(nodeImpl: domTypes.EventTarget | null): boolean {
return Boolean(
nodeImpl &&
2019-07-16 00:19:26 -04:00
(nodeImpl[domTypes.eventTargetNodeType] ===
domTypes.NodeType.ELEMENT_NODE ||
nodeImpl[domTypes.eventTargetNodeType] === domTypes.NodeType.TEXT_NODE)
2019-05-27 09:20:34 -04:00
);
}
// https://dom.spec.whatwg.org/#node-trees
// const domSymbolTree = Symbol("DOM Symbol Tree");
// https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-ancestor
export function isShadowInclusiveAncestor(
ancestor: domTypes.EventTarget | null,
node: domTypes.EventTarget | null
): boolean {
while (isNode(node)) {
if (node === ancestor) {
return true;
}
if (isShadowRoot(node)) {
2019-07-16 00:19:26 -04:00
node = node && node[domTypes.eventTargetHost];
2019-05-27 09:20:34 -04:00
} else {
node = null; // domSymbolTree.parent(node);
}
}
return false;
}
export function getRoot(
node: domTypes.EventTarget | null
): domTypes.EventTarget | null {
const root = node;
2019-05-27 09:20:34 -04:00
// for (const ancestor of domSymbolTree.ancestorsIterator(node)) {
// root = ancestor;
// }
return root;
}
// https://dom.spec.whatwg.org/#retarget
export function retarget(
a: domTypes.EventTarget | null,
b: domTypes.EventTarget
): domTypes.EventTarget | null {
while (true) {
if (!isNode(a)) {
return a;
}
const aRoot = getRoot(a);
if (aRoot) {
if (
!isShadowRoot(aRoot) ||
(isNode(b) && isShadowInclusiveAncestor(aRoot, b))
) {
return a;
}
2019-07-16 00:19:26 -04:00
a = aRoot[domTypes.eventTargetHost];
2019-05-27 09:20:34 -04:00
}
}
}