2016-06-23 09:47:54 -07:00
|
|
|
/**
|
|
|
|
* @license
|
|
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
|
|
* found in the LICENSE file at https://angular.io/license
|
|
|
|
*/
|
|
|
|
|
2016-04-28 17:50:03 -07:00
|
|
|
import {Injector} from '../di';
|
|
|
|
import {RenderDebugInfo} from '../render/api';
|
2016-01-13 21:35:21 -08:00
|
|
|
|
|
|
|
export class EventListener { constructor(public name: string, public callback: Function){}; }
|
|
|
|
|
2016-05-25 15:00:05 -07:00
|
|
|
/**
|
2016-06-27 12:27:23 -07:00
|
|
|
* @experimental All debugging apis are currently experimental.
|
2016-05-25 15:00:05 -07:00
|
|
|
*/
|
2016-01-13 21:35:21 -08:00
|
|
|
export class DebugNode {
|
|
|
|
nativeNode: any;
|
|
|
|
listeners: EventListener[];
|
|
|
|
parent: DebugElement;
|
|
|
|
|
2016-01-06 14:13:44 -08:00
|
|
|
constructor(nativeNode: any, parent: DebugNode, private _debugInfo: RenderDebugInfo) {
|
2016-01-13 21:35:21 -08:00
|
|
|
this.nativeNode = nativeNode;
|
2016-11-03 16:58:27 -07:00
|
|
|
if (parent && parent instanceof DebugElement) {
|
2016-01-13 21:35:21 -08:00
|
|
|
parent.addChild(this);
|
|
|
|
} else {
|
|
|
|
this.parent = null;
|
|
|
|
}
|
|
|
|
this.listeners = [];
|
|
|
|
}
|
|
|
|
|
2016-11-03 16:58:27 -07:00
|
|
|
get injector(): Injector { return this._debugInfo ? this._debugInfo.injector : null; }
|
2016-01-06 14:13:44 -08:00
|
|
|
|
2016-11-03 16:58:27 -07:00
|
|
|
get componentInstance(): any { return this._debugInfo ? this._debugInfo.component : null; }
|
2016-01-06 14:13:44 -08:00
|
|
|
|
2016-11-03 16:58:27 -07:00
|
|
|
get context(): any { return this._debugInfo ? this._debugInfo.context : null; }
|
2016-04-28 14:00:31 -07:00
|
|
|
|
|
|
|
get references(): {[key: string]: any} {
|
2016-11-03 16:58:27 -07:00
|
|
|
return this._debugInfo ? this._debugInfo.references : null;
|
2016-01-13 21:35:21 -08:00
|
|
|
}
|
|
|
|
|
2016-11-03 16:58:27 -07:00
|
|
|
get providerTokens(): any[] { return this._debugInfo ? this._debugInfo.providerTokens : null; }
|
2016-01-06 14:13:44 -08:00
|
|
|
|
2016-11-03 16:58:27 -07:00
|
|
|
get source(): string { return this._debugInfo ? this._debugInfo.source : null; }
|
2016-01-13 21:35:21 -08:00
|
|
|
}
|
|
|
|
|
2016-05-25 15:00:05 -07:00
|
|
|
/**
|
2016-06-27 12:27:23 -07:00
|
|
|
* @experimental All debugging apis are currently experimental.
|
2016-05-25 15:00:05 -07:00
|
|
|
*/
|
2016-01-13 21:35:21 -08:00
|
|
|
export class DebugElement extends DebugNode {
|
|
|
|
name: string;
|
2016-06-03 10:51:13 -07:00
|
|
|
properties: {[key: string]: any};
|
2016-01-06 14:13:44 -08:00
|
|
|
attributes: {[key: string]: string};
|
2016-06-01 16:57:12 -07:00
|
|
|
classes: {[key: string]: boolean};
|
|
|
|
styles: {[key: string]: string};
|
2016-01-13 21:35:21 -08:00
|
|
|
childNodes: DebugNode[];
|
|
|
|
nativeElement: any;
|
|
|
|
|
2016-01-06 14:13:44 -08:00
|
|
|
constructor(nativeNode: any, parent: any, _debugInfo: RenderDebugInfo) {
|
|
|
|
super(nativeNode, parent, _debugInfo);
|
|
|
|
this.properties = {};
|
|
|
|
this.attributes = {};
|
2016-06-01 16:57:12 -07:00
|
|
|
this.classes = {};
|
|
|
|
this.styles = {};
|
2016-01-13 21:35:21 -08:00
|
|
|
this.childNodes = [];
|
|
|
|
this.nativeElement = nativeNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
addChild(child: DebugNode) {
|
2016-11-03 16:58:27 -07:00
|
|
|
if (child) {
|
2016-01-13 21:35:21 -08:00
|
|
|
this.childNodes.push(child);
|
|
|
|
child.parent = this;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
removeChild(child: DebugNode) {
|
2016-11-03 16:58:27 -07:00
|
|
|
const childIndex = this.childNodes.indexOf(child);
|
2016-01-13 21:35:21 -08:00
|
|
|
if (childIndex !== -1) {
|
|
|
|
child.parent = null;
|
|
|
|
this.childNodes.splice(childIndex, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
insertChildrenAfter(child: DebugNode, newChildren: DebugNode[]) {
|
2016-11-03 16:58:27 -07:00
|
|
|
const siblingIndex = this.childNodes.indexOf(child);
|
2016-01-13 21:35:21 -08:00
|
|
|
if (siblingIndex !== -1) {
|
2017-02-14 21:03:18 -08:00
|
|
|
this.childNodes.splice(siblingIndex + 1, 0, ...newChildren);
|
|
|
|
newChildren.forEach(c => {
|
|
|
|
if (c.parent) {
|
|
|
|
c.parent.removeChild(c);
|
2016-01-13 21:35:21 -08:00
|
|
|
}
|
2017-02-14 21:03:18 -08:00
|
|
|
c.parent = this;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
insertBefore(refChild: DebugNode, newChild: DebugNode): void {
|
|
|
|
const refIndex = this.childNodes.indexOf(refChild);
|
|
|
|
if (refIndex === -1) {
|
|
|
|
this.addChild(newChild);
|
|
|
|
} else {
|
|
|
|
if (newChild.parent) {
|
|
|
|
newChild.parent.removeChild(newChild);
|
2016-01-13 21:35:21 -08:00
|
|
|
}
|
2017-02-14 21:03:18 -08:00
|
|
|
newChild.parent = this;
|
|
|
|
this.childNodes.splice(refIndex, 0, newChild);
|
2016-01-13 21:35:21 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
query(predicate: Predicate<DebugElement>): DebugElement {
|
2016-11-03 16:58:27 -07:00
|
|
|
const results = this.queryAll(predicate);
|
|
|
|
return results[0] || null;
|
2016-01-13 21:35:21 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
queryAll(predicate: Predicate<DebugElement>): DebugElement[] {
|
2016-11-03 16:58:27 -07:00
|
|
|
const matches: DebugElement[] = [];
|
2016-01-13 21:35:21 -08:00
|
|
|
_queryElementChildren(this, predicate, matches);
|
|
|
|
return matches;
|
|
|
|
}
|
|
|
|
|
|
|
|
queryAllNodes(predicate: Predicate<DebugNode>): DebugNode[] {
|
2016-11-03 16:58:27 -07:00
|
|
|
const matches: DebugNode[] = [];
|
2016-01-13 21:35:21 -08:00
|
|
|
_queryNodeChildren(this, predicate, matches);
|
|
|
|
return matches;
|
|
|
|
}
|
|
|
|
|
|
|
|
get children(): DebugElement[] {
|
2016-11-03 16:58:27 -07:00
|
|
|
return this.childNodes.filter((node) => node instanceof DebugElement) as DebugElement[];
|
2016-01-13 21:35:21 -08:00
|
|
|
}
|
|
|
|
|
2016-01-06 14:13:44 -08:00
|
|
|
triggerEventHandler(eventName: string, eventObj: any) {
|
2016-01-13 21:35:21 -08:00
|
|
|
this.listeners.forEach((listener) => {
|
|
|
|
if (listener.name == eventName) {
|
|
|
|
listener.callback(eventObj);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-25 15:00:05 -07:00
|
|
|
/**
|
|
|
|
* @experimental
|
|
|
|
*/
|
2016-01-13 21:35:21 -08:00
|
|
|
export function asNativeElements(debugEls: DebugElement[]): any {
|
|
|
|
return debugEls.map((el) => el.nativeElement);
|
|
|
|
}
|
|
|
|
|
2016-06-08 16:38:52 -07:00
|
|
|
function _queryElementChildren(
|
|
|
|
element: DebugElement, predicate: Predicate<DebugElement>, matches: DebugElement[]) {
|
2016-01-13 21:35:21 -08:00
|
|
|
element.childNodes.forEach(node => {
|
|
|
|
if (node instanceof DebugElement) {
|
|
|
|
if (predicate(node)) {
|
|
|
|
matches.push(node);
|
|
|
|
}
|
|
|
|
_queryElementChildren(node, predicate, matches);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-06-08 16:38:52 -07:00
|
|
|
function _queryNodeChildren(
|
|
|
|
parentNode: DebugNode, predicate: Predicate<DebugNode>, matches: DebugNode[]) {
|
2016-01-13 21:35:21 -08:00
|
|
|
if (parentNode instanceof DebugElement) {
|
|
|
|
parentNode.childNodes.forEach(node => {
|
|
|
|
if (predicate(node)) {
|
|
|
|
matches.push(node);
|
|
|
|
}
|
|
|
|
if (node instanceof DebugElement) {
|
|
|
|
_queryNodeChildren(node, predicate, matches);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Need to keep the nodes in a global Map so that multiple angular apps are supported.
|
2016-11-03 16:58:27 -07:00
|
|
|
const _nativeNodeToDebugNode = new Map<any, DebugNode>();
|
2016-01-13 21:35:21 -08:00
|
|
|
|
2016-05-25 15:00:05 -07:00
|
|
|
/**
|
|
|
|
* @experimental
|
|
|
|
*/
|
2016-01-13 21:35:21 -08:00
|
|
|
export function getDebugNode(nativeNode: any): DebugNode {
|
|
|
|
return _nativeNodeToDebugNode.get(nativeNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getAllDebugNodes(): DebugNode[] {
|
2016-11-03 16:58:27 -07:00
|
|
|
return Array.from(_nativeNodeToDebugNode.values());
|
2016-01-13 21:35:21 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
export function indexDebugNode(node: DebugNode) {
|
|
|
|
_nativeNodeToDebugNode.set(node.nativeNode, node);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function removeDebugNodeFromIndex(node: DebugNode) {
|
|
|
|
_nativeNodeToDebugNode.delete(node.nativeNode);
|
|
|
|
}
|
2017-03-01 14:10:59 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* A boolean-valued function over a value, possibly including context information
|
|
|
|
* regarding that value's position in an array.
|
|
|
|
*
|
|
|
|
* @experimental All debugging apis are currently experimental.
|
|
|
|
*/
|
|
|
|
export interface Predicate<T> { (value: T, index?: number, array?: T[]): boolean; }
|