in src/xpath.ts [14:81]
export function getXpath(element: HTMLElement): ElementInfo {
let xpathSegments = [];
let analyticsSegments: Array<string> = [];
// We have an
let elementData: {[key: string]: string} = {};
for (xpathSegments = []; element && element.nodeType == 1; element = element.parentNode as HTMLElement) {
if (element.hasAttribute("data-analytics")) {
const aKey = element.getAttribute("data-analytics-type") || "tag";
const aValue = element.getAttribute("data-analytics") || "";
analyticsSegments.unshift(`${aKey}(${aValue})`);
// [June 22nd 2020]
//
// We have been asked to provide a way for team's to enrich the events that
// are interacted with beyond just the tagging syntax, this will allow us to pass
// back a key/value object where we populate it with the the tagging types and their values
// passed back
//
// We'll keep track of all the different values we see along the way
// in this we'll set our analyticData to have a key that contains key/type
// for example...
//
// /serviceSubSection(someSection)/tag(createUserWizard)/context(userContext)
//
// would yield:
//
// {
// "serviceSubSection": "someSection",
// "tag": "createUserWizard",
// "context": "userContext"
// }
//
// Note #1: What would happen if a value is doubly defined? E.g. /tag(value1)/tag(value2)
// Since we populate the tag string as we move up the DOM tree, the last one defined
// will "win". In this case "tag" would be assigned to "value1"
elementData[aKey] = aValue;
}
// Currently we only let the xpath contain a id or a class
if (element.hasAttribute("id")) {
var elementId = element.getAttribute("id");
xpathSegments.unshift(element.localName.toLowerCase() + '[@id="' + elementId + '"]');
} else if (element.hasAttribute("class")) {
xpathSegments.unshift(element.localName.toLowerCase() + '[@class="' + element.getAttribute("class") + '"]');
} else {
// This chunk of code adds the index to the element
// if it is surrounded by siblings
let index;
let sib = element.previousSibling as HTMLElement;
for (index = 1; sib; sib = sib.previousSibling as HTMLElement) {
if (sib.localName == element.localName) {
index++;
}
}
const indexPlaceholder = index > 1 ? `[${index - 1}]` : "";
// We decrement the index by 1 to make it 0-indexed
xpathSegments.unshift(element.localName.toLowerCase() + indexPlaceholder);
}
}
return {
xpath: "/" + xpathSegments.join("/"),
customPath: analyticsSegments.length > 0 ? "/" + analyticsSegments.join("/") : "",
elementData,
};
}