UNPKG

json-timeline

Version:

Generate Interactive Timelines stored in JSON Advents with Tags.

224 lines (198 loc) 6.85 kB
/** * @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); } }