dynatrace-cordova-outsystems-plugin
Version:
This plugin gives you the ability to use the Dynatrace instrumentation in your hybrid application (Cordova, Ionic, ..). It uses the Mobile Agent, the JavaScript Agent and the Javascript Bridge. The Mobile Agent will give you all device specific values con
182 lines (142 loc) • 5.3 kB
JavaScript
'use strict';
//Const
const NOAH_ARK_CAPACITY = 3;
//List of formatting elements
class FormattingElementList {
constructor(treeAdapter) {
this.length = 0;
this.entries = [];
this.treeAdapter = treeAdapter;
this.bookmark = null;
}
//Noah Ark's condition
//OPTIMIZATION: at first we try to find possible candidates for exclusion using
//lightweight heuristics without thorough attributes check.
_getNoahArkConditionCandidates(newElement) {
const candidates = [];
if (this.length >= NOAH_ARK_CAPACITY) {
const neAttrsLength = this.treeAdapter.getAttrList(newElement).length;
const neTagName = this.treeAdapter.getTagName(newElement);
const neNamespaceURI = this.treeAdapter.getNamespaceURI(newElement);
for (let i = this.length - 1; i >= 0; i--) {
const entry = this.entries[i];
if (entry.type === FormattingElementList.MARKER_ENTRY) {
break;
}
const element = entry.element;
const elementAttrs = this.treeAdapter.getAttrList(element);
const isCandidate =
this.treeAdapter.getTagName(element) === neTagName &&
this.treeAdapter.getNamespaceURI(element) === neNamespaceURI &&
elementAttrs.length === neAttrsLength;
if (isCandidate) {
candidates.push({ idx: i, attrs: elementAttrs });
}
}
}
return candidates.length < NOAH_ARK_CAPACITY ? [] : candidates;
}
_ensureNoahArkCondition(newElement) {
const candidates = this._getNoahArkConditionCandidates(newElement);
let cLength = candidates.length;
if (cLength) {
const neAttrs = this.treeAdapter.getAttrList(newElement);
const neAttrsLength = neAttrs.length;
const neAttrsMap = Object.create(null);
//NOTE: build attrs map for the new element so we can perform fast lookups
for (let i = 0; i < neAttrsLength; i++) {
const neAttr = neAttrs[i];
neAttrsMap[neAttr.name] = neAttr.value;
}
for (let i = 0; i < neAttrsLength; i++) {
for (let j = 0; j < cLength; j++) {
const cAttr = candidates[j].attrs[i];
if (neAttrsMap[cAttr.name] !== cAttr.value) {
candidates.splice(j, 1);
cLength--;
}
if (candidates.length < NOAH_ARK_CAPACITY) {
return;
}
}
}
//NOTE: remove bottommost candidates until Noah's Ark condition will not be met
for (let i = cLength - 1; i >= NOAH_ARK_CAPACITY - 1; i--) {
this.entries.splice(candidates[i].idx, 1);
this.length--;
}
}
}
//Mutations
insertMarker() {
this.entries.push({ type: FormattingElementList.MARKER_ENTRY });
this.length++;
}
pushElement(element, token) {
this._ensureNoahArkCondition(element);
this.entries.push({
type: FormattingElementList.ELEMENT_ENTRY,
element: element,
token: token
});
this.length++;
}
insertElementAfterBookmark(element, token) {
let bookmarkIdx = this.length - 1;
for (; bookmarkIdx >= 0; bookmarkIdx--) {
if (this.entries[bookmarkIdx] === this.bookmark) {
break;
}
}
this.entries.splice(bookmarkIdx + 1, 0, {
type: FormattingElementList.ELEMENT_ENTRY,
element: element,
token: token
});
this.length++;
}
removeEntry(entry) {
for (let i = this.length - 1; i >= 0; i--) {
if (this.entries[i] === entry) {
this.entries.splice(i, 1);
this.length--;
break;
}
}
}
clearToLastMarker() {
while (this.length) {
const entry = this.entries.pop();
this.length--;
if (entry.type === FormattingElementList.MARKER_ENTRY) {
break;
}
}
}
//Search
getElementEntryInScopeWithTagName(tagName) {
for (let i = this.length - 1; i >= 0; i--) {
const entry = this.entries[i];
if (entry.type === FormattingElementList.MARKER_ENTRY) {
return null;
}
if (this.treeAdapter.getTagName(entry.element) === tagName) {
return entry;
}
}
return null;
}
getElementEntry(element) {
for (let i = this.length - 1; i >= 0; i--) {
const entry = this.entries[i];
if (entry.type === FormattingElementList.ELEMENT_ENTRY && entry.element === element) {
return entry;
}
}
return null;
}
}
//Entry types
FormattingElementList.MARKER_ENTRY = 'MARKER_ENTRY';
FormattingElementList.ELEMENT_ENTRY = 'ELEMENT_ENTRY';
module.exports = FormattingElementList;