Skip to content

Commit

Permalink
added assets versioning support for themes, like it is for other stat…
Browse files Browse the repository at this point in the history
…ic assets too, so cache can be better utilized
  • Loading branch information
Henjuro committed Jun 18, 2018
1 parent cf5eb90 commit d59b86f
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 129 deletions.
263 changes: 137 additions & 126 deletions templates/partials/themes.js
Original file line number Diff line number Diff line change
@@ -1,146 +1,157 @@
'use strict';
// this code is directly included into the base.html because the css element needs to be included during the first pass
// this code is directly included into the base.html because the css element
// needs to be included during the first pass
// otherwise people will see a unstyled page flash
if (!waitlist) {
var waitlist = {};
var waitlist = {};
}

waitlist.themes = (function() {
let settings = {
'id': 'theme-css',
'base_path': "/static/css/",
'setting_key_prefix': 'themes-',
'def_type': 'local',
'def_file': 'themes/default.css',
};
// file_name = null == standard file
function setTheme(file_name, type, integrity, crossorigin) {
localStorage.setItem(settings.setting_key_prefix+"file", file_name);
localStorage.setItem(settings.setting_key_prefix+"type", type);
if (integrity === null) {
localStorage.removeItem(settings.setting_key_prefix+"integrity");
} else {
localStorage.setItem(settings.setting_key_prefix+"integrity", integrity);
}
if (crossorigin === null) {
localStorage.removeItem(settings.setting_key_prefix+"crossorigin");
} else {
localStorage.setItem(settings.setting_key_prefix+"crossorigin", crossorigin);
}
let settings = {
'css_element_id': 'theme-css',
'select_id': 'theme-selector',
'setting_key_prefix': 'themes-',
'default_theme_id': 'default',
'themes': {
'default': {
id: 'default',
path: {% assets "themes.default" %}'{{ ASSET_URL }}'{% endassets %},
type: 'local',
integrity: null,
crossorigin: null,
},
'dark': {
id: 'dark',
path: {% assets "themes.dark" %}'{{ ASSET_URL }}'{% endassets %},
type: 'local',
integrity: null,
crossorigin: null,
},
'dark_purple': {
id: 'dark_purple',
path: {% assets "themes.dark_purple" %}'{{ ASSET_URL }}'{% endassets %},
type: 'local',
integrity: null,
crossorigin: null,
}
},
};

let new_element = false;
let theme_element = document.getElementById(settings.id);
// we got none yet
if (theme_element === null) {
// add one
let parser = new DOMParser();
let htmlPart = parser.parseFromString('<html><body><link rel="stylesheet" href="" id="'+settings.id+'"></body></html>', "text/html");
theme_element = htmlPart.getElementById(settings.id);
new_element = true;
}
// file_name = null == standard file
function setTheme(theme_id) {
localStorage.setItem(settings.setting_key_prefix + "id", theme_id);

let pure_element = theme_element;
let new_element = false;
let theme_element = document.getElementById(settings.css_element_id);
// we got none yet
if (theme_element === null) {
// add one
let parser = new DOMParser();
let htmlPart = parser.parseFromString(
'<html><body><link rel="stylesheet" href="" id="' + settings.css_element_id
+ '"></body></html>', "text/html");
theme_element = htmlPart.getElementById(settings.css_element_id);
new_element = true;
}

// lets check if we have a local or remote theme
if (type === 'remote' && integrity !== null && (!pure_element.hasAttribute('integrity')
|| !pure_element.getAttribute('integrity') !== integrity)) {
pure_element.setAttribute('integrity', integrity);
}
if (type === 'remote' && crossorigin !== null && (!pure_element.hasAttribute('crossorigin')
|| !pure_element.getAttribute('crossorigin') !== crossorigin)) {
pure_element.setAttribute('crossorigin', crossorigin);
}
let pure_element = theme_element;
let theme = settings.themes[theme_id];
// lets check if we have a local or remote theme
if (theme.type === 'remote'
&& theme.integrity !== null
&& (!pure_element.hasAttribute('integrity') || !pure_element
.getAttribute('integrity') !== theme.integrity)) {
pure_element.setAttribute('integrity', theme.integrity);
}
if (theme.type === 'remote'
&& theme.crossorigin !== null
&& (!pure_element.hasAttribute('crossorigin') || !pure_element
.getAttribute('crossorigin') !== theme.crossorigin)) {
pure_element.setAttribute('crossorigin', theme.crossorigin);
}

if ((type === 'local' || integrity === null) && pure_element.hasAttribute('integrity')) {
pure_element.removeAttribute('integrity')
}
if ((type === 'local' || crossorigin === null) && pure_element.hasAttribute('crossorigin')) {
pure_element.removeAttribute('crossorigin');
}
// lets set the href
let href = type === "remote" ? file_name : settings.base_path+file_name;
pure_element.setAttribute('href', href);
if (new_element) {
if ((theme.type === 'local' || theme.integrity === null)
&& pure_element.hasAttribute('integrity')) {
pure_element.removeAttribute('integrity')
}
if ((theme.type === 'local' || theme.crossorigin === null)
&& pure_element.hasAttribute('crossorigin')) {
pure_element.removeAttribute('crossorigin');
}
// lets set the href
let href = theme.path;
pure_element.setAttribute('href', href);
if (new_element) {

document.write(pure_element.outerHTML);
//let headElement = document.getElementsByTagName("head")[0];
//let themLoaderElement = document.getElementById("themeloader");
//themLoaderElement.insertAdjacentHTML("afterend", pure_element.outerHTML)
//headElement.insertAfter(pure_element, themLoaderElement);
}
}
document.write(pure_element.outerHTML);
// let headElement = document.getElementsByTagName("head")[0];
// let themLoaderElement = document.getElementById("themeloader");
// themLoaderElement.insertAdjacentHTML("afterend",
// pure_element.outerHTML)
// headElement.insertAfter(pure_element, themLoaderElement);
}
}

function selectionChangeHandler(event) {
let url = event.target.value;
let target_option = event.target.options[event.target.options.selectedIndex];
let type = target_option.getAttribute('data-type');
let integrity = target_option.hasAttribute('data-integrity') ? target_option.getAttribute('data-integrity') : null;
let crossorigin = target_option.hasAttribute('data-crossorigin') ? target_option.getAttribute('data-crossorigin') : null;
setTheme(this.value, type, integrity, crossorigin); //
}
function selectionChangeHandler(event) {
let theme_id = event.target.value;
setTheme(theme_id);
}

function setCurrentTheme() {
let file = localStorage.getItem(settings.setting_key_prefix+"file");
let type = localStorage.getItem(settings.setting_key_prefix+"type");
let integrity = localStorage.getItem(settings.setting_key_prefix+"integrity");
let crossorigin = localStorage.getItem(settings.setting_key_prefix+"crossorigin");
if (file === null || file === "null") {
// set the default theme
document.addEventListener('DOMContentLoaded', function () {
setSelectionAfterPageReady(settings.def_file);
});
setTheme(settings.def_file, settings.def_type, settings.def_integrity, settings.def_crossorigin)
} else {
document.addEventListener('DOMContentLoaded', function () {
setSelectionAfterPageReady(file);
});
setTheme(file, type, integrity, crossorigin);
}
}
function setUpTheme() {
let theme_id = localStorage.getItem(settings.setting_key_prefix + "id");

if (theme_id === null || theme_id === "null" || !(theme_id in settings.themes) ) {
// set the default theme
theme_id = settings.default_theme_id;
}

function initThemeAfterPageReady() {
let selector = $('#theme-selector')[0];
let firstOption = selector[selector.selectedIndex];
let file = firstOption.getAttribute('value');
let type = firstOption.getAttribute('data-type');
let integrity = firstOption.hasAttribute('data-integrity') ? firstOption.getAttribute('data-integrity') : null;
let crossorigin = firstOption.hasAttribute('data-crossorigin') ? firstOption.getAttribute('data-crossorigin') : null;
setTheme(file, type, integrity, crossorigin);
}
let theme = settings.themes[theme_id];

function setSelectionAfterPageReady(file) {
let selector = document.getElementById('theme-selector');
let foundTheme = false;
for(let idx=0; idx < selector.length; idx++) {
if (selector[idx].getAttribute('value') === file) {
selector[idx].selected = true;
foundTheme = true;
break;
}
}
setTheme(theme_id);
// set selection after dome is done
// and then setup a handler for theme selection
document.addEventListener('DOMContentLoaded', function() {
setSelectionAfterPageReady(theme_id);
let selector = document.getElementById(settings.select_id);
selector.addEventListener('change', selectionChangeHandler);
});
}

function initThemeAfterPageReady() {
let selector = $('#theme-selector')[0];
let firstOption = selector[selector.selectedIndex];
let file = firstOption.getAttribute('value');
let type = firstOption.getAttribute('data-type');
let integrity = firstOption.hasAttribute('data-integrity') ? firstOption
.getAttribute('data-integrity')
: null;
let crossorigin = firstOption.hasAttribute('data-crossorigin') ? firstOption
.getAttribute('data-crossorigin')
: null;
setTheme(file, type, integrity, crossorigin);
}

if (!foundTheme) {
if (selector.options.length > 0) {
selector[0].selected = true;
let target_option = selector[0];
let url = target_option.value;
let type = target_option.getAttribute('data-type');
let integrity = target_option.hasAttribute('data-integrity') ? target_option.getAttribute('data-integrity') : null;
let crossorigin = target_option.hasAttribute('data-crossorigin') ? target_option.getAttribute('data-crossorigin') : null;
setTheme(url, type, integrity, crossorigin); //
}
}
function setSelectionAfterPageReady(theme_id) {
let selector = document.getElementById(settings.select_id);
let foundTheme = false;
for (let idx = 0; idx < selector.length; idx++) {
if (selector[idx].getAttribute('value') === theme_id) {
selector[idx].selected = true;
foundTheme = true;
break;
}
}

}
if (!foundTheme) {
console.error('No theme with value ' + theme_id + ' was found in selector, this should never happen.');

}

// apply our current theme and set handlers
function init() {
let selector = $('#theme-selector');
selector.on("change", selectionChangeHandler);
}
setCurrentTheme();
document.addEventListener('DOMContentLoaded', init);
// nothing to export
return {};
}

// this
setUpTheme();
// nothing to export
return {};
})();
6 changes: 3 additions & 3 deletions templates/partials/themes_selector.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<select id="theme-selector" class="col-2 h-25 custom-select">
<option value="themes/default.css" data-type="local">Default</option>
<option value="themes/dark.css" data-type="local">Dark</option>
<option value="themes/dark_purple.css" data-type="local">Dark Purple</option>
<option value="default">Default</option>
<option value="dark">Dark</option>
<option value="dark_purple">Dark Purple</option>
</select>
2 changes: 2 additions & 0 deletions waitlist/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from flask_limiter.extension import Limiter
from flask_limiter.util import get_ipaddr
from flask.globals import request
from waitlist.utility.assets import register_asset_bundles

app = Flask(import_name=__name__, static_url_path="/static",
static_folder="../static", template_folder=path.join("..", "templates"))
Expand Down Expand Up @@ -94,6 +95,7 @@
# init assets environment
assets = Environment(app)
register_filter(BabiliFilter)
register_asset_bundles(assets)


class MiniJSONEncoder(JSONEncoder):
Expand Down
20 changes: 20 additions & 0 deletions waitlist/utility/assets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from webassets.bundle import Bundle
from flask_assets import Environment


def register_asset_bundles(assets: Environment):
themes_dark = Bundle('css/themes/dark.css',
filters='cssmin',
output='gen/themes/dark.%(version)s.css')
themes_darkpurple = Bundle('css/themes/dark_purple.css',
filters='cssmin',
output='gen/themes/dark_purple.%(version)s.css')
themes_default = Bundle('css/themes/default.css',
filters='cssmin',
output='gen/themes/default.%(version)s.css')
bundles = {
'themes.dark': themes_dark,
'themes.dark_purple': themes_darkpurple,
'themes.default': themes_default
}
assets.register(bundles)

0 comments on commit d59b86f

Please sign in to comment.