diff --git a/bundle.js b/bundle.js
index aefad89..14ba99c 100755
--- a/bundle.js
+++ b/bundle.js
@@ -104,7 +104,7 @@ async function bundleJS(inputDir, outputDir, watch) {
let buildContext = await esbuild.context({
entryPoints: {
carts: `${inputDir}/carts.js`,
- "changes-new": `${inputDir}/changes-new.js`,
+ changes: `${inputDir}/changes.js`,
index: `${inputDir}/index.js`,
},
bundle: true,
diff --git a/site/changes-new.html b/site/changes-new.html
deleted file mode 100644
index 5d429e6..0000000
--- a/site/changes-new.html
+++ /dev/null
@@ -1,11 +0,0 @@
-%%_templates/_header.html%% %%_templates/_menu.html%%
-
-
-
Preisänderungen
-
-
-
-
-
-
-%%_templates/_footer.html%%
diff --git a/site/changes-new.js b/site/changes-new.js
deleted file mode 100644
index e042841..0000000
--- a/site/changes-new.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const model = require("./model");
-require("./views");
-
-(async () => {
- await model.load();
- const itemsFilter = document.querySelector("items-filter");
- const itemsList = document.querySelector("items-list");
- itemsList.elements.sort.value = "chain-and-name";
- itemsFilter.model = itemsList.model = model.items;
- itemsFilter.filter();
-})();
diff --git a/site/changes-old.html b/site/changes-old.html
new file mode 100644
index 0000000..557528e
--- /dev/null
+++ b/site/changes-old.html
@@ -0,0 +1,25 @@
+%%_templates/_header.html%% %%_templates/_menu.html%%
+
+
+
Preisänderungen
+
+
+
+
+
+
+
+
+
+%%_templates/_footer.html%%
diff --git a/site/changes-old.js b/site/changes-old.js
new file mode 100644
index 0000000..3fb08fe
--- /dev/null
+++ b/site/changes-old.js
@@ -0,0 +1,164 @@
+let changeDates = [];
+let items = [];
+
+async function load() {
+ items = await loadItems();
+ 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;
+ });
+
+ const dates = {};
+ for (const item of items) {
+ if (item.priceHistory.length == 1) continue;
+ for (let i = 0; i < item.priceHistory.length; i++) {
+ const price = item.priceHistory[i];
+ if (i + 1 < item.priceHistory.length) {
+ if (item.priceHistory[i].price != item.priceHistory[i + 1].price) dates[price.date] = dates[price.date] ? dates[price.date] + 1 : 1;
+ }
+ }
+ }
+ const dateNames = Object.keys(dates).sort((a, b) => b.localeCompare(a));
+
+ const dateSelection = document.querySelector("#dates");
+ dateNames.forEach((dateName, index) => {
+ const option = dom("option", dateName + " (" + dates[dateName] + ")");
+ option.setAttribute("value", dateName);
+ if (index == 0) option.selected = true;
+ dateSelection.appendChild(option);
+ });
+
+ document.querySelectorAll("#type").forEach((changeType) => {
+ changeType.addEventListener("change", () => showResults(items));
+ });
+
+ dateSelection.addEventListener("change", () => {
+ showResults(items);
+ });
+
+ const filtersStore = document.querySelector("#filters-store");
+ filtersStore.innerHTML = `
+ ${customCheckbox(`all`, "Alle", true, "gray")}
+ ${STORE_KEYS.map((store) =>
+ customCheckbox(store, stores[store].name, stores[store].name.toLowerCase().endsWith("de") ? false : true, stores[store].color)
+ ).join(" ")}
+ `;
+ filtersStore.querySelector("#all").addEventListener("change", () => {
+ const checked = filtersStore.querySelector("#all").checked;
+ STORE_KEYS.forEach((store) => (filtersStore.querySelector(`#${store}`).checked = checked));
+ showResults(items);
+ });
+
+ document.querySelector("#filters-changes").innerHTML = `
+ ${customCheckbox(`increases`, "Teurer", true, "gray")}
+ ${customCheckbox(`decreases`, "Billiger", true, "gray")}
+ `;
+
+ document.querySelectorAll("input").forEach((input) => {
+ if (input.id == "all" && input.id != "type") return;
+ input.addEventListener("change", () => showResults(items));
+ });
+
+ let timeoutId;
+ document.querySelector("#filter").addEventListener("input", () => {
+ clearTimeout(timeoutId);
+ timeoutId = setTimeout(() => {
+ if (document.querySelector("#filter").value.trim().startsWith("!")) {
+ document.querySelector("#filters-store").classList.add("hidden");
+ document.querySelector("#filters-changes").classList.add("hidden");
+ } else {
+ document.querySelector("#filters-store").classList.remove("hidden");
+ document.querySelector("#filters-changes").classList.remove("hidden");
+ }
+ showResults(items);
+ }, 50);
+ });
+
+ showResults(items);
+}
+
+function showResults(items) {
+ const query = document.querySelector("#filter").value.trim();
+ let today = null;
+ if (document.querySelector("#date").checked) {
+ today = document.querySelector("#dates").value;
+ if (!query.startsWith("!")) document.querySelector("#filters-changes").classList.remove("hidden");
+ } else {
+ document.querySelector("#filters-changes").classList.add("hidden");
+ }
+ const increases = document.querySelector("#increases").checked;
+ const decreases = document.querySelector("#decreases").checked;
+ const storeCheckboxes = STORE_KEYS.map((store) => document.querySelector(`#${store}`));
+ const checkedStores = STORE_KEYS.filter((store, i) => storeCheckboxes[i].checked);
+ let changedItems = [];
+ for (const item of items) {
+ if (item.priceHistory.length < 2) continue;
+ if (!checkedStores.includes(item.store)) continue;
+
+ if (today) {
+ for (let i = 0; i < item.priceHistory.length; i++) {
+ if (item.priceHistory[i].date == today && i + 1 < item.priceHistory.length) {
+ if (increases && item.priceHistory[i].price > item.priceHistory[i + 1].price) {
+ changedItems.push(item);
+ }
+ if (decreases && item.priceHistory[i].price < item.priceHistory[i + 1].price) {
+ changedItems.push(item);
+ }
+ }
+ }
+ } else {
+ if (item.priceHistory[0].price < item.priceHistory[1].price) changedItems.push(item);
+ }
+ }
+
+ const total = changedItems.length;
+ if (query.startsWith("!") || query.length >= 3)
+ changedItems = searchItems(changedItems, document.querySelector("#filter").value, checkedStores, false, 0, 10000, false, false);
+ document.querySelector("#numresults").innerText = "Resultate: " + changedItems.length + (total > changedItems.length ? " / " + total : "");
+ const table = document.querySelector("#result");
+ table.innerHTML = "";
+ if (changedItems.length == 0) return;
+ const header = dom(
+ "thead",
+ `
+ Kette |
+ Name |
+
+ Preis
+ +
+ |
+
+ `
+ );
+ const showHideAll = header.querySelectorAll("th:nth-child(3)")[0];
+ showHideAll.style["cursor"] = "pointer";
+ showHideAll.showAll = true;
+ showHideAll.addEventListener("click", () => {
+ showHideAll.querySelector(".expander").innerText = showHideAll.querySelector(".expander").innerText == "+" ? "-" : "+";
+ table.querySelectorAll(".priceinfo").forEach((el) => (showHideAll.showAll ? el.classList.remove("hidden") : el.classList.add("hidden")));
+ showHideAll.showAll = !showHideAll.showAll;
+ });
+
+ table.appendChild(header);
+
+ for (let item of changedItems) {
+ item = JSON.parse(JSON.stringify(item));
+ const itemDom = itemToDOM(item);
+ table.appendChild(itemDom);
+ }
+
+ table.classList.remove("hidden");
+}
+
+load();
diff --git a/site/changes.html b/site/changes.html
index 13a9112..fe6eb6f 100644
--- a/site/changes.html
+++ b/site/changes.html
@@ -2,24 +2,10 @@
Preisänderungen
-
-
-
+
+
-
-
%%_templates/_footer.html%%
diff --git a/site/changes.js b/site/changes.js
index 3fb08fe..e042841 100644
--- a/site/changes.js
+++ b/site/changes.js
@@ -1,164 +1,11 @@
-let changeDates = [];
-let items = [];
+const model = require("./model");
+require("./views");
-async function load() {
- items = await loadItems();
- 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;
- });
-
- const dates = {};
- for (const item of items) {
- if (item.priceHistory.length == 1) continue;
- for (let i = 0; i < item.priceHistory.length; i++) {
- const price = item.priceHistory[i];
- if (i + 1 < item.priceHistory.length) {
- if (item.priceHistory[i].price != item.priceHistory[i + 1].price) dates[price.date] = dates[price.date] ? dates[price.date] + 1 : 1;
- }
- }
- }
- const dateNames = Object.keys(dates).sort((a, b) => b.localeCompare(a));
-
- const dateSelection = document.querySelector("#dates");
- dateNames.forEach((dateName, index) => {
- const option = dom("option", dateName + " (" + dates[dateName] + ")");
- option.setAttribute("value", dateName);
- if (index == 0) option.selected = true;
- dateSelection.appendChild(option);
- });
-
- document.querySelectorAll("#type").forEach((changeType) => {
- changeType.addEventListener("change", () => showResults(items));
- });
-
- dateSelection.addEventListener("change", () => {
- showResults(items);
- });
-
- const filtersStore = document.querySelector("#filters-store");
- filtersStore.innerHTML = `
- ${customCheckbox(`all`, "Alle", true, "gray")}
- ${STORE_KEYS.map((store) =>
- customCheckbox(store, stores[store].name, stores[store].name.toLowerCase().endsWith("de") ? false : true, stores[store].color)
- ).join(" ")}
- `;
- filtersStore.querySelector("#all").addEventListener("change", () => {
- const checked = filtersStore.querySelector("#all").checked;
- STORE_KEYS.forEach((store) => (filtersStore.querySelector(`#${store}`).checked = checked));
- showResults(items);
- });
-
- document.querySelector("#filters-changes").innerHTML = `
- ${customCheckbox(`increases`, "Teurer", true, "gray")}
- ${customCheckbox(`decreases`, "Billiger", true, "gray")}
- `;
-
- document.querySelectorAll("input").forEach((input) => {
- if (input.id == "all" && input.id != "type") return;
- input.addEventListener("change", () => showResults(items));
- });
-
- let timeoutId;
- document.querySelector("#filter").addEventListener("input", () => {
- clearTimeout(timeoutId);
- timeoutId = setTimeout(() => {
- if (document.querySelector("#filter").value.trim().startsWith("!")) {
- document.querySelector("#filters-store").classList.add("hidden");
- document.querySelector("#filters-changes").classList.add("hidden");
- } else {
- document.querySelector("#filters-store").classList.remove("hidden");
- document.querySelector("#filters-changes").classList.remove("hidden");
- }
- showResults(items);
- }, 50);
- });
-
- showResults(items);
-}
-
-function showResults(items) {
- const query = document.querySelector("#filter").value.trim();
- let today = null;
- if (document.querySelector("#date").checked) {
- today = document.querySelector("#dates").value;
- if (!query.startsWith("!")) document.querySelector("#filters-changes").classList.remove("hidden");
- } else {
- document.querySelector("#filters-changes").classList.add("hidden");
- }
- const increases = document.querySelector("#increases").checked;
- const decreases = document.querySelector("#decreases").checked;
- const storeCheckboxes = STORE_KEYS.map((store) => document.querySelector(`#${store}`));
- const checkedStores = STORE_KEYS.filter((store, i) => storeCheckboxes[i].checked);
- let changedItems = [];
- for (const item of items) {
- if (item.priceHistory.length < 2) continue;
- if (!checkedStores.includes(item.store)) continue;
-
- if (today) {
- for (let i = 0; i < item.priceHistory.length; i++) {
- if (item.priceHistory[i].date == today && i + 1 < item.priceHistory.length) {
- if (increases && item.priceHistory[i].price > item.priceHistory[i + 1].price) {
- changedItems.push(item);
- }
- if (decreases && item.priceHistory[i].price < item.priceHistory[i + 1].price) {
- changedItems.push(item);
- }
- }
- }
- } else {
- if (item.priceHistory[0].price < item.priceHistory[1].price) changedItems.push(item);
- }
- }
-
- const total = changedItems.length;
- if (query.startsWith("!") || query.length >= 3)
- changedItems = searchItems(changedItems, document.querySelector("#filter").value, checkedStores, false, 0, 10000, false, false);
- document.querySelector("#numresults").innerText = "Resultate: " + changedItems.length + (total > changedItems.length ? " / " + total : "");
- const table = document.querySelector("#result");
- table.innerHTML = "";
- if (changedItems.length == 0) return;
- const header = dom(
- "thead",
- `
- Kette |
- Name |
-
- Preis
- +
- |
-
- `
- );
- const showHideAll = header.querySelectorAll("th:nth-child(3)")[0];
- showHideAll.style["cursor"] = "pointer";
- showHideAll.showAll = true;
- showHideAll.addEventListener("click", () => {
- showHideAll.querySelector(".expander").innerText = showHideAll.querySelector(".expander").innerText == "+" ? "-" : "+";
- table.querySelectorAll(".priceinfo").forEach((el) => (showHideAll.showAll ? el.classList.remove("hidden") : el.classList.add("hidden")));
- showHideAll.showAll = !showHideAll.showAll;
- });
-
- table.appendChild(header);
-
- for (let item of changedItems) {
- item = JSON.parse(JSON.stringify(item));
- const itemDom = itemToDOM(item);
- table.appendChild(itemDom);
- }
-
- table.classList.remove("hidden");
-}
-
-load();
+(async () => {
+ await model.load();
+ const itemsFilter = document.querySelector("items-filter");
+ const itemsList = document.querySelector("items-list");
+ itemsList.elements.sort.value = "chain-and-name";
+ itemsFilter.model = itemsList.model = model.items;
+ itemsFilter.filter();
+})();
diff --git a/site/index-old.html b/site/index-old.html
index 9b44633..a0e2aa8 100644
--- a/site/index-old.html
+++ b/site/index-old.html
@@ -26,6 +26,6 @@
-
+
%%_templates/_footer.html%%
diff --git a/site/model/items.js b/site/model/items.js
index f6dd154..9d005e3 100644
--- a/site/model/items.js
+++ b/site/model/items.js
@@ -69,30 +69,9 @@ class Items extends Model {
return this._lookup;
}
- async load() {
- let start = performance.now();
- const compressedItemsPerStore = [];
- for (const store of STORE_KEYS) {
- compressedItemsPerStore.push(
- new Promise(async (resolve) => {
- const start = performance.now();
- try {
- const response = await fetch(`data/latest-canonical.${store}.compressed.json`);
- const json = await response.json();
- log(`Items - loading compressed items for ${store} took ${deltaTime(start)} secs`);
- resolve(decompress(json));
- } catch (e) {
- log(`Items - error while loading compressed items for ${store} ${e.message}`);
- resolve([]);
- }
- })
- );
- }
- const items = [].concat(...(await Promise.all(compressedItemsPerStore)));
- log(`Items - loaded ${items.length} items took ${deltaTime(start).toFixed(4)} secs`);
-
+ processItems(items) {
const lookup = {};
- start = performance.now();
+ const start = performance.now();
for (const item of items) {
lookup[item.store + item.id] = item;
item.search = item.name + " " + item.quantity + " " + item.unit;
@@ -136,10 +115,34 @@ class Items extends Model {
});
log(`Items - processing ${items.length} items took ${deltaTime(start).toFixed(4)} secs`);
-
this._items = items;
this._lookup = lookup;
}
+
+ async load() {
+ let start = performance.now();
+ const compressedItemsPerStore = [];
+ for (const store of STORE_KEYS) {
+ compressedItemsPerStore.push(
+ new Promise(async (resolve) => {
+ const start = performance.now();
+ try {
+ const response = await fetch(`data/latest-canonical.${store}.compressed.json`);
+ const json = await response.json();
+ log(`Items - loading compressed items for ${store} took ${deltaTime(start)} secs`);
+ resolve(decompress(json));
+ } catch (e) {
+ log(`Items - error while loading compressed items for ${store} ${e.message}`);
+ resolve([]);
+ }
+ })
+ );
+ }
+ const items = [].concat(...(await Promise.all(compressedItemsPerStore)));
+ log(`Items - loaded ${items.length} items took ${deltaTime(start).toFixed(4)} secs`);
+
+ this.processItems(items);
+ }
}
exports.Items = Items;