class ProductSlider { constructor() { this.sliders = new Map(); } /** * Creates a slider container with products * @param {Object} config - Configuration object * @param {string} config.urlProducts - URL to fetch products from * @param {string} config.title - Section title * @param {string|number} config.id - Unique identifier for the slider */ createSliderContainer({ urlProducts, title, id, quantity }) { const wrapper = this.createElement('div', { className: 'hotspot mb-5 --slider col-12 p-0' }); const titleElement = this.createElement('h2', { innerHTML: `${title}` }); const mainContainer = this.createElement('div', { className: 'products d-flex flex-wrap justify-content-center --adaptive' }); // Slider configuration this.setDataAttributes(mainContainer, { idm_id: id, href: urlProducts, count: quantity, slider: 3, scroll: 1, autoplay: 2000, margin: 5 }); wrapper.appendChild(titleElement); wrapper.appendChild(mainContainer); const container = document.querySelector(`[data-idm-id="${id}"]`); if (container) { container.appendChild(wrapper); this.initializeSlider(id); } else { console.error('Container element #container not found'); } } createElement(tag, attributes = {}) { const element = document.createElement(tag); Object.assign(element, attributes); return element; } setDataAttributes(element, attributes) { Object.entries(attributes).forEach(([key, value]) => { element.dataset[key] = value; }); } async initializeSlider(id) { const container = document.querySelector(`[data-idm-id="${id}"] .products`); if (!container) { console.error(`Container products in wrapper with data-idm-id="${id}" not found`); return; } const config = this.getSliderConfig(container); try { await this.loadAndRenderProducts(container, config); await this.waitForDOMReady(container); this.initializeSlickSlider(container, config); } catch (error) { console.error('Failed to load products:', error); } } waitForDOMReady(container) { return new Promise((resolve) => { requestAnimationFrame(() => { requestAnimationFrame(() => { resolve(); }); }); }); } getSliderConfig(container) { return { count: parseInt(container.dataset.count) || 16, slider: parseInt(container.dataset.slider) || 6, scroll: parseInt(container.dataset.scroll) || 6, autoplay: parseInt(container.dataset.autoplay) || 2000, margin: parseInt(container.dataset.margin) || 5, url: container.dataset.href }; } async fetchXMLData(url) { return new Promise((resolve, reject) => { const xhr = new XMLHttpRequest(); xhr.timeout = 12000; xhr.open('GET', `${url}?getProductXML=true`); xhr.responseType = 'document'; xhr.onload = () => { if (xhr.status === 200) { resolve(xhr.responseXML); } else { reject(new Error(`HTTP ${xhr.status}`)); } }; xhr.onerror = () => reject(new Error('Network error')); xhr.ontimeout = () => reject(new Error('Request timeout')); xhr.send(); }); } extractPriceInfo(productXML) { const priceEl = productXML.querySelector('price'); if (!priceEl) return null; return { price: priceEl.getAttribute('price_formatted'), value: parseFloat(priceEl.getAttribute('value')) || 0, maxPrice: priceEl.getAttribute('srp_formatted'), unitPrice: priceEl.getAttribute('unit_converted_price_formatted'), unitFormat: priceEl.getAttribute('unit_converted_format'), points: parseInt(priceEl.getAttribute('points')) || 0, pointsSum: parseInt(priceEl.getAttribute('points_sum')) || 0, rabatePercent: priceEl.getAttribute('srp_diff_percent') }; } generateProductHTML(product, productClasses) { const name = product.querySelectorAll('name')[1]?.textContent || ''; const id = product.getAttribute('id'); const photo = product.querySelector('icon_src')?.textContent || ''; const url = product.getAttribute('link'); const priceInfo = this.extractPriceInfo(product); const priceConfig = { isVat: false, isOmnibus: false }; if (!priceInfo) return ''; const priceHTML = this.generatePriceHTML(priceInfo, priceConfig); const unitPriceHTML = priceInfo.unitPrice ? `${priceInfo.unitPrice} / ${priceInfo.unitFormat}` : ''; return `
`; } generatePriceHTML(priceInfo, priceConfig) { if (priceInfo.price === 0) { return ` Cena na telefon `; } let priceHTML = ''; // Omnibus if (priceInfo.maxPrice) { priceHTML += `