@phantomstudios/ft-lib
Version:
A collection of Javascript UI & tracking utils for FT sites
109 lines • 4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
function sanitise(str) {
return typeof str === "string" ? str.trim() : str;
}
function assignIfUndefined(subject, target) {
for (var prop in subject) {
if (!target[prop]) {
target[prop] = subject[prop];
}
else {
console.warn("You can't set a custom property called ".concat(prop));
}
}
}
var elementPropertiesToCollect = [
"nodeName",
"className",
"id",
"href",
"text",
"role",
];
// For a given container element, get the number of elements that match the
// original element (siblings); and the index of the original element (position).
var getSiblingsAndPosition = function (el, originalEl, selector) {
var siblings = Array.from(el.querySelectorAll(selector));
var position = siblings.findIndex(function (item) { return item === originalEl; });
if (position === -1) {
return;
}
return {
siblings: siblings.length,
position: position,
};
};
// Get all (sanitised) properties of a given element.
var getAllElementProperties = function (el) {
return elementPropertiesToCollect.reduce(function (returnObject, property) {
if (el[property]) {
returnObject[property] = sanitise(el[property]);
}
else if (el.getAttribute(property)) {
returnObject[property] = sanitise(el.getAttribute(property));
}
else if (el.hasAttribute(property)) {
returnObject[property] = el.hasAttribute(property);
}
return returnObject;
}, {});
};
// Get some properties of a given element.
var getDomPathProps = function (attrs, props) {
// Collect any attribute that matches given strings.
attrs
.filter(function (attribute) {
return attribute.name.match(/^data-trackable|^data-o-|^aria-/i);
})
.forEach(function (attribute) {
props[attribute.name] = attribute.value;
});
return props;
};
// Get only the custom data-trackable-context-? properties of a given element
var getContextProps = function (attrs, props, isOriginalEl) {
var customProps = {};
// for the original element collect properties like className, nodeName
if (isOriginalEl) {
elementPropertiesToCollect.forEach(function (name) {
if (typeof props[name] !== "undefined" && name !== "id") {
customProps[name] = props[name];
}
});
}
// Collect any attribute that matches given strings.
attrs
.filter(function (attribute) { return attribute.name.match(/^data-trackable-context-/i); })
.forEach(function (attribute) {
customProps[attribute.name.replace("data-trackable-context-", "")] =
attribute.value;
});
return customProps;
};
function getTrace(el) {
var rootEl = document;
var originalEl = el;
var selector = originalEl.getAttribute("data-trackable")
? "[data-trackable=\"".concat(originalEl.getAttribute("data-trackable"), "\"]")
: originalEl.nodeName;
var trace = [];
var customContext = {};
while (el && el !== rootEl) {
var props = getAllElementProperties(el);
var attrs = Array.from(el.attributes);
var domPathProps = getDomPathProps(attrs, props);
// If the element happens to have a data-trackable attribute, get the siblings
// and position of the element (relative to the current element).
if (domPathProps["data-trackable"]) {
domPathProps = Object.assign(domPathProps, getSiblingsAndPosition(el, originalEl, selector));
}
trace.push(domPathProps);
var contextProps = getContextProps(attrs, props, el === originalEl);
assignIfUndefined(contextProps, customContext);
el = el.parentNode;
}
return { trace: trace, customContext: customContext };
}
exports.default = getTrace;
//# sourceMappingURL=getTrace.js.map