if a theme is no longer available, js will now fall back to previous or default theme

This commit is contained in:
Robert Clarke 2019-05-08 11:40:39 +01:00
parent 4847d3f171
commit 6a19102b82
4 changed files with 82 additions and 13 deletions

View file

@ -6,6 +6,7 @@
//Variables
let link = null;
let previousLink = null;
let theme = localStorage.getItem(THEME_KEY);
//Private Methods
@ -16,21 +17,27 @@
fileref.rel = "stylesheet";
fileref.type = "text/css";
fileref.href = `/${themeName}.css`;
fileref.id = themeName;
//append it to the head
link = document.getElementsByTagName("head")[0].appendChild(fileref);
//when it's loaded, call onLinkLoad
link.addEventListener('load', onLinkLoad);
//if it errors, call onLinkError
link.addEventListener('error', onLinkError);
//if this is the first load of the page, remove the current stylesheet early to avoid flash of wrongly styled content
if (firstLoad) {
//keep the old link in case something goes wrong
previousLink = document.querySelectorAll(`.${STYLESHEET_CLASSNAME}`)[0];
removeStylesheets();
}
saveTheme(themeName);
};
/* Removes all current stylesheets on the page */
function removeStylesheets() {
document.querySelectorAll(`.${STYLESHEET_CLASSNAME}`).forEach((el) => {
el.remove();
@ -39,11 +46,35 @@
/* The function called when the css has finished loading */
function onLinkLoad() {
//remove event listeners
link.removeEventListener('load', onLinkLoad);
link.removeEventListener('error', onLinkError);
//remove the previous stylesheet(s)
removeStylesheets();
//add stylesheet class
link.className += STYLESHEET_CLASSNAME;
//everything is good, so we don't need this
previousLink = null;
//make body visible again if it was hidden
showBody();
};
function onLinkError() {
//remove event listeners
link.removeEventListener('load', onLinkLoad);
link.removeEventListener('error', onLinkError);
//remove theme from localstorage
clearTheme();
//remove theme from dropdown list
removeFromThemeSelect(link.id);
//remove link from page
link.remove();
//re-add the previous stylesheet (if any)
if (previousLink) {
document.getElementsByTagName("head")[0].appendChild(previousLink);
}
//set the theme select to the previous stylesheet
setThemeSelect(document.querySelectorAll(`.${STYLESHEET_CLASSNAME}`)[0].id)
//make body visible again if it was hidden
showBody();
};
@ -53,6 +84,11 @@
localStorage.setItem(THEME_KEY, themeName);
};
/* Clears the current theme in localstorage */
function clearTheme() {
localStorage.removeItem(THEME_KEY);
};
/* Hides the body of the page */
function hideBody() {
var head = document.getElementsByTagName('head')[0];
@ -76,6 +112,43 @@
css.remove();
};
/* Sets the theme selection to the given theme */
function setThemeSelect(theme) {
//get all select options
let elements = document.querySelectorAll('#theme-select>option');
//if there are elements, the page is loaded and continue
if (elements.length) {
elements.forEach(element => {
if (element.value === theme) {
element.selected = 'selected';
}
});
} else {
//if there are no elements, the page is not yet loaded; wait for loaded event and try again.
window.addEventListener('DOMContentLoaded', () => {
setThemeSelect(theme)
});
}
}
function removeFromThemeSelect(theme) {
//get all select options
let elements = document.querySelectorAll('#theme-select>option');
//if there are elements, the page is loaded
if (elements.length) {
elements.forEach(element => {
if (element.value === theme) {
element.remove();
}
});
} else {
//if there are no elements, the page is not yet loaded; wait for loaded event and try again.
window.addEventListener('DOMContentLoaded', () => {
removeFromThemeSelect(theme)
});
}
}
//Public Methods
switch_css.init = function () {
//if user has selected and theme and it is not the current theme
@ -85,13 +158,7 @@
//change the theme
changeTheme(theme, true);
//when the DOM is loaded, change the select to their current choice
window.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('#theme-select>option').forEach(element => {
if (element.value === theme) {
element.selected = 'selected';
}
});
});
setThemeSelect(theme);
}
//when the DOM is loaded, set the dropdown to trigger the theme change
window.addEventListener('DOMContentLoaded', () => {