Watch
1
0
Fork
You've already forked Seyyed_arc
0
forked from hesabix/arc
Seyyed_arc/extraScripts/shabake-tamin/assets/js/catalog.js

858 lines
25 KiB
JavaScript

/**
* کاتالوگ عمومی — بدون وابستگی به CDN؛ فقط fetch به REST وردپرس.
*/
(function () {
'use strict';
function t(key) {
var S = window.shabakeTamin || {};
var i = S.i18n || {};
return i[key] || key;
}
function absUrl(path) {
var base = (window.shabakeTamin && window.shabakeTamin.apiPublicBase) || '';
if (!path) return '';
if (/^https?:\/\//i.test(path)) return path;
if (!base) return path;
return base.replace(/\/$/, '') + (path.charAt(0) === '/' ? path : '/' + path);
}
function noImageUrl() {
return (window.shabakeTamin && window.shabakeTamin.noImageUrl) || '';
}
function productImageSrc(p) {
var img = (p && (p.thumbnail_url || p.image_url)) || '';
return img ? absUrl(img) : noImageUrl();
}
function telHref(num) {
if (!num) return '';
return 'tel:' + String(num).replace(/[^\d+]/g, '');
}
function renderSupplierContactBlock(sup, opts) {
opts = opts || {};
var compact = !!opts.compact;
if (!sup) return '';
var hasContact =
sup.business_name ||
sup.address ||
sup.province ||
sup.city ||
sup.country ||
(sup.show_contact && (sup.phone || sup.mobile));
if (!hasContact) return '';
var loc = [sup.province, sup.city].filter(Boolean).join(' — ');
var country = sup.country ? String(sup.country) : '';
var locationLine = [loc, country].filter(Boolean).join(' · ');
var parts = [];
parts.push(
'<div class="st-supplier-contact' + (compact ? ' st-supplier-contact--compact' : '') + '">'
);
if (!compact) {
parts.push(
'<div class="st-supplier-contact-title">' + esc(t('supplierContactTitle')) + '</div>'
);
}
if (sup.business_name) {
parts.push(
'<div class="st-supplier-contact-name">' + esc(sup.business_name) + '</div>'
);
}
parts.push('<div class="st-supplier-contact-rows">');
if (sup.address) {
parts.push(
'<div class="st-supplier-contact-row"><span class="st-supplier-contact-icon" aria-hidden="true">📍</span><span class="st-supplier-contact-text">' +
nl2br(sup.address) +
'</span></div>'
);
}
if (locationLine) {
parts.push(
'<div class="st-supplier-contact-row"><span class="st-supplier-contact-icon" aria-hidden="true">🗺</span><span class="st-supplier-contact-text">' +
esc(locationLine) +
'</span></div>'
);
}
if (sup.show_contact) {
if (sup.phone) {
parts.push(
'<div class="st-supplier-contact-row"><span class="st-supplier-contact-icon" aria-hidden="true">☎</span><a class="st-supplier-contact-link" href="' +
esc(telHref(sup.phone)) +
'">' +
esc(sup.phone) +
'</a></div>'
);
}
if (sup.mobile) {
parts.push(
'<div class="st-supplier-contact-row"><span class="st-supplier-contact-icon" aria-hidden="true">📱</span><a class="st-supplier-contact-link" href="' +
esc(telHref(sup.mobile)) +
'">' +
esc(sup.mobile) +
'</a></div>'
);
}
}
parts.push('</div></div>');
return parts.join('');
}
function esc(s) {
var d = document.createElement('div');
d.textContent = s == null ? '' : String(s);
return d.innerHTML;
}
function nl2br(s) {
return esc(s).replace(/\n/g, '<br />');
}
function sanitizeHtmlBasic(html) {
if (!html) return '';
var d = document.createElement('div');
d.innerHTML = String(html);
var bad = d.querySelectorAll('script,style,iframe,object,embed');
for (var i = 0; i < bad.length; i++) {
bad[i].parentNode.removeChild(bad[i]);
}
return d.innerHTML;
}
function renderGallery(p) {
var thumbs = p.gallery_thumbnail_urls || [];
var full = p.gallery_urls || [];
if (!thumbs.length) return '';
var items = '';
for (var gi = 0; gi < thumbs.length; gi++) {
var tu = absUrl(thumbs[gi]);
var fu = absUrl(full[gi] || thumbs[gi]);
items +=
'<button type="button" class="st-gallery-thumb" data-full="' +
esc(fu) +
'"><img src="' +
esc(tu) +
'" alt="" loading="lazy" /></button>';
}
return (
'<div class="st-detail-gallery-wrap"><strong class="st-detail-gallery-label">' +
esc(t('galleryLabel')) +
'</strong><div class="st-detail-gallery">' +
items +
'</div></div>'
);
}
function parseCfg(root) {
var el = root.querySelector('.st-json-config');
if (!el || !el.textContent) return {};
try {
return JSON.parse(el.textContent);
} catch (e) {
return {};
}
}
function fmtPrice(n) {
if (n === null || n === undefined || n === '') return t('priceNA');
var x = Number(n);
if (isNaN(x)) return t('priceNA');
try {
return new Intl.NumberFormat('fa-IR').format(x);
} catch (e) {
return String(x);
}
}
function fmtCount(n) {
if (n === Infinity || n === 'Infinity') {
return '…';
}
var x = Number(n);
if (isNaN(x)) {
return String(n);
}
try {
return new Intl.NumberFormat('fa-IR').format(x);
} catch (e2) {
return String(x);
}
}
function errMsg(payload) {
if (!payload) return t('errorGeneric');
if (payload.error && typeof payload.error === 'string') return payload.error;
var r = payload.remote;
if (r && r.error && r.error.message) return r.error.message;
if (r && r.detail && r.detail.error && r.detail.error.message) return r.detail.error.message;
if (r && r.detail && r.detail.message) return r.detail.message;
if (r && r.detail && typeof r.detail === 'string') return r.detail;
return t('errorGeneric');
}
function renderSpecsTable(specs) {
if (!specs || !specs.length) return '';
var rows = '';
for (var i = 0; i < specs.length; i++) {
var s = specs[i] || {};
var label = s.label || s.key || '';
var value = s.value || '';
if (!label || !value) continue;
rows +=
'<tr><th scope="row">' +
esc(label) +
'</th><td>' +
esc(value) +
'</td></tr>';
}
if (!rows) return '';
return (
'<div class="st-detail-specs-wrap"><strong class="st-detail-specs-label">' +
esc(t('specsLabel')) +
'</strong><table class="st-detail-specs"><tbody>' +
rows +
'</tbody></table></div>'
);
}
function initRoot(root) {
var cfg = parseCfg(root);
var rest = (window.shabakeTamin && window.shabakeTamin.restBase) || '';
var configured = window.shabakeTamin && window.shabakeTamin.configured;
var grid = root.querySelector('.st-grid');
var statusEl = root.querySelector('.st-catalog-status');
var loadBtn = root.querySelector('.st-loadmore');
var searchInp = root.querySelector('.st-search-input');
var searchBtn = root.querySelector('.st-search-btn');
var statsEl = root.querySelector('.st-pub-result-stats');
if (searchInp) searchInp.placeholder = t('search');
var skip = 0;
var take = cfg.take || 20;
var total = Infinity;
var loading = false;
var q = '';
function updateResultStats() {
if (!statsEl) return;
var tpl = t('resultCountTemplate');
var totStr = total === Infinity ? '…' : fmtCount(total);
statsEl.textContent = tpl.replace('{shown}', fmtCount(skip)).replace('{total}', totStr);
}
function setStatus( msg, isErr, isInfo ) {
if (!statusEl) return;
if (!msg) {
statusEl.hidden = true;
statusEl.textContent = '';
statusEl.classList.remove('st-is-error', 'st-is-info');
return;
}
statusEl.hidden = false;
statusEl.textContent = msg;
statusEl.classList.toggle('st-is-error', !!isErr);
statusEl.classList.toggle('st-is-info', !!isInfo && !isErr);
}
function setLoading(on) {
root.classList.toggle('st-is-loading', !!on);
}
var provInput = root.querySelector('.st-filter-province');
var cityInput = root.querySelector('.st-filter-city');
var brandInput = root.querySelector('.st-filter-brand');
var filterBtn = root.querySelector('.st-filter-apply');
if (brandInput) brandInput.placeholder = t('brandFilterPlaceholder');
function effectiveProvince() {
if (provInput) return String(provInput.value || '').trim();
return cfg.province != null && cfg.province !== '' ? String(cfg.province) : '';
}
function effectiveCity() {
if (cityInput) return String(cityInput.value || '').trim();
return cfg.city != null && cfg.city !== '' ? String(cfg.city) : '';
}
function effectiveBrand() {
if (brandInput) return String(brandInput.value || '').trim();
return cfg.brand != null && cfg.brand !== '' ? String(cfg.brand) : '';
}
function params() {
var p = new URLSearchParams();
p.set('skip', String(skip));
p.set('take', String(take));
if (cfg.businessId) p.set('business_id', String(cfg.businessId));
if (cfg.categoryId) p.set('category_id', String(cfg.categoryId));
var pv = effectiveProvince();
var cv = effectiveCity();
var bv = effectiveBrand();
if (pv) p.set('province', pv);
if (cv) p.set('city', cv);
if (bv) p.set('brand', bv);
if (q) p.set('search', q);
return p.toString();
}
function renderItem(row) {
var p = row.product || {};
var sup = row.supplier || {};
var uuid = p.catalog_public_uuid || '';
var imgSrc = productImageSrc(p);
var price = fmtPrice(p.base_sales_price);
var card = document.createElement('article');
card.className = 'st-card';
card.dataset.uuid = uuid;
card.dataset.businessId = String(row.business_id || '');
var html = '';
html += '<div class="st-card-img-wrap">';
html +=
'<img class="st-card-img' +
(imgSrc === noImageUrl() ? ' st-card-img--fallback' : '') +
'" src="' +
esc(imgSrc) +
'" alt="" loading="lazy" />';
html += '</div>';
html += '<div class="st-card-body">';
html += '<h3 class="st-card-title">' + esc(p.name || '') + '</h3>';
if (p.short_description) {
html += '<div class="st-card-short">' + esc(p.short_description) + '</div>';
}
if (p.brand || p.model) {
html += '<div class="st-card-brand">' + esc([p.brand, p.model].filter(Boolean).join(' — ')) + '</div>';
}
if (p.category_name) html += '<div class="st-card-meta">' + esc(p.category_name) + '</div>';
html += '<div class="st-card-price">' + esc(price) + '</div>';
html += renderSupplierContactBlock(sup, { compact: true });
html += '<div class="st-card-actions">';
if (cfg.showProductDetails !== false) {
html += '<button type="button" class="st-btn-details button">' + esc(t('details')) + '</button>';
}
html += '<button type="button" class="st-btn-contact button">' + esc(t('contact')) + '</button>';
html += '</div></div>';
card.innerHTML = html;
return card;
}
function appendItems(items) {
if (!grid) return;
for (var i = 0; i < items.length; i++) {
grid.appendChild(renderItem(items[i]));
}
Array.prototype.forEach.call(grid.querySelectorAll('.st-btn-contact'), function (btn) {
btn.addEventListener('click', onContactClick);
});
Array.prototype.forEach.call(grid.querySelectorAll('.st-btn-details'), function (btn) {
btn.addEventListener('click', onDetailClick);
});
}
function onContactClick(ev) {
ev.preventDefault();
ev.stopPropagation();
var card = ev.target.closest('.st-card');
if (!card) return;
openContactModal({
businessId: parseInt(card.dataset.businessId, 10),
productUuid: card.dataset.uuid || null,
});
}
function onDetailClick(ev) {
ev.preventDefault();
ev.stopPropagation();
var card = ev.target.closest('.st-card');
if (!card) return;
var id = card.dataset.uuid || '';
if (id) openProductDetail(id);
}
function openProductDetail(uuid) {
if (!uuid || !configured) {
if (!configured) window.alert(t('notConfigured'));
return;
}
var overlay = document.createElement('div');
overlay.className = 'st-modal-overlay st-detail-overlay';
overlay.setAttribute('role', 'dialog');
overlay.setAttribute('aria-modal', 'true');
overlay.innerHTML =
'<div class="st-modal st-detail-modal">' +
'<button type="button" class="st-modal-close" aria-label="' +
esc(t('close')) +
'">&times;</button>' +
'<div class="st-detail-loading">' +
esc(t('loading')) +
'</div></div>';
document.body.appendChild(overlay);
function closeDetail() {
overlay.remove();
}
overlay.querySelector('.st-modal-close').addEventListener('click', closeDetail);
overlay.addEventListener('click', function (e) {
if (e.target === overlay) closeDetail();
});
fetch(rest + 'product/' + encodeURIComponent(uuid), { credentials: 'same-origin' })
.then(function (r) {
return r.json().then(function (j) {
return { ok: r.ok, json: j };
});
})
.then(function (x) {
var j = x.json;
if (!x.ok || !j.ok || !j.data || !j.data.item) throw new Error(errMsg(j));
var row = j.data.item;
var p = row.product || {};
var sup = row.supplier || {};
var bid = parseInt(row.business_id, 10) || 0;
var imgSrc = productImageSrc(p);
var parts = [];
parts.push(
'<button type="button" class="st-modal-close" aria-label="' +
esc(t('close')) +
'">&times;</button>'
);
parts.push('<h2 class="st-modal-title st-detail-title">' + esc(p.name || '') + '</h2>');
parts.push(
'<div class="st-detail-img-wrap" id="st-detail-main-img-wrap"><img class="st-detail-img' +
(imgSrc === noImageUrl() ? ' st-detail-img--fallback' : '') +
'" id="st-detail-main-img" src="' +
esc(imgSrc) +
'" alt="" /></div>'
);
parts.push(renderGallery(p));
if (p.category_name) {
parts.push('<div class="st-detail-meta">' + esc(p.category_name) + '</div>');
}
parts.push('<div class="st-detail-price">' + esc(fmtPrice(p.base_sales_price)) + '</div>');
parts.push(renderSupplierContactBlock(sup));
if (p.main_unit) {
parts.push(
'<div class="st-detail-unit"><strong>' +
esc(t('unitLabel')) +
'</strong> ' +
esc(p.main_unit) +
'</div>'
);
}
if (p.min_order_qty != null && p.min_order_qty !== '') {
parts.push(
'<div class="st-detail-min-order"><strong>' +
esc(t('minOrderLabel')) +
'</strong> ' +
esc(fmtCount(p.min_order_qty)) +
'</div>'
);
}
if (p.lead_time_days != null && p.lead_time_days !== '') {
parts.push(
'<div class="st-detail-lead-time"><strong>' +
esc(t('leadTimeLabel')) +
'</strong> ' +
esc(fmtCount(p.lead_time_days)) +
' ' +
esc(t('daysSuffix')) +
'</div>'
);
}
if (p.brand || p.model) {
var bm = [p.brand, p.model].filter(Boolean).join(' — ');
parts.push(
'<div class="st-detail-brand"><strong>' +
esc(t('brandModelLabel')) +
'</strong> ' +
esc(bm) +
'</div>'
);
}
if (p.country_of_origin) {
parts.push(
'<div class="st-detail-origin"><strong>' +
esc(t('originLabel')) +
'</strong> ' +
esc(p.country_of_origin) +
'</div>'
);
}
if (p.video_url) {
parts.push(
'<div class="st-detail-video"><a href="' +
esc(p.video_url) +
'" target="_blank" rel="noopener noreferrer">' +
esc(t('videoLabel')) +
'</a></div>'
);
}
if (p.updated_at) {
parts.push(
'<div class="st-detail-updated"><strong>' +
esc(t('updatedLabel')) +
'</strong> ' +
esc(p.updated_at) +
'</div>'
);
}
if (p.short_description) {
parts.push(
'<div class="st-detail-short-wrap"><strong class="st-detail-short-label">' +
esc(t('shortDescriptionLabel')) +
'</strong><div class="st-detail-short">' +
nl2br(p.short_description) +
'</div></div>'
);
}
if (p.description) {
parts.push(
'<div class="st-detail-desc-wrap"><strong class="st-detail-desc-label">' +
esc(t('descriptionLabel')) +
'</strong><div class="st-detail-desc">' +
nl2br(p.description) +
'</div></div>'
);
}
if (p.expert_review) {
parts.push(
'<div class="st-detail-expert-wrap"><strong class="st-detail-expert-label">' +
esc(t('expertReviewLabel')) +
'</strong><div class="st-detail-expert st-detail-expert-html"></div></div>'
);
}
parts.push(renderSpecsTable(p.specifications));
parts.push('<div class="st-detail-actions">');
if (bid > 0) {
parts.push(
'<button type="button" class="button st-detail-contact">' +
esc(t('contact')) +
'</button>'
);
}
parts.push('</div>');
var modal = overlay.querySelector('.st-detail-modal');
modal.innerHTML = parts.join('');
var expertEl = modal.querySelector('.st-detail-expert-html');
if (expertEl && p.expert_review) {
expertEl.innerHTML = sanitizeHtmlBasic(p.expert_review);
}
Array.prototype.forEach.call(modal.querySelectorAll('.st-gallery-thumb'), function (btn) {
btn.addEventListener('click', function () {
var main = modal.querySelector('#st-detail-main-img');
var full = btn.getAttribute('data-full');
if (main && full) main.src = full;
});
});
modal.querySelector('.st-modal-close').addEventListener('click', closeDetail);
var cbtn = modal.querySelector('.st-detail-contact');
if (cbtn) {
cbtn.addEventListener('click', function () {
closeDetail();
openContactModal({ businessId: bid, productUuid: uuid });
});
}
})
.catch(function (e) {
var modal = overlay.querySelector('.st-detail-modal');
modal.innerHTML =
'<button type="button" class="st-modal-close" aria-label="' +
esc(t('close')) +
'">&times;</button>' +
'<p class="st-detail-error">' +
esc(e.message || t('detailLoadError')) +
'</p>';
modal.querySelector('.st-modal-close').addEventListener('click', closeDetail);
});
}
function openContactModal(ctx) {
if (!ctx.businessId || isNaN(ctx.businessId) || ctx.businessId < 1) {
window.alert(t('errorGeneric'));
return;
}
var overlay = document.createElement('div');
overlay.className = 'st-modal-overlay';
overlay.innerHTML =
'<div class="st-modal" role="dialog" aria-modal="true">' +
'<button type="button" class="st-modal-close" aria-label="' +
esc(t('close')) +
'">&times;</button>' +
'<h2 class="st-modal-title">' +
esc(t('contact')) +
'</h2>' +
'<form class="st-contact-form">' +
'<label>' +
esc(t('name')) +
'<input type="text" name="sender_name" required maxlength="200" /></label>' +
'<label>' +
esc(t('contactField')) +
'<input type="text" name="sender_contact" required maxlength="200" /></label>' +
'<label>' +
esc(t('message')) +
'<textarea name="message" required maxlength="2000" rows="4"></textarea></label>' +
'<div class="st-captcha-row">' +
'<img class="st-captcha-img" alt="" />' +
'<button type="button" class="st-captcha-refresh">' +
esc(t('refreshCaptcha')) +
'</button></div>' +
'<label>' +
esc(t('captcha')) +
'<input type="text" name="captcha_code" required maxlength="16" autocomplete="off" /></label>' +
'<input type="hidden" name="captcha_id" />' +
'<div class="st-form-status" hidden></div>' +
'<button type="submit" class="button st-submit">' +
esc(t('send')) +
'</button>' +
'</form></div>';
document.body.appendChild(overlay);
var form = overlay.querySelector('.st-contact-form');
var capImg = overlay.querySelector('.st-captcha-img');
var capId = form.querySelector('input[name="captcha_id"]');
var formStatus = overlay.querySelector('.st-form-status');
function close() {
overlay.remove();
}
overlay.querySelector('.st-modal-close').addEventListener('click', close);
overlay.addEventListener('click', function (e) {
if (e.target === overlay) close();
});
function loadCaptcha() {
return fetch(rest + 'captcha', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'same-origin',
body: '{}',
})
.then(function (r) {
return r.json().then(function (j) {
return { ok: r.ok, json: j };
});
})
.then(function (x) {
var j = x.json;
if (!x.ok || !j.ok || !j.data) throw new Error(errMsg(j));
capId.value = j.data.captcha_id || '';
var b64 = j.data.image_base64 || '';
capImg.src = 'data:image/png;base64,' + b64;
});
}
overlay.querySelector('.st-captcha-refresh').addEventListener('click', function () {
loadCaptcha().catch(function (e) {
formStatus.hidden = false;
formStatus.textContent = e.message || t('errorGeneric');
});
});
loadCaptcha().catch(function (e) {
formStatus.hidden = false;
formStatus.textContent = e.message || t('errorGeneric');
});
form.addEventListener('submit', function (e) {
e.preventDefault();
formStatus.hidden = true;
var fd = new FormData(form);
var body = {
business_id: ctx.businessId,
sender_name: fd.get('sender_name'),
sender_contact: fd.get('sender_contact'),
message: fd.get('message'),
captcha_id: fd.get('captcha_id'),
captcha_code: fd.get('captcha_code'),
};
if (ctx.productUuid) body.product_catalog_uuid = ctx.productUuid;
fetch(rest + 'contact', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
credentials: 'same-origin',
body: JSON.stringify(body),
})
.then(function (r) {
return r.json().then(function (j) {
return { ok: r.ok, json: j };
});
})
.then(function (x) {
if (x.json && x.json.ok && x.json.data && x.json.data.saved) {
formStatus.hidden = false;
formStatus.classList.remove('st-is-error');
formStatus.textContent = t('sentOk');
form.reset();
loadCaptcha();
return;
}
throw new Error(errMsg(x.json));
})
.catch(function (err) {
formStatus.hidden = false;
formStatus.classList.add('st-is-error');
formStatus.textContent = err.message || t('errorGeneric');
loadCaptcha();
});
});
}
function updateSupplierBanner(items, reset) {
var bannerEl = root.querySelector('.st-supplier-banner');
if (!bannerEl) return;
if (!reset) return;
var sup = null;
if (cfg.businessId && items.length && items[0].supplier) {
sup = items[0].supplier;
} else if (items.length) {
var bid = items[0].business_id;
var allSame = true;
for (var bi = 0; bi < items.length; bi++) {
if (items[bi].business_id !== bid) {
allSame = false;
break;
}
}
if (allSame && items[0].supplier) {
sup = items[0].supplier;
}
}
if (!sup) {
bannerEl.hidden = true;
bannerEl.innerHTML = '';
return;
}
var html = renderSupplierContactBlock(sup);
if (!html) {
bannerEl.hidden = true;
bannerEl.innerHTML = '';
return;
}
bannerEl.innerHTML = html;
bannerEl.hidden = false;
}
function load(reset) {
if (!configured) {
setStatus(t('notConfigured'), true);
return;
}
if (loading) return;
loading = true;
if (reset) {
skip = 0;
total = Infinity;
if (grid) grid.innerHTML = '';
var bannerEl = root.querySelector('.st-supplier-banner');
if (bannerEl) {
bannerEl.hidden = true;
bannerEl.innerHTML = '';
}
}
setStatus('');
setLoading(true);
if (loadBtn) loadBtn.disabled = true;
fetch(rest + 'catalog?' + params(), { credentials: 'same-origin' })
.then(function (r) {
return r.json().then(function (j) {
return { ok: r.ok, json: j };
});
})
.then(function (x) {
var j = x.json;
if (!x.ok || !j.ok) throw new Error(errMsg(j));
var data = j.data || {};
var items = data.items || [];
total = typeof data.total_count === 'number' ? data.total_count : total;
appendItems(items);
updateSupplierBanner(items, reset);
skip += items.length;
if (loadBtn) {
loadBtn.hidden = skip >= total;
loadBtn.disabled = false;
loadBtn.textContent = t('loadMore');
}
if (reset && items.length === 0) {
setStatus(t('emptyResults'), false, true);
}
if (statsEl) {
updateResultStats();
}
})
.catch(function (e) {
setStatus(e.message || t('errorGeneric'), true, false);
if (loadBtn) loadBtn.disabled = false;
})
.then(function () {
loading = false;
setLoading(false);
});
}
if (loadBtn) {
loadBtn.addEventListener('click', function () {
load(false);
});
}
function doSearch() {
q = searchInp ? String(searchInp.value || '').trim() : '';
load(true);
}
function doApplyFilters() {
load(true);
}
if (filterBtn) {
filterBtn.addEventListener('click', doApplyFilters);
}
function bindEnterApply(el) {
if (!el) return;
el.addEventListener('keydown', function (e) {
if (e.key === 'Enter') {
e.preventDefault();
doApplyFilters();
}
});
}
bindEnterApply(provInput);
bindEnterApply(cityInput);
bindEnterApply(brandInput);
if (searchBtn && searchInp) {
searchBtn.addEventListener('click', doSearch);
searchInp.addEventListener('keydown', function (e) {
if (e.key === 'Enter') {
e.preventDefault();
doSearch();
}
});
}
load(true);
}
function boot() {
var roots = document.querySelectorAll('.st-catalog-root[data-st-root="1"]');
for (var i = 0; i < roots.length; i++) {
initRoot(roots[i]);
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', boot);
} else {
boot();
}
})();