erpnext.ProductSearch = class { constructor() { this.MAX_RECENT_SEARCHES = 4; this.searchBox = $("#search-box"); this.setupSearchDropDown(); this.bindSearchAction(); } setupSearchDropDown() { this.search_area = $("#dropdownMenuSearch"); this.setupSearchResultContainer(); this.populateRecentSearches(); } bindSearchAction() { let me = this; // Show Search dropdown this.searchBox.on("focus", () => { this.search_dropdown.removeClass("hidden"); }); // If click occurs outside search input/results, hide results. // Click can happen anywhere on the page $("body").on("click", (e) => { let searchEvent = $(e.target).closest('#search-box').length; let resultsEvent = $(e.target).closest('#search-results-container').length; let isResultHidden = this.search_dropdown.hasClass("hidden"); if (!searchEvent && !resultsEvent && !isResultHidden) { this.search_dropdown.addClass("hidden"); } }); // Process search input this.searchBox.on("input", (e) => { let query = e.target.value; if (query.length == 0) { me.populateResults([]); me.populateCategoriesList([]); } if (query.length < 3 || !query.length) return; // Populate recent search chips me.setRecentSearches(query); // Fetch and populate product results frappe.call({ method: "erpnext.templates.pages.product_search.search", args: { query: query }, callback: (data) => { me.populateResults(data); } }); // Populate categories if (me.category_container) { frappe.call({ method: "erpnext.templates.pages.product_search.get_category_suggestions", args: { query: query }, callback: (data) => { me.populateCategoriesList(data); } }); } this.search_dropdown.removeClass("hidden"); }); } setupSearchResultContainer() { this.search_dropdown = this.search_area.append(` `).find("#search-results-container"); this.setupCategoryContainer() this.setupProductsContainer(); this.setupRecentsContainer(); } setupProductsContainer() { this.products_container = this.search_dropdown.append(`
`).find("#product-scroll"); } setupCategoryContainer() { this.category_container = this.search_dropdown.append(`
`).find(".category-chips"); } setupRecentsContainer() { let $recents_section = this.search_dropdown.append(`
${ __("Recent") }
`).find(".recent-searches"); this.recents_container = $recents_section.append(`
`).find("#recents"); } getRecentSearches() { return JSON.parse(localStorage.getItem("recent_searches") || "[]"); } attachEventListenersToChips() { let me = this; const chips = $(".recent-search"); window.chips = chips; for (let chip of chips) { chip.addEventListener("click", () => { me.searchBox[0].value = chip.innerText.trim(); // Start search with `recent query` me.searchBox.trigger("input"); me.searchBox.focus(); }); } } setRecentSearches(query) { let recents = this.getRecentSearches(); if (recents.length >= this.MAX_RECENT_SEARCHES) { // Remove the `first` query recents.splice(0, 1); } if (recents.indexOf(query) >= 0) { return; } recents.push(query); localStorage.setItem("recent_searches", JSON.stringify(recents)); this.populateRecentSearches(); } populateRecentSearches() { let recents = this.getRecentSearches(); if (!recents.length) { this.recents_container.html(`No searches yet.`); return; } let html = ""; recents.forEach((key) => { html += ` `; }); this.recents_container.html(html); this.attachEventListenersToChips(); } populateResults(data) { if (data.length === 0 || data.message.results.length === 0) { let empty_html = ``; this.products_container.html(empty_html); return; } let html = ""; let search_results = data.message.results; search_results.forEach((res) => { let thumbnail = res.thumbnail || '/assets/erpnext/images/ui-states/cart-empty-state.png'; html += ` `; }); this.products_container.html(html); } populateCategoriesList(data) { if (data.length === 0 || data.message.results.length === 0) { let empty_html = `
`; this.category_container.html(empty_html); return; } let html = `
${ __("Categories") }
`; let search_results = data.message.results; search_results.forEach((category) => { html += ` ${ category.name } `; }); this.category_container.html(html); } };