aws-ddk-core
Version:
The AWS DataOps Development Kit is an open source development framework for customers that build data workflows and modern data architecture on AWS.
182 lines (148 loc) • 5.36 kB
JavaScript
/**
* Configure the tabs behavior.
*/
const jekyllTabsConfiguration = {
syncTabsWithSameLabels: false,
addCopyToClipboardButton: false,
copyToClipboardButtonHtml: '<button>Copy</button>',
};
const jekyllTabsModule = (function() {
/**
* Remove all "active" classes on li elements that belong to the given ul element.
*/
const removeActiveClasses = function (ulElement) {
const liElements = ulElement.querySelectorAll('ul > li');
Array.prototype.forEach.call(liElements, function(liElement) {
liElement.classList.remove('active');
});
}
/**
* Get the element position looking from the perspective of the parent element.
*
* Considering the following html:
*
* <ul>
* <li class="zero">0</li>
* <li class="one">1</li>
* <li class="two">2</li>
* </ul>
*
* Then getChildPosition(document.querySelector('.one')) would return 1.
*/
const getChildPosition = function (element) {
var parent = element.parentNode;
var i = 0;
for (var i = 0; i < parent.children.length; i++) {
if (parent.children[i] === element) {
return i;
}
}
throw new Error('No parent found');
}
/**
* Returns a list of elements of the given tag that contains the given text.
*/
const findElementsContaining = function(elementTag, text) {
const elements = document.querySelectorAll(elementTag);
const elementsThatContainText = [];
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
if (element.textContent.includes(text)) {
elementsThatContainText.push(element);
}
}
return elementsThatContainText;
}
/**
* Handle adding or removing active classes on tab list items.
*/
const handleTabClicked = function(link) {
liTab = link.parentNode;
ulTab = liTab.parentNode;
liPositionInUl = getChildPosition(liTab);
if (liTab.className.includes('active')) {
return;
}
tabContentId = ulTab.getAttribute('data-tab');
tabContentElement = document.getElementById(tabContentId);
// Remove all "active" classes first.
removeActiveClasses(ulTab);
removeActiveClasses(tabContentElement);
// Then add back active classes depending on the tab (ul element) that was clicked on.
tabContentElement.querySelectorAll('ul > li')[liPositionInUl].classList.add('active');
liTab.classList.add('active');
}
/**
* Create a javascript element from html markup.
*/
const createElementFromHtml = function(html) {
const template = document.createElement('template');
template.innerHTML = html.trim();
return template.content.firstChild;
}
/**
* Copy the given text in the clipboard.
*
* See https://stackoverflow.com/questions/51805395/navigator-clipboard-is-undefined
*/
const copyToClipboard = function(text) {
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(text);
} else {
// Use the 'out of viewport hidden text area' trick
const textArea = document.createElement("textarea");
textArea.value = text;
// Move textarea out of the viewport so it's not visible
textArea.style.position = "absolute";
textArea.style.left = "-999999px";
document.body.prepend(textArea);
textArea.select();
try {
document.execCommand('copy');
} catch (error) {
console.error(error);
} finally {
textArea.remove();
}
};
}
return {
findElementsContaining,
handleTabClicked,
createElementFromHtml,
copyToClipboard,
};
})();
window.addEventListener('load', function () {
const tabLinks = document.querySelectorAll('ul.tab > li > a');
Array.prototype.forEach.call(tabLinks, function(link) {
link.addEventListener('click', function (event) {
event.preventDefault();
jekyllTabsModule.handleTabClicked(link);
if (jekyllTabsConfiguration.syncTabsWithSameLabels) {
const linksWithSameName = jekyllTabsModule.findElementsContaining('a', link.textContent);
for(let i = 0; i < linksWithSameName.length; i++) {
if (linksWithSameName[i] !== link) {
jekyllTabsModule.handleTabClicked(linksWithSameName[i]);
}
}
}
}, false);
});
if (jekyllTabsConfiguration.addCopyToClipboardButton) {
const preElements = document.querySelectorAll('ul.tab-content > li pre');
for(let i = 0; i < preElements.length; i++) {
const preElement = preElements[i];
const preParentNode = preElement.parentNode;
const button = jekyllTabsModule.createElementFromHtml(jekyllTabsConfiguration.copyToClipboardButtonHtml);
preParentNode.style.position = 'relative';
button.style.position = 'absolute';
button.style.top = '0px';
button.style.right = '0px';
preParentNode.appendChild(button);
button.addEventListener('click', function () {
jekyllTabsModule.copyToClipboard(preElement.innerText);
});
}
}
});