in tools/chrome-debug-extension/src/helpers.ts [262:472]
export function formatLogElements(target: Object, tmLabel: string, key: string, level: number, textFilter: string, excludeKeys: string[], thingsReferenced?: any[], includeFunctions?:boolean): any {
let openState = false;
if (!level) {
level = 0;
}
if (!thingsReferenced) {
thingsReferenced = [];
}
let isObj = isObject(target) || Util.isError(target);
let isErr = target && target["baseType"] && target["baseType"] === "ExceptionData" || Util.isError(target);
const children: HTMLElement[] = [];
function _openNode(currentLine: HTMLElement) {
openState = true;
arrForEach(children, (child) => {
rootDiv.appendChild(child);
});
currentLine.className = "obj-key expandable open"
}
function _collapseNode(currentLine: HTMLElement) {
// rootDiv.innerHTML = '';
arrForEach(children, (child) => {
rootDiv.removeChild(child);
});
// rootDiv.appendChild(currentLine);
openState = false;
currentLine.className = "obj-key expandable closed"
}
let matched: boolean;
// Always displayed opened if there is no filter
let childOpened = textFilter ? false : true;
const keys = getTargetKeys(target, excludeKeys, includeFunctions as boolean);
if (keys.length === 0) { keys.push("<empty>"); }
if (level >= MAX_DEPTH) { keys.unshift("<maxdepth>"); }
for (const key of keys) {
if (excludeKeys.indexOf(key) !== -1) {
continue;
}
let targetValue = target[key];
if (isSymbol(targetValue)) {
targetValue = targetValue.toString();
}
if (key === "<maxdepth>") {
const builder = document.createElement("div");
builder.className = "empty";
builder.innerText = "<max allowed depth reached>";
children.push(builder);
break;
}
else if (key === "<empty>") {
const builder = document.createElement("div");
builder.className = "empty";
builder.innerText = "<empty>";
children.push(builder);
}
else if (targetValue !== null && arrIndexOf(thingsReferenced, targetValue) !== -1) {
const builder = document.createElement("div");
builder.className = "empty";
builder.innerText = `<circular (${key}) - "${getTargetName(targetValue)}">`;
children.push(builder);
}
else if (targetValue !== null && (isObject(targetValue) || Util.isError(targetValue))) {
thingsReferenced.push(target);
let formatted = formatLogElements(targetValue, "", key, level + 1, textFilter, excludeKeys, thingsReferenced, includeFunctions);
thingsReferenced.pop();
// Always displayed opened if there is no filter
if (!textFilter || formatted.matched) {
childOpened = true;
}
if (formatted.isErr) {
isErr = true;
}
children.push(formatted.root);
} else {
const builder = document.createElement("div");
builder.setAttribute("tabindex", "0");
builder.onclick = (evt: MouseEvent) => {
evt.stopPropagation();
}
builder.ontouchend = (evt: TouchEvent) => {
evt.stopPropagation();
}
builder.onkeydown = (evt: KeyboardEvent) => {
evt.stopPropagation();
_navHandler(evt);
}
builder.onfocus = (evt: Event) => {
focusHandler(evt, target, level, excludeKeys, includeFunctions as boolean);
}
const outerSpan = document.createElement("span");
const keySpan = document.createElement("span");
keySpan.className = "key";
if (_setInnerText(keySpan, `${key}: `, textFilter)) {
childOpened = true;
}
outerSpan.appendChild(keySpan);
const valueSpan = document.createElement("span");
if (isFunction(targetValue)) {
const fnStr = targetValue.toString();
const fnHead = fnStr.match(/^([^{]+)/)[1];
valueSpan.textContent = `${fnHead}{...}`;
} else {
if (_setInnerText(valueSpan, `${targetValue}`, textFilter)) {
childOpened = true;
}
}
valueSpan.className = `${typeof targetValue}`;
outerSpan.appendChild(valueSpan);
builder.appendChild(outerSpan);
children.push(builder);
}
}
const rootDiv = document.createElement("div");
let innerText = "";
let currentLine = document.createElement("span");
if (isObj || children.length) {
innerText = `${key ? key : "obj"}: `;
if (Util.isArray(target)) {
innerText += `[${getTargetKeys(target, excludeKeys, includeFunctions as boolean).length}]`;
} else {
let targetName = getTargetName(target);
if (targetName) {
innerText += ` <"${targetName}"> `
}
innerText += `{${getTargetKeys(target, excludeKeys, includeFunctions as boolean).length}}`;
}
matched = _setInnerText(currentLine, innerText, textFilter);
if (tmLabel) {
const tmWrapper = document.createElement("span");
const tmDetails = document.createElement("span");
tmDetails.className = "obj-time";
tmDetails.innerText = tmLabel;
tmWrapper.appendChild(tmDetails);
tmWrapper.appendChild(currentLine);
currentLine = tmWrapper;
}
currentLine.className = "obj-key expandable closed"
} else {
innerText = `${key ? key : "obj"}: ${target.toString()}`;
matched = _setInnerText(currentLine, innerText, textFilter);
currentLine.className = "obj-key";
}
rootDiv.appendChild(currentLine);
rootDiv.setAttribute("tabindex", "0");
if (childOpened) {
// A child node matched so auto-expand
_openNode(currentLine);
}
if (isObj) {
if (isErr) { rootDiv.className = "exception" }
const openHandler = (evt: Event, forceState?: boolean) => {
evt.stopPropagation();
if (Util.getIEVersion()) {
focusHandler(evt, target, level, excludeKeys, includeFunctions as boolean);
}
if (forceState !== undefined && openState === forceState) {
return;
}
if (lastSelectedElement === rootDiv) {
if (openState) {
_collapseNode(currentLine);
}
else {
_openNode(currentLine);
}
}
}
rootDiv.onkeydown = (evt: KeyboardEvent) => {
_navHandler(evt, openHandler, openState);
}
rootDiv.onclick = (evt: MouseEvent) => {
openHandler(evt);
}
rootDiv.ontouchend = (evt: TouchEvent) => {
openHandler(evt);
}
rootDiv.onfocus = (evt: Event) => {
focusHandler(evt, target, level, excludeKeys, includeFunctions as boolean);
}
}
return {
root: rootDiv,
isErr: isErr,
matched: matched || childOpened
};
}