Files
wyczarujprezent.pl/modules/zakeke/views/js/configurator/configurator.js
2024-10-28 22:14:22 +01:00

226 lines
8.1 KiB
JavaScript

/**
* Copyright (C) 2020 Futurenext srl
*
* This file is part of Zakeke.
*
* Zakeke Interactive Product Designer can not be copied and/or distributed
* without the express permission of Futurenext srl
*
* @author Futurenext srl <help@zakeke.com>
* @copyright 2019 Futurenext srl
* @license https://www.zakeke.com/privacy/#general_conditions
*/
function zakekeConfigurator(config) {
if (!config) {
return;
}
function emitProductDataEvent(productData) {
iframe.contentWindow.postMessage(productData, '*');
}
function isPSAttribute(attribute) {
try {
return JSON.parse(attribute.attributeCode).zakekePlatform && JSON.parse(attribute.optionCode).zakekePlatform;
} catch (e) {
return false;
}
}
function toPSAttribute(attribute) {
return {[JSON.parse(attribute.attributeCode).id]: JSON.parse(attribute.optionCode).id};
}
function toZakekeAttribute(attribute, option) {
return [
{
id: attribute,
isGlobal: false,
zakekePlatform: true
},
{
id: option,
zakekePlatform: false
}
];
}
function updatedAttributes(attributes) {
return Object.assign(config.attributes, attributes.filter(isPSAttribute).reduce((acc, attribute) =>
Object.assign(acc, toPSAttribute(attribute)),
{}));
}
function asAddToCartAttributes(attributes) {
return Object.keys(attributes).reduce((acc, attribute) => {
if (acc['group'] === undefined) {
acc['group'] = {};
}
acc['group'][attribute] = attributes[attribute];
return acc;
}, {});
}
function productData(messageId, attributes, compositionPrice, quantity) {
var params = Object.assign({
'product_id': config.modelCode,
'zakeke-price': compositionPrice
}, config.request, asAddToCartAttributes(updatedAttributes(attributes)));
var queryString = jQuery.param(params),
cached = productDataCache[queryString];
if (cached !== undefined) {
emitProductDataEvent(Object.assign(cached, {
messageId: messageId
}));
return;
}
if (pendingProductDataRequests.indexOf(queryString) !== -1) {
return;
}
pendingProductDataRequests.push(queryString);
jQuery.ajax({
url: config.priceEndpoint,
type: 'POST',
data: params
})
.done(function (product) {
var productData = {
messageId: messageId,
zakekeMessageType: "Price",
message: product.finalPrice
};
productDataCache[queryString] = productData;
emitProductDataEvent(productData);
})
.fail(function (request, status, error) {
console.error(request + ' ' + status + ' ' + error);
})
.always(function () {
var index = pendingProductDataRequests.indexOf(queryString);
if (index !== -1) {
pendingProductDataRequests.splice(index, 1);
}
});
}
var productDataCache = {},
pendingProductDataRequests = [],
container = document.getElementById('zakeke-configurator-container'),
iframe = container.querySelector('iframe'),
iframeOrigin = (new URL(iframe.src)).origin,
sendIframeParamsInterval = null,
createCartSubInput = function (form, value, key, prevKey) {
if (value instanceof String || typeof (value) !== 'object') {
createCartInput(form, prevKey ? prevKey + '[' + key + ']' : key, value);
} else {
Object.keys(value).forEach(function (subKey) {
createCartSubInput(form, value[subKey], subKey, prevKey ? prevKey + '[' + key + ']' : key);
});
}
},
createCartInput = function (form, key, value) {
var input = document.createElement('INPUT');
input.type = 'hidden';
input.name = key;
input.value = value.toString().replace(/\\/g, '');
form.appendChild(input);
},
addToCart = function (composition, attributes, preview, quantity) {
var params = Object.assign({
'add-to-cart': config.modelCode,
'product_id': config.modelCode
},
config.request,
asAddToCartAttributes(updatedAttributes(attributes)),
{
'quantity': quantity,
'zakeke_configuration': composition,
});
var form = document.getElementById('zakeke-addtocart');
delete params['controller'];
params['action'] = 'update';
params['add'] = '1';
jQuery.ajax({
url: config.addEndpoint,
type: 'POST',
headers: {
Accept: 'application/json'
},
data: params
}).done(function (response) {
if (response.errors) {
console.error(JSON.stringify(response));
return;
}
params['id_customization'] = response.id_customization;
params['id_product_attribute'] = response.ipa;
delete params['fc'];
delete params['module'];
Object.keys(params).forEach(function (key) {
if (params[key] instanceof String || typeof(params[key]) !== 'object') {
var input = document.createElement('INPUT');
input.type = 'hidden';
input.name = key;
input.value = params[key];
form.appendChild(input);
} else {
Object.keys(params[key]).forEach(function (subKey) {
var input = document.createElement('INPUT');
input.type = 'hidden';
input.name = key + '[' + subKey + ']';
input.value = params[key][subKey];
form.appendChild(input);
});
}
});
jQuery(form).submit();
})
.fail(function (request, status, error) {
console.error('Request addToCart failed: ' + status );
});
};
window.addEventListener('message', function (event) {
if (event.origin !== iframeOrigin) {
return;
}
if (event.data.zakekeMessageType === 'AddToCart') {
if (config.request.remove_from_cart_url) {
jQuery.ajax(config.request.remove_from_cart_url).always(function () {
addToCart(event.data.message.composition, event.data.message.attributes, event.data.message.preview, event.data.message.quantity);
});
} else {
addToCart(event.data.message.composition, event.data.message.attributes, event.data.message.preview, event.data.message.quantity);
}
} else if (event.data.zakekeMessageType === 'Price') {
productData(event.data.messageId, event.data.message.attributes, event.data.message.compositionPrice, event.data.message.quantity);
}
}, false);
sendIframeParamsInterval = setInterval(function () {
iframe.contentWindow.postMessage({
type: 'load',
parameters: Object.assign({}, config, {
attributes: Object.keys(config.attributes).map(function (attribute) {
return toZakekeAttribute(attribute, config.attributes[attribute]);
})
})
}, '*');
}, 500);
}
document.addEventListener('DOMContentLoaded', function () {
zakekeConfigurator(JSON.parse(window.zakekeConfiguratorConfig));
});