mirror of
https://github.com/badlogic/heissepreise.git
synced 2024-06-30 20:35:50 +02:00
Implement sorts in items-list, fix items-filter filtering.
This commit is contained in:
parent
5964cc5de2
commit
1bb276addb
|
@ -1,5 +1,5 @@
|
||||||
<div class="flex justify-center gap-4 py-2 font-bold text-primary border border-primary/50 lg:rounded-b-xl">
|
<div class="flex justify-center gap-4 py-2 font-bold text-primary border border-primary/50 lg:rounded-b-xl">
|
||||||
<a href="index.html">Suche</a>
|
<a href="index.html">Suche</a>
|
||||||
<a href="changes.html">Preisänderungen</a>
|
<a href="changes.html">Preisänderungen</a>
|
||||||
<a href="carts.html">Warenkorb</a>
|
<a href="carts.html">Warenkörbe</a>
|
||||||
</div>
|
</div>
|
|
@ -5,6 +5,7 @@ require("./views");
|
||||||
await model.load();
|
await model.load();
|
||||||
const itemsFilter = document.querySelector("items-filter");
|
const itemsFilter = document.querySelector("items-filter");
|
||||||
const itemsList = document.querySelector("items-list");
|
const itemsList = document.querySelector("items-list");
|
||||||
|
itemsList.elements.sort.value = "chain-and-name";
|
||||||
itemsFilter.model = itemsList.model = model.items;
|
itemsFilter.model = itemsList.model = model.items;
|
||||||
itemsFilter.filter();
|
itemsFilter.filter();
|
||||||
})();
|
})();
|
||||||
|
|
156
site/knn.js
Normal file
156
site/knn.js
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
const { stem, stopWords } = require("./stem");
|
||||||
|
|
||||||
|
function dotProduct(vector1, vector2) {
|
||||||
|
let product = 0;
|
||||||
|
for (const key in vector1) {
|
||||||
|
if (vector2.hasOwnProperty(key)) {
|
||||||
|
product += vector1[key] * vector2[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
exports.dotProduct = dotProduct;
|
||||||
|
|
||||||
|
function addVector(vector1, vector2) {
|
||||||
|
for (const key in vector2) {
|
||||||
|
vector1[key] = (vector1[key] || 0) + vector2[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.addVector = addVector;
|
||||||
|
|
||||||
|
function scaleVector(vector, scalar) {
|
||||||
|
for (const key in vector) {
|
||||||
|
vector[key] *= scalar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.scaleVector = scaleVector;
|
||||||
|
|
||||||
|
function normalizeVector(vector) {
|
||||||
|
const len = magnitude(vector);
|
||||||
|
for (const key in vector) {
|
||||||
|
vector[key] /= len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.normalizeVector = normalizeVector;
|
||||||
|
|
||||||
|
function magnitude(vector) {
|
||||||
|
let sumOfSquares = 0;
|
||||||
|
for (const key in vector) {
|
||||||
|
sumOfSquares += vector[key] ** 2;
|
||||||
|
}
|
||||||
|
return Math.sqrt(sumOfSquares);
|
||||||
|
}
|
||||||
|
exports.magnitude = magnitude;
|
||||||
|
|
||||||
|
function findMostSimilarItem(refItem, items) {
|
||||||
|
let maxSimilarity = -1;
|
||||||
|
let similarItem = null;
|
||||||
|
let similarItemIdx = -1;
|
||||||
|
items.forEach((item, idx) => {
|
||||||
|
let similarity = dotProduct(refItem.vector, item.vector);
|
||||||
|
if (similarity > maxSimilarity) {
|
||||||
|
maxSimilarity = similarity;
|
||||||
|
similarItem = item;
|
||||||
|
similarItemIdx = idx;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
similarity: maxSimilarity,
|
||||||
|
item: similarItem,
|
||||||
|
index: similarItemIdx,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
exports.findMostSimilarItem = findMostSimilarItem;
|
||||||
|
|
||||||
|
function findMostSimilarItems(refItem, items, k = 5, accept = (ref, item) => true) {
|
||||||
|
let topSimilarItems = [];
|
||||||
|
let topSimilarities = [];
|
||||||
|
|
||||||
|
items.forEach((item, idx) => {
|
||||||
|
if (!accept(refItem, item)) return;
|
||||||
|
let similarity = dotProduct(refItem.vector, item.vector);
|
||||||
|
|
||||||
|
if (topSimilarItems.length < k) {
|
||||||
|
topSimilarItems.push(item);
|
||||||
|
topSimilarities.push(similarity);
|
||||||
|
} else {
|
||||||
|
let minSimilarity = Math.min(...topSimilarities);
|
||||||
|
let minIndex = topSimilarities.indexOf(minSimilarity);
|
||||||
|
|
||||||
|
if (similarity > minSimilarity) {
|
||||||
|
topSimilarItems[minIndex] = item;
|
||||||
|
topSimilarities[minIndex] = similarity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let similarItemsWithIndices = topSimilarItems.map((item, index) => {
|
||||||
|
return {
|
||||||
|
similarity: topSimilarities[index],
|
||||||
|
item: item,
|
||||||
|
index: items.indexOf(item),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return similarItemsWithIndices;
|
||||||
|
}
|
||||||
|
exports.findMostSimilarItems = findMostSimilarItems;
|
||||||
|
|
||||||
|
function similaritySortItems(items) {
|
||||||
|
if (items.length == 0) return items;
|
||||||
|
sortedItems = [items.shift()];
|
||||||
|
let refItem = sortedItems[0];
|
||||||
|
while (items.length > 0) {
|
||||||
|
const similarItem = findMostSimilarItem(refItem, items);
|
||||||
|
sortedItems.push(similarItem.item);
|
||||||
|
items.splice(similarItem.index, 1);
|
||||||
|
refItem = similarItem.item;
|
||||||
|
}
|
||||||
|
return sortedItems;
|
||||||
|
}
|
||||||
|
exports.similaritySortItems = similaritySortItems;
|
||||||
|
|
||||||
|
const NGRAM = 4;
|
||||||
|
function vectorizeTokens(tokens) {
|
||||||
|
const vector = {};
|
||||||
|
for (token of tokens) {
|
||||||
|
if (token.length > NGRAM) {
|
||||||
|
for (let i = 0; i < token.length - NGRAM; i++) {
|
||||||
|
let trigram = token.substring(i, i + NGRAM);
|
||||||
|
vector[trigram] = (vector[trigram] || 0) + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vector[token] = (vector[token] || 0) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
normalizeVector(vector);
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
exports.vectorizeTokens = vectorizeTokens;
|
||||||
|
|
||||||
|
function vectorizeItem(item, useUnit = true, useStem = true) {
|
||||||
|
const isNumber = /^\d+\.\d+$/;
|
||||||
|
let name = item.name
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^\w\s]|_/g, "")
|
||||||
|
.replace("-", " ")
|
||||||
|
.replace(",", " ");
|
||||||
|
item.tokens = name
|
||||||
|
.split(/\s+/)
|
||||||
|
.filter((token) => !stopWords.includes(token))
|
||||||
|
.filter((token) => !isNumber.test(token))
|
||||||
|
.map((token) => (useStem ? stem(token) : token));
|
||||||
|
if (useUnit) {
|
||||||
|
if (item.quantity) item.tokens.push("" + item.quantity);
|
||||||
|
if (item.unit) item.tokens.push(item.unit);
|
||||||
|
}
|
||||||
|
item.vector = vectorizeTokens(item.tokens);
|
||||||
|
}
|
||||||
|
exports.vectorizeItem = vectorizeItem;
|
||||||
|
|
||||||
|
function vectorizeItems(items, useUnit = true) {
|
||||||
|
items.forEach((item) => {
|
||||||
|
if (!item.vector) vectorizeItem(item, useUnit);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.vectorizeItems = vectorizeItems;
|
|
@ -53,6 +53,10 @@ if (typeof window !== "undefined") {
|
||||||
setupLiveEdit();
|
setupLiveEdit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.isMobile = () => {
|
||||||
|
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
||||||
|
};
|
||||||
|
|
||||||
exports.today = () => {
|
exports.today = () => {
|
||||||
const currentDate = new Date();
|
const currentDate = new Date();
|
||||||
const year = currentDate.getFullYear();
|
const year = currentDate.getFullYear();
|
||||||
|
|
952
site/stem.js
Normal file
952
site/stem.js
Normal file
|
@ -0,0 +1,952 @@
|
||||||
|
/* by Joder Illi, Snowball mailing list */
|
||||||
|
function stem(word) {
|
||||||
|
/*
|
||||||
|
Put u and y between vowels into upper case
|
||||||
|
*/
|
||||||
|
word = word.replace(/([aeiouyäöü])u([aeiouyäöü])/g, "$1U$2");
|
||||||
|
word = word.replace(/([aeiouyäöü])y([aeiouyäöü])/g, "$1Y$2");
|
||||||
|
|
||||||
|
/*
|
||||||
|
and then do the following mappings,
|
||||||
|
(a) replace ß with ss,
|
||||||
|
(a) replace ae with ä, Not doing these,
|
||||||
|
have trouble with diphtongs
|
||||||
|
(a) replace oe with ö, Not doing these,
|
||||||
|
have trouble with diphtongs
|
||||||
|
(a) replace ue with ü unless preceded by q. Not doing these,
|
||||||
|
have trouble with diphtongs
|
||||||
|
So in quelle, ue is not mapped to ü because it follows q, and in
|
||||||
|
feuer it is not mapped because the first part of the rule changes it to
|
||||||
|
feUer, so the u is not found.
|
||||||
|
*/
|
||||||
|
word = word.replace(/ß/g, "ss");
|
||||||
|
//word = word.replace(/ae/g, 'ä');
|
||||||
|
//word = word.replace(/oe/g, 'ö');
|
||||||
|
//word = word.replace(/([^q])ue/g, '$1ü');
|
||||||
|
|
||||||
|
/*
|
||||||
|
R1 and R2 are first set up in the standard way (see the note on R1
|
||||||
|
and R2), but then R1 is adjusted so that the region before it contains at
|
||||||
|
least 3 letters.
|
||||||
|
R1 is the region after the first non-vowel following a vowel, or is
|
||||||
|
the null region at the end of the word if there is no such non-vowel.
|
||||||
|
R2 is the region after the first non-vowel following a vowel in R1,
|
||||||
|
or is the null region at the end of the word if there is no such non-vowel.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var r1Index = word.search(/[aeiouyäöü][^aeiouyäöü]/);
|
||||||
|
var r1 = "";
|
||||||
|
if (r1Index != -1) {
|
||||||
|
r1Index += 2;
|
||||||
|
r1 = word.substring(r1Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
var r2Index = -1;
|
||||||
|
var r2 = "";
|
||||||
|
|
||||||
|
if (r1Index != -1) {
|
||||||
|
var r2Index = r1.search(/[aeiouyäöü][^aeiouyäöü]/);
|
||||||
|
if (r2Index != -1) {
|
||||||
|
r2Index += 2;
|
||||||
|
r2 = r1.substring(r2Index);
|
||||||
|
r2Index += r1Index;
|
||||||
|
} else {
|
||||||
|
r2 = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r1Index != -1 && r1Index < 3) {
|
||||||
|
r1Index = 3;
|
||||||
|
r1 = word.substring(r1Index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Define a valid s-ending as one of b, d, f, g, h, k, l, m, n, r or t.
|
||||||
|
Define a valid st-ending as the same list, excluding letter r.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Do each of steps 1, 2 and 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Step 1:
|
||||||
|
Search for the longest among the following suffixes,
|
||||||
|
(a) em ern er
|
||||||
|
(b) e en es
|
||||||
|
(c) s (preceded by a valid s-ending)
|
||||||
|
*/
|
||||||
|
var a1Index = word.search(/(em|ern|er)$/g);
|
||||||
|
var b1Index = word.search(/(e|en|es)$/g);
|
||||||
|
var c1Index = word.search(/([bdfghklmnrt]s)$/g);
|
||||||
|
if (c1Index != -1) {
|
||||||
|
c1Index++;
|
||||||
|
}
|
||||||
|
var index1 = 10000;
|
||||||
|
var optionUsed1 = "";
|
||||||
|
if (a1Index != -1 && a1Index < index1) {
|
||||||
|
optionUsed1 = "a";
|
||||||
|
index1 = a1Index;
|
||||||
|
}
|
||||||
|
if (b1Index != -1 && b1Index < index1) {
|
||||||
|
optionUsed1 = "b";
|
||||||
|
index1 = b1Index;
|
||||||
|
}
|
||||||
|
if (c1Index != -1 && c1Index < index1) {
|
||||||
|
optionUsed1 = "c";
|
||||||
|
index1 = c1Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
and delete if in R1. (Of course the letter of the valid s-ending is
|
||||||
|
not necessarily in R1.) If an ending of group (b) is deleted, and the ending
|
||||||
|
is preceded by niss, delete the final s.
|
||||||
|
(For example, äckern -> äck, ackers -> acker, armes -> arm,
|
||||||
|
bedürfnissen -> bedürfnis)
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (index1 != 10000 && r1Index != -1) {
|
||||||
|
if (index1 >= r1Index) {
|
||||||
|
word = word.substring(0, index1);
|
||||||
|
if (optionUsed1 == "b") {
|
||||||
|
if (word.search(/niss$/) != -1) {
|
||||||
|
word = word.substring(0, word.length - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Step 2:
|
||||||
|
Search for the longest among the following suffixes,
|
||||||
|
(a) en er est
|
||||||
|
(b) st (preceded by a valid st-ending, itself preceded by at least 3
|
||||||
|
letters)
|
||||||
|
*/
|
||||||
|
|
||||||
|
var a2Index = word.search(/(en|er|est)$/g);
|
||||||
|
var b2Index = word.search(/(.{3}[bdfghklmnt]st)$/g);
|
||||||
|
if (b2Index != -1) {
|
||||||
|
b2Index += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
var index2 = 10000;
|
||||||
|
var optionUsed2 = "";
|
||||||
|
if (a2Index != -1 && a2Index < index2) {
|
||||||
|
optionUsed2 = "a";
|
||||||
|
index2 = a2Index;
|
||||||
|
}
|
||||||
|
if (b2Index != -1 && b2Index < index2) {
|
||||||
|
optionUsed2 = "b";
|
||||||
|
index2 = b2Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
and delete if in R1.
|
||||||
|
(For example, derbsten -> derbst by step 1, and derbst -> derb by
|
||||||
|
step 2, since b is a valid st-ending, and is preceded by just 3 letters)
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (index2 != 10000 && r1Index != -1) {
|
||||||
|
if (index2 >= r1Index) {
|
||||||
|
word = word.substring(0, index2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Step 3: d-suffixes (*)
|
||||||
|
Search for the longest among the following suffixes, and perform the
|
||||||
|
action indicated.
|
||||||
|
end ung
|
||||||
|
delete if in R2
|
||||||
|
if preceded by ig, delete if in R2 and not preceded by e
|
||||||
|
ig ik isch
|
||||||
|
delete if in R2 and not preceded by e
|
||||||
|
lich heit
|
||||||
|
delete if in R2
|
||||||
|
if preceded by er or en, delete if in R1
|
||||||
|
keit
|
||||||
|
delete if in R2
|
||||||
|
if preceded by lich or ig, delete if in R2
|
||||||
|
*/
|
||||||
|
|
||||||
|
var a3Index = word.search(/(end|ung)$/g);
|
||||||
|
var b3Index = word.search(/[^e](ig|ik|isch)$/g);
|
||||||
|
var c3Index = word.search(/(lich|heit)$/g);
|
||||||
|
var d3Index = word.search(/(keit)$/g);
|
||||||
|
if (b3Index != -1) {
|
||||||
|
b3Index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
var index3 = 10000;
|
||||||
|
var optionUsed3 = "";
|
||||||
|
if (a3Index != -1 && a3Index < index3) {
|
||||||
|
optionUsed3 = "a";
|
||||||
|
index3 = a3Index;
|
||||||
|
}
|
||||||
|
if (b3Index != -1 && b3Index < index3) {
|
||||||
|
optionUsed3 = "b";
|
||||||
|
index3 = b3Index;
|
||||||
|
}
|
||||||
|
if (c3Index != -1 && c3Index < index3) {
|
||||||
|
optionUsed3 = "c";
|
||||||
|
index3 = c3Index;
|
||||||
|
}
|
||||||
|
if (d3Index != -1 && d3Index < index3) {
|
||||||
|
optionUsed3 = "d";
|
||||||
|
index3 = d3Index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index3 != 10000 && r2Index != -1) {
|
||||||
|
if (index3 >= r2Index) {
|
||||||
|
word = word.substring(0, index3);
|
||||||
|
var optionIndex = -1;
|
||||||
|
var optionSubsrt = "";
|
||||||
|
if (optionUsed3 == "a") {
|
||||||
|
optionIndex = word.search(/[^e](ig)$/);
|
||||||
|
if (optionIndex != -1) {
|
||||||
|
optionIndex++;
|
||||||
|
if (optionIndex >= r2Index) {
|
||||||
|
word = word.substring(0, optionIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (optionUsed3 == "c") {
|
||||||
|
optionIndex = word.search(/(er|en)$/);
|
||||||
|
if (optionIndex != -1) {
|
||||||
|
if (optionIndex >= r1Index) {
|
||||||
|
word = word.substring(0, optionIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (optionUsed3 == "d") {
|
||||||
|
optionIndex = word.search(/(lich|ig)$/);
|
||||||
|
if (optionIndex != -1) {
|
||||||
|
if (optionIndex >= r2Index) {
|
||||||
|
word = word.substring(0, optionIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Finally,
|
||||||
|
turn U and Y back into lower case, and remove the umlaut accent from
|
||||||
|
a, o and u.
|
||||||
|
*/
|
||||||
|
word = word.replace(/U/g, "u");
|
||||||
|
word = word.replace(/Y/g, "y");
|
||||||
|
word = word.replace(/ä/g, "a");
|
||||||
|
word = word.replace(/ö/g, "o");
|
||||||
|
word = word.replace(/ü/g, "u");
|
||||||
|
|
||||||
|
return word;
|
||||||
|
}
|
||||||
|
exports.stem = stem;
|
||||||
|
|
||||||
|
exports.stopWords = [
|
||||||
|
"ab",
|
||||||
|
"aber",
|
||||||
|
"alle",
|
||||||
|
"allein",
|
||||||
|
"allem",
|
||||||
|
"allen",
|
||||||
|
"aller",
|
||||||
|
"allerdings",
|
||||||
|
"allerlei",
|
||||||
|
"alles",
|
||||||
|
"allmählich",
|
||||||
|
"allzu",
|
||||||
|
"als",
|
||||||
|
"alsbald",
|
||||||
|
"also",
|
||||||
|
"am",
|
||||||
|
"an",
|
||||||
|
"and",
|
||||||
|
"ander",
|
||||||
|
"andere",
|
||||||
|
"anderem",
|
||||||
|
"anderen",
|
||||||
|
"anderer",
|
||||||
|
"andererseits",
|
||||||
|
"anderes",
|
||||||
|
"anderm",
|
||||||
|
"andern",
|
||||||
|
"andernfalls",
|
||||||
|
"anders",
|
||||||
|
"anstatt",
|
||||||
|
"auch",
|
||||||
|
"auf",
|
||||||
|
"aus",
|
||||||
|
"ausgenommen",
|
||||||
|
"ausser",
|
||||||
|
"ausserdem",
|
||||||
|
"außer",
|
||||||
|
"außerdem",
|
||||||
|
"außerhalb",
|
||||||
|
"bald",
|
||||||
|
"bei",
|
||||||
|
"beide",
|
||||||
|
"beiden",
|
||||||
|
"beiderlei",
|
||||||
|
"beides",
|
||||||
|
"beim",
|
||||||
|
"beinahe",
|
||||||
|
"bereits",
|
||||||
|
"besonders",
|
||||||
|
"besser",
|
||||||
|
"beträchtlich",
|
||||||
|
"bevor",
|
||||||
|
"bezüglich",
|
||||||
|
"bin",
|
||||||
|
"bis",
|
||||||
|
"bisher",
|
||||||
|
"bislang",
|
||||||
|
"bist",
|
||||||
|
"bloß",
|
||||||
|
"bsp.",
|
||||||
|
"bzw",
|
||||||
|
"ca",
|
||||||
|
"ca.",
|
||||||
|
"content",
|
||||||
|
"da",
|
||||||
|
"dabei",
|
||||||
|
"dadurch",
|
||||||
|
"dafür",
|
||||||
|
"dagegen",
|
||||||
|
"daher",
|
||||||
|
"dahin",
|
||||||
|
"damals",
|
||||||
|
"damit",
|
||||||
|
"danach",
|
||||||
|
"daneben",
|
||||||
|
"dann",
|
||||||
|
"daran",
|
||||||
|
"darauf",
|
||||||
|
"daraus",
|
||||||
|
"darin",
|
||||||
|
"darum",
|
||||||
|
"darunter",
|
||||||
|
"darüber",
|
||||||
|
"darüberhinaus",
|
||||||
|
"das",
|
||||||
|
"dass",
|
||||||
|
"dasselbe",
|
||||||
|
"davon",
|
||||||
|
"davor",
|
||||||
|
"dazu",
|
||||||
|
"daß",
|
||||||
|
"dein",
|
||||||
|
"deine",
|
||||||
|
"deinem",
|
||||||
|
"deinen",
|
||||||
|
"deiner",
|
||||||
|
"deines",
|
||||||
|
"dem",
|
||||||
|
"demnach",
|
||||||
|
"demselben",
|
||||||
|
"den",
|
||||||
|
"denen",
|
||||||
|
"denn",
|
||||||
|
"dennoch",
|
||||||
|
"denselben",
|
||||||
|
"der",
|
||||||
|
"derart",
|
||||||
|
"derartig",
|
||||||
|
"derem",
|
||||||
|
"deren",
|
||||||
|
"derer",
|
||||||
|
"derjenige",
|
||||||
|
"derjenigen",
|
||||||
|
"derselbe",
|
||||||
|
"derselben",
|
||||||
|
"derzeit",
|
||||||
|
"des",
|
||||||
|
"deshalb",
|
||||||
|
"desselben",
|
||||||
|
"dessen",
|
||||||
|
"desto",
|
||||||
|
"deswegen",
|
||||||
|
"dich",
|
||||||
|
"die",
|
||||||
|
"diejenige",
|
||||||
|
"dies",
|
||||||
|
"diese",
|
||||||
|
"dieselbe",
|
||||||
|
"dieselben",
|
||||||
|
"diesem",
|
||||||
|
"diesen",
|
||||||
|
"dieser",
|
||||||
|
"dieses",
|
||||||
|
"diesseits",
|
||||||
|
"dir",
|
||||||
|
"direkt",
|
||||||
|
"direkte",
|
||||||
|
"direkten",
|
||||||
|
"direkter",
|
||||||
|
"doch",
|
||||||
|
"dort",
|
||||||
|
"dorther",
|
||||||
|
"dorthin",
|
||||||
|
"drauf",
|
||||||
|
"drin",
|
||||||
|
"drunter",
|
||||||
|
"drüber",
|
||||||
|
"du",
|
||||||
|
"dunklen",
|
||||||
|
"durch",
|
||||||
|
"durchaus",
|
||||||
|
"eben",
|
||||||
|
"ebenfalls",
|
||||||
|
"ebenso",
|
||||||
|
"eher",
|
||||||
|
"eigenen",
|
||||||
|
"eigenes",
|
||||||
|
"eigentlich",
|
||||||
|
"ein",
|
||||||
|
"eine",
|
||||||
|
"einem",
|
||||||
|
"einen",
|
||||||
|
"einer",
|
||||||
|
"einerseits",
|
||||||
|
"eines",
|
||||||
|
"einfach",
|
||||||
|
"einführen",
|
||||||
|
"einführte",
|
||||||
|
"einführten",
|
||||||
|
"eingesetzt",
|
||||||
|
"einig",
|
||||||
|
"einige",
|
||||||
|
"einigem",
|
||||||
|
"einigen",
|
||||||
|
"einiger",
|
||||||
|
"einigermaßen",
|
||||||
|
"einiges",
|
||||||
|
"einmal",
|
||||||
|
"eins",
|
||||||
|
"einseitig",
|
||||||
|
"einseitige",
|
||||||
|
"einseitigen",
|
||||||
|
"einseitiger",
|
||||||
|
"einst",
|
||||||
|
"einstmals",
|
||||||
|
"einzig",
|
||||||
|
"entsprechend",
|
||||||
|
"entweder",
|
||||||
|
"er",
|
||||||
|
"erst",
|
||||||
|
"es",
|
||||||
|
"etc",
|
||||||
|
"etliche",
|
||||||
|
"etwa",
|
||||||
|
"etwas",
|
||||||
|
"euch",
|
||||||
|
"euer",
|
||||||
|
"eure",
|
||||||
|
"eurem",
|
||||||
|
"euren",
|
||||||
|
"eurer",
|
||||||
|
"eures",
|
||||||
|
"falls",
|
||||||
|
"fast",
|
||||||
|
"ferner",
|
||||||
|
"folgende",
|
||||||
|
"folgenden",
|
||||||
|
"folgender",
|
||||||
|
"folgendes",
|
||||||
|
"folglich",
|
||||||
|
"fuer",
|
||||||
|
"für",
|
||||||
|
"gab",
|
||||||
|
"ganze",
|
||||||
|
"ganzem",
|
||||||
|
"ganzen",
|
||||||
|
"ganzer",
|
||||||
|
"ganzes",
|
||||||
|
"gar",
|
||||||
|
"gegen",
|
||||||
|
"gemäss",
|
||||||
|
"ggf",
|
||||||
|
"gleich",
|
||||||
|
"gleichwohl",
|
||||||
|
"gleichzeitig",
|
||||||
|
"glücklicherweise",
|
||||||
|
"gänzlich",
|
||||||
|
"hab",
|
||||||
|
"habe",
|
||||||
|
"haben",
|
||||||
|
"haette",
|
||||||
|
"hast",
|
||||||
|
"hat",
|
||||||
|
"hatte",
|
||||||
|
"hatten",
|
||||||
|
"hattest",
|
||||||
|
"hattet",
|
||||||
|
"heraus",
|
||||||
|
"herein",
|
||||||
|
"hier",
|
||||||
|
"hier",
|
||||||
|
"hinter",
|
||||||
|
"hiermit",
|
||||||
|
"hiesige",
|
||||||
|
"hin",
|
||||||
|
"hinein",
|
||||||
|
"hinten",
|
||||||
|
"hinter",
|
||||||
|
"hinterher",
|
||||||
|
"http",
|
||||||
|
"hätt",
|
||||||
|
"hätte",
|
||||||
|
"hätten",
|
||||||
|
"höchstens",
|
||||||
|
"ich",
|
||||||
|
"igitt",
|
||||||
|
"ihm",
|
||||||
|
"ihn",
|
||||||
|
"ihnen",
|
||||||
|
"ihr",
|
||||||
|
"ihre",
|
||||||
|
"ihrem",
|
||||||
|
"ihren",
|
||||||
|
"ihrer",
|
||||||
|
"ihres",
|
||||||
|
"im",
|
||||||
|
"immer",
|
||||||
|
"immerhin",
|
||||||
|
"in",
|
||||||
|
"indem",
|
||||||
|
"indessen",
|
||||||
|
"infolge",
|
||||||
|
"innen",
|
||||||
|
"innerhalb",
|
||||||
|
"ins",
|
||||||
|
"insofern",
|
||||||
|
"inzwischen",
|
||||||
|
"irgend",
|
||||||
|
"irgendeine",
|
||||||
|
"irgendwas",
|
||||||
|
"irgendwen",
|
||||||
|
"irgendwer",
|
||||||
|
"irgendwie",
|
||||||
|
"irgendwo",
|
||||||
|
"ist",
|
||||||
|
"ja",
|
||||||
|
"je",
|
||||||
|
"jed",
|
||||||
|
"jede",
|
||||||
|
"jedem",
|
||||||
|
"jeden",
|
||||||
|
"jedenfalls",
|
||||||
|
"jeder",
|
||||||
|
"jederlei",
|
||||||
|
"jedes",
|
||||||
|
"jedoch",
|
||||||
|
"jemand",
|
||||||
|
"jene",
|
||||||
|
"jenem",
|
||||||
|
"jenen",
|
||||||
|
"jener",
|
||||||
|
"jenes",
|
||||||
|
"jenseits",
|
||||||
|
"jetzt",
|
||||||
|
"jährig",
|
||||||
|
"jährige",
|
||||||
|
"jährigen",
|
||||||
|
"jähriges",
|
||||||
|
"kam",
|
||||||
|
"kann",
|
||||||
|
"kannst",
|
||||||
|
"kaum",
|
||||||
|
"kein",
|
||||||
|
"keine",
|
||||||
|
"keinem",
|
||||||
|
"keinen",
|
||||||
|
"keiner",
|
||||||
|
"keinerlei",
|
||||||
|
"keines",
|
||||||
|
"keineswegs",
|
||||||
|
"klar",
|
||||||
|
"klare",
|
||||||
|
"klaren",
|
||||||
|
"klares",
|
||||||
|
"klein",
|
||||||
|
"kleinen",
|
||||||
|
"kleiner",
|
||||||
|
"kleines",
|
||||||
|
"koennen",
|
||||||
|
"koennt",
|
||||||
|
"koennte",
|
||||||
|
"koennten",
|
||||||
|
"komme",
|
||||||
|
"kommen",
|
||||||
|
"kommt",
|
||||||
|
"konkret",
|
||||||
|
"konkrete",
|
||||||
|
"konkreten",
|
||||||
|
"konkreter",
|
||||||
|
"konkretes",
|
||||||
|
"können",
|
||||||
|
"könnt",
|
||||||
|
"künftig",
|
||||||
|
"leider",
|
||||||
|
"machen",
|
||||||
|
"man",
|
||||||
|
"manche",
|
||||||
|
"manchem",
|
||||||
|
"manchen",
|
||||||
|
"mancher",
|
||||||
|
"mancherorts",
|
||||||
|
"manches",
|
||||||
|
"manchmal",
|
||||||
|
"mehr",
|
||||||
|
"mehrere",
|
||||||
|
"mein",
|
||||||
|
"meine",
|
||||||
|
"meinem",
|
||||||
|
"meinen",
|
||||||
|
"meiner",
|
||||||
|
"meines",
|
||||||
|
"mich",
|
||||||
|
"mir",
|
||||||
|
"mit",
|
||||||
|
"mithin",
|
||||||
|
"muessen",
|
||||||
|
"muesst",
|
||||||
|
"muesste",
|
||||||
|
"muss",
|
||||||
|
"musst",
|
||||||
|
"musste",
|
||||||
|
"mussten",
|
||||||
|
"muß",
|
||||||
|
"mußt",
|
||||||
|
"müssen",
|
||||||
|
"müsste",
|
||||||
|
"müssten",
|
||||||
|
"müßt",
|
||||||
|
"müßte",
|
||||||
|
"nach",
|
||||||
|
"nachdem",
|
||||||
|
"nachher",
|
||||||
|
"nachhinein",
|
||||||
|
"nahm",
|
||||||
|
"natürlich",
|
||||||
|
"neben",
|
||||||
|
"nebenan",
|
||||||
|
"nehmen",
|
||||||
|
"nein",
|
||||||
|
"nicht",
|
||||||
|
"nichts",
|
||||||
|
"nie",
|
||||||
|
"niemals",
|
||||||
|
"niemand",
|
||||||
|
"nirgends",
|
||||||
|
"nirgendwo",
|
||||||
|
"noch",
|
||||||
|
"nun",
|
||||||
|
"nur",
|
||||||
|
"nächste",
|
||||||
|
"nämlich",
|
||||||
|
"nötigenfalls",
|
||||||
|
"ob",
|
||||||
|
"oben",
|
||||||
|
"oberhalb",
|
||||||
|
"obgleich",
|
||||||
|
"obschon",
|
||||||
|
"obwohl",
|
||||||
|
"oder",
|
||||||
|
"oft",
|
||||||
|
"per",
|
||||||
|
"plötzlich",
|
||||||
|
"schließlich",
|
||||||
|
"schon",
|
||||||
|
"sehr",
|
||||||
|
"sehrwohl",
|
||||||
|
"seid",
|
||||||
|
"sein",
|
||||||
|
"seine",
|
||||||
|
"seinem",
|
||||||
|
"seinen",
|
||||||
|
"seiner",
|
||||||
|
"seines",
|
||||||
|
"seit",
|
||||||
|
"seitdem",
|
||||||
|
"seither",
|
||||||
|
"selber",
|
||||||
|
"selbst",
|
||||||
|
"sich",
|
||||||
|
"sicher",
|
||||||
|
"sicherlich",
|
||||||
|
"sie",
|
||||||
|
"sind",
|
||||||
|
"so",
|
||||||
|
"sobald",
|
||||||
|
"sodass",
|
||||||
|
"sofort",
|
||||||
|
"sofern",
|
||||||
|
"sog",
|
||||||
|
"sogar",
|
||||||
|
"solange",
|
||||||
|
"solch",
|
||||||
|
"solche",
|
||||||
|
"solchem",
|
||||||
|
"solchen",
|
||||||
|
"solcher",
|
||||||
|
"solches",
|
||||||
|
"soll",
|
||||||
|
"sollen",
|
||||||
|
"sollst",
|
||||||
|
"sollt",
|
||||||
|
"sollte",
|
||||||
|
"sollten",
|
||||||
|
"somit",
|
||||||
|
"sondern",
|
||||||
|
"sonst",
|
||||||
|
"sonstige",
|
||||||
|
"sonstigen",
|
||||||
|
"sonstiger",
|
||||||
|
"sonstiges",
|
||||||
|
"sooft",
|
||||||
|
"soviel",
|
||||||
|
"soweit",
|
||||||
|
"sowie",
|
||||||
|
"sowieso",
|
||||||
|
"sowohl",
|
||||||
|
"später",
|
||||||
|
"statt",
|
||||||
|
"stattfinden",
|
||||||
|
"stattfand",
|
||||||
|
"stattgefunden",
|
||||||
|
"steht",
|
||||||
|
"stets",
|
||||||
|
"such",
|
||||||
|
"suche",
|
||||||
|
"suchen",
|
||||||
|
"tatsächlich",
|
||||||
|
"tatsächlichen",
|
||||||
|
"tatsächlicher",
|
||||||
|
"tatsächliches",
|
||||||
|
"tatsächlich",
|
||||||
|
"tatsächlichen",
|
||||||
|
"tatsächlicher",
|
||||||
|
"tatsächliches",
|
||||||
|
"tief",
|
||||||
|
"tiefer",
|
||||||
|
"trotz",
|
||||||
|
"trotzdem",
|
||||||
|
"tun",
|
||||||
|
"über",
|
||||||
|
"überall",
|
||||||
|
"überallhin",
|
||||||
|
"überdies",
|
||||||
|
"überhaupt",
|
||||||
|
"übrig",
|
||||||
|
"übrigens",
|
||||||
|
"um",
|
||||||
|
"umso",
|
||||||
|
"umsoweniger",
|
||||||
|
"unbedingt",
|
||||||
|
"und",
|
||||||
|
"unmöglich",
|
||||||
|
"unnötig",
|
||||||
|
"unser",
|
||||||
|
"unsere",
|
||||||
|
"unserem",
|
||||||
|
"unseren",
|
||||||
|
"unserer",
|
||||||
|
"unseres",
|
||||||
|
"unserseits",
|
||||||
|
"unter",
|
||||||
|
"unterhalb",
|
||||||
|
"unterhalb",
|
||||||
|
"untereinander",
|
||||||
|
"untergebracht",
|
||||||
|
"unterhalb",
|
||||||
|
"unterhalb",
|
||||||
|
"unterhalb",
|
||||||
|
"unterhalb",
|
||||||
|
"unterhalb",
|
||||||
|
"unterhalb",
|
||||||
|
"unterschiedlich",
|
||||||
|
"unterschiedliche",
|
||||||
|
"unterschiedlichen",
|
||||||
|
"unterschiedlicher",
|
||||||
|
"unterschiedliches",
|
||||||
|
"unterschiedlich",
|
||||||
|
"unterschiedliche",
|
||||||
|
"unterschiedlichen",
|
||||||
|
"unterschiedlicher",
|
||||||
|
"unterschiedliches",
|
||||||
|
"unzwar",
|
||||||
|
"usw",
|
||||||
|
"usw.",
|
||||||
|
"vermag",
|
||||||
|
"vermögen",
|
||||||
|
"vermutlich",
|
||||||
|
"verrate",
|
||||||
|
"verraten",
|
||||||
|
"verrätst",
|
||||||
|
"verschieden",
|
||||||
|
"verschiedene",
|
||||||
|
"verschiedenen",
|
||||||
|
"verschiedener",
|
||||||
|
"verschiedenes",
|
||||||
|
"versorgen",
|
||||||
|
"versorgt",
|
||||||
|
"versorgte",
|
||||||
|
"versorgten",
|
||||||
|
"viel",
|
||||||
|
"viele",
|
||||||
|
"vielem",
|
||||||
|
"vielen",
|
||||||
|
"vieler",
|
||||||
|
"vieles",
|
||||||
|
"vielleicht",
|
||||||
|
"vielmals",
|
||||||
|
"vier",
|
||||||
|
"vierte",
|
||||||
|
"viertel",
|
||||||
|
"vierten",
|
||||||
|
"vierter",
|
||||||
|
"viertes",
|
||||||
|
"vom",
|
||||||
|
"von",
|
||||||
|
"vor",
|
||||||
|
"vorbei",
|
||||||
|
"vorgestern",
|
||||||
|
"vorher",
|
||||||
|
"vorüber",
|
||||||
|
"wach",
|
||||||
|
"wachen",
|
||||||
|
"wahrend",
|
||||||
|
"wann",
|
||||||
|
"war",
|
||||||
|
"warauf",
|
||||||
|
"ward",
|
||||||
|
"waren",
|
||||||
|
"warst",
|
||||||
|
"wart",
|
||||||
|
"warum",
|
||||||
|
"was",
|
||||||
|
"weder",
|
||||||
|
"weil",
|
||||||
|
"weiter",
|
||||||
|
"weitere",
|
||||||
|
"weiterem",
|
||||||
|
"weiteren",
|
||||||
|
"weiterer",
|
||||||
|
"weiteres",
|
||||||
|
"weiterhin",
|
||||||
|
"weitgehend",
|
||||||
|
"welche",
|
||||||
|
"welchem",
|
||||||
|
"welchen",
|
||||||
|
"welcher",
|
||||||
|
"welches",
|
||||||
|
"wem",
|
||||||
|
"wen",
|
||||||
|
"wenig",
|
||||||
|
"wenige",
|
||||||
|
"wenigem",
|
||||||
|
"wenigen",
|
||||||
|
"weniger",
|
||||||
|
"wenigstens",
|
||||||
|
"wenn",
|
||||||
|
"wenngleich",
|
||||||
|
"wer",
|
||||||
|
"werde",
|
||||||
|
"werden",
|
||||||
|
"werdet",
|
||||||
|
"weshalb",
|
||||||
|
"wessen",
|
||||||
|
"wichtig",
|
||||||
|
"wie",
|
||||||
|
"wieder",
|
||||||
|
"wiederum",
|
||||||
|
"wieso",
|
||||||
|
"will",
|
||||||
|
"willst",
|
||||||
|
"wir",
|
||||||
|
"wird",
|
||||||
|
"wirklich",
|
||||||
|
"wirst",
|
||||||
|
"wissen",
|
||||||
|
"wo",
|
||||||
|
"woanders",
|
||||||
|
"wohl",
|
||||||
|
"woher",
|
||||||
|
"wohin",
|
||||||
|
"wohingegen",
|
||||||
|
"wohl",
|
||||||
|
"wohlweislich",
|
||||||
|
"wollen",
|
||||||
|
"wollt",
|
||||||
|
"wollte",
|
||||||
|
"wollten",
|
||||||
|
"womit",
|
||||||
|
"woraufhin",
|
||||||
|
"woraus",
|
||||||
|
"woraussichtlich",
|
||||||
|
"worauf",
|
||||||
|
"woraus",
|
||||||
|
"worin",
|
||||||
|
"worüber",
|
||||||
|
"wovon",
|
||||||
|
"wovor",
|
||||||
|
"wozu",
|
||||||
|
"während",
|
||||||
|
"währenddessen",
|
||||||
|
"wär",
|
||||||
|
"wäre",
|
||||||
|
"wären",
|
||||||
|
"wärst",
|
||||||
|
"wäre",
|
||||||
|
"wären",
|
||||||
|
"wärst",
|
||||||
|
"würde",
|
||||||
|
"würden",
|
||||||
|
"würdest",
|
||||||
|
"würdet",
|
||||||
|
"zB",
|
||||||
|
"z.b.",
|
||||||
|
"zehn",
|
||||||
|
"zeigen",
|
||||||
|
"zeitweise",
|
||||||
|
"zu",
|
||||||
|
"zufolge",
|
||||||
|
"zugleich",
|
||||||
|
"zuletzt",
|
||||||
|
"zum",
|
||||||
|
"zumal",
|
||||||
|
"zumeist",
|
||||||
|
"zunächst",
|
||||||
|
"zur",
|
||||||
|
"zurück",
|
||||||
|
"zurückgehend",
|
||||||
|
"zurückgehen",
|
||||||
|
"zurückgegangen",
|
||||||
|
"zurückgekommen",
|
||||||
|
"zurückgekommen",
|
||||||
|
"zurückgekommen",
|
||||||
|
"zurückgekommen",
|
||||||
|
"zurückgezogen",
|
||||||
|
"zusammen",
|
||||||
|
"zusätzlich",
|
||||||
|
"zusammen",
|
||||||
|
"zuvor",
|
||||||
|
"zuviel",
|
||||||
|
"zuweilen",
|
||||||
|
"zwanzig",
|
||||||
|
"zwar",
|
||||||
|
"zwei",
|
||||||
|
"zweite",
|
||||||
|
"zweiten",
|
||||||
|
"zweiter",
|
||||||
|
"zweites",
|
||||||
|
"zwischen",
|
||||||
|
"zwischendurch",
|
||||||
|
"zwölf",
|
||||||
|
"überall",
|
||||||
|
"überallhin",
|
||||||
|
"überdies",
|
||||||
|
"überhaupt",
|
||||||
|
"übrig",
|
||||||
|
"übrigens",
|
||||||
|
];
|
|
@ -150,8 +150,22 @@ class ItemsFilter extends View {
|
||||||
const decreased = elements.priceDecreased.checked;
|
const decreased = elements.priceDecreased.checked;
|
||||||
filteredItems = filteredItems.filter((item) => {
|
filteredItems = filteredItems.filter((item) => {
|
||||||
if (item.priceHistory.length == 1) return false;
|
if (item.priceHistory.length == 1) return false;
|
||||||
if (increased && item.priceHistory[0].price > item.priceHistory[1].price) return true;
|
if (this._filterByPriceChanges && elements.priceChangesToday.checked) {
|
||||||
if (decreased && item.priceHistory[0].price < item.priceHistory[1].price) return true;
|
const today = elements.priceChangesDate.value;
|
||||||
|
for (let i = 0; i < item.priceHistory.length; i++) {
|
||||||
|
if (item.priceHistory[i].date == today && i + 1 < item.priceHistory.length) {
|
||||||
|
if (increased && item.priceHistory[i].price > item.priceHistory[i + 1].price) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (decreased && item.priceHistory[i].price < item.priceHistory[i + 1].price) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (increased && item.priceHistory[0].price > item.priceHistory[1].price) return true;
|
||||||
|
if (decreased && item.priceHistory[0].price < item.priceHistory[1].price) return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -182,11 +196,11 @@ class ItemsFilter extends View {
|
||||||
filteredItems = queryItems(query, filteredItems);
|
filteredItems = queryItems(query, filteredItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("Filtering items took " + (performance.now() - now) / 1000 + " secs");
|
||||||
|
|
||||||
this.model.removeListener(this._listener);
|
this.model.removeListener(this._listener);
|
||||||
this.model.filteredItems = filteredItems;
|
this.model.filteredItems = filteredItems;
|
||||||
this.model.addListener(this._listener);
|
this.model.addListener(this._listener);
|
||||||
|
|
||||||
console.log("Filtering items took " + (performance.now() - now) / 1000 + " secs");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
const { downloadJSON, dom, getDynamicElements, onVisibleOnce } = require("../misc");
|
const { downloadJSON, dom, getDynamicElements, onVisibleOnce, isMobile } = require("../misc");
|
||||||
|
const { vectorizeItems, similaritySortItems } = require("../knn");
|
||||||
const { stores } = require("../model/stores");
|
const { stores } = require("../model/stores");
|
||||||
const { View } = require("./view");
|
const { View } = require("./view");
|
||||||
|
|
||||||
|
@ -20,12 +21,13 @@ class ItemsList extends View {
|
||||||
</div>
|
</div>
|
||||||
<label>
|
<label>
|
||||||
Sortieren
|
Sortieren
|
||||||
<select x-id="sort">
|
<select x-id="sort" x-change>
|
||||||
<option value="price-asc">Preis aufsteigend</option>
|
<option value="price-asc">Preis aufsteigend</option>
|
||||||
<option value="price-desc">Preis absteigend</option>
|
<option value="price-desc">Preis absteigend</option>
|
||||||
<option value="quantity-asc">Menge aufsteigend</option>
|
<option value="quantity-asc">Menge aufsteigend</option>
|
||||||
<option value="quantity-desc">Menge absteigend</option>
|
<option value="quantity-desc">Menge absteigend</option>
|
||||||
<option value="name-similarity">Namensähnlichkeit</option>
|
<option value="chain-and-name">Kette & Name</option>
|
||||||
|
<option value="name-similarity" x-id="nameSimilarity" disabled>Namensähnlichkeit</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,7 +36,7 @@ class ItemsList extends View {
|
||||||
<tr class="bg-primary text-white hidden md:table-row uppercase text-sm">
|
<tr class="bg-primary text-white hidden md:table-row uppercase text-sm">
|
||||||
<th class="text-center">Kette</th>
|
<th class="text-center">Kette</th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th class="cursor-pointer">Preis <span x-id="expandPrices">+</span></th>
|
<th x-id="expandPriceHistories" class="cursor-pointer">Preis +</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -63,6 +65,65 @@ class ItemsList extends View {
|
||||||
</td>
|
</td>
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const elements = this.elements;
|
||||||
|
|
||||||
|
elements.json.addEventListener("click", (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
if (!this.model) return;
|
||||||
|
downloadJSON("items.json", this.model.filteredItems);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Cache in a field, so we don't have to call this.elements in each renderItem() call.
|
||||||
|
this._showAllPriceHistories = false;
|
||||||
|
elements.expandPriceHistories.addEventListener("click", () => {
|
||||||
|
const showAll = (this._showAllPriceHistories = !this._showAllPriceHistories);
|
||||||
|
elements.expandPriceHistories.innerText = showAll ? "Preis -" : "Preis +";
|
||||||
|
elements.tableBody.querySelectorAll(".priceinfo").forEach((el) => (showAll ? el.classList.remove("hidden") : el.classList.add("hidden")));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.addEventListener("change", () => {
|
||||||
|
this.render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sort(items) {
|
||||||
|
const sortType = this.elements.sort.value;
|
||||||
|
if (sortType == "price-asc") {
|
||||||
|
items.sort((a, b) => a.price - b.price);
|
||||||
|
} else if (sortType == "price-desc") {
|
||||||
|
items.sort((a, b) => b.price - a.price);
|
||||||
|
} else if (sortType == "quantity-asc") {
|
||||||
|
items.sort((a, b) => {
|
||||||
|
if (a.unit != b.unit) return a.unit.localeCompare(b.unit);
|
||||||
|
return a.quantity - b.quantity;
|
||||||
|
});
|
||||||
|
} else if (sortType == "quantity-desc") {
|
||||||
|
items.sort((a, b) => {
|
||||||
|
if (a.unit != b.unit) return a.unit.localeCompare(b.unit);
|
||||||
|
return b.quantity - a.quantity;
|
||||||
|
});
|
||||||
|
} else if (sortType == "chain-and-name") {
|
||||||
|
items.sort((a, b) => {
|
||||||
|
if (a.store < b.store) {
|
||||||
|
return -1;
|
||||||
|
} else if (a.store > b.store) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a.name < b.name) {
|
||||||
|
return -1;
|
||||||
|
} else if (a.name > b.name) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
vectorizeItems(items);
|
||||||
|
items = similaritySortItems(items);
|
||||||
|
}
|
||||||
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderItem(item) {
|
renderItem(item) {
|
||||||
|
@ -139,12 +200,20 @@ class ItemsList extends View {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
if (this._showAllPriceHistories) elements.priceHistory.classList.remove("hidden");
|
||||||
return itemDom;
|
return itemDom;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const items = this.model.filteredItems;
|
|
||||||
const elements = this.elements;
|
const elements = this.elements;
|
||||||
|
if (this.model.filteredItems.length != 0 && this.model.filteredItems.length <= (isMobile() ? 200 : 1000)) {
|
||||||
|
elements.nameSimilarity.removeAttribute("disabled");
|
||||||
|
} else {
|
||||||
|
elements.nameSimilarity.setAttribute("disabled", "true");
|
||||||
|
if (elements.sort.value == "name-similarity") elements.sort.value = "price-asc";
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = this.sort([...this.model.filteredItems]);
|
||||||
elements.numItems.innerHTML =
|
elements.numItems.innerHTML =
|
||||||
"<strong>Resultate:</strong> " + items.length + (this.model.totalItems > items.length ? " / " + this.model.totalItems : "");
|
"<strong>Resultate:</strong> " + items.length + (this.model.totalItems > items.length ? " / " + this.model.totalItems : "");
|
||||||
const tableBody = elements.tableBody;
|
const tableBody = elements.tableBody;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user