Refactor js

This commit is contained in:
Schmelczer András 2019-12-14 14:55:29 +01:00
commit 5de596c38a
28 changed files with 859 additions and 0 deletions

157
js/content.js Normal file
View file

@ -0,0 +1,157 @@
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 `<p>${element}</p>`;
} else if (element.type === 'a') {
return `<a href="${element.href}" target="_blank"> ${element.text} </a>`;
} else if (element.type === 'video') {
return `<video controls><source src="${element.src}" /></video>`;
} 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) => `
<section>
<div class="line">
${date ? `<p class="date-wide-screen">${date}</p>` : ''}
</div>
<div class="card">
<h2>${title}</h2>
${date ? `<p class="date-narrow-screen">${date}</p>` : ''}
${picture ? `<img src="${picture}" onclick="showPhoto('${picture}');" alt="${picture}"/>` : ''}
${description ? `<p class="description">${description}</p>` : ''}
${more ? `
<div class="collapsed" id="${idToActivityId(id)}">
${listToHtml(more)}
</div>
<a id="${idToButtonId(id)}" onclick="toggleLongDescription(${id})">
${showMore}
</a>
`
: (link ? `<a href="http://${link}" target="_blank">${link}</a>` : '')}
</div>
</section>
`;
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;
};

15
js/main.js Normal file
View file

@ -0,0 +1,15 @@
(async () => {
const src = 'content-en.json';
const ids = {
pictureId: 'header-pic',
nameId: 'name',
aboutId: 'about',
timelineId: 'timeline',
emailId: 'email',
photoViewerId: 'photo-viewer',
photoId: 'photo'
};
await createPageFactory(ids)(src);
document.body.style.visibility = 'visible';
})();