Skip to content

Commit

Permalink
Render algolia search bars
Browse files Browse the repository at this point in the history
Render algolia search bars
  • Loading branch information
pkong-ds authored May 30, 2024
2 parents 14ff231 + 2bcfad4 commit 0caf488
Show file tree
Hide file tree
Showing 13 changed files with 359 additions and 242 deletions.
4 changes: 4 additions & 0 deletions public/Images/search-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
125 changes: 76 additions & 49 deletions public/scripts/device.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
const isDebug = true;
const isDebug = false;
const NUM_DEFAULT_MODEL_ITEMS_TO_DISPLAY = 0;
const NUM_DEFAULT_BRAND_ITEMS_TO_DISPLAY = 0;

function ready(fn) {
if (document.readyState != "loading") {
Expand All @@ -14,15 +16,19 @@ class RootViewModel {
selectedBrand = "all";
_deviceList;
_brandDeviceList;
_modelItems;
_brandItems;

constructor(deviceList, brandDeviceList) {
constructor(deviceList, brandDeviceList, modelItems, brandItems) {
mobx.makeObservable(this, {
searchText: mobx.observable,
selectedBrand: mobx.observable,
shouldShowSearchClear: mobx.computed,
});
this._deviceList = deviceList;
this._brandDeviceList = brandDeviceList;
this._modelItems = modelItems;
this._brandItems = brandItems;
}

get shouldShowSearchClear() {
Expand Down Expand Up @@ -95,67 +101,81 @@ function handleSelectBrandOption(selectParent, viewModel) {

function handleSearchInput(viewModel) {
// both inputs: header for lg-screen & top-of-page for sm-screen
const searchInputList = document.querySelectorAll(
".device-list__search-input",
);
const searchInputList = document.querySelectorAll(".aa-Input");
searchInputList.forEach((searchInput) => {
searchInput.addEventListener("input", (e) => {
viewModel.searchText = e.target.value;
});
});

// both inputs: header for lg-screen & top-of-page for sm-screen
const searchContainerList = document.querySelectorAll(
".device-list__search-container",
);
searchContainerList.forEach((searchContainer, i) => {
searchContainer.addEventListener("click", () => {
searchInputList[i].focus();
});
});
}

function handleSearchClearBtn(viewModel) {
const searchInputList = document.querySelectorAll(
".device-list__search-input",
);
const searchClearBtnList = document.querySelectorAll(
".device-list__search-input__clear-btn",
);

searchClearBtnList.forEach((searchClearBtn) => {
searchClearBtn.addEventListener("click", () => {
viewModel.searchText = "";
});
function initializeSearch(viewModel, containerId) {
console.log(containerId);
const { autocomplete } = window["@algolia/autocomplete-js"];
autocomplete({
container: containerId,
placeholder: "Search Device",
getSources() {
return [
{
sourceId: "models",
getItems({ query }) {
const defaultDisplayItems = modelItems.slice(
0,
NUM_DEFAULT_MODEL_ITEMS_TO_DISPLAY,
);
const filtered = modelItems.filter((model) => {
return model.name.toLowerCase().includes(query.toLowerCase());
});
return filtered.length > 0 ? filtered : defaultDisplayItems;
},
templates: {
item({ item, html }) {
return html`<a class="aa-ItemWrapper" href="${item.pathname}"
>${item.name}</a
>`;
},
},
getItemUrl({ item }) {
return `${window.location.origin}${item.pathname}`;
},
},
{
sourceId: "brands",
getItems({ query }) {
const defaultDisplayItems = brandItems.slice(
0,
NUM_DEFAULT_BRAND_ITEMS_TO_DISPLAY,
);
const filtered = brandItems.filter((brand) => {
return brand.name.toLowerCase().includes(query.toLowerCase());
});
return filtered.length > 0 ? filtered : defaultDisplayItems;
},
templates: {
item({ item, components, html }) {
return html`<a class="aa-ItemWrapper" href="${item.pathname}"
>${item.name}</a
>`;
},
},
getItemUrl({ item }) {
return `${window.location.origin}${item.pathname}`;
},
},
];
},
});

mobx.reaction(
() => viewModel.searchText,
() => {
searchInputList.forEach((searchInput) => {
searchInput.value = viewModel.searchText;
});
searchClearBtnList.forEach((searchClearBtn) => {
if (viewModel.shouldShowSearchClear) {
searchClearBtn.classList.remove("d-none");
} else {
searchClearBtn.classList.add("d-none");
}
});
},
);
handleSearchInput(viewModel);

tippy("[data-tippy-content]", {
tippy(".aa-ClearButton", {
content: "Clear",
placement: "bottom",
theme: "light-border",
});
}

function handleSearch(viewModel) {
handleSearchInput(viewModel);
handleSearchClearBtn(viewModel);
}

function main() {
const deviceGrids = document.querySelectorAll(".device-grid");
const brands = document.querySelectorAll(".device-brand-list__item-button");
Expand All @@ -164,12 +184,19 @@ function main() {
const viewModel = new RootViewModel(
window.deviceList,
window.brandDeviceList,
window.modelItems,
window.brandItems,
);
if (isDebug) {
window.viewModel = viewModel;
}

handleSearch(viewModel);
[
"#device-list__header__autocomplete",
"#device-list__page__autocomplete",
].forEach((containerId) => {
initializeSearch(viewModel, containerId);
});

mobx.reaction(
() => viewModel.selectedBrand,
Expand Down
102 changes: 73 additions & 29 deletions public/scripts/home.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
const NUM_DEFAULT_MODEL_ITEMS_TO_DISPLAY = 0;
const NUM_DEFAULT_BRAND_ITEMS_TO_DISPLAY = 0;

function ready(fn) {
if (document.readyState != "loading") {
fn();
Expand All @@ -9,12 +12,16 @@ ready(main);

class RootViewModel {
searchText = "";
_modelItems;
_brandItems;

constructor() {
constructor(modelItems, brandItems) {
mobx.makeObservable(this, {
searchText: mobx.observable,
shouldShowSearchClear: mobx.computed,
});
this._modelItems = modelItems;
this._brandItems = brandItems;
}

get shouldShowSearchClear() {
Expand All @@ -23,45 +30,82 @@ class RootViewModel {
}

function handleSearchInput(viewModel) {
const searchInput = document.querySelector(".search-device__input");
const searchInput = document.querySelector(".aa-Input");
searchInput.addEventListener("input", (e) => {
viewModel.searchText = e.target.value;
});

const searchContainer = document.querySelector(".search-device__container");
searchContainer.addEventListener("click", () => {
searchInput.focus();
});
}

function handleSearchClearBtn(viewModel) {
const searchInput = document.querySelector(".search-device__input");
const searchClearBtn = document.querySelector(".search-device__clear-btn");
searchClearBtn.addEventListener("click", () => {
viewModel.searchText = "";
});
function initializeAutocomplete(viewModel) {
const { autocomplete } = window["@algolia/autocomplete-js"];

const modelItems = viewModel._modelItems;
const brandItems = viewModel._brandItems;

mobx.reaction(
() => viewModel.searchText,
() => {
searchInput.value = viewModel.searchText;
if (viewModel.shouldShowSearchClear) {
searchClearBtn.classList.remove("d-none");
} else {
searchClearBtn.classList.add("d-none");
}
autocomplete({
container: "#homepage-autocomplete",
placeholder: "Search Device",
getSources() {
return [
{
sourceId: "models",
getItems({ query }) {
const defaultDisplayItems = modelItems.slice(
0,
NUM_DEFAULT_MODEL_ITEMS_TO_DISPLAY,
);
const filtered = modelItems.filter((model) => {
return model.name.toLowerCase().includes(query.toLowerCase());
});
return filtered.length > 0 ? filtered : defaultDisplayItems;
},
templates: {
item({ item, html }) {
return html`<a class="aa-ItemWrapper" href="${item.pathname}"
>${item.name}</a
>`;
},
},
getItemUrl({ item }) {
return `${window.location.origin}${item.pathname}`;
},
},
{
sourceId: "brands",
getItems({ query }) {
const defaultDisplayItems = brandItems.slice(
0,
NUM_DEFAULT_BRAND_ITEMS_TO_DISPLAY,
);
const filtered = brandItems.filter((brand) => {
return brand.name.toLowerCase().includes(query.toLowerCase());
});
return filtered.length > 0 ? filtered : defaultDisplayItems;
},
templates: {
item({ item, components, html }) {
return html`<a class="aa-ItemWrapper" href="${item.pathname}"
>${item.name}</a
>`;
},
},
getItemUrl({ item }) {
return `${window.location.origin}${item.pathname}`;
},
},
];
},
);
});

tippy("[data-tippy-content]", {
handleSearchInput(viewModel);

tippy(".aa-ClearButton", {
content: "Clear",
placement: "bottom",
theme: "light-border",
});
}

function main() {
const viewModel = new RootViewModel();

handleSearchInput(viewModel);
handleSearchClearBtn(viewModel);
const viewModel = new RootViewModel(window.modelItems, window.brandItems);
initializeAutocomplete(viewModel);
}
26 changes: 8 additions & 18 deletions src/layouts/BaseLayout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ const { shouldRenderSearchBar } = Astro.props;
rel="stylesheet"
href="https://unpkg.com/tippy.js@6/themes/light-border.css"
/>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/@algolia/autocomplete-theme-classic"
/>

<script type="text/javascript" src="/scripts/jquery/jquery-1.10.2.min.js"
></script>
Expand All @@ -64,6 +68,8 @@ const { shouldRenderSearchBar } = Astro.props;
<script type="text/javascript" src="https://unpkg.com/@popperjs/core@2"
></script>
<script type="text/javascript" src="https://unpkg.com/tippy.js@6"></script>
<script src="https://cdn.jsdelivr.net/npm/@algolia/autocomplete-js"
></script>
<script type="text/javascript" src="/scripts/main.js"></script>
<!-- ${ self.javascript() } -->

Expand Down Expand Up @@ -132,25 +138,9 @@ const { shouldRenderSearchBar } = Astro.props;
{
!!shouldRenderSearchBar ? (
<div class="header__search-container">
<div class="header__search-device__container device-list__search-container">
<img src="/Images/search.svg" />
<input
class="header__search-device__input device-list__search-input"
placeholder="Search Device"
type="search"
/>
<button
class="header__search-device__clear-btn d-none device-list__search-input__clear-btn"
data-tippy-content="Clear"
>
<img src="/Images/cross-gray.svg" />
</button>
</div>
{/* Add suggestion list here */}
<div id="device-list__header__autocomplete" />
</div>
) : (
<div class="header__search-container"> </div>
)
) : undefined
}

<div class="header__share">
Expand Down
Loading

0 comments on commit 0caf488

Please sign in to comment.