Ver código fonte

Working on search and lists.

cixo 1 ano atrás
pai
commit
4eadd57788

+ 16 - 9
assets/core.js

@@ -2,20 +2,27 @@ import { search } from "./search.js";
 import { pixel, percent, auto } from "./size.js";
 import { position, place_top } from "./position.js";
 import { sticky } from "./sticky.js";
+import { loader } from "./loader.js";
+import { database } from "./database.js";
 
-document.addEventListener("DOMContentLoaded", () => {
+document.addEventListener("DOMContentLoaded", async () => {
     const container = document.querySelector(".container");
     
-    const top_bar = new sticky();
-    top_bar.width = new percent(100);
-    top_bar.height = new auto();
-    top_bar.position = new place_top();
+    const parser = new loader("./database", "project.json");
+    await parser.load();
 
-    const top_bar_element = top_bar.element;
+    const store = new database(parser.loaded);
+    
+    const top_bar_builder = new sticky();
+    top_bar_builder.width = new percent(100);
+    top_bar_builder.height = new auto();
+    top_bar_builder.position = new place_top();
+
+    const top_bar = top_bar_builder.element;
 
-    const search_bar = new search();
-    top_bar_element.appendChild(search_bar.ui);
+    const search_bar = new search(store);
+    top_bar.appendChild(search_bar.ui);
 
-    container.appendChild(top_bar_element);
+    container.appendChild(top_bar);
 });
 

+ 27 - 46
assets/database.js

@@ -1,64 +1,45 @@
 import { element } from "./element.js";
 import { submission } from "./submission.js";
+import { project } from "./project.js";
+import { is_string } from "./functions.js";
 
 class database {
-    #submissions;
+    #content;
 
-    constructor() {
-        this.clean();
+    constructor(content) {
+        if (!(content instanceof project)) {
+            throw "Content must be instance of an project.";
+        }
+
+        this.#content = content;
+    }
+
+    get content() {
+        return this.#content;
     }
 
     search(input) {
-        const phrase = input.trim();
-        const found = [];
-        
-        this.submissions.forEach(name => {
-            const current = this.#submissions[name];
+        if (!is_string(input)) {
+            throw "Phrase to search must be string.";
+        }
 
-            if (name.search(phrase) !== -1) {
-                found.push(current);
+        const content = this.#content;
+        const phrase = input.trim().toLowerCase();
+        const result = [];
+        
+        content.submissions.forEach(submission => {
+            if (submission.name.toLowerCase().search(phrase) !== -1 ) {
+                result.push(submission);
             }
 
-            current.elemenets.forEach(name => {
-                if (name.search(phrase) !== -1) {
-                    found.push(current.get(name));
+            submission.elements.forEach(element => {
+                if (element.name.toLowerCase().search(phrase) !== -1) {
+                    result.push(element);
                 }
             });
         });
 
-        return found;
-    }
-    
-    clean() {
-        this.#submissions = {};
-    }   
-
-    add(container) {
-        if (!(container instanceof submission)) {
-            throw "Trying to add something which is not an submission.";
-        }
-        
-        if (container.name in this.#submissions) {
-            throw "Trying to add submission which already exists.";
-        }   
-
-        this.#submissions[container.name] = container;
-    }
-
-    get submissions() {
-        return Object.keys(this.#submissions);
-    }
-
-    get(name) {
-        if (typeof(name) !== "string") {
-            throw "Submission name must be an string.";
-        }
-
-        if (!(name in this.#submissions)) {
-            throw "Trying to get submission which not exists.";
-        }
-
-        return this.#submissions[name];
+        return result;
     }
 } 
 

+ 73 - 0
assets/items_list.js

@@ -0,0 +1,73 @@
+import { element } from "./element.js";
+import { submission } from "./submission.js";
+import { project } from "./project.js";
+
+class items_list {
+    #container;
+    #click;
+
+    constructor(container, click) {
+        if (!(container instanceof HTMLElement)) {
+            throw "Container must be HTML element.";
+        }
+
+        if (typeof(click) !== "function") {
+            throw "Click must be an function.";
+        }
+
+        this.#click = click;
+        this.#container = container;
+        this.#container.classList.add("elements-list");
+    }
+
+    get container() {
+        return this.#container;
+    }
+
+    #clean() {
+        while (this.container.firstChild) {
+            this.container.firstChild.remove();
+        }
+    }
+
+    #add(content) {
+        const container = document.createElement("div");
+        const text = document.createElement("p");
+        const icon = document.createElement("span");
+        const name = document.createElement("span");
+
+        name.innerText = content.name;
+        container.className = "single-element";
+
+        container.addEventListener("click", () => {
+            this.#click(content);
+        });
+
+        if (content instanceof project) {
+            icon.innerText = "project";
+        } else if (content instanceof element) {
+            icon.innerText = "element";
+        } else if (content instanceof submission) {
+            icon.innerText = "submission";
+        }
+
+        text.appendChild(icon);
+        text.appendChild(name);
+        container.appendChild(text);
+        this.container.appendChild(container);
+    }
+
+    update(list) {
+        if (!(list instanceof Array)) {
+            throw "List elements to update must be an array.";
+        }
+
+        this.#clean();
+
+        list.forEach(count => {
+            this.#add(count); 
+        });
+    }
+}
+
+export { items_list };

+ 62 - 54
assets/loader.js

@@ -24,79 +24,51 @@ class loader {
 
     async load() {
         const fetched = await fetch(this.#load_from);
-        const result = await fetched.json();
-
-        this.#content = result;
-    }
-
-    get loaded() {
-        if (this.#content === null) {
-            throw "Must load database before trying to access it.";
-        }
         
-        const content = this.#content;
-        
-        if (!exists(content.name)) {
-            content.name = "Unnamed";
+        if (fetched.status !== 200) {
+            throw "Can not load database from " + this.#load_from;
         }
-        
-        const result = new project(content.name);
 
-        if (exists(content.description)) {
-            result.description = content.description;
-        }
-
-        if (!exists(content.submissions)) {
-            return result;
+        try {
+            const result = await fetched.json();
+            this.#content = result;
+        } catch (error) {
+            throw "Database JSON is bad formated.";
         }
-
-        const submissions = Array.from(content.submissions);
-
-        submissions.forEach(submission => {
-            const item = this.#prepare_one(submission);
-
-            if (item === null) {
-                return;
-            }
-
-            result.add(item);
-        });
-
-        return result;
     }
-
+    
     #prepare_image(url) {
         return this.#database + "/" + url;
     }
 
     #prepare_element(input) {
-        if (exists(input.name)) {
+        if (!exists(input.name)) {
             return null;
         }
 
-        const element = new element(input.name);
+        const result = new element(input.name);
 
         if (exists(input.description)) {
-            element.description = input.description;
+            result.description = input.description;
         }
 
         if (exists(input.mesh)) {
-            element.mesh = this.#prepare_image(input.mesh);
+            result.mesh = this.#prepare_image(input.mesh);
         }
 
         if (exists(input.thumbnail)) {
-            element.thumbnail = this.#prepare_image(input.thumbnail);
+            result.thumbnail = this.#prepare_image(input.thumbnail);
         }
         
         if (exists(input.pictures)) {
             const pictures = Array.from(input.pictures);
         
             pictures.forEach(picture => {
-                if (!is_string(picture) {
+                if (!is_string(picture)) {
                     return;
                 }
 
-                element.pictures.add(this.#prepare_image(picture));                
+                result.pictures.add(this.#prepare_image(picture));                
             });
         }
 
@@ -108,15 +80,15 @@ class loader {
                     return;
                 }
 
-                element.params.set(name, input.params[name]);
+                result.params.set(name, input.params[name]);
             });
         }
 
         if (exists(input.shop)) {
-            element.shop = input.shop;
+            result.shop = input.shop;
         }
 
-        return element;
+        return result;
     }
 
     #prepare_one(input) {
@@ -124,31 +96,67 @@ class loader {
             return null;
         }
 
-        const submission = new submission(input.name)
+        const result = new submission(input.name)
         
         if (typeof(input.description) !== "undefined") {
-            submission.description = input.description;
+            result.description = input.description;
         }
 
         if (typeof(input.thumbnail) !== "undefined") {
-            submission.thumbnail = this.#prepare_image(input.thumbnail);
+            result.thumbnail = this.#prepare_image(input.thumbnail);
         }
 
         if (typeof(input.elements) === "undefined") {
-            return submission;
+            return result;
         }
 
         const elements = Array.from(input.elements);
 
         elements.forEach(data => {
-            const element = new this.#prepare_element(data);
+            const current = this.#prepare_element(data);
 
-            if (element !== null) {
-                submission.add(element);
+            if (current !== null) {
+                result.add(current);
             }
         });
 
-        return submission;
+        return result;
+    }
+
+    get loaded() {
+        if (this.#content === null) {
+            throw "Must load database before trying to access it.";
+        }
+        
+        const content = this.#content;
+        
+        if (!exists(content.name)) {
+            content.name = "Unnamed";
+        }
+        
+        const result = new project(content.name);
+
+        if (exists(content.description)) {
+            result.description = content.description;
+        }
+
+        if (!exists(content.submissions)) {
+            return result;
+        }
+
+        const submissions = Array.from(content.submissions);
+
+        submissions.forEach(submission => {
+            const item = this.#prepare_one(submission);
+
+            if (item === null) {
+                return;
+            }
+
+            result.add(item);
+        });
+
+        return result;
     }
 }
 

+ 5 - 1
assets/project.js

@@ -28,10 +28,14 @@ class project {
         this.#description = content;
     }
 
-    get submissions() {
+    get names() {
         return Object.keys(this.#submissions);
     }
 
+    get submissions() {
+        return Object.values(this.#submissions);
+    }
+
     get(name) {
         if (typeof(name) !== "string") {
             throw "Name of submission must be an string.";

+ 29 - 6
assets/search.js

@@ -1,13 +1,22 @@
+import { database } from "./database.js";
 import { lang } from "./lang.js";
+import { items_list } from "./items_list.js";
 
 class search {
     #container;
     #hint;
     #input;
     #last_content;
+    #store;
+    #list;
     
-    constructor() {
+    constructor(store) {
+        if (!(store instanceof database)) {
+            throw "Store must be instance of database";
+        }
+
         this.#last_content = "";
+        this.#store = store;
 
         this.#container = document.createElement("div");
         this.#container.className = "search";
@@ -24,7 +33,9 @@ class search {
         submit.value = lang.search.find;
 
         const form = document.createElement("form");
-        
+    
+        this.#list = new items_list(this.#hint, this.click);
+
         form.addEventListener("submit", (action) => {
             action.preventDefault();
             this.find();
@@ -48,6 +59,10 @@ class search {
         this.#container.appendChild(this.#hint);
     }
 
+    click(item) {
+        console.log(item.name);
+    }
+
     get content() {
         return this.#input.value.trim();
     }
@@ -62,20 +77,28 @@ class search {
         return true;
     }
 
+    get results() {
+        if (this.content.length === 0) {
+            return [];
+        }
+
+        return this.#store.search(this.content);
+    }
+
     find() {
         if (!this.changed) {
             return;
         }
-
-        console.log("UwU");
+        
+        this.#list.update(this.results);
     }
 
     refresh() {
         if (!this.changed) {
             return;
         }
-
-        console.log("OwO");
+    
+        this.#list.update(this.results);
     }
 
     get ui() {

+ 5 - 1
assets/submission.js

@@ -46,10 +46,14 @@ class submission {
         this.#thumbnail = content;
     }
 
-    get elements() {
+    get names() {
         return Object.keys(this.#elements);
     }
 
+    get elements() {
+        return Object.values(this.#elements);
+    }
+
     add(item) {
         if (!(item instanceof element)) {
             throw "Trying to add something which is not an element.";

+ 33 - 0
database/project.json

@@ -0,0 +1,33 @@
+{
+    "name": "Test project",
+    "description": "This is test project description.",
+    "submissions": [
+        {
+            "name": "First submission",
+            "description": "This is first submission.",
+            "thumbnail": "test.jpg"
+        },
+        {
+            "name": "Second submission",
+            "description": "This is second submission.",
+            "thumbnail": "test.png",
+            "elements": [
+                {
+                    "name": "Element",
+                    "description": "This is element description",
+                    "mesh": "element.stl",
+                    "shop": "https://allegro.pl",
+                    "thumbnail": "element.png",
+                    "params": {
+                        "width": "100mm",
+                        "height": "50mm"
+                    },
+                    "pictures": [
+                        "test_a.png",
+                        "test_b.jpg"
+                    ]
+                }
+            ]
+        }
+    ]
+}

+ 0 - 3
tests/element.js

@@ -7,8 +7,6 @@ item.name = "Simple item";
 item.mesh = "sample.stl";
 item.thumbnail = 
 item.description = "This is simple test item.";
-item.links.set("ref", "https://uwu.com");
-item.links.set("ebay", "https://ebay.com/item");
 item.params.set("width", "100mm");
 item.params.set("height", "100mm");
 item.params.set("depth", "100mm");
@@ -16,6 +14,5 @@ item.params.set("depth", "100mm");
 console.log(item.name);
 console.log(item.mesh);
 console.log(item.description);
-console.log(item.links);
 console.log(item.params);
 console.log(item.pictures);

+ 12 - 0
tests/loader.html

@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <meta charset="UTF-8">
+        <title>Loader test</title>
+        <script type="module" src="./loader.js"></script>
+    </head>
+
+    <body>
+    </body>
+</html>

+ 16 - 0
tests/loader.js

@@ -0,0 +1,16 @@
+import { loader } from "../assets/loader.js";
+
+const test = async () => {
+    console.log("Trying to create loader...");
+    const check = new loader("./", "test-database.json");
+
+    console.log("Trying to load...");
+    await check.load();
+
+    const project = check.loaded;
+
+    console.log("Results:");
+    console.log(project);
+};
+
+test();

+ 33 - 0
tests/test-database.json

@@ -0,0 +1,33 @@
+{
+    "name": "Test project",
+    "description": "This is test project description.",
+    "submissions": [
+        {
+            "name": "First submission",
+            "description": "This is first submission.",
+            "thumbnail": "test.jpg"
+        },
+        {
+            "name": "Second submission",
+            "description": "This is second submission.",
+            "thumbnail": "test.png",
+            "elements": [
+                {
+                    "name": "Element",
+                    "description": "This is element description",
+                    "mesh": "element.stl",
+                    "shop": "https://allegro.pl",
+                    "thumbnail": "element.png",
+                    "params": {
+                        "width": "100mm",
+                        "height": "50mm"
+                    },
+                    "pictures": [
+                        "test_a.png",
+                        "test_b.jpg"
+                    ]
+                }
+            ]
+        }
+    ]
+}