(function($, wp, PC){
wp.hooks.addAction('PC.fe.init.modal', 'mkl/product_configurator', function(Configurator){
if(PC_config.config.hide_outofstock_items){
Configurator.$el.addClass('hide-outofstock-items');
}});
wp.hooks.addAction('PC.fe.start', 'mkl/product_configurator', function(Configurator){
if(PC_config.config.hide_outofstock_items){
Configurator.toolbar.$('li.out-of-stock').each(function(ind, item){
$parent=$(item).closest('ul');
$(item).remove();
if(! $parent.find('li').length){
$parent.append('<li class="out-of-stock--no-more-choice">' + PC_config.lang.outofstock_nomorechoice + '</li>');
}});
}});
wp.hooks.addAction('PC.fe.start', 'mkl/product_configurator', function(Configurator){
linked_stock_ready=true;
refresh_linked_stock_state();
}, 20000);
wp.hooks.addAction('PC.fe.setContent.parse.before', 'mkl/product_configurator', function(){
linked_stock_ready=false;
if(PC.fe.currentProductData.linked_products_data&&! PC.fe.currentProductData.linked_products){
PC.fe.currentProductData.linked_products=new Backbone.Collection(PC.fe.currentProductData.linked_products_data);
}});
wp.hooks.addAction('PC.fe.reset_configurator', 'mkl/product_configurator', function(){
linked_stock_ready=true;
refresh_linked_stock_state();
});
const get_choice_qty=function(model){
const default_min_qty=wp.hooks.applyFilters('PC.fe.linked_product.default_min_qty', 1, model);
let qty=parseFloat(model.get('linked_product_qty') );
if(Number.isNaN(qty)||qty <=0){
qty=default_min_qty;
}
return Math.abs(qty);
};
const is_linked_choice=function(model){
return (
model
&& 'linked'===model.get('manage_stock')
&& model.get('linked_product_id')
&& false!==model.get('cshow')
&& ! model.get('is_group')
);
};
const get_choice_value=function(choice, key){
if(choice&&'function'===typeof choice.get) return choice.get(key);
return choice ? choice[key]:undefined;
};
const set_choice_value=function(choice, key, value){
if(choice&&'function'===typeof choice.set){
choice.set(key, value);
}else if(choice){
choice[key]=value;
}};
const should_use_linked_product_text=function(choice, field){
const global_settings={
name: 'link_choice_name_from_product',
description: 'link_choice_description_from_product',
advanced_description: 'link_advanced_description_from_product',
};
const choice_settings={
name: 'linked_product_name_override',
description: 'linked_product_description_override',
advanced_description: 'linked_product_advanced_description_override',
};
if(! global_settings[field]||! choice_settings[field]) return false;
if('advanced_description'===field&&get_choice_value(choice, 'is_advanced_description_disabled') ) return false;
const mode=get_choice_value(choice, choice_settings[field])||'inherit';
if('use_from_product'===mode) return true;
if('no_override'===mode) return false;
return !! PC.fe.config[global_settings[field]];
};
const update_linked_product_text=function(choice, product){
if(should_use_linked_product_text(choice, 'name') ){
const linked_choice_name=product.get('extensions' )?.mkl_pc_stock?.linked_choice_name;
if(null!==linked_choice_name&&'undefined'!==typeof linked_choice_name){
set_choice_value(choice, 'name', linked_choice_name);
}}
if(should_use_linked_product_text(choice, 'description') ){
const linked_choice_description=product.get('extensions' )?.mkl_pc_stock?.linked_choice_description;
if(null!==linked_choice_description&&'undefined'!==typeof linked_choice_description){
set_choice_value(choice, 'description', linked_choice_description);
}}
if(should_use_linked_product_text(choice, 'advanced_description') ){
const linked_choice_advanced_description=product.get('extensions' )?.mkl_pc_stock?.linked_choice_advanced_description;
if(null!==linked_choice_advanced_description&&'undefined'!==typeof linked_choice_advanced_description){
set_choice_value(choice, 'advanced_description', linked_choice_advanced_description);
}}
};
let linked_stock_ready=false;
const get_linked_choices_map=function(){
const map={};
if(! PC.fe.layers) return map;
PC.fe.layers.each(function(layer){
const content=PC.fe.getLayerContent(layer.id);
if(! content) return;
content.each(function(choice){
if(! is_linked_choice(choice) ) return;
const linked_product_id=choice.get('linked_product_id');
if(! map[linked_product_id]){
map[linked_product_id]=[];
}
map[linked_product_id].push(choice);
});
});
return map;
};
const get_linked_stock=function(choice){
if(! choice||! PC.fe.currentProductData.linked_products) return null;
const linked_product_id=choice.get('linked_product_id');
if(! linked_product_id) return null;
const product=PC.fe.currentProductData.linked_products.get(linked_product_id);
if(! product) return null;
const maximum=product.get('is_in_stock') ? parseFloat(product.get('add_to_cart').maximum)||0:0;
return {
product: product,
maximum: maximum,
};};
const get_required_quantity=function(linked_choices, target_choice=null, include_target=false){
return linked_choices.reduce(function(required_qty, choice){
let is_active = !! choice.get('active');
if(target_choice&&choice.cid===target_choice.cid){
is_active=include_target;
}
if(! is_active) return required_qty;
return required_qty + get_choice_qty(choice);
}, 0);
};
const refresh_linked_stock_state=function(){
return;
if(! linked_stock_ready) return;
if(! PC.fe.currentProductData.linked_products) return;
const linked_choices_map=get_linked_choices_map();
Object.values(linked_choices_map).forEach(function(linked_choices){
if(! linked_choices.length) return;
const stock_data=get_linked_stock(linked_choices[0]);
if(! stock_data) return;
let used_stock=0;
linked_choices.forEach(function(choice){
const own_qty=get_choice_qty(choice);
const is_active = !! choice.get('active');
const remaining_for_choice=Math.max(0, stock_data.maximum - used_stock);
const can_backorder='yes'===choice.get('wc_backorder')||'notify'===choice.get('wc_backorder');
choice.set('stock', stock_data.maximum, { silent: true });
choice.set('available', can_backorder||own_qty <=remaining_for_choice);
if(typeof choice.get('linked_product_max_qty_raw')==='undefined'){
const raw_max_qty=choice.get('linked_product_max_qty');
choice.set('linked_product_max_qty_raw', raw_max_qty, { silent: true });
}
const configured_max=parseFloat(choice.get('linked_product_max_qty_raw') );
let max_qty=remaining_for_choice;
if(! Number.isNaN(configured_max)&&configured_max > 0){
max_qty=Math.min(max_qty, configured_max);
}
choice.set('linked_product_max_qty', max_qty);
if(is_active){
used_stock +=own_qty;
}});
});
};
wp.hooks.addAction('PC.fe.models.choice.init', 'mkl/product_configurator', function(Model){
var linked_product_id=Model.get('linked_product_id');
var stock_management=Model.get('manage_stock');
if(linked_product_id&&PC.fe.currentProductData.linked_products){
var product=PC.fe.currentProductData.linked_products.get(linked_product_id);
if(product){
const prices=product.get('prices');
Model.set('linked_product_price', prices.price / 10 ** prices.currency_minor_unit);
if('linked'===stock_management){
update_linked_product_text(Model, product);
if(PC.fe.config.link_extra_price
&& !PC.fe.config.extra_price_overrides_product_price
&& (
!Model.get('override_linked_price')
|| (
Model.get('override_linked_price')
&& 'replace'!==Model.get('override_linked_price_mode')
)
)
){
if(PC_config.config.tax_settings&&'incl'==PC_config.config.tax_settings.tax_display_mode&&! PC_config.config.tax_settings.prices_include_tax&&product.get('extensions').mkl_pc_stock.price_excl_tax){
Model.set('linked_product_price', product.get('extensions').mkl_pc_stock.price_excl_tax);
if(product.get('extensions').mkl_pc_stock?.regular_price_excl_tax) Model.set('linked_product_regular_price', product.get('extensions').mkl_pc_stock?.regular_price_excl_tax);
}else if(PC_config.config.tax_settings&&'excl'===PC_config.config.tax_settings.tax_display_mode&&PC_config.config.tax_settings.prices_include_tax&&product.get('extensions').mkl_pc_stock.price_incl_tax){
Model.set('linked_product_price', product.get('extensions').mkl_pc_stock.price_incl_tax);
if(product.get('extensions').mkl_pc_stock?.regular_price_incl_tax) Model.set('linked_product_regular_price', product.get('extensions').mkl_pc_stock?.regular_price_incl_tax);
}else{
Model.set('linked_product_price', prices.price / 10 ** prices.currency_minor_unit);
Model.set('linked_product_regular_price', prices.regular_price / 10 ** prices.currency_minor_unit);
}
if(product.get('extensions').mkl_pc_stock.wholesale_price){
const wholesale_price=product.get('extensions').mkl_pc_stock.wholesale_price;
if(PC_config.config.tax_enabled){
if(PC_config.config.tax_settings.prices_include_tax){
var price=wholesale_price.wholesale_price_with_tax;
}else{
var price=wholesale_price.wholesale_price_with_no_tax;
}}else{
var price=wholesale_price.wholesale_price;
}
Model.set('linked_product_price', price);
}}
if(product.get('is_in_stock') ){
Model.set('stock', product.get('add_to_cart').maximum);
}else{
Model.set('stock', 0);
}
if(product.get('add_to_cart').maximum < Model.get('linked_product_max_qty') ){
Model.set('linked_product_max_qty', product.get('add_to_cart').maximum);
}
if(Model.get('linked_product_default_qty')&&product.get('add_to_cart').maximum < Model.get('linked_product_default_qty') ){
Model.set('linked_product_default_qty', product.get('add_to_cart').maximum);
}
if(product.get('is_on_backorder') ){
if(product.get('extensions')&&product.get('extensions').mkl_pc_stock&&product.get('extensions').mkl_pc_stock.wc_backorder){
Model.set('wc_backorder', product.get('extensions').mkl_pc_stock.wc_backorder);
}else{
Model.set('wc_backorder', 'yes');
}}else{
Model.set('wc_backorder', 'no');
}
if(!Model.get('override_linked_price')&&product.get('on_sale') ){
Model.set('on_sale', true);
}}
}else{
if('linked'===stock_management){
Model.set('stock', 0);
Model.set('available', false);
Model.set('hide-item', true);
console.warn('Product #' + linked_product_id + ' - ' + Model.get('linked_product_name') + ' was not found in linked product data. The product is linked to Choice ' + Model.get('name') );
}}
}
var quantity_to_decrease=Model.get('linked_product_qty')||1;
quantity_to_decrease=(quantity_to_decrease==null||stock_management!='linked') ? 1:Math.abs(quantity_to_decrease);
if('none'!=stock_management&&quantity_to_decrease > Model.get('stock') ){
if('simple'==stock_management){
if(! Model.get('backorder') ){
Model.set('available', false);
}}else if(Model.get('wc_backorder') ){
if('no'==Model.get('wc_backorder') ){
Model.set('available', false);
}}else{
Model.set('available', false);
}}
});
wp.hooks.addFilter('PC.fe.configurator.choice_data', 'mkl/pc/stock_management_linked_product_text', function(attributes){
if(! attributes||'linked'!==attributes.manage_stock||! attributes.linked_product_id||! PC.fe.currentProductData.linked_products) return attributes;
const product=PC.fe.currentProductData.linked_products.get(attributes.linked_product_id);
if(product) update_linked_product_text(attributes, product);
return attributes;
}, 20);
wp.hooks.addAction('PC.fe.choice.init', 'mkl/pc/stock_management', function(view){
view.listenTo(view.model, 'change:linked_product_qty', function(item, value){
if(view.$('.mkl-pc-choice-qty').val()!=value){
view.$('.mkl-pc-choice-qty').val(value);
}});
});
wp.hooks.addFilter('PC.extra_price_to_display', 'mkl/product_configurator', function(extra_price_do_display, choice){
if('linked'!=choice.get('manage_stock')||! PC.fe.config.link_extra_price) return extra_price_do_display;
let qty=1;
const default_min_qty=wp.hooks.applyFilters('PC.fe.linked_product.default_min_qty', 1, choice);
if((( ! choice.get('linked_product_qty_mode')||'multiply'===choice.get('linked_product_qty_mode') )&&choice.get('quantity_multiplies_price') )
||(! PC_config.extra_price_overrides_product_price&&choice.get('linked_product_qty')&&! choice.get('override_linked_price') )
) qty=parseFloat(choice.get('linked_product_qty'))||default_min_qty;
return parseFloat(extra_price_do_display) / qty;
});
wp.hooks.addFilter('pc.get_extra_price', 'mkl/product_configurator', function(extra_price, choice, context){
if('linked'!=choice.get('manage_stock')||! PC.fe.config.link_extra_price) return extra_price;
const forRegularTotal=context&&context.forRegularTotal;
const linked_regular=choice.get('linked_product_regular_price');
const use_regular_linked=forRegularTotal&&'undefined'!=typeof linked_regular&&null!==linked_regular&&''!==linked_regular&&! isNaN(parseFloat(linked_regular) );
const default_min_qty=wp.hooks.applyFilters('PC.fe.linked_product.default_min_qty', 1, choice);
let qty=default_min_qty;
if((( ! choice.get('linked_product_qty_mode')||'multiply'===choice.get('linked_product_qty_mode') )&&choice.get('quantity_multiplies_price') )
||(! PC_config.extra_price_overrides_product_price&&choice.get('linked_product_qty')&&! choice.get('override_linked_price') )
) qty=parseFloat(choice.get('linked_product_qty'))||default_min_qty;
if(choice.get('override_linked_price') ){
if('multiply'==choice.get('override_linked_price_mode') ){
let multiply_factor=choice.get('linked_product_price');
if(use_regular_linked){
multiply_factor=parseFloat(linked_regular);
}
extra_price=multiply_factor * extra_price;
}}else if('undefined'!=typeof choice.get('linked_product_price')||use_regular_linked){
extra_price=use_regular_linked ? parseFloat(linked_regular):choice.get('linked_product_price');
const linked_product_id=choice.get('linked_product_id');
if(linked_product_id&&PC.fe.currentProductData.linked_products){
const product=PC.fe.currentProductData.linked_products.get(linked_product_id);
const quantity=parseFloat(choice.get('linked_product_qty'));
if(product&&product.get('extensions' )?.mkl_pc_stock?.price_tiers){
const product_is_on_sale=product?.get('on_sale');
const price_tiers=product.get('extensions').mkl_pc_stock.price_tiers;
const update_price_to_display = ! forRegularTotal&&!(PC_config.config.relative_price&&'simple'==choice.collection.layer_type);
let tiered_pricing_used=false;
const tier=price_tiers.find(( item)=> quantity >=parseInt(item.start) );
if(tier){
if(tier.type.includes('percent') ){
extra_price=extra_price -(parseFloat(tier.price) * parseFloat(extra_price) / 100);
}else{
extra_price=parseFloat(tier.price||0);
}
if(update_price_to_display&&(extra_price * qty)!=choice.get('extra_price_to_display') ){
choice.set('extra_price_to_display', extra_price * qty);
}
tiered_pricing_used=true;
}
if(update_price_to_display&&!tiered_pricing_used&&(extra_price * qty)!=choice.get('extra_price_to_display') ){
choice.set('extra_price_to_display', extra_price * qty);
}
if(! forRegularTotal){
if(tiered_pricing_used&&!choice.get('on_sale') ){
choice.set('on_sale', true) ;
}else if(!tiered_pricing_used&&choice.get('on_sale')&&!product_is_on_sale){
choice.set('on_sale', false) ;
}}
}}
}
return parseFloat(extra_price) * qty;
});
wp.hooks.addFilter('PC.ExtraPrice.view.data', 'mkl/pc/stock_management', function(data, choice, view){
if(PC_config.config.relative_price&&'simple'==choice.collection.layer_type) return data;
if(choice.get('linked_product_regular_price') ){
data.formatted_regular_price=PC.utils.formatMoney(Math.abs(pc_maybe_apply_taxes(choice.get('linked_product_regular_price') )) );
}
return data;
});
wp.hooks.addAction('PC.fe.configurator.choice-item.render.after-template', 'mkl/pc/stock_management', function(view){
if(view.$('.mkl-pc-choice-qty').length) view.$el.addClass('has-qty');
view.$('.mkl-pc-choice-qty').on('change', function(){
view.model.set('linked_product_qty', $(this).val());
wp.hooks.doAction('PC.fe.linked_product_qty.updated', view);
});
const default_min_qty=wp.hooks.applyFilters('PC.fe.linked_product.default_min_qty', 1, view.model);
view.$('.mkl-pc-choice-qty--btn').on('click', function(){
var current_val=parseInt(view.$('.mkl-pc-choice-qty').val());
if($(this).is('.mkl-minus') ){
var min=view.model.get('linked_product_min_qty')||default_min_qty;
if(current_val==min){
view.model.collection.selectChoice(view.model.id, false);
return;
}
view.$('.mkl-pc-choice-qty').val(--current_val).trigger('change');
}else{
if(view.model.get('linked_product_max_qty')&&current_val==view.model.get('linked_product_max_qty') ) return;
view.$('.mkl-pc-choice-qty').val(++current_val).trigger('change');
}});
});
wp.hooks.addAction('PC.fe.configurator.choice-item.render', 'MKL/PC/stock_management', function(view){
const choice=view.model;
if('user_defined'===choice.get('linked_product_qty_mode') ){
view.$('input.mkl-pc-choice-qty').trigger('change');
}});
wp.hooks.addFilter('PC.fe.choices.add_one', 'MKL/PC/stock_management', function(add_one, model){
if(model.get('hide-item') ) return false;
return add_one;
});
wp.hooks.addAction('PC.fe.setConfig.setItem', 'MKL/PC/stock_management', function(config_item, layer_content){
var choice=layer_content.get(config_item.choice_id);
if(! choice||! config_item.hasOwnProperty('linked_product_qty') ) return;
var qty=choice.set('linked_product_qty', config_item.linked_product_qty);
refresh_linked_stock_state();
});
wp.hooks.addFilter('PC.fe.save_data.parse_choices.added_choice', 'MKL/PC/stock_management', function(parsed_choice, choice_model){
if(! choice_model||! choice_model.get('linked_product_qty') ) return parsed_choice;
if('user_defined'===choice_model.get('linked_product_qty_mode') ){
parsed_choice.linked_product_qty=choice_model.get('linked_product_qty');
}
return parsed_choice;
});
wp.hooks.addFilter('PC.fe.close_choices_after_selection', 'MKL/PC/stock_management', function(close_choices, choice_model){
if(choice_model.get('linked_product_qty_mode')&&'user_defined'===choice_model.get('linked_product_qty_mode') ) return false;
return close_choices;
});
wp.hooks.addAction('PC.fe.choice.change', 'MKL/PC/stock_management', function(choice){
if('multiple'===choice.collection.layer_type){
var has_max_selection=false;
if(choice.get('parent')
&& choice.collection.get(choice.get('parent') )
&& choice.collection.get(choice.get('parent') ).get('max_selection')
) has_max_selection=true;
if(choice.collection.layer.get('max_selection') ) has_max_selection=true;
if(has_max_selection&&choice.get('linked_product_qty_mode')&&'user_defined'===choice.get('linked_product_qty_mode') ){
if(! choice.get('active') ) choice.set('linked_product_qty', choice.get('linked_product_min_qty')||1);
}}
refresh_linked_stock_state();
});
wp.hooks.addAction('PC.fe.linked_product_qty.updated', 'MKL/PC/stock_management', function( { model }){
if(model.get('linked_product_qty_mode')&&'user_defined'===model.get('linked_product_qty_mode') ){
var can_change=wp.hooks.applyFilters('PC.choices.canSelectChoice', true, model, model.collection, 'linked_product_quantity');
if(! can_change){
model.set('linked_product_qty', model._previousAttributes.linked_product_qty||1);
}}
refresh_linked_stock_state();
});
wp.hooks.addFilter('PC.choices.canSelectChoice', 'MKL/PC/stock_management/shared_stock', function(canSelect, choice, choices, context){
if(! canSelect||! is_linked_choice(choice) ) return canSelect;
if('choice'===context&&! linked_stock_ready) return canSelect;
const stock_data=get_linked_stock(choice);
if(! stock_data) return canSelect;
const can_backorder='yes'===choice.get('wc_backorder')||'notify'===choice.get('wc_backorder');
if(can_backorder) return canSelect;
const linked_choices_map=get_linked_choices_map();
const linked_choices=linked_choices_map[choice.get('linked_product_id')]||[ choice ];
return get_required_quantity(linked_choices, choice, true) <=stock_data.maximum;
}, 110);
wp.hooks.addFilter('PC.fe.multiple_choice.item_quantity', 'MKL/PC/stock_management', function(current_count, item, choice){
if(!item.get('manage_stock')||'linked'!==item.get('manage_stock')||'user_defined'!==item.get('linked_product_qty_mode') ) return current_count;
let count=0;
const default_min_qty=wp.hooks.applyFilters('PC.fe.linked_product.default_min_qty', 1, item);
if(choice===item){
count +=(parseInt(item.get('linked_product_qty') )||default_min_qty) - 1;
}else{
count=parseInt(item.get('linked_product_qty') )||default_min_qty;
}
return count;
}, 100);
})(jQuery, window.wp, window.PC);