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

@ -39,9 +39,9 @@ That's it! No more configuration should be required, however head to the [Option
### Sources
All the source javascript files live in `javascript/src`. This is a list of the javascript files, their purpose, and their sources. All files are prefixed with `zulma_` to avoid any name clashes.
- `zulma_search.js` - Used when a user types into the search box on the navbar (if enabled). The search is shamefully stolen from [Zola's site](https://github.com/getzola/zola/blob/6100a43/docs/static/search.js). Thanks, Vincent!
- `zulma_search.js` - Used when a user types into the search box on the navbar (if enabled). Taken from [Zola's site](https://github.com/getzola/zola/blob/6100a43/docs/static/search.js).
- `zulma_navbar.js` - Used for the mobile navbar toggle. Taken from the [bulma template](https://github.com/dansup/bulma-templates/blob/6263eb7/js/bulma.js) at Bulmaswatch
- `zulma_switchcss.js` - Used for swapping themes. Created by me.
- `zulma_switchcss.js` - Used for swapping themes (if enabled). Created by me.
### Building
These are transpiled by babel, minified by webpack, sourcemaps are generated and then everything placed in `static/js`. The repo already contains the transpiled and minified files along with their corrosponding sourcemaps so you don't need to do anything to use these. If you would prefer to build it yourself, feel free to inspect the js files and then run the build process yourself (please ensure that you have [node, npm](https://nodejs.org/en/) and [yarn](https://yarnpkg.com/lang/en/) installed.):
@ -181,13 +181,15 @@ zulma_theme = "darkly"
Additionally, in extra, you can also set the `zulma_allow_theme_selection` boolean. Setting this to `true` will allow a menu in the footer to allow users to select their own theme. This option will store their theme choice in their localstorage and apply it on every page, assuming `zulma_allow_theme_selection` is still true. This requires javascript to be enabled to function; if the page detects javascript is disabled on the clients machine, it will hide itself.
Each theme contains the entirety of Bulma, and will weigh in at ~180kb. If you're running on a server severely limited on space, then I'd recommend you delete each theme you're not using, either from the source or from `/public`. Obviously, doing this will cause `zulma_allow_theme_selection` to work improperly, so make sure you either override `extra.zulma_themes` in `config.toml` to only show themes you have left or to not enable this option at all.
```toml
[extra]
zulma_allow_theme_selection = true
```
## Original
This template is based on the [blog template](https://dansup.github.io/bulma-templates/templates/blog.html) over at [Free Bulma Templates](https://dansup.github.io/bulma-templates/). All themes were taken from [Bulmaswatch](https://jenil.github.io/bulmaswatch/). The code behind from adapted from the [after-dark](https://github.com/getzola/after-dark/blob/master/README.md) zola template.
This template is based on the [blog template](https://dansup.github.io/bulma-templates/templates/blog.html) over at [Free Bulma Templates](https://dansup.github.io/bulma-templates/). All themes were taken from [Bulmaswatch](https://jenil.github.io/bulmaswatch/). The code behind from originally adapted from the [after-dark](https://github.com/getzola/after-dark/blob/master/README.md) zola template.
## Known Bugs
If user theme swapping is enabled and the user selects a theme different to the default, a slight delay will be introduced in page rendering as the css gets swapped out and in by the javascript. This is better than the alternative FOUC or flashes of the old theme, but still annoying. I don't know any way around this, but with browser caching it should be fast enough to not cause serious issues.
- If user theme swapping is enabled and the user selects a theme different to the default, a slight delay will be introduced in page rendering as the css gets swapped out and in by the javascript. This is better than the alternative FOUC or flashes of the old theme, but still annoying. I don't know any way around this, but with browser caching it should be fast enough to not cause serious issues.

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', () => {

View file

@ -1,2 +1,2 @@
!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=2)}({2:function(e,t){!function(e){var t="ZULMA_THEME",n="stop-blink",o="stylesheet",r=null,c=localStorage.getItem(t);function i(e,n){var o=document.createElement("link");o.rel="stylesheet",o.type="text/css",o.href="/".concat(e,".css"),(r=document.getElementsByTagName("head")[0].appendChild(o)).addEventListener("load",u),n&&l(),function(e){localStorage.setItem(t,e)}(e)}function l(){document.querySelectorAll(".".concat(o)).forEach(function(e){e.remove()})}function u(){var e;r.removeEventListener("load",u),l(),r.className+=o,(e=document.getElementById(n))&&e.remove()}e.init=function(){var e,t;c&&!document.getElementById(c)&&(e=document.getElementsByTagName("head")[0],(t=document.createElement("style")).id=n,t.setAttribute("type","text/css"),t.styleSheet?t.styleSheet.cssText=css:t.appendChild(document.createTextNode("body{visibility:hidden;}")),e.appendChild(t),i(c,!0),window.addEventListener("DOMContentLoaded",function(){document.querySelectorAll("#theme-select>option").forEach(function(e){e.value===c&&(e.selected="selected")})})),window.addEventListener("DOMContentLoaded",function(){document.getElementById("theme-select").onchange=function(){i(this.value)}})}}(switch_css=window.switch_css||{}),switch_css.init()}});
!function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=2)}({2:function(e,t){!function(e){var t="ZULMA_THEME",n="stop-blink",o="stylesheet",r=null,c=null,l=localStorage.getItem(t);function i(e,n){var l=document.createElement("link");l.rel="stylesheet",l.type="text/css",l.href="/".concat(e,".css"),l.id=e,(r=document.getElementsByTagName("head")[0].appendChild(l)).addEventListener("load",d),r.addEventListener("error",a),n&&(c=document.querySelectorAll(".".concat(o))[0],u()),function(e){localStorage.setItem(t,e)}(e)}function u(){document.querySelectorAll(".".concat(o)).forEach(function(e){e.remove()})}function d(){r.removeEventListener("load",d),r.removeEventListener("error",a),u(),r.className+=o,c=null,s()}function a(){r.removeEventListener("load",d),r.removeEventListener("error",a),localStorage.removeItem(t),function e(t){var n=document.querySelectorAll("#theme-select>option");n.length?n.forEach(function(e){e.value===t&&e.remove()}):window.addEventListener("DOMContentLoaded",function(){e(t)})}(r.id),r.remove(),c&&document.getElementsByTagName("head")[0].appendChild(c),f(document.querySelectorAll(".".concat(o))[0].id),s()}function s(){var e=document.getElementById(n);e&&e.remove()}function f(e){var t=document.querySelectorAll("#theme-select>option");t.length?t.forEach(function(t){t.value===e&&(t.selected="selected")}):window.addEventListener("DOMContentLoaded",function(){f(e)})}e.init=function(){var e,t;l&&!document.getElementById(l)&&(e=document.getElementsByTagName("head")[0],(t=document.createElement("style")).id=n,t.setAttribute("type","text/css"),t.styleSheet?t.styleSheet.cssText=css:t.appendChild(document.createTextNode("body{visibility:hidden;}")),e.appendChild(t),i(l,!0),f(l)),window.addEventListener("DOMContentLoaded",function(){document.getElementById("theme-select").onchange=function(){i(this.value)}})}}(switch_css=window.switch_css||{}),switch_css.init()}});
//# sourceMappingURL=zulma_switchcss.js.map

File diff suppressed because one or more lines are too long