documentverification/staticfiles/admin/js/SelectBox.js

178 lines
6.8 KiB
JavaScript
Raw Permalink Normal View History

"use strict";
{
const getOptionGroupName = (option) => option.parentElement.label;
const SelectBox = {
cache: {},
init: function (id) {
const box = document.getElementById(id);
SelectBox.cache[id] = [];
const cache = SelectBox.cache[id];
for (const node of box.options) {
const group = getOptionGroupName(node);
cache.push({
group,
value: node.value,
text: node.text,
displayed: 1,
});
}
// Only sort if there are any groups (to preserve existing behavior for non-grouped selects)
if (cache.some((item) => item.group)) {
SelectBox.sort(id);
}
},
redisplay: function (id) {
// Repopulate HTML select box from cache
const box = document.getElementById(id);
const scroll_value_from_top = box.scrollTop;
box.innerHTML = "";
let node = box;
let currentOptgroup = null;
for (const option of SelectBox.cache[id]) {
if (option.displayed) {
// Create a new optgroup when the group changes
if (option.group && option.group !== currentOptgroup) {
currentOptgroup = option.group;
node = document.createElement("optgroup");
node.setAttribute("label", option.group);
box.appendChild(node);
} else if (!option.group && currentOptgroup !== null) {
// Back to ungrouped options
currentOptgroup = null;
node = box;
}
const new_option = new Option(
option.text,
option.value,
false,
false,
);
// Shows a tooltip when hovering over the option
new_option.title = option.text;
node.appendChild(new_option);
}
}
box.scrollTop = scroll_value_from_top;
},
filter: function (id, text) {
// Redisplay the HTML select box, displaying only the choices containing ALL
// the words in text. (It's an AND search.)
const tokens = text.toLowerCase().split(/\s+/);
for (const node of SelectBox.cache[id]) {
node.displayed = 1;
const node_text = node.text.toLowerCase();
for (const token of tokens) {
if (!node_text.includes(token)) {
node.displayed = 0;
break; // Once the first token isn't found we're done
}
}
}
SelectBox.redisplay(id);
},
get_hidden_node_count(id) {
const cache = SelectBox.cache[id] || [];
return cache.filter((node) => node.displayed === 0).length;
},
delete_from_cache: function (id, value) {
let delete_index = null;
const cache = SelectBox.cache[id];
for (const [i, node] of cache.entries()) {
if (node.value === value) {
delete_index = i;
break;
}
}
cache.splice(delete_index, 1);
},
add_to_cache: function (id, option) {
SelectBox.cache[id].push({
group: option.group,
value: option.value,
text: option.text,
displayed: 1,
});
},
cache_contains: function (id, value) {
// Check if an item is contained in the cache
for (const node of SelectBox.cache[id]) {
if (node.value === value) {
return true;
}
}
return false;
},
move: function (from, to) {
const from_box = document.getElementById(from);
for (const option of from_box.options) {
const option_value = option.value;
if (
option.selected &&
SelectBox.cache_contains(from, option_value)
) {
const group = getOptionGroupName(option);
SelectBox.add_to_cache(to, {
group,
value: option_value,
text: option.text,
displayed: 1,
});
SelectBox.delete_from_cache(from, option_value);
}
}
// Only sort if there are any groups (to preserve existing behavior for non-grouped selects)
if (SelectBox.cache[to].some((item) => item.group)) {
SelectBox.sort(to);
}
SelectBox.redisplay(from);
SelectBox.redisplay(to);
},
move_all: function (from, to) {
const from_box = document.getElementById(from);
for (const option of from_box.options) {
const option_value = option.value;
if (SelectBox.cache_contains(from, option_value)) {
const group = getOptionGroupName(option);
SelectBox.add_to_cache(to, {
group,
value: option_value,
text: option.text,
displayed: 1,
});
SelectBox.delete_from_cache(from, option_value);
}
}
// Only sort if there are any groups (to preserve existing behavior for non-grouped selects)
if (SelectBox.cache[to].some((item) => item.group)) {
SelectBox.sort(to);
}
SelectBox.redisplay(from);
SelectBox.redisplay(to);
},
sort: function (id) {
SelectBox.cache[id].sort(function (a, b) {
a =
((a.group && a.group.toLowerCase()) || "") +
a.text.toLowerCase();
b =
((b.group && b.group.toLowerCase()) || "") +
b.text.toLowerCase();
if (a > b) {
return 1;
}
if (a < b) {
return -1;
}
return 0;
});
},
select_all: function (id) {
const box = document.getElementById(id);
for (const option of box.options) {
option.selected = true;
}
},
};
window.SelectBox = SelectBox;
}