(function (){
"use strict";
var MAX_SELECTED_SWATCHES=10;
function getProductRoot(block){
var el=block;
while (el&&el!==document.body){
if((el.classList&&el.classList.contains("product")) ||
(el.classList&&el.classList.contains("type-product")) ||
(el.matches&&el.matches(".woocommerce div.product"))
) return el;
el=el.parentElement;
}
return document;
}
function getNearestVariationForm(block){
if(!window.jQuery) return null;
var $=window.jQuery;
var $block=$(block);
var $product=$block.closest(".product, .type-product, .woocommerce div.product");
if($product.length){
var $f=$product.find("form.variations_form").first();
if($f.length) return $f;
}
var $prev=$block.prevAll("form.variations_form").first();
if($prev.length) return $prev;
var $next=$block.nextAll("form.variations_form").first();
if($next.length) return $next;
var $any=$("form.variations_form").first();
return $any.length ? $any:null;
}
function getScopedMainImage(block){
var root=getProductRoot(block);
return (
root.querySelector(".woocommerce-product-gallery__wrapper img") ||
root.querySelector(".woocommerce-product-gallery__image img") ||
root.querySelector(".woocommerce-product-gallery img.wp-post-image") ||
root.querySelector(".breakdance-woocommerce-product-images img") ||
root.querySelector("img.wp-post-image") ||
null
);
}
function hardSwapMainImageWithRetry(block, newSrc, newSrcset, newSizes, newAlt){
var tries=0;
var maxTries=12;
var timer=setInterval(function (){
tries++;
var img=getScopedMainImage(block);
if(img){
img.setAttribute("src", newSrc);
if(newSrcset) img.setAttribute("srcset", newSrcset);
if(newSizes) img.setAttribute("sizes", newSizes);
if(newAlt) img.setAttribute("alt", newAlt);
var link=img.closest("a");
if(link) link.setAttribute("href", newSrc);
}
if(tries >=maxTries) clearInterval(timer);
}, 100);
}
function getVariationDataMap($form){
if(!$form||!$form.length||!window.jQuery) return {};
var raw=$form.attr("data-product_variations");
var arr=[];
if(raw){
try { arr=JSON.parse(raw); } catch (e){ arr=[]; }}else{
var data=$form.data("product_variations");
if(Array.isArray(data)) arr=data;
}
var map={};
if(!Array.isArray(arr)) return map;
for (var i=0; i < arr.length; i++){
var v=arr[i];
var vid=parseInt((v&&v.variation_id)||"0", 10);
if(vid > 0) map[vid]=v;
}
return map;
}
function findFirstSelectableVariationId(localContainer, colorSlug){
if(!localContainer) return 0;
var input=localContainer.querySelector('.zoop-qty-input[data-variation_id]:not([disabled])');
if(input) return parseInt(input.getAttribute("data-variation_id")||"0", 10)||0;
var row=localContainer.querySelector('tr[data-zoop-color-row="' + colorSlug + '"]');
if(row){
var rowInput=row.querySelector('.zoop-qty-input[data-variation_id]');
if(rowInput) return parseInt(rowInput.getAttribute("data-variation_id")||"0", 10)||0;
}
var any=localContainer.querySelector('.zoop-qty-input[data-variation_id]');
return any ? (parseInt(any.getAttribute("data-variation_id")||"0", 10)||0):0;
}
function triggerWooVariationGallery(block, localContainer, colorSlug){
if(!window.jQuery) return;
var $form=getNearestVariationForm(block);
if(!$form||!$form.length) return;
var vid=findFirstSelectableVariationId(localContainer, colorSlug);
if(!vid) return;
var map=getVariationDataMap($form);
var variation=map[vid];
if(!variation) return;
$form.trigger("found_variation", [variation]);
$form.trigger("show_variation", [variation]);
$form.trigger("woocommerce_variation_select_change");
$form.trigger("check_variations");
setTimeout(function (){ $form.trigger("check_variations"); }, 0);
}
function initBlock(block){
var swatches=block.querySelectorAll(".zoop-swatch");
var container=block.querySelector(".zoop-bulk-variations-container");
if(!swatches||!swatches.length||!container||typeof ZoopBulkAjax==="undefined") return;
var rowCache={};
var prefetching={};
var selected=[];
function notifyGalleryColorSelected(colorSlug){
var productId=parseInt(block.dataset.currentProductId||"0", 10)||0;
document.dispatchEvent(new CustomEvent("zoop:color-selected", {
detail: {
productId: productId,
colorSlug: String(colorSlug||"")
}}));
}
function cssEscapeSafe(str){
if(window.CSS&&typeof window.CSS.escape==="function") return window.CSS.escape(str);
return String(str).replace(/"/g, '\\"');
}
function isMobileView(){
return window.matchMedia&&window.matchMedia("(max-width: 768px)").matches;
}
function scrollToQuantityTableOnMobile(){
if(!isMobileView()) return;
var target =
container.querySelector(".zoop-mobile-cards-wrap") ||
container.querySelector(".zoop-desktop-table-wrap") ||
container.querySelector(".zoop-bulk-form") ||
container;
if(!target) return;
requestAnimationFrame(function (){
var rect=target.getBoundingClientRect();
var y=window.pageYOffset + rect.top - 16;
window.scrollTo({ top: Math.max(0, y), behavior: "smooth" });
});
}
function ensureOverlay(){
var root=getProductRoot(block);
if(!root||root===document) root=block;
if(window.getComputedStyle(root).position==="static"){
root.style.position="relative";
}
var overlay=root.querySelector(".zoop-loading-overlay");
if(overlay) return overlay;
overlay=document.createElement("div");
overlay.className="zoop-loading-overlay";
overlay.setAttribute("aria-hidden", "true");
overlay.innerHTML =
'<div class="zoop-loading-overlay__content">' +
'<span class="zoop-loading-overlay__dot" aria-hidden="true"></span>' +
'<span class="zoop-loading-overlay__text">Kraunama...</span>' +
'</div>';
root.appendChild(overlay);
return overlay;
}
function showOverlay(){
var overlay=ensureOverlay();
if(!overlay) return;
overlay.classList.add("is-visible");
overlay.setAttribute("aria-hidden", "false");
}
function hideOverlay(){
var root=getProductRoot(block);
if(!root||root===document) root=block;
var overlay=root.querySelector(".zoop-loading-overlay");
if(!overlay) return;
overlay.classList.remove("is-visible");
overlay.setAttribute("aria-hidden", "true");
}
function setSwatchActive(el, active){
if(!el) return;
el.classList.toggle("is-active", !!active);
el.setAttribute("aria-pressed", active ? "true":"false");
}
function buildRowPayloadObj(colorSlug){
return {
action: ZoopBulkAjax.action_row,
nonce: ZoopBulkAjax.nonce,
product_id: block.dataset.currentProductId||"",
color_slug: colorSlug||"",
color_taxonomy: block.dataset.colorTaxonomy||"",
size_taxonomy: block.dataset.sizeTaxonomy||""
};}
function syncWooVariationSelection(colorSlug, localContainer){
if(!window.jQuery) return;
var $form=getNearestVariationForm(block);
if(!$form||!$form.length) return;
var colorTax=block.dataset.colorTaxonomy||"";
var sizeTax=block.dataset.sizeTaxonomy||"";
if(!colorTax) return;
var colorAttrName="attribute_" + colorTax;
var sizeAttrName=sizeTax ? "attribute_" + sizeTax:"";
var $colorSelect=$form.find('select[name="' + colorAttrName + '"]');
if($colorSelect.length) $colorSelect.val(colorSlug).trigger("change");
if(sizeAttrName&&localContainer){
var $sizeSelect=$form.find('select[name="' + sizeAttrName + '"]');
if($sizeSelect.length){
var firstAvailableInput=localContainer.querySelector('.zoop-qty-input[data-size-slug]:not([disabled])');
if(firstAvailableInput){
var firstSizeSlug=firstAvailableInput.getAttribute("data-size-slug")||"";
if(firstSizeSlug) $sizeSelect.val(firstSizeSlug).trigger("change");
}}
}
$form.trigger("woocommerce_variation_select_change");
$form.trigger("check_variations");
setTimeout(function (){ $form.trigger("check_variations"); }, 0);
triggerWooVariationGallery(block, localContainer, colorSlug);
}
function syncMainProductImageFromRow(colorSlug){
var rowImg=null;
if(colorSlug){
var escaped=(window.CSS&&CSS.escape) ? CSS.escape(colorSlug):String(colorSlug).replace(/"/g, '\\"');
var row=container.querySelector('tr[data-zoop-color-row="' + escaped + '"]');
if(row) rowImg=row.querySelector(".zoop-selected-variation-image");
}
if(!rowImg) rowImg=container.querySelector(".zoop-selected-variation-image");
if(!rowImg) return;
var newSrc=rowImg.getAttribute("src");
if(!newSrc) return;
var $form=getNearestVariationForm(block);
if($form&&window.jQuery){
var imagePayload={
src: newSrc,
full_src: newSrc,
gallery_thumbnail_src: newSrc,
thumb_src: newSrc,
srcset: rowImg.getAttribute("srcset")||"",
sizes: rowImg.getAttribute("sizes")||"",
title: rowImg.getAttribute("title")||"",
caption: "",
alt: rowImg.getAttribute("alt")||""
};
$form.trigger("found_variation", [{ image: imagePayload }]);
$form.trigger("show_variation", [{ image: imagePayload }]);
}
hardSwapMainImageWithRetry(
block,
newSrc,
rowImg.getAttribute("srcset")||"",
rowImg.getAttribute("sizes")||"",
rowImg.getAttribute("alt")||""
);
}
function renderSingle(html, colorSlug){
window.ZoopBulkRender.renderSingleColorHtml({
container: container,
syncWooVariationSelection: syncWooVariationSelection,
syncMainProductImageFromRow: syncMainProductImageFromRow
}, html, colorSlug);
}
function renderSingleFromStructure(data, colorSlug){
window.ZoopBulkRender.renderSingleFromStructure({
container: container,
syncWooVariationSelection: syncWooVariationSelection,
syncMainProductImageFromRow: syncMainProductImageFromRow
}, data, colorSlug);
}
function parseDesktopPiecesFromHtml(html){
var wrapper=document.createElement("div");
wrapper.innerHTML=html;
var table=wrapper.querySelector(".zoop-bulk-table");
if(!table) return null;
var headerThs=Array.prototype.slice.call(table.querySelectorAll("thead th"));
var rowTr=table.querySelector("tbody tr");
if(!rowTr) return null;
var rowTds=Array.prototype.slice.call(rowTr.children||[]);
if(!rowTds.length) return null;
return { headerThs: headerThs, previewCell: rowTds[0], sizeTds: rowTds.slice(1) };}
function ensureDesktopMultiSkeleton(){
if(container.querySelector("form.zoop-bulk-form.zoop-multi")) return;
var productId=block.dataset.currentProductId||"";
container.innerHTML=[
'<form class="zoop-bulk-form zoop-multi" method="post" action="">',
'  <input type="hidden" name="product_id" value="' + String(productId).replace(/"/g, "&quot;") + '">',
'  <div class="zoop-desktop-table-wrap"><table class="zoop-bulk-table zoop-bulk-table-multi"><thead><tr><th class="zoop-col-preview"></th></tr></thead><tbody></tbody></table></div>',
'  <button type="button" class="button alt zoop-add-selected"><span class="zoop-btn-text">Į krepšelį</span><span class="zoop-btn-spinner" aria-hidden="true"></span></button>',
'</form>'
].join("");
window.ZoopBulkRender.bindBulkAdd(container.querySelector("form.zoop-bulk-form"));
}
function setMultiHeaderFrom(headerThs, sizeCellCount){
var table=container.querySelector(".zoop-bulk-table-multi");
if(!table) return;
var headRow=table.querySelector("thead tr");
if(!headRow) return;
var currentSizeHeaders=Math.max(0, headRow.children.length - 1);
var needed=Math.max(currentSizeHeaders, sizeCellCount, Math.max(0, headerThs.length - 1));
while ((headRow.children.length - 1) < needed){
var idx=headRow.children.length;
var th=headerThs[idx] ? headerThs[idx].cloneNode(true):document.createElement("th");
if(!th.textContent||!th.textContent.trim()) th.textContent="";
headRow.appendChild(th);
}}
function insertOrReplaceMultiRow(colorSlug, pieces){
ensureDesktopMultiSkeleton();
var table=container.querySelector(".zoop-bulk-table-multi");
var tbody=table ? table.querySelector("tbody"):null;
if(!tbody) return;
setMultiHeaderFrom(pieces.headerThs, pieces.sizeTds.length);
var tr=document.createElement("tr");
tr.setAttribute("data-zoop-color-row", colorSlug);
tr.appendChild(pieces.previewCell.cloneNode(true));
for (var z=0; z < pieces.sizeTds.length; z++) tr.appendChild(pieces.sizeTds[z].cloneNode(true));
var existing=tbody.querySelector('tr[data-zoop-color-row="' + cssEscapeSafe(colorSlug) + '"]');
if(existing) existing.parentNode.replaceChild(tr, existing);
else tbody.appendChild(tr);
}
function removeMultiRow(colorSlug){
var table=container.querySelector(".zoop-bulk-table-multi");
if(!table) return;
var tbody=table.querySelector("tbody");
if(!tbody) return;
var row=tbody.querySelector('tr[data-zoop-color-row="' + cssEscapeSafe(colorSlug) + '"]');
if(row) row.parentNode.removeChild(row);
if(!tbody.querySelector("tr")) container.innerHTML="";
}
function prefetchColor(colorSlug){
if(!colorSlug||window.ZoopBulkCore.cacheGet(rowCache, colorSlug)||prefetching[colorSlug]) return;
prefetching[colorSlug]=true;
var payload=buildRowPayloadObj(colorSlug);
window.ZoopBulkCore.fetchWithNonceRetry(payload)
.then(function (res){
var json=res&&res.json ? res.json:null;
if(json&&json.success&&json.data&&json.data.html){
window.ZoopBulkCore.cacheSet(rowCache, colorSlug, json.data.html);
}})
.catch(function (){})
.finally(function (){ delete prefetching[colorSlug]; });
}
function loadSingleColor(colorSlug){
showOverlay();
var cached=window.ZoopBulkCore.cacheGet(rowCache, colorSlug);
if(cached){
renderSingle(cached, colorSlug);
scrollToQuantityTableOnMobile();
hideOverlay();
return;
}
window.ZoopBulkCore.postFormEncoded({
action: ZoopBulkAjax.action_row_structure,
nonce: ZoopBulkAjax.nonce,
product_id: block.dataset.currentProductId||"",
color_slug: colorSlug||""
}).then(function (json){
if(!json||!json.success||!json.data) throw new Error("Failed to load structure.");
renderSingleFromStructure(json.data, colorSlug);
scrollToQuantityTableOnMobile();
hideOverlay();
}).catch(function (){
var payload=buildRowPayloadObj(colorSlug);
return window.ZoopBulkCore.fetchWithNonceRetry(payload).then(function (res){
var json=res&&res.json ? res.json:null;
if(!json||!json.success||!json.data||!json.data.html) throw new Error("Failed to load variations.");
window.ZoopBulkCore.cacheSet(rowCache, colorSlug, json.data.html);
renderSingle(json.data.html, colorSlug);
scrollToQuantityTableOnMobile();
hideOverlay();
});
}).catch(function (err){
hideOverlay();
window.ZoopBulkRender.setError(container, err&&err.message ? err.message:"Failed to load variations.");
});
}
function toggleDesktopMulti(colorSlug, swatchEl){
var idx=selected.indexOf(colorSlug);
if(idx!==-1){
selected.splice(idx, 1);
setSwatchActive(swatchEl, false);
removeMultiRow(colorSlug);
return;
}
if(selected.length >=MAX_SELECTED_SWATCHES){
alert("You can select up to " + MAX_SELECTED_SWATCHES + " colors at a time.");
return;
}
selected.push(colorSlug);
setSwatchActive(swatchEl, true);
notifyGalleryColorSelected(colorSlug);
showOverlay();
var cached=window.ZoopBulkCore.cacheGet(rowCache, colorSlug);
if(cached){
var pieces=parseDesktopPiecesFromHtml(cached);
if(pieces) insertOrReplaceMultiRow(colorSlug, pieces);
syncWooVariationSelection(colorSlug, container);
hideOverlay();
return;
}
var payload=buildRowPayloadObj(colorSlug);
window.ZoopBulkCore.fetchWithNonceRetry(payload).then(function (res){
var json=res&&res.json ? res.json:null;
if(!json||!json.success||!json.data||!json.data.html) throw new Error("Failed to load variations.");
window.ZoopBulkCore.cacheSet(rowCache, colorSlug, json.data.html);
var pieces=parseDesktopPiecesFromHtml(json.data.html);
if(!pieces||!pieces.sizeTds||!pieces.sizeTds.length) throw new Error("No sizes found for selected color");
insertOrReplaceMultiRow(colorSlug, pieces);
syncWooVariationSelection(colorSlug, container);
syncMainProductImageFromRow(colorSlug);
hideOverlay();
}).catch(function (err){
hideOverlay();
selected=selected.filter(function (s){ return s!==colorSlug; });
setSwatchActive(swatchEl, false);
removeMultiRow(colorSlug);
alert((err&&err.message) ? err.message:"No sizes found for selected color.");
});
}
for (var i=0; i < swatches.length; i++) (function (swatch){
var slug=swatch.dataset.zoopColor||"";
swatch.addEventListener("click", function (e){
e.preventDefault();
e.stopPropagation();
if(isMobileView()){
for (var j=0; j < swatches.length; j++) setSwatchActive(swatches[j], false);
setSwatchActive(swatch, true);
notifyGalleryColorSelected(slug);
selected=[slug];
loadSingleColor(slug);
return;
}
toggleDesktopMulti(slug, swatch);
}, true);
swatch.addEventListener("mouseenter", function (){
prefetchColor(slug);
}, { passive: true });
swatch.addEventListener("touchstart", function (){
prefetchColor(slug);
}, { passive: true });
})(swatches[i]);
container.innerHTML="";
}
document.addEventListener("DOMContentLoaded", function (){
var blocks=document.querySelectorAll(".zoop-product-variations-block");
for (var i=0; i < blocks.length; i++) initBlock(blocks[i]);
});
})();