Skip to content

Commit

Permalink
chore: continue to implement search bar
Browse files Browse the repository at this point in the history
  • Loading branch information
fraxken committed Jun 14, 2020
1 parent 333c0ef commit 02023ab
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 4 deletions.
6 changes: 3 additions & 3 deletions public/components/searchbar/searchbar.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
<p>options de recherche</p>
</div>
<ul>
<li><b>alarm:</b><p>alarm</p></li>
<li><b>entity:</b><p>nom de l'entité</p></li>
<li><b>mic:</b><p>nom ou id</p></li>
<li data-value="alarm"><b>alarm:</b><p>alarm</p></li>
<li data-value="entity"><b>entity:</b><p>nom de l'entité</p></li>
<li data-value="mic"><b>mic:</b><p>nom ou id</p></li>
</ul>
</div>
<hr>
Expand Down
125 changes: 124 additions & 1 deletion public/components/searchbar/searchbar.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
import { createDOMElement } from "../../js/utils.js";

// CONSTANTS
const kFiltersName = new Set(["alarm", "entity", "mic"]);

class SearchBar extends HTMLElement {
constructor() {
super();
const tmpl = document.getElementById("searchbar");
const clone = tmpl.content.cloneNode(true);

this.inputUpdateValue = false;
this.queries = [];
this.activeFilters = new Set();

// elements
this.input = clone.querySelector("input.search-bar");
this.resultsContainer = clone.querySelector(".search-results");
this.filterSearchGroup = clone.querySelector(".search-results > #helper");
this.filtersContainer = clone.querySelector(".input-filters");
this.allResultsElements = clone.querySelectorAll("#items ul li")

// When we click in the Searchbar, then we want to open the results container
this.addEventListener("click", () => {
Expand All @@ -25,15 +35,128 @@ class SearchBar extends HTMLElement {
}
});

let currentActiveFilterName = null;
let confirmBackspace = false;
this.input.addEventListener("keyup", (event) => {
if ((this.input.value === null || this.input.value === "")) {
this.showFilterGroup();

// hide all results if there is no active queries!
if (this.activeFilters.size === 0) {
this.allResultsElements.forEach((element) => element.classList.add("hidden"));
}

else if (event.key === "Backspace") {
if (confirmBackspace) {
this.removeLatestFilter();
currentActiveFilterName = null;
}
else {
confirmBackspace = true;
}
}

return;
}

confirmBackspace = false;
if (currentActiveFilterName === null) {
this.showFilterByInputText();
}

if (event.key === ":" || this.inputUpdateValue) {
if (this.inputUpdateValue) {
setTimeout(() => (this.inputUpdateValue = false), 1);
}

// here .split is important because we may have to re-proceed complete search string like 'filter: text'.
const [filterName] = this.input.value.split(":");
if (kFiltersName.has(filterName)) {
currentActiveFilterName = filterName;
this.showFilterGroup(currentActiveFilterName);
}
}

if (currentActiveFilterName === null) {
return;
}
const text = this.input.value.slice(currentActiveFilterName.length + 1).trim();

this.showFilterByInputText(text);
if (text.length === 0) {
return;
}
console.log(text);

if (event.key === "Enter") {
this.createNewFilter(currentActiveFilterName, text);
this.showFilterGroup();
currentActiveFilterName = null;
this.input.value = "";
}
});

this.attachShadow({ mode: "open" }).appendChild(clone);
}

showFilterGroup(filterName = null) {
if (filterName !== null && !kFiltersName.has(filterName)) {
this.filterSearchGroup.classList.add("hidden");

return;
}

this.filterSearchGroup.querySelectorAll("ul li").forEach((element) => element.classList.remove("hidden"));
this.filterSearchGroup.classList.remove("hidden");
}

showFilterByInputText(text = this.input.value.trim()) {
const elements = this.filterSearchGroup.querySelectorAll("ul li");

for (const pkgElement of elements) {
const dataValue = pkgElement.getAttribute("data-value");
if (text === "") {
pkgElement.classList.remove("hidden");
}
else {
pkgElement.classList[dataValue.match(text) ? "remove" : "add"]("hidden");
}
}
}

createNewFilter(filterName, searchStr = null) {
const text = searchStr === null ? `${filterName}:` : `${filterName}: ${searchStr}`;
const pElement = createDOMElement("p", { text });

this.activeFilters.add(filterName);
this.queries.push([`${filterName}:${searchStr}`, pElement])
this.filtersContainer.appendChild(pElement);
}

updateCurrentFilter(text = "", erase = false) {
const pElement = this.filtersContainer.lastChild;
if (erase) {
pElement.textContent = text;
}
else {
pElement.textContent = pElement.textContent + text;
}
}

removeLatestFilter() {
const [fullQuery, pElement] = this.queries.pop();
const [filterName] = fullQuery.split(":");

this.activeFilters.delete(filterName);
this.filtersContainer.removeChild(pElement);
this.input.value = fullQuery;
this.inputUpdateValue = true;
this.input.focus();
this.input.dispatchEvent(new Event("keyup"));
}

close() {
this.results_container.classList.add("hidden");
this.resultsContainer.classList.add("hidden");
this.input.value = "";
this.input.blur();
}
Expand Down
14 changes: 14 additions & 0 deletions public/css/searchbar.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@ p, ul, li {
padding: 0;
}

.input-filters {
display: flex;
height: 24px;
}
.input-filters > p {
background: #B0BEC5;
color: #FFF;
border-radius: 2px;
line-height: 24px;
padding: 0 3px;
margin-right: 5px;
font-size: 15px;
font-style: oblique;
}
input {
border: none;
outline: none;
Expand Down

0 comments on commit 02023ab

Please sign in to comment.