/**
* @module renderAdvents
*/
import { advents, tags } from './advents.js';
/**
* @constant
* @type {Object[][]}
* @name adventDomGroups
* @description Array of Advent Group and Advent DOMs
*/
const adventDomGroups = advents
// Map Each Advent in a Group to an Advent DOM
.map(group =>
group.map(advent => ({
advent,
adventDiv: renderAdvent(advent)
}))
)
// Map Each Group to an Advent Group DOM
.map(group => ({
group,
groupDom: renderAdventGroup(group)
}));
/**
* @function
* @name renderAdvent
* @description Render Advent DOM Object from Advent Object
* @param {Object} advent Advent Object
* @returns {HTMLElement} Advent DOM Object
*/
function renderAdvent(advent) {
// Advent div
const adventDiv = document.createElement('div');
adventDiv.classList.add('advent');
// Title p
const titleP = document.createElement('p');
titleP.classList.add('title');
titleP.classList.add('mono-text');
titleP.innerText = advent.title;
adventDiv.appendChild(titleP);
// Date p
const dateP = document.createElement('p');
dateP.classList.add('date');
dateP.classList.add('mono-text');
dateP.innerText = (
`${advent.start.month}/${advent.start.day}/${advent.start.year}` +
((advent.end === null)
? ''
: `-${advent.end.month}/${advent.end.day}/${advent.end.year}`)
);
adventDiv.appendChild(dateP);
// Tags p
const tagsP = document.createElement('p');
tagsP.classList.add('tags');
tagsP.classList.add('mono-text');
tagsP.innerText = `Tags:${advent.tags.join(',')}`;
adventDiv.appendChild(tagsP);
// Content p
const contentP = document.createElement('p');
contentP.classList.add('content');
contentP.classList.add('read-text');
contentP.innerText = advent.content;
adventDiv.appendChild(contentP);
return adventDiv;
}
/**
* @function
* @name renderAdventGroup
* @description Render Advent Group DOM Object from Advent Group
* @param {Object[]} group Advent Group
* @returns {HTMLElement} Advent Group DOM Object
*/
function renderAdventGroup(group) {
// Group div
const groupDiv = document.createElement('div');
groupDiv.classList.add('group');
// Date Toggle p
const dateToggleP = document.createElement('p');
dateToggleP.classList.add('group-date');
dateToggleP.classList.add('mono-text');
dateToggleP.addEventListener('click', toggleVisibility());
const { advent: { start: { month, day, year } } } = group[0];
const date = `${month}/${day}/${year}`;
dateToggleP.innerText = `${date} [▼]`;
groupDiv.appendChild(dateToggleP);
// Advents div
const adventsDiv = document.createElement('div');
adventsDiv.classList.add('advents');
adventsDiv.classList.add('hidden');
groupDiv.appendChild(adventsDiv);
return groupDiv;
}
/**
* @function
* @name renderTagToggles
* @description Render Tag Toggles from Tags
* @param {HTMLElement} target1 Target to render Tag Toggles
* @param {HTMLElement} target2 Target to render Timeline
*/
export function renderTagToggles(target1, target2) {
// Toggle Title p
const toggleTitle = document.createElement('p');
toggleTitle.classList.add('toggle-container-title');
toggleTitle.classList.add('mono-text');
toggleTitle.innerText = 'Tags [▼]';
toggleTitle.addEventListener('click', toggleVisibility());
target1.appendChild(toggleTitle);
// Toggle Container div
const toggleContainer = document.createElement('div');
toggleContainer.classList.add('toggles-container');
toggleContainer.classList.add('hidden');
target1.appendChild(toggleContainer);
// Add Tag Toggle per Tag Key
for (const key of tags.keys()) {
// Tag Toggle div
const tagToggleDiv = document.createElement('div');
tagToggleDiv.classList.add('toggle-container');
// Tag Toggle Checkbox input
const tagToggleCheck = document.createElement('input');
tagToggleCheck.setAttribute('type', 'checkbox');
tagToggleCheck.setAttribute('checked', true);
tagToggleCheck.classList.add('tag-toggle');
tagToggleCheck.addEventListener('click', () => {
tags.set(key, !tags.get(key));
renderTimeline(target2);
});
tagToggleDiv.appendChild(tagToggleCheck);
// Tag Toggle Label label
const tagToggleLabel = document.createElement('label');
tagToggleLabel.classList.add('tag-toggle-label');
tagToggleLabel.classList.add('mono-text');
tagToggleLabel.innerText = key;
tagToggleDiv.appendChild(tagToggleLabel);
toggleContainer.appendChild(tagToggleDiv);
}
}
/**
* @function
* @name toggleVisibility
* @description Creates Function to toggle Visibility of Element given a Find Function
* @param {Function} findFn Function to find Element to Toggle from Target
* @returns {Function} Function to toggle Visibility of Element
*/
function toggleVisibility(findFn = target => target.nextElementSibling) {
// Function to toggle Visibility
return function ({ target }) {
// Element to Toggle
const container = findFn(target);
const end = target.innerText.length - 3;
// Hide Element
if (target.innerText.endsWith('[▼]')) {
container.classList.remove('hidden');
target.innerText = `${target.innerText.slice(0, end)}[▲]`;
}
// Show Element
else {
container.classList.add('hidden');
target.innerText = `${target.innerText.slice(0, end)}[▼]`;
}
};
}
/**
* @function
* @name renderTimeline
* @description Render Timeline from Advent DOM Groups
* @param {HTMLElement} target Target to render Timeline
*/
export function renderTimeline(target) {
// Clear Timeline
removeChildren(target);
// For every Advent DOM Group
for (const { group, groupDom } of adventDomGroups) {
const [_, advents] = groupDom.children;
// Remove all Advents from Advent Group DOM
removeChildren(advents);
// Append Advent if some Tag is toggled
for (const { advent, adventDiv } of group) {
if (advent.tags.some(tag => tags.get(tag))) {
advents.appendChild(adventDiv);
}
}
// Append Advent Group DOM if not empty
if (advents.firstChild) {
target.appendChild(groupDom);
}
}
}
/**
* @function
* @name removeChildren
* @description Removes all children elements from Target Element
* @param {HTMLElement} element Target Element
*/
function removeChildren(element) {
while (element.firstChild) {
element.removeChild(element.firstChild);
}
}