gallery/script/gallery.js

127 lines
2.6 KiB
JavaScript

(function() {
'use strict';
let items;
let reqBoxes;
let excBoxes;
let allBoxes;
let tags;
function fillSets() {
let checkedValues = boxes =>
new Set(boxes.filter(b => b.checked).map(b => b.value));
return [checkedValues(reqBoxes), checkedValues(excBoxes)];
}
function updateItems() {
let [reqTags, excTags] = fillSets();
let anyReq = reqTags.size > 0;
for (let item of items) {
let req = tags.get(item).some(x => reqTags.has(x));
let exc = tags.get(item).some(x => excTags.has(x));
item.hidden = exc || (anyReq && !req);
}
}
function update() {
updateItems();
history.pushState(null, "", makeFragment());
}
function converseId(id) {
if (id.match(/^require/)) {
return id.replace('require', 'exclude');
} else {
return id.replace('exclude', 'require');
}
}
function toggle(checkbox, thisSet, thatSet) {
if (checkbox.checked)
document.getElementById(converseId(checkbox.id)).checked = false;
update();
}
function clearForm() {
allBoxes.forEach(b => b.checked = false);
}
function clear(e) {
clearForm();
update();
if (e) e.preventDefault();
}
function resetForm() {
allBoxes.forEach(b => b.checked = b.defaultChecked);
}
function reset(e) {
resetForm();
update();
if (e) e.preventDefault();
}
function makeFragment() {
let ids = allBoxes.filter(b => b.checked).map(b => b.id);
if (ids.length == 0) {
return '#all';
} else if (allBoxes.every(b => b.checked == b.defaultChecked)) {
return '#';
} else {
return '#' + ids.join(';');
}
}
function useFragment() {
let frag = location.hash.replace(/^#/, '');
if (frag == 'all') {
clearForm();
} else if (frag) {
let set = new Set(frag.split(';'));
allBoxes.forEach(b => b.checked = set.has(b.id));
document.getElementById('filters-details').open = true;
} else {
resetForm();
}
updateItems();
}
function setup() {
items = Array.from(document.getElementsByClassName('post'));
function inputs(id) {
let iter = document.getElementById(id).getElementsByTagName('input');
return Array.from(iter);
}
reqBoxes = inputs('require');
excBoxes = inputs('exclude');
allBoxes = [...reqBoxes, ...excBoxes];
tags = new Map(items.map(item => [item, item.dataset.tags.split(';')]));
allBoxes.forEach(b => b.addEventListener('change', () => toggle(b)));
document.getElementById('clear').addEventListener('click', clear);
document.getElementById('reset').addEventListener('click', reset);
window.addEventListener('popstate', useFragment);
useFragment();
}
window.addEventListener('DOMContentLoaded', setup);
})();