All files / src/dom domtree.ts

100% Statements 21/21
75% Branches 3/4
100% Functions 12/12
100% Lines 20/20
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 641x 1x     1x         1204x 1204x       1235x       1246x 11x     1235x       6545x             1235x       25x       1834x       1x       10x 10x       6x 6x       16x 16x      
import { DOMNode } from './domnode';
import { Selector } from './selector';
import { MetaTable } from '../meta';
 
export class DOMTree {
	readonly root: DOMNode;
	private active: DOMNode;
 
	constructor(){
		this.root = DOMNode.rootNode();
		this.active = this.root;
	}
 
	pushActive(node: DOMNode): void {
		this.active = node;
	}
 
	popActive(): void {
		if (this.active.isRootElement()){
			return; /* root element should never be popped, continue as if
			         * nothing happened */
		}
		this.active = this.active.parent;
	}
 
	getActive(): DOMNode {
		return this.active;
	}
 
	/**
	 * Resolve dynamic meta expressions.
	 */
	resolveMeta(table: MetaTable){
		this.visitDepthFirst((node: DOMNode) => table.resolve(node));
	}
 
	getElementsByTagName(tagName: string) {
		return this.root.getElementsByTagName(tagName);
	}
 
	visitDepthFirst(callback: (node: DOMNode) => void): void {
		this.root.visitDepthFirst(callback);
	}
 
	find(callback: (node: DOMNode) => boolean): DOMNode {
		return this.root.find(callback);
	}
 
	querySelector(selector: string): DOMNode {
		const it = this.querySelectorImpl(selector);
		return it.next().value || null;
	}
 
	querySelectorAll(selector: string): DOMNode[] {
		const it = this.querySelectorImpl(selector);
		return Array.from(it);
	}
 
	private *querySelectorImpl(selector: string): IterableIterator<DOMNode> {
		const pattern = new Selector(selector);
		yield* pattern.match(this.root);
	}
}