@salla.sa/twilight-components
Version:
Salla Web Component
169 lines (164 loc) • 8.86 kB
JavaScript
/*!
* Crafted with ❤ by Salla
*/
'use strict';
var index = require('./index-B99uI20k.js');
var search = require('./search-c7Aa7lM9.js');
var Helper = require('./Helper-CU4Xuiki.js');
require('./anime.es-BqW8JHZi.js');
const sallaSearchCss = ".s-search-placeholder-wrapper{position:relative;display:inline-block}.s-search-input-wrapper{position:relative}.s-search-placeholder-trigger{cursor:pointer;appearance:none;text-align:start}";
const SallaSearch = class {
constructor(hostRef) {
index.registerInstance(this, hostRef);
this.inputValue = '';
this.translationLoaded = false;
this.loading = false;
this.typing = false;
this.debounce = setTimeout(() => '', 1000);
/**
* Set the component to display as a placeholder (button) that will open the modal. Defaults to `false`
*/
this.placeholder = false;
/**
* Set the component display without modal window. Defaults to `false`
*/
this.inline = false;
/**
* Adds a border radius to the input. Half of the height.
*/
this.oval = false;
/**
* Sets the height of the input
*/
this.height = 60;
/**
* Maximum number of words allowed in the input
*/
this.maxWords = 5;
/**
* Show submit action buttons at the end.
*/
this.showAction = false;
this.productSlot =
this.host.querySelector('[slot="product"]')?.innerHTML || this.getDefaultProductSlot();
salla.event.on('search::open', () => this.open());
salla.lang.onLoaded(() => {
this.translationLoaded = true;
});
salla.event.on('modalClosed', () => this.onModalClose());
}
async open() {
if (!this.inline) {
await this.modal.open().then(() => setTimeout(() => this.searchInput.focus(), 300));
}
}
onModalClose() {
this.searchInput.value = '';
this.results = undefined;
this.afterSearching();
this.container.classList.remove('s-search-no-results');
}
handleKeyDown(ev) {
if (ev.key === 'Enter' && this.search_term?.length) {
window.location.href = salla.url.get('search?q=' + encodeURI(this.search_term));
}
}
getDefaultProductSlot() {
return ('<div class="s-search-product-image-container">' +
' <img class="s-search-product-image" src="{image}" alt="{name}"/>' +
'</div>' +
'<div class="s-search-product-details">' +
' <div class="s-search-product-title">{name}</div> <div class="s-search-product-price">{price} <span class="s-search-product-regular-price">{regular_price}</span></div>' +
'</div>');
}
debounceSearch(event) {
this.typing = true;
clearTimeout(this.debounce);
this.debounce = setTimeout(() => {
this.typing = false;
this.search_term = event.target.value;
}, 700);
}
limitWordsAndSearch(event) {
let value = event.target.value;
const words = value.trim().split(/\s+/);
if (words.length > this.maxWords) {
const truncatedInput = words.slice(0, this.maxWords).join(' ');
this.searchInput.value = truncatedInput;
}
this.debounceSearch(event);
}
getQueryParam(param) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(param);
}
handleActionClick() {
if (!!this.search_term && this.search_term.length > 2) {
return this.search(this.search_term);
}
}
handleSearch(val) {
this.inputValue = val;
if (val.length > 2) {
this.search(val);
}
else {
this.results = undefined;
this.afterSearching();
}
}
search(val) {
this.noResults.style.display = 'none';
//run loading spinner or stop it
this.loading = true;
salla.product
.fetch({ source: 'search', source_value: val })
.then(response => {
this.results = response;
salla.event.emit('Products Searched', val);
})
.catch(err => (err !== 'Query is same as previous one!' ? (this.results = undefined) : null))
.finally(() => this.afterSearching(/*isEmpty*/ false));
}
afterSearching(isEmpty = true) {
this.noResults.style.display = isEmpty || this.results?.data.length > 0 ? 'none' : 'block';
Helper.Helper.toggleElementClassIf(this.container, 's-search-container-open', 's-search-no-results', () => this.results?.data.length);
this.loading = false;
salla.product.api.previousQuery = ''; //avoid having error 'Query is same as previous one!' after reopen modal;
this.inputValue.length < 3 ? this.container.classList.remove('s-search-no-results') : '';
}
render() {
const searchContent = (index.h("div", { key: 'a403e7257b398cce5c26c61f55e143775575bb7b', class: { 's-search-container': true, 's-search-inline': this.inline }, ref: container => (this.container = container) }, index.h("div", { key: '3c3d523d181ec1c7b4e9d9e05988d1d2a4e0362d', class: "s-search-input-wrapper" }, index.h("span", { key: '86a8bcf0ab96c8818fc940d7ed4cfd70429ee2c1', class: "s-search-icon-wrap" }, index.h("span", { key: '0bacbc11b2b9c63c2167e79f46c73cb80804869a', class: "s-search-icon", innerHTML: this.loading ? '<i class="s-search-spinner-loader"/>' : search.Search })), index.h("input", { key: '766e7ae8ce9c2bdcf984d76c47a234ba5dc60d43', type: "search", enterkeyhint: "search", autocomplete: "off", class: "s-search-input", placeholder: salla.lang.get('blocks.header.search_placeholder'), onInput: (e) => this.limitWordsAndSearch(e), onKeyDown: e => this.handleKeyDown(e), ref: input => (this.searchInput = input), style: {
height: this.height + 'px',
borderRadius: this.oval ? this.height / 2 + 'px' : '',
} }), this.showAction ? (index.h("salla-button", { loading: this.loading, class: { 's-search-action': true, 's-search-action-oval': this.oval }, onClick: () => this.handleActionClick() }, !this.loading && index.h("span", { innerHTML: search.Search }))) : null), index.h("div", { key: '307c8fc64860af188bf1f1ba6eea480c357ac46d', class: "s-search-results" }, this.results?.data.map(product => (index.h("a", { href: product.url + '?from=search-bar', class: {
's-search-product': true,
's-search-product-not-available': !product.is_available,
}, innerHTML: this.productSlot
.replace(/\{name\}/g, product.name)
.replace(/\{price\}/g, product.price ? salla.money(product.price) : '')
.replace(/\{regular_price\}/g, product.is_on_sale && product.regular_price
? salla.money(product.regular_price)
: '')
.replace(/\{image\}/g, product.image.url) }))), index.h("p", { key: 'b0971a0eb27a98f2e4e53da6462b0a8fa1b7fa42', ref: el => (this.noResults = el), class: "s-search-no-results-placeholder" }, salla.lang.get('common.elements.no_options')))));
const modalContent = (index.h("salla-modal", { key: '9394500f337c06afad44d5202e8e84dc2feb317f', position: "top", class: "s-search-modal", ref: modal => (this.modal = modal) }, searchContent));
const placeholderContent = (index.h("div", { key: 'f092b80ca35842209eae7b1ef143619d2a718229', class: "s-search-placeholder-wrapper s-search-inline" }, index.h("div", { key: '020d98faaa926578057e49734d7f11077a0b933b', class: "s-search-input-wrapper" }, index.h("span", { key: '44b6f78b74952d562efcb6dcd652432b5b1a7053', class: "s-search-icon-wrap" }, index.h("span", { key: 'd4e4166510cc4d38e53668f0f4f3995861a65d24', class: "s-search-icon", innerHTML: search.Search })), index.h("button", { key: '615e5dd776936c182fa7f50efaebbe5fa0fb7c61', type: "button", class: "s-search-input s-search-placeholder-trigger", onClick: () => this.open(), style: {
height: this.height + 'px',
borderRadius: this.oval ? this.height / 2 + 'px' : '',
} }, salla.lang.get('blocks.header.search_placeholder'))), modalContent));
return this.placeholder ? (placeholderContent) : this.inline ? (index.h("div", { class: "s-search-modal" }, searchContent)) : (modalContent);
}
/**
* Run it one time after load
*/
componentDidLoad() {
this.afterSearching();
this.searchInput.value = this.getQueryParam('q');
}
get host() { return index.getElement(this); }
static get watchers() { return {
"search_term": ["handleSearch"]
}; }
};
SallaSearch.style = sallaSearchCss;
exports.salla_search = SallaSearch;