import jQ from "jquery";
import Utils from "../../../helpers/utils";
import Class from "../../../helpers/class";
import Settings from "../../../helpers/settings";
import Globals from "../../../helpers/globals";
import InstantSearchResultItem from "./instant-search-result-item";
/**
* Instant search result item - Product item
* @extends InstantSearchResultItem
*/
class InstantSearchResultItemProduct extends InstantSearchResultItem {
/**
* @constructs
*/
constructor() {
super();
this.id = '';
this.title = '';
this.imageUrl = '';
this.url = '';
this.sku = '';
this.label = '';
this.vendor = '';
this.isShow = false;
}
/**
* Enum of Product item templates (SKU, VENDOR, IMAGE, PRICE_SALE)
* @enum {Object}
*/
static get tempType() {
return {
SKU: 'sku',
VENDOR: 'vendor',
IMAGE: 'thumb',
PRICE: 'regular_price',
PRICE_SALE: 'sale_price'
};
}
/**
* Get the raw template of Instant search result item - Product item
* @returns {String} The raw HTML string
*/
getTemplate(tempType) {
switch (tempType) {
case InstantSearchResultItemProduct.tempType.IMAGE:
return `
<div class="{{class.searchSuggestion}}-left">
<img src="{{imageUrl}}" alt="{{escapedTitle}}">
</div>
`;
case InstantSearchResultItemProduct.tempType.SKU:
return `
<p class="{{class.searchSuggestion}}-product-sku">SKU: {{sku}}</p>
`;
case InstantSearchResultItemProduct.tempType.VENDOR:
return `
<p class="{{class.searchSuggestion}}-product-vendor">{{vendor}}</p>
`;
case InstantSearchResultItemProduct.tempType.PRICE:
return `
<p class="{{class.searchSuggestion}}-product-price">
<span class="{{class.searchSuggestion}}-product-regular-price">{{regularPrice}}</span>
</p>
`;
case InstantSearchResultItemProduct.tempType.PRICE_SALE:
return `
<p class="{{class.searchSuggestion}}-product-price">
<s>{{compareAtPrice}}</s>
<span class="{{class.searchSuggestion}}-product-sale-price">{{regularPrice}}</span>
</p>
`;
default:
return `
<li class="{{class.searchSuggestionItem}} {{class.searchSuggestionItem}}-product {{class.searchUiAutocompleteItem}}" aria-label="{{escapedBlockType}}: {{escapedTitle}}" data-id="{{id}}">
<a href="{{url}}" {{newTabAttribute}}>
{{itemProductImage}}
<div class="{{class.searchSuggestion}}-right">
<p class="{{class.searchSuggestion}}-product-title">{{title}}</p>
{{itemProductSku}}
{{itemProductVendor}}
{{itemProductPrice}}
</div>
</a>
</li>
`;
}
}
/**
* Replace the brackets in raw html template with proper values
* @returns {String} HTML string
*/
compileTemplate() {
if (this.isShow) {
var searchTerm = Utils.escape(Globals.currentTerm);
// Product image
var imageHTML = '';
if (Settings.getSettingValue('search.showSuggestionProductImage') && this.imageUrl.length) {
imageHTML = this.getTemplate(InstantSearchResultItemProduct.tempType.IMAGE);
imageHTML = imageHTML.replace(/{{imageUrl}}/g, this.imageUrl);
}
// Product title
var productTitle = this.customizeProductTitle();
productTitle = this._highlightSuggestionResult(productTitle, searchTerm);
// SKU
var skuHTML = '';
if (Settings.getSettingValue('search.showSuggestionProductSku') && this.sku.length) {
skuHTML = this.getTemplate(InstantSearchResultItemProduct.tempType.SKU);
skuHTML = skuHTML.replace(/{{sku}}/g, this.sku);
}
// Vendor
var vendorHTML = '';
if (Settings.getSettingValue('search.showSuggestionProductVendor') && this.vendor.length) {
vendorHTML = this.getTemplate(InstantSearchResultItemProduct.tempType.VENDOR);
vendorHTML = vendorHTML.replace(/{{vendor}}/g, this.vendor);
}
// Price
var priceHTML = this.compileSuggestionProductPrice();
// Open the result item in new tab when selected
var newTabAttr = Settings.getSettingValue('search.openProductNewTab') ? 'target="_blank"' : '';
return this.getTemplate()
.replace(/{{id}}/g, this.id)
.replace(/{{escapedBlockType}}/g, Utils.escape(this.parent.type))
.replace(/{{url}}/g, this.url)
.replace(/{{newTabAttribute}}/g, newTabAttr)
.replace(/{{itemProductImage}}/g, imageHTML)
.replace(/{{title}}/g, productTitle)
.replace(/{{escapedTitle}}/g, Utils.escape(productTitle))
.replace(/{{itemProductSku}}/g, skuHTML)
.replace(/{{itemProductVendor}}/g, vendorHTML)
.replace(/{{itemProductPrice}}/, priceHTML)
.replace(/{{class.searchSuggestion}}/g, Class.searchSuggestion)
.replace(/{{class.searchSuggestionItem}}/g, Class.searchSuggestionItem)
.replace(/{{class.searchUiAutocompleteItem}}/g, Class.searchUiAutocompleteItem);
} else {
return '';
}
}
/**
* Render the Instant search result item - Product item
* @returns {Object} jQuery object
*/
render() {
if (this.isShow) {
this.$element = jQ(this.compileTemplate());
// Set item data for ui-autocomplete-item
var type = Utils.escape(this.parent.type);
var title = Utils.escape(this.title);
this.$element.data('ui-autocomplete-item', {
label: type + ': ' + title,
value: title
});
} else {
this.$element = null;
}
}
/**
* Set data for Instant search result item - Product item
* @param {Object} data Instant search result item data
*/
setData(data) {
if (data) {
this.data = data;
this.id = data.id;
this.title = data.title;
this.imageUrl = data.images_info.length > 0 ? Utils.optimizeImage(data.images_info[0].src, '200x') : boostPFSConfig.general.no_image_url;
this.url = Utils.buildProductItemUrl(data, false);
this.sku = data.skus && data.skus.length > 0 ? data.skus[0] : '';
this.label = data.label;
this.vendor = data.vendor;
this.isShow = true;
} else {
this.data = null;
this.id = '';
this.title = '';
this.imageUrl = '';
this.url = '';
this.sku = '';
this.label = '';
this.vendor = '';
this.isShow = false;
}
}
/**
* Build the product price and replace with the brackets in raw html template
*/
compileSuggestionProductPrice() {
// If the multi-currency feature is enabled, update the product price
this.prepareSuggestionProductPriceData();
// Check on sale
var onSale = this.data.compare_at_price_min > this.data.price_min;
// Format price
var price = Utils.formatMoney(this.data.price_min);
var compareAtPrice = '';
if (this.data && this.data.compare_at_price_min) {
compareAtPrice = Utils.formatMoney(this.data.compare_at_price_min);
if (Settings.getSettingValue('search.removePriceDecimal')) {
price = Utils.removeDecimal(price);
compareAtPrice = Utils.removeDecimal(compareAtPrice);
}
}
// Build Price
var result = '';
if (Settings.getSettingValue('search.showSuggestionProductPrice')) {
if (onSale && Settings.getSettingValue('search.showSuggestionProductSalePrice')) {
result = this.getTemplate(InstantSearchResultItemProduct.tempType.PRICE_SALE);
} else {
result = this.getTemplate(InstantSearchResultItemProduct.tempType.PRICE);
}
}
return result
.replace(/{{regularPrice}}/g, price)
.replace(/{{compareAtPrice}}/g, compareAtPrice);
}
/**
* Customize the Isntant search result item - product title
*/
customizeProductTitle() {
// Override this method for customization
return this.title;
}
/**
* Prepare product price data for multi-currency feature
*/
prepareSuggestionProductPriceData() {
var currenciesSeting = Settings.getSettingValue('general.currencies');
if (typeof currenciesSeting != 'undefined' && currenciesSeting.length > 1) {
var currentCurrency = Settings.getSettingValue('general.current_currency').toLowerCase().trim();
var prices = ['price_min', 'price_max', 'compare_at_price_min', 'compare_at_price_max'];
prices.forEach((priceKey) => {
var currentPriceKey = priceKey + '_' + currentCurrency;
if (typeof this.data[currentPriceKey] !== 'undefined') {
this.data[priceKey] = this.data[currentPriceKey];
}
});
}
}
}
export default InstantSearchResultItemProduct;