|
/** A key for the session storage to keep track of the component labels visibility */ |
|
const storageKey = 'TCL-bookmarklet-visible-component-classNames' |
|
|
|
/** A class name for component labels to indentify and remove them upon request */ |
|
const labelClassName = 'TCL-bookmarklet__label' |
|
|
|
/** A CSS selector to find components on a page */ |
|
const componentNodesQuery = '[class*=component]' |
|
|
|
/** |
|
* Generates a random color. Doesn’t take into account its luminance, so be cautious about potential contrast-related accessibility problems |
|
* @returns A HEX-code of a newly generarted color |
|
*/ |
|
function generateRandomColor() { |
|
return Math.floor(Math.random() * 16777215).toString(16) |
|
} |
|
|
|
// Determine if component labels are presented on the page |
|
const labelsVisible = window.sessionStorage.getItem(storageKey) === '1' |
|
|
|
// If the labels aren’t shown, create them |
|
if (!labelsVisible) { |
|
|
|
// Find all component nodes |
|
const componentNodes = document.querySelectorAll(componentNodesQuery) |
|
|
|
// Loop through each of the component nodes |
|
componentNodes.forEach(node => { |
|
|
|
// Generate a random color for a component node |
|
const color = generateRandomColor() |
|
|
|
// Add an outline to the component |
|
node.style.outline = '1px solid #' + color |
|
|
|
// Find the class names of the node which indicates that it is a component node |
|
const componentClasses = [...node.classList] |
|
.filter(c => c.match('component')) |
|
|
|
// Extract component names out of the component classes |
|
const componentNames = componentClasses.map(c => c.replace(/_+component.*/, '')) |
|
|
|
// Create a label |
|
const el = document.createElement('span') |
|
|
|
// Put the list of the component names to the label |
|
el.innerText = componentNames.join() |
|
|
|
// Set up a custom class to easily find the label upon request |
|
el.className = labelClassName |
|
|
|
// Configure the styles of the label |
|
el.style.fontFamily = 'SFMono, Consolas, monospace' |
|
el.style.fontSize = '10px' |
|
el.style.lineHeight = '1.2' |
|
el.style.textAlign = 'left' |
|
el.style.textTransform = 'none' |
|
|
|
el.style.backgroundColor = '#' + color |
|
el.style.color = 'white' |
|
el.style.opacity = '0.9' |
|
|
|
el.style.display = 'block' |
|
el.style.position = 'absolute' |
|
el.style.padding = '0 4px' |
|
el.style.borderRadius = '4px' |
|
|
|
// Insert the label into the component node |
|
node.appendChild(el) |
|
}) |
|
|
|
// Save the current state that indicates that the labels are currently visible |
|
window.sessionStorage.setItem(storageKey, '1') |
|
|
|
} else { |
|
// If the labels have already been added to the page, find them |
|
const labels = document.querySelectorAll('.' + labelClassName) |
|
|
|
// Loop through each of the labels and remove it |
|
labels.forEach(node => node.remove()) |
|
|
|
// Find component nodes |
|
const componentNodes = document.querySelectorAll(componentNodesQuery) |
|
|
|
// Remove the outlines |
|
componentNodes.forEach(node => node.style.outline = 'none') |
|
|
|
// Save the current state |
|
window.sessionStorage.setItem(storageKey, '') |
|
} |