const createPageFactory = ({ nameId, pictureId, aboutId, timelineId, emailId, photoId, photoViewerId, }) => { const createPage = async (src) => { const {config, header, timeline, footer} = await getData(src); processHeader(header); processTimeline(timeline, config); processFooter(footer); setupGlobals(config); }; const processHeader = ({name, picture, about}) => { document.title = name; getElement(nameId).textContent = name; getElement(pictureId).src = picture; getElement(pictureId).onclick = () => showPhoto(picture); getElement(aboutId).innerHTML = listToHtml(about); }; const listToHtml = list => list.map(element => { if (!element.type || element.type === 'p') { return `

${element}

`; } else if (element.type === 'a') { return ` ${element.text} `; } else if (element.type === 'video') { return ``; } else return ''; }).join('\n'); const processTimeline = (timeline, {showMore}) => { getElement(timelineId).innerHTML = timeline.map( element => timelineElementToHTML(element, createId(), showMore) ).join('\n'); }; const timelineElementToHTML = ({date, title, picture, description, more, link}, id, showMore) => `
${date ? `

${date}

` : ''}

${title}

${date ? `

${date}

` : ''} ${picture ? `${picture}` : ''} ${description ? `

${description}

` : ''} ${more ? ` ${showMore} ` : (link ? `${link}` : '')}
`; const processFooter = ({email}) => { getElement(emailId).href = `mailto:${email}`; getElement(emailId).textContent = email; }; const hideFrame = () => { getElement(photoViewerId).style['z-index'] = -1; getElement(photoViewerId).style.opacity = '0'; }; const showPhoto = src => { getElement(photoId).src = src; getElement(photoViewerId).style['z-index'] = 1000; getElement(photoViewerId).style.opacity = '1'; }; const setupGlobals = config => { window.toggleLongDescription = toggleLongDescriptionFactory(config); window.showPhoto = showPhoto; window.hideFrame = hideFrame; getElement(photoViewerId).addEventListener('click', hideFrame); window.addEventListener('resize', onResize); document.body.addEventListener('keydown', handleEscape); }; const toggleLongDescriptionFactory = ({showMore, showLess}) => (id) => { const button = getElement(idToButtonId(id)); const element = getElement(idToActivityId(id)); if (isClosed(element)) { open(element); button.textContent = showLess; } else { close(element); button.textContent = showMore; } }; const onResize = () => { const elements = document.getElementsByClassName('collapsed'); Array.prototype.forEach.call(elements, element => { if (isOpen(element)) { element.style.height = 'auto'; setTimeout(() => open(element), 100); } }); }; const isClosed = element => ['0px', '0', 0, ''].includes(element.style.height); const isOpen = element => !isClosed(element); const close = element => element.style.height = '0'; const open = element => element.style.height = `${element.scrollHeight}px`; const handleEscape = event => { if (event.key === 'Escape') { hideFrame(); } }; const getElementFactory = () => { const foundElements = {}; return id => { if (!(id in foundElements)) { foundElements[id] = document.getElementById(id); } return foundElements[id]; } }; const getElement = getElementFactory(); const getData = async (src) => await (await fetch(src, { method: 'GET', mode: 'cors', cache: 'no-cache' })).json(); const createIdFactory = () => { let id = 0; return () => id++; }; const createId = createIdFactory(); const idToButtonId = (id) => `button_${id}`; const idToActivityId = (id) => `activity_${id}`; return createPage; };