(function($){
const removeAttrClass=cfvsw_swatches_settings.remove_attr_class;
const addRemoveWithCommonClass=`${ removeAttrClass } cfvsw-swatches-out-of-stock`;
const addRemoveDisableClass=removeAttrClass + '-disable';
const addRemoveDisableClassCommon=`${ addRemoveDisableClass } cfvsw-swatches-disabled`;
const SW={
init: ()=> {
if(cfvsw_swatches_settings.disable_out_of_stock){
SW.firstTime();
SW.Events();
}},
firstTime: ()=> {
const getVariationTable=$('table.variations').not('.cfvsw-variation-disable-logic'
);
getVariationTable.addClass('cfvsw-variation-disable-logic');
getVariationTable.each(function (){
const table=$(this);
const getForm=table.closest('[data-product_id][data-product_variations]'
);
const getFormData=getForm.data('product_variations');
SW.swatchesOptions(getForm, getFormData);
});
},
chooseOption(){
const option=$(this);
const getForm=option.closest('[data-product_id][data-product_variations]'
);
getForm
.find('.disable-to-select')
.removeClass('disable-to-select');
const td=option.closest('td');
const checkTdSelected=td
.find('.cfvsw-hidden-select select')
.val();
if(''!==checkTdSelected){
td.addClass('disable-to-select');
}
const getFormData=getForm.data('product_variations');
SW.swatchesOptions(getForm, getFormData);
},
getSelectedOptions:(getForm)=> {
const getSelectedSwatches=getForm.find('.cfvsw-hidden-select select'
);
const selected={};
getSelectedSwatches.each(function (){
const select=$(this);
const getValue=select.val();
const getAttrName=select.attr('data-attribute_name');
if(''!==getValue&&''!==getAttrName){
selected[ getAttrName ]=getValue;
}});
return selected;
},
swatchesOptions:(getForm, getFormData)=> {
const getTdAvoidCurrent=getForm
.find('td')
.not('.disable-to-select');
const getAllSelect=getTdAvoidCurrent.find('.cfvsw-swatches-container[swatches-attr]'
);
if(! getAllSelect.length){
return;
}
const getSelectedOptions=SW.getSelectedOptions(getForm);
const findToRemoveClass=getTdAvoidCurrent.find(`.${ addRemoveDisableClass }`
);
if(findToRemoveClass.length){
findToRemoveClass.removeClass(addRemoveDisableClassCommon);
}
getAllSelect.each(function (){
const select=$(this);
const getAttrName=select.attr('swatches-attr');
if(''!==getAttrName){
const findOptions=select.find('.cfvsw-swatches-option');
findOptions.each(function (){
const optValue=$(this);
const currentTermSlug=optValue.attr('data-slug');
if(currentTermSlug&&''!==currentTermSlug){
const hasStock=SW.checkOptionAvail(getAttrName,
currentTermSlug,
getSelectedOptions,
getFormData
);
if(! hasStock){
optValue.addClass(addRemoveDisableClassCommon
);
}}
});
}});
},
checkOptionAvail: (
getAttrName,
currentTermSlug,
getSelectedOptions,
getFormData
)=> {
let hasThisSwatch;
for(let index=0; index < getFormData.length; index++){
const productVariations=getFormData[ index ];
const { attributes, is_in_stock }=productVariations;
const passedInRaw=SW.checkInPreRawData(getSelectedOptions,
attributes,
getAttrName,
currentTermSlug,
is_in_stock
);
if(passedInRaw){
hasThisSwatch=is_in_stock;
break;
}}
return hasThisSwatch;
},
checkInPreRawData: (
getSelectedOptions,
attributes,
getAttrName,
currentTermSlug,
is_in_stock
)=> {
let hasThisSwatch=false;
const copySelected={ ...getSelectedOptions };
const selectedKeys=Object.keys(getSelectedOptions);
const getCurrentIndex=selectedKeys.indexOf(getAttrName);
const currentObj={};
currentObj[ getAttrName ]=currentTermSlug;
if(getCurrentIndex >=0){
selectedKeys.splice(getCurrentIndex, 1);
delete copySelected[ getAttrName ];
}
hasThisSwatch=SW.checkInRawData(attributes,
copySelected,
currentObj,
is_in_stock
);
return hasThisSwatch;
},
checkInRawData:(attribute, selected, currentObj, is_in_stock)=> {
const cloneAttr={ ...attribute };
const selectedCurrent={ ...selected, ...currentObj };
let checkAndAvail=true;
for(const checkIsAvail in selectedCurrent){
const value=selectedCurrent[ checkIsAvail ];
const attrValue=attribute[ checkIsAvail ];
if(''===attrValue){
delete cloneAttr[ checkIsAvail ];
continue;
}
if(value===attrValue){
delete cloneAttr[ checkIsAvail ];
continue;
}
checkAndAvail=false;
}
if(is_in_stock){
return checkAndAvail;
}
for(const cloneKey in cloneAttr){
const cloneValue=cloneAttr[ cloneKey ];
if(''!==cloneValue){
checkAndAvail=false;
}}
return checkAndAvail;
},
Events: ()=> {
$(document).on('click',
'.cfvsw-swatches-container .cfvsw-swatches-option[data-slug]',
SW.chooseOption
);
$(document).on('berocket_ajax_products_infinite_loaded',
function (){
SW.firstTime();
}
);
},
};
$(document).on('click', '.cfvsw-swatches-option', function (){
const swatchesOption=$(this);
if(swatchesOption.hasClass('cfvsw-swatches-disabled') ||
swatchesOption.hasClass('cfvsw-swatches-out-of-stock')
){
return;
}
onClickSwatchesOption(swatchesOption);
addVariationFunctionality();
});
$('body').on('click',
'.cfvsw_ajax_add_to_cart.cfvsw_variation_found',
function(e){
e.preventDefault();
triggerAddToCart($(this) );
}
);
function onClickSwatchesOption(swatch){
if(swatch.hasClass('cfvsw-selected-swatch') ){
swatch.removeClass('cfvsw-selected-swatch');
resetPrice(swatch);
resetThumbnail(swatch);
resetButtonData(swatch);
}else{
const parent=swatch.parent();
parent.find('.cfvsw-swatches-option').each(function (){
$(this).removeClass('cfvsw-selected-swatch');
});
swatch.addClass('cfvsw-selected-swatch');
}
updateSelectOption(swatch);
if(cfvsw_swatches_settings.html_design!=='inline'){
updateTitle(swatch);
}}
function updateSelectOption(swatch){
const value=swatch.hasClass('cfvsw-selected-swatch')
? swatch.data('slug')
: '';
const select=swatch
.closest('.cfvsw-swatches-container')
.prev()
.find('select');
select.val(value).change();
}
function updateTitle(swatch){
const label=swatch.closest('tr').children('.label');
label.find('.cfvsw-selected-label').remove();
if(! swatch.hasClass('cfvsw-selected-swatch') ){
return;
}
label
.children('label')
.append('<span class="cfvsw-selected-label"></span>');
label
.children('label')
.children('.cfvsw-selected-label')
.html(swatch.data('title') );
}
function triggerAddToCart(variant){
if(variant.is('.wc-variation-is-unavailable') ){
return window.alert(cfvsw_swatches_settings.unavailable_text);
}
const productId=variant.data('product_id');
let variationId=variant.attr('data-variation_id');
variationId=parseInt(variationId);
if(isNaN(productId) ||
productId===0 ||
isNaN(variationId) ||
variationId===0
){
return true;
}
let variation=variant.attr('data-selected_variant');
variation=JSON.parse(variation);
const data={
action: 'cfvsw_ajax_add_to_cart',
security: cfvsw_swatches_settings.ajax_add_to_cart_nonce,
product_id: productId,
variation_id: variationId,
variation,
};
$(document.body).trigger('adding_to_cart', [ variant, data ]);
variant.removeClass('added').addClass('loading');
$.ajax({
type: 'POST',
url: cfvsw_swatches_settings.ajax_url,
data,
dataType: 'json',
success(response){
if(! response){
return;
}
if(response.error&&response.product_url){
window.location=response.product_url;
return;
}
$(document.body).trigger('added_to_cart', [
response.fragments,
response.cart_hash,
variant,
]);
$(document.body).trigger('update_checkout');
variant.removeClass('loading').addClass('added');
},
error(errorThrown){
variant.removeClass('loading');
console.log(errorThrown);
},
});
}
$(document).on('change', '.cfvsw-hidden-select select', function (){
setTimeout(()=> {
updateSwatchesAvailability();
}, 1);
});
$('.reset_variations').on('click', function (){
resetSwatches($(this) );
});
$(document).on({
mouseenter(){
const addToTooltip=$(this);
const tooltip=addToTooltip.data('tooltip');
if(''===tooltip ||
'undefined'===typeof tooltip ||
addToTooltip.hasClass('cfvsw-label-option')
){
return;
}
if(addToTooltip.children('.cfvsw-tooltip').length===0){
addToTooltip.prepend(`<div class="cfvsw-tooltip"><span class="cfvsw-tooltip-label">${ tooltip }</span></div>`
);
$('.cfvsw-tooltip').fadeIn(500);
const swatchHeight=addToTooltip
.children('.cfvsw-swatch-inner')
.innerHeight();
$('.cfvsw-tooltip').css({
bottom: swatchHeight,
});
if(cfvsw_swatches_settings.tooltip_image &&
addToTooltip.hasClass('cfvsw-image-option')
){
$('.cfvsw-tooltip').prepend("<span class='cfvsw-tooltip-preview'></span>"
);
const preview=addToTooltip
.children('.cfvsw-swatch-inner')
.css('backgroundImage');
$('.cfvsw-tooltip').css({
bottom: swatchHeight - 30,
padding: '2px',
});
$('.cfvsw-tooltip-preview').css({
backgroundImage: preview,
backgroundSize: 'cover',
});
}}
},
mouseleave(){
$('.cfvsw-tooltip').remove();
},
},
'.cfvsw-swatches-option'
);
$(document).on('ready', function (){
setTimeout(()=> {
setSwatchesSelection();
}, 1);
$('.woocommerce-widget-layered-nav-list').each(function (){
if($(this).find('.cfvsw-swatches-container').length){
$(this).addClass('cfvsw-filters');
}});
});
$('.cfvsw-shop-variations').on('click', function(e){
e.preventDefault();
});
$('.cfvsw-shop-variations .cfvsw-more-link').on('click', function(e){
window.location=e.target.href;
});
function updateSwatchesAvailability(){
$('.cfvsw-hidden-select select').each(function (){
const availableOptions=[];
$(this)
.children('option')
.each(function (){
if(''!==$(this).val()){
availableOptions.push($(this).val());
}});
$(this)
.parent()
.next()
.find('.cfvsw-swatches-option')
.each(function (){
if(-1===$.inArray($(this).attr('data-slug'),
availableOptions
)
){
$(this).addClass(addRemoveWithCommonClass);
}else{
$(this).removeClass(addRemoveWithCommonClass);
}});
});
}
function setSwatchesSelection(){
$('.cfvsw-hidden-select select').each(function (){
const selected=$(this).val();
$(this)
.parent()
.next()
.find(`[data-slug='${ selected }']`)
.trigger('click');
});
}
function resetSwatches(resetButton){
$('.cfvsw-swatches-option').each(function (){
$(this).removeClass('cfvsw-selected-swatch');
});
$('.cfvsw-selected-label').remove();
if(cfvsw_swatches_settings.disable_out_of_stock){
const table=resetButton.closest('table');
const findDisabledAttr=table.find(`.${ addRemoveDisableClass }`
);
const findDisableSelect=table.find('.disable-to-select');
if(findDisableSelect.length){
findDisableSelect.removeClass('disable-to-select');
}
if(findDisabledAttr){
findDisabledAttr.removeClass(addRemoveDisableClassCommon);
}
setTimeout(()=> {
SW.firstTime();
}, 20);
}}
function addVariationFunctionality(){
$('.cfvsw_variations_form:not(.variation-function-added)').each(function (){
const thisForm=$(this);
thisForm.addClass('variation-function-added');
thisForm.wc_variation_form();
thisForm.on('found_variation', function(e, variation){
updateThumbnail(thisForm, variation.image);
if(thisForm.attr('data-cfvsw-catalog') ){
return;
}
updatePrice(thisForm, variation);
updatebuttonData(thisForm, variation);
});
}
);
}
$(window).on('load', function (){
addVariationFunctionality();
});
function updateThumbnail(swatch, imageData){
const listItem=swatch.closest('li');
const thumbnail=listItem.find('img:first');
if(0===listItem.find('.cfvsw-original-thumbnail').length){
const originalThumbnail=thumbnail.clone();
thumbnail.after('<span class="cfvsw-original-thumbnail"></span>');
listItem
.find('.cfvsw-original-thumbnail')
.html(originalThumbnail);
}
thumbnail.attr('src', imageData.thumb_src);
thumbnail.attr('srcset', '');
}
function resetThumbnail(swatch){
const listItem=swatch.closest('li');
if(listItem.find('.cfvsw-original-thumbnail').length){
const thumbnail=listItem.find('img:first');
thumbnail.replaceWith(listItem.find('.cfvsw-original-thumbnail').html()
);
listItem.find('.cfvsw-original-thumbnail').remove();
}}
function updatePrice(swatch, variation){
if(0===variation.price_html.length){
return;
}
if(swatch.parents('li').find('.cfvsw-original-price').length){
const price=swatch.parents('li').find('.price');
price.replaceWith(variation.price_html);
}else{
const price=swatch.parents('li').find('.price');
price.after(variation.price_html);
price.removeClass('price').addClass('cfvsw-original-price');
}}
function resetPrice(swatch){
if(swatch.parents('li').find('.cfvsw-original-price').length){
swatch.parents('li').find('.price').remove();
swatch
.parents('li')
.find('.cfvsw-original-price')
.removeClass('cfvsw-original-price')
.addClass('price');
}}
function updatebuttonData(variant, variation){
const select=variant.find('.variations select');
const data={};
const button=variant
.parents('li')
.find('.cfvsw_ajax_add_to_cart');
select.each(function (){
const attributeName =
$(this).data('attribute_name')||$(this).attr('name');
const value=$(this).val()||'';
data[ attributeName ]=value;
});
button.html(button.data('add_to_cart_text') );
button.addClass('cfvsw_variation_found');
button.attr('data-variation_id', variation.variation_id);
button.attr('data-selected_variant', JSON.stringify(data) );
}
function resetButtonData(variant){
const button=variant
.parents('li')
.find('.cfvsw_ajax_add_to_cart');
button.html(button.data('select_options_text') );
button.removeClass('cfvsw_variation_found');
button.attr('data-variation_id', '');
button.attr('data-selected_variant', '');
}
SW.init();
document.addEventListener('astraInfinitePaginationLoaded', function (){
SW.firstTime();
addVariationFunctionality();
});
document.addEventListener('cfvswVariationLoad', function (){
SW.firstTime();
addVariationFunctionality();
});
})(jQuery);
(()=>{function e(){var n,r,o="function"==typeof Symbol?Symbol:{},c=o.iterator||"@@iterator",a=o.toStringTag||"@@toStringTag";function i(e,o,c,a){var i=o&&o.prototype instanceof s?o:s,l=Object.create(i.prototype);return t(l,"_invoke",function(e,t,o){var c,a,i,s=0,l=o||[],p=!1,d={p:0,n:0,v:n,a:f,f:f.bind(n,4),d:function(e,t){return c=e,a=0,i=n,d.n=t,u}};function f(e,t){for(a=e,i=t,r=0;!p&&s&&!o&&r<l.length;r++){var o,c=l[r],f=d.p,P=c[2];e>3?(o=P===t)&&(i=c[(a=c[4])?5:(a=3,3)],c[4]=c[5]=n):c[0]<=f&&((o=e<2&&f<c[1])?(a=0,d.v=t,d.n=c[1]):f<P&&(o=e<3||c[0]>t||t>P)&&(c[4]=e,c[5]=t,d.n=P,a=0))}if(o||e>1)return u;throw p=!0,t}return function(o,l,P){if(s>1)throw TypeError("Generator is already running");for(p&&1===l&&f(l,P),a=l,i=P;(r=a<2?n:i)||!p;){c||(a?a<3?(a>1&&(d.n=-1),f(a,i)):d.n=i:d.v=i);try{if(s=2,c){if(a||(o="next"),r=c[o]){if(!(r=r.call(c,i)))throw TypeError("iterator result is not an object");if(!r.done)return r;i=r.value,a<2&&(a=0)}else 1===a&&(r=c.return)&&r.call(c),a<2&&(i=TypeError("The iterator does not provide a '"+o+"' method"),a=1);c=n}else if((r=(p=d.n<0)?i:e.call(t,d))!==u)break}catch(e){c=n,a=1,i=e}finally{s=1}}return{value:r,done:p}}}(e,c,a),!0),l}var u={};function s(){}function l(){}function p(){}r=Object.getPrototypeOf;var d=[][c]?r(r([][c]())):(t(r={},c,function(){return this}),r),f=p.prototype=s.prototype=Object.create(d);function P(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,p):(e.__proto__=p,t(e,a,"GeneratorFunction")),e.prototype=Object.create(f),e}return l.prototype=p,t(f,"constructor",p),t(p,"constructor",l),l.displayName="GeneratorFunction",t(p,a,"GeneratorFunction"),t(f),t(f,a,"Generator"),t(f,c,function(){return this}),t(f,"toString",function(){return"[object Generator]"}),(e=function(){return{w:i,m:P}})()}function t(e,n,r,o){var c=Object.defineProperty;try{c({},"",{})}catch(e){c=0}t=function(e,n,r,o){function a(n,r){t(e,n,function(e){return this._invoke(n,r,e)})}n?c?c(e,n,{value:r,enumerable:!o,configurable:!o,writable:!o}):e[n]=r:(a("next",0),a("throw",1),a("return",2))},t(e,n,r,o)}function n(e,t,n,r,o,c,a){try{var i=e[c](a),u=i.value}catch(e){return void n(e)}i.done?t(u):Promise.resolve(u).then(r,o)}function r(e){return function(){var t=this,r=arguments;return new Promise(function(o,c){var a=e.apply(t,r);function i(e){n(a,o,c,i,u,"next",e)}function u(e){n(a,o,c,i,u,"throw",e)}i(void 0)})}}!function(t){"use strict";var n=window.ppcpRecaptchaSettings||{},o=null,c=null,a=null,i=!1;function u(){return new Promise(function(e){"undefined"!=typeof grecaptcha&&grecaptcha.execute?(console.log("PPCP reCAPTCHA: reCAPTCHA v3 loaded and ready"),e()):(console.log("PPCP reCAPTCHA: Waiting for reCAPTCHA v3 to load..."),setTimeout(function(){u().then(e)},100))})}function s(e,r){if(!n.isBlocks){var o=n.isSingleProduct?"form.cart":n.isCheckout?"form.checkout":null;if(o){var c=t(o);0!==c.length?(c.find('input[name="ppcp_recaptcha_token"]').remove(),c.find('input[name="ppcp_recaptcha_version"]').remove(),c.append('<input type="hidden" name="ppcp_recaptcha_token" value="'+e+'">'),c.append('<input type="hidden" name="ppcp_recaptcha_version" value="'+r+'">')):console.error("PPCP reCAPTCHA: Form not found for token update")}}}function l(e){console.log("PPCP reCAPTCHA: Checkout error detected");var t=e&&("string"==typeof e?e.toLowerCase().includes("captcha"):e.some(function(e){return e.content&&e.content.toLowerCase().includes("captcha")}));i?null!==a&&"undefined"!=typeof grecaptcha&&grecaptcha.reset&&(console.log("PPCP reCAPTCHA: Resetting v2 widget"),grecaptcha.reset(a),c=null):t?(console.log("PPCP reCAPTCHA: v3 failed on checkout, rendering v2"),f()):n.siteKeyV3&&(console.log("PPCP reCAPTCHA: Regenerating v3 token"),p())}function p(){return d.apply(this,arguments)}function d(){return(d=r(e().m(function t(){var r;return e().w(function(e){for(;;)switch(e.p=e.n){case 0:if("undefined"!=typeof grecaptcha&&grecaptcha.execute){e.n=1;break}return console.error("PPCP reCAPTCHA: grecaptcha v3 not loaded"),e.a(2);case 1:return e.p=1,e.n=2,grecaptcha.execute(n.siteKeyV3,{action:"ppcp"});case 2:o=e.v,console.log("PPCP reCAPTCHA: New v3 token generated"),s(o,"v3"),n.isBlocks&&window.wp&&window.wp.data&&window.wp.data.dispatch("wc/store/checkout").__internalSetExtensionData("ppcp_recaptcha",{token:o,version:"v3"}),e.n=4;break;case 3:e.p=3,r=e.v,console.error("PPCP reCAPTCHA: Failed to generate v3 token",r),o=null;case 4:return e.a(2)}},t,null,[[1,3]])}))).apply(this,arguments)}function f(){if(!i&&n.siteKeyV2){var e=document.getElementById(n.v2ContainerId);if(e)if("undefined"!=typeof grecaptcha&&grecaptcha.render){e.innerHTML="";var t=document.createElement("div");t.className="g-recaptcha",t.setAttribute("data-sitekey",n.siteKeyV2),t.setAttribute("data-theme",n.theme),e.appendChild(t),a=grecaptcha.render(t,{sitekey:n.siteKeyV2,theme:n.theme,callback:function(e){c=e,console.log("PPCP reCAPTCHA: v2 verified"),s(e,"v2"),n.isBlocks&&window.wp&&window.wp.data&&window.wp.data.dispatch("wc/store/checkout").__internalSetExtensionData("ppcp_recaptcha",{token:e,version:"v2"})},"expired-callback":function(){c=null,s("","v2"),n.isBlocks&&window.wp&&window.wp.data&&window.wp.data.dispatch("wc/store/checkout").__internalSetExtensionData("ppcp_recaptcha",{token:"",version:"v2"})}}),i=!0}else console.error("PPCP reCAPTCHA: grecaptcha v2 not loaded");else console.error("PPCP reCAPTCHA: v2 container not found")}}var P=window.fetch;if(window.fetch=function(){var t=r(e().m(function t(r){var u,s,l,p,d,h=arguments;return e().w(function(e){for(;;)switch(e.n){case 0:if(u=h.length>1&&void 0!==h[1]?h[1]:{},(s="string"==typeof r?r:r.url)&&s.includes("ppc-create-order")){e.n=1;break}return e.a(2,P.call(this,r,u));case 1:if(console.log("PPCP reCAPTCHA: Intercepting AJAX",s),i&&c?(l=c,p="v2"):(l=o,p="v3"),l){e.n=2;break}return console.error("PPCP reCAPTCHA: No token available"),e.a(2,Promise.reject(new Error("Missing reCAPTCHA token")));case 2:try{(d=JSON.parse(u.body)).ppcp_recaptcha_token=l,d.ppcp_recaptcha_version=p,u.body=JSON.stringify(d),console.log("PPCP reCAPTCHA: Token injected",p)}catch(e){console.error("PPCP reCAPTCHA: Failed to inject token",e)}return e.a(2,P.call(this,r,u).then(function(e){return 403!==e.status&&400!==e.status||e.clone().json().then(function(e){e.data.code===n.errorCodeVerificationFailed&&(i?(console.log("PPCP reCAPTCHA: v2 verification failed, resetting v2 widget"),grecaptcha.reset(a),c=null):(console.log("PPCP reCAPTCHA: v3 failed, rendering v2"),f()))}),e}))}},t,this)}));return function(_x){return t.apply(this,arguments)}}(),t(document).ready(function(){n.siteKeyV3&&u().then(function(){console.log("PPCP reCAPTCHA: Pre-generating v3 token"),p(),setInterval(p,9e4)})}),!n.isBlocks&&n.isCheckout&&t(document.body).on("checkout_error",function(){l(t(".woocommerce-error, .woocommerce-NoticeGroup-checkout").text())}),n.isBlocks&&window.wp&&window.wp.data){var h=window.wp.data,C=h.subscribe,v=h.select,w=!1;C(function(){var e=v("wc/store/checkout");if(e){var n=e.hasError();n&&!w&&(console.log("PPCP reCAPTCHA: Block checkout error detected"),setTimeout(function(){var e=t(".wc-block-components-notice-banner__content");if(e.length>0){var n=e.text();console.log("PPCP reCAPTCHA: Error message extracted:",n),l(n)}else console.error("PPCP reCAPTCHA: Error banner not found in DOM")},100)),w=n}})}}(jQuery)})();