/** * 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 * @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)); });