UNPKG

@phantomstudios/ft-lib

Version:

A collection of Javascript UI & tracking utils for FT sites

109 lines 4 kB
"use strict"; 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