bf29018a60
* fix sort keys not clearing * ingredient searching * add dura and charges * modify comment * fix effectiveness formula) * remove comment
365 lines
15 KiB
JavaScript
365 lines
15 KiB
JavaScript
|
|
let types;
|
|
let search_tiers;
|
|
const filters = [], excludes = [];
|
|
let item_filters = [];
|
|
let filter_id_counter = 0;
|
|
|
|
let search_db;
|
|
let expr_parser;
|
|
|
|
function do_item_search() {
|
|
document.getElementById("summary").style.color = "red"; // to display errors, changed to white if search successful
|
|
window.scrollTo(0, 0);
|
|
let queries = [];
|
|
|
|
// name
|
|
if (document.getElementById("item-name-choice").value != "") {
|
|
queries.push("f:name?=\"" + document.getElementById("item-name-choice").value.trim() + "\"");
|
|
}
|
|
|
|
if (!filter_types_tiers(queries)) return;
|
|
|
|
|
|
// filters
|
|
for (const filter of filters) {
|
|
let min = parseInt(filter.min_elem.value);
|
|
let max = parseInt(filter.max_elem.value);
|
|
if (min > max) {
|
|
document.getElementById("summary").innerHTML = "Error: The minimum of filter " + filter.input_elem.value + " (" + min + ") is greater than its maximum (" + max + ")";
|
|
return;
|
|
}
|
|
let zero_in_min_max = (isNaN(min) || min < 0) && (isNaN(max) || max > 0);
|
|
|
|
let raw_name = filter.input_elem.value;
|
|
if (raw_name == "") {
|
|
continue; // empty
|
|
}
|
|
let filter_name = translate_mappings[raw_name];
|
|
if (filter_name === undefined) {
|
|
filter_name = special_mappings[raw_name];
|
|
if (filter_name === undefined) {
|
|
document.getElementById("summary").innerHTML = "Error: The filter \"" + filter.input_elem.value + "\" is not recognized";
|
|
return;
|
|
}
|
|
filter_name = "(" + filter_name + ")";
|
|
}
|
|
|
|
if (!isNaN(min)) {
|
|
queries.push("f:" + filter_name + ">=" + min);
|
|
}
|
|
if (!isNaN(max)) {
|
|
queries.push("f:" + filter_name + "<=" + max);
|
|
}
|
|
if (zero_in_min_max) {
|
|
queries.push("f:" + filter_name + "!=0");
|
|
}
|
|
queries.push("s:" + (filter.ascending ? "0-" : "") + filter_name);
|
|
}
|
|
|
|
// excludes
|
|
for (const exclude of excludes) {
|
|
let raw_name = exclude.input_elem.value;
|
|
if (raw_name == "") {
|
|
continue; // empty
|
|
}
|
|
let filter_name = translate_mappings[raw_name];
|
|
if (filter_name === undefined) {
|
|
filter_name = special_mappings[raw_name];
|
|
if (filter_name === undefined) {
|
|
document.getElementById("summary").innerHTML = "Error: The excluded filter \"" + exclude.input_elem.value + "\" is not recognized";
|
|
return;
|
|
}
|
|
filter_name = "(" + filter_name + ")";
|
|
}
|
|
queries.push("f:" + filter_name + "=0");
|
|
}
|
|
|
|
let filter_query = "true";
|
|
let sort_queries = [];
|
|
console.log(queries);
|
|
for (const query of queries) {
|
|
if (query.startsWith("s:")) {
|
|
sort_queries.push(query.slice(2));
|
|
}
|
|
else if (query.startsWith("f:")) {
|
|
filter_query = filter_query + "&" + query.slice(2);
|
|
}
|
|
}
|
|
document.getElementById("search-results").textContent = "";
|
|
let results = [];
|
|
try {
|
|
const filter_expr = expr_parser.parse(filter_query);
|
|
const sort_exprs = sort_queries.map(q => expr_parser.parse(q));
|
|
for (let i = 0; i < search_db.length; ++i) {
|
|
const item = search_db[i][0];
|
|
const itemExp = search_db[i][1];
|
|
if (checkBool(filter_expr.resolve(item, itemExp))) {
|
|
results.push({ item, itemExp, sortKeys: sort_exprs.map(e => e.resolve(item, itemExp)) });
|
|
}
|
|
}
|
|
results.sort((a, b) => {
|
|
return compareLexico(a.item, a.sortKeys, b.item, b.sortKeys);
|
|
});
|
|
} catch (e) {
|
|
document.getElementById("summary").textContent = e.message;
|
|
return;
|
|
}
|
|
document.getElementById("summary").textContent = results.length + " results:";
|
|
document.getElementById("summary").style.color = "white";
|
|
display(results);
|
|
}
|
|
|
|
|
|
function init_search() {
|
|
init_values();
|
|
|
|
// init type buttons
|
|
for (const type of Object.keys(types)) {
|
|
document.getElementById("type-" + type).addEventListener("click", function() {
|
|
types[type] = !types[type];
|
|
this.classList.toggle("type-selected");
|
|
});
|
|
}
|
|
document.getElementById("all-types").addEventListener("click", function() {
|
|
for (const type of Object.keys(types)) {
|
|
types[type] = true;
|
|
document.getElementById("type-" + type).classList.add("type-selected");
|
|
}
|
|
});
|
|
document.getElementById("none-types").addEventListener("click", function() {
|
|
for (const type of Object.keys(types)) {
|
|
types[type] = false;
|
|
document.getElementById("type-" + type).classList.remove("type-selected");
|
|
}
|
|
});
|
|
|
|
// init rarity buttons
|
|
for (const tier of Object.keys(search_tiers)) {
|
|
document.getElementById("tier-" + tier).addEventListener("click", function() {
|
|
search_tiers[tier] = !search_tiers[tier];
|
|
this.classList.toggle("tier-selected");
|
|
});
|
|
}
|
|
document.getElementById("all-tiers").addEventListener("click", function() {
|
|
for (const tier of Object.keys(search_tiers)) {
|
|
search_tiers[tier] = true;
|
|
document.getElementById("tier-" + tier).classList.add("tier-selected");
|
|
}
|
|
});
|
|
document.getElementById("none-tiers").addEventListener("click", function() {
|
|
for (const tier of Object.keys(search_tiers)) {
|
|
search_tiers[tier] = false;
|
|
document.getElementById("tier-" + tier).classList.remove("tier-selected");
|
|
}
|
|
});
|
|
|
|
// filters
|
|
document.getElementById("add-filter").addEventListener("click", create_filter);
|
|
document.getElementById("add-exclude").addEventListener("click", create_exclude);
|
|
create_filter();
|
|
filters[0].input_elem.value = "Combat Level";
|
|
init_filter_drag();
|
|
}
|
|
|
|
function reset_item_search() {
|
|
document.getElementById("item-name-choice").value = "";
|
|
document.getElementById("all-types").click();
|
|
document.getElementById("all-tiers").click();
|
|
}
|
|
|
|
function create_filter() {
|
|
let data = {ascending: false};
|
|
|
|
let row = make_elem("div", ["row", "filter-row"], {});
|
|
let col = make_elem("div", ["col"], {});
|
|
row.appendChild(col);
|
|
data.div = row;
|
|
|
|
let reorder_img = make_elem("img", ["reorder-filter"], {src: "../media/icons/3-lines.svg", draggable: "true"});
|
|
col.appendChild(reorder_img);
|
|
|
|
let filter_input = make_elem("input",
|
|
["col", "border-dark", "text-light", "dark-5", "rounded", "scaled-font", "form-control", "form-control-sm", "filter-input"],
|
|
{id: "filter-input-" + filter_id_counter, type: "text", placeholder: "Filter"}
|
|
);
|
|
filter_id_counter++;
|
|
col.appendChild(filter_input);
|
|
data.input_elem = filter_input;
|
|
|
|
let asc_desc = make_elem("div", [], {style: "cursor: pointer; display: inline-block;"});
|
|
asc_desc.appendChild(make_elem("img", ["desc-icon", "asc-sel"], {src: "../media/icons/triangle.svg"}));
|
|
asc_desc.appendChild(make_elem("img", ["asc-icon"], {src: "../media/icons/triangle.svg"}));
|
|
asc_desc.addEventListener("click", function() {
|
|
data.ascending = !data.ascending;
|
|
asc_desc.children[0].classList.toggle("asc-sel");
|
|
asc_desc.children[1].classList.toggle("asc-sel");
|
|
});
|
|
col.appendChild(asc_desc);
|
|
|
|
let min = make_elem("input",
|
|
["col", "border-dark", "text-light", "dark-5", "rounded", "scaled-font", "form-control", "form-control-sm", "min-max-input"],
|
|
{type: "number", placeholder: "-\u221E"}
|
|
);
|
|
col.appendChild(min);
|
|
data.min_elem = min;
|
|
|
|
let to = make_elem("span", [], {innerHTML: " to "});
|
|
col.appendChild(to);
|
|
|
|
let max = make_elem("input",
|
|
["col", "border-dark", "text-light", "dark-5", "rounded", "scaled-font", "form-control", "form-control-sm", "min-max-input"],
|
|
{type: "number", placeholder: "\u221E"}
|
|
);
|
|
col.appendChild(max);
|
|
data.max_elem = max;
|
|
|
|
let trash = make_elem("img", ["delete-filter"], {src: "../media/icons/trash.svg"});
|
|
trash.addEventListener("click", function() {
|
|
filters.splice(Array.from(row.parentElement.children).indexOf(row) - 1, 1);
|
|
row.remove();
|
|
});
|
|
col.appendChild(trash);
|
|
|
|
document.getElementById("filter-container").insertBefore(row, document.getElementById("add-filter").parentElement);
|
|
filters.push(data);
|
|
init_filter_dropdown(data);
|
|
}
|
|
|
|
let currently_dragging = null;
|
|
function init_filter_drag() {
|
|
let container = document.getElementById("filter-container");
|
|
|
|
container.addEventListener("dragstart", function(e) {
|
|
if (e.path[0].classList.contains("reorder-filter")) {
|
|
currently_dragging = filters[Array.from(e.path[3].children).indexOf(e.path[2]) - 1];
|
|
} else {
|
|
e.preventDefault();
|
|
}
|
|
});
|
|
|
|
container.addEventListener("dragenter", function(e) {
|
|
e.preventDefault();
|
|
});
|
|
|
|
container.addEventListener("dragleave", function(e) {
|
|
e.preventDefault();
|
|
});
|
|
|
|
container.addEventListener("dragend", function(e) {
|
|
e.preventDefault();
|
|
for (const el of document.getElementsByClassName("filter-dragged-over")) {
|
|
el.classList.remove("filter-dragged-over");
|
|
}
|
|
currently_dragging = null;
|
|
});
|
|
|
|
container.addEventListener("dragover", function(e) {
|
|
e.preventDefault();
|
|
for (const el of document.getElementsByClassName("filter-dragged-over")) {
|
|
el.classList.remove("filter-dragged-over");
|
|
}
|
|
if (!e.path.includes(currently_dragging.div)) {
|
|
for (let i = 0; i < e.path.length; i++) {
|
|
if (e.path[i].classList.contains("filter-row")) {
|
|
e.path[i].classList.add("filter-dragged-over");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
container.addEventListener("drop", function(e) {
|
|
e.preventDefault();
|
|
for (const el of document.getElementsByClassName("filter-dragged-over")) {
|
|
el.classList.remove("filter-dragged-over");
|
|
}
|
|
if (!e.path.includes(currently_dragging.div)) {
|
|
for (let i = 0; i < e.path.length; i++) {
|
|
if (e.path[i].classList.contains("filter-row")) {
|
|
let old_index = filters.indexOf(currently_dragging);
|
|
let new_index = Array.from(e.path[i + 1].children).indexOf(e.path[i]) - 1;
|
|
filters.splice(old_index, 1);
|
|
filters.splice(new_index, 0, currently_dragging);
|
|
currently_dragging.div.remove();
|
|
container.insertBefore(currently_dragging.div, container.children[new_index + 1]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
currently_dragging = null;
|
|
});
|
|
}
|
|
|
|
function create_exclude() {
|
|
let data = {};
|
|
|
|
let row = make_elem("div", ["row", "filter-row"], {});
|
|
let col = make_elem("div", ["col"], {});
|
|
row.appendChild(col);
|
|
data.div = row;
|
|
|
|
let filter_input = make_elem("input",
|
|
["col", "border-dark", "text-light", "dark-5", "rounded", "scaled-font", "form-control", "form-control-sm", "filter-input"],
|
|
{id: "filter-input-" + filter_id_counter, type: "text", placeholder: "Excluded Filter"}
|
|
);
|
|
filter_id_counter++;
|
|
col.appendChild(filter_input);
|
|
data.input_elem = filter_input;
|
|
|
|
let trash = make_elem("img", ["delete-filter"], {src: "../media/icons/trash.svg"});
|
|
trash.addEventListener("click", function() {
|
|
excludes.splice(Array.from(row.parentElement.children).indexOf(row) - 1, 1);
|
|
row.remove();
|
|
});
|
|
col.appendChild(trash);
|
|
|
|
document.getElementById("exclude-container").insertBefore(row, document.getElementById("add-exclude").parentElement);
|
|
excludes.push(data);
|
|
init_filter_dropdown(data);
|
|
}
|
|
|
|
function init_filter_dropdown(filter) {
|
|
let field_choice = filter.input_elem;
|
|
field_choice.onclick = function() {field_choice.dispatchEvent(new Event('input', {bubbles:true}));};
|
|
filter.autoComplete = new autoComplete({
|
|
data: {
|
|
src: item_filters,
|
|
},
|
|
threshold: 0,
|
|
selector: "#" + field_choice.id,
|
|
wrapper: false,
|
|
resultsList: {
|
|
maxResults: 100,
|
|
tabSelect: true,
|
|
noResults: true,
|
|
class: "search-box dark-7 rounded-bottom px-2 fw-bold dark-shadow-sm",
|
|
element: (list, data) => {
|
|
let position = field_choice.getBoundingClientRect();
|
|
list.style.top = position.bottom + window.scrollY +"px";
|
|
list.style.left = position.x+"px";
|
|
list.style.width = position.width+"px";
|
|
list.style.maxHeight = position.height * 4 +"px";
|
|
if (!data.results.length) {
|
|
const message = make_elem('li', ['scaled-font'], {textContent: "No results found!"});
|
|
list.prepend(message);
|
|
};
|
|
},
|
|
},
|
|
resultItem: {
|
|
class: "scaled-font search-item",
|
|
selected: "dark-5",
|
|
},
|
|
events: {
|
|
input: {
|
|
selection: (event) => {
|
|
if (event.detail.selection.value) {
|
|
event.target.value = event.detail.selection.value;
|
|
};
|
|
},
|
|
},
|
|
}
|
|
});
|
|
}
|
|
|
|
|