PHOTO GUIDELINES
- Saved as JPG or PNG
- Minimum size of 250px. x 250px.
- Borders not recommended
- View all Photo Customization and Editing Tips here
NOTE: Your photos must touch the solid dark blue line in order to prevent any unwanted white spaces.
PERSONALIZE
Additional setup fee USD $5.95
By uploading to our site, you are confirming that you have the rights to use these images and agree to our terms + conditions.
');s.css({width:8,height:8,borderRadius:"50%",margin:"0 2%",backgroundColor:"#fff",animation:"sclupndown .7s",animationIterationCount:"infinite",boxShadow:"1px 1px 2px 0px rgba(0,0,0,0.1)"}),s.css("animation-delay",.1*e+"s"),n.overlay.append(s)}n.overlay.css({display:"flex",justifyContent:"center",alignItems:"center",position:"absolute",backgroundColor:"rgba(0,0,0,.4)",top:n.element.position().top+parseInt(n.element.css("margin-top"),10)-parseInt(t("html").css("padding-top"),10)-parseInt(t("html").css("margin-top"),10),left:n.element.position().left+parseInt(n.element.css("margin-left"),10)-parseInt(t("html").css("padding-left"),10)-parseInt(t("html").css("margin-left"),10),width:n.element.outerWidth(),height:n.element.outerHeight(),opacity:0,transition:"opacity .3s",zIndex:100}),n.element.offsetParent().append(n.overlay);var o=n.overlay;setTimeout(function(){o.css("opacity",1)},50)}})},n.prototype.stop=function(){var t=this;return new Promise(function(e){var n=t.overlay;n?(n.css("opacity",0),t.element.css("opacity",1),t.element.children().css("opacity",1),setTimeout(function(){n.remove(),e()},300)):e()})},this.loading=this.loading||new n(this),e){case"stop":this.loading.stop();break;case"start":this.loading.start();break;default:this.loading.start()}}),this}):0})(jQuery); const CUSTOMILY_LOADED_EVENT = 'customily-loaded'; const CUSTOMILY_OPTIONS_LOADED_EVENT = 'customily-options-loaded'; const CUSTOMILY_LOADED_DEFAULTS_EVENT = 'customily-loaded-defaults'; const CUSTOMILY_PERSONALIZATION_ENABLED = 'customily-personalization-enabled'; const CUSTOMILY_PERSONALIZATION_DISABLED = 'customily-personalization-disabled'; const CUSTOMILY_SWATCH_THUMBNAILS_URL_PATH = 'catalog/product/customily/swatches/thumbnails/'; customily.product = { id: '122567', type: 'configurable', price: '13.99' }; customily.template = { id: '3e465aaf-fadd-418e-866e-3c6cc865df61', isLoaded: false }; customily.personalization = { type: 'page-preview', isOptional: '1', attachTo: 'child', behavior: 'visible', childrenInfo: JSON.parse('[{"id":"122441","personalizationIsOptional":"0"},{"id":"122444","personalizationIsOptional":"0"},{"id":"122447","personalizationIsOptional":"0"}]'), showCheckbox: '0', active: false, handlePrices: '1' }; customily.saveFilesIn = 'customily'; var swatchesMaxSize = '120'; swatchesMaxSize = parseInt(swatchesMaxSize) || 100; customily.swatches = { enabled: '1', maxSize: swatchesMaxSize }; customily.imagePlaceholder = 'https://weddingshop.theknot.com/static/version1717655714/frontend/Weddingstar/Knot/en_US/Customily_Categories/images/placeholder.png'; customily.preview = { canDisplay: false, ready: false, export: '1', exportSize: 800, exportQuality: 0.75, hoverZoom: '0', isVisible: false, positioned: { byFotoramaReady: false, byContentLoaded: false, byTemplateLoaded: false }, position: { top: null, left: null }, resize: '0', savePlaceholdersSettings: '1', width: 0 }; customily.sticky = { enabled: '1', leftContainer: '.catalog-product-view .product.media', rightContainer: '.products-group-container-info', padding: '1' }; customily.sticky.padding = parseInt(customily.sticky.padding) || 40; customily.productionFile = { export: '1', rename: '0' }; customily.cart = { customThumbnail: '1', $btn: null, $btn_clone: null }; customily.isEditMode = '0'; customily.collapsibleOptions = '0'; customily.magento = { baseUrl: 'https://weddingshop.theknot.com/', baseMediaUrl: 'https://weddingshop.theknot.com/media/', version: '2.4.6-p3' }; var endpoints = { customilyApi: 'https://sh-api.customily.com/api', magentoApi: 'https://weddingshop.theknot.com/rest/V1/customily' }; var apiKeys = { magentoApiKey: 'VTBCdGVTb3hOVEEwTWpBeE9GOUVhVzl6YldGdWFTbzRNVEF6TXpCZlRHbHNZU280TWpFeE1UWQ==', previewApiKey: 'bUMvlIypAanwBL5iOCRwEjqygs2qKHEGGMwtdDC4CgQ8ksg6aRjDzZ8FrN7u19GOc6qYnYL8H2ATPiAl' }; var previewApiDnsPrefetchLink = document.createElement('link'); previewApiDnsPrefetchLink.id = 'preview-api-dns-prefetch' previewApiDnsPrefetchLink.rel = 'dns-prefetch'; var previewApiPreConnectLink = document.createElement('link'); previewApiPreConnectLink.id = 'preview-api-preconnect' previewApiPreConnectLink.rel = 'preconnect'; var preconnectUrl; if (customily.saveFilesIn == 'magento') { preconnectUrl = endpoints.magentoApi; } else { preconnectUrl = endpoints.customilyApi; } previewApiDnsPrefetchLink.href = preconnectUrl + '/status'; previewApiPreConnectLink.href = preconnectUrl + '/status'; document.head.appendChild(previewApiDnsPrefetchLink); document.head.appendChild(previewApiPreConnectLink); console.log('Customily Magento: preconnecting to ' + previewApiPreConnectLink.href); customily.lastFiles = {}; customily.hasDefaultValues = false; customily.loggingEnabled = '0'; console.log( 'Customily Magento: extension version ' + customily.extensionVersion + ', magento version ' + customily.magento.version ); customily.replaceSpecialChars = function (text) { return text.replace(/&/g, '&') .replace(/'/g, ''') .replace(/"/g, '"') .replace(//g, '>'); }; customily.restoreSpecialChars = function (text) { return text.replace(new RegExp('&', 'g'), '&') .replace(new RegExp(''', 'g'), "'") .replace(new RegExp('"', 'g'), '\"') .replace(new RegExp('<', 'g'), '<') .replace(new RegExp('>', 'g'), '>'); }; customily.createLog = function (title, message) { if (customily.loggingEnabled == '1') { return new Promise(function (resolve) { var url = endpoints.magentoApi + '/createLog'; var data = { productId: customily.product.id, templateId: customily.template.id, title: title, message: '' + message }; var headers = { 'm-api-key': apiKeys.magentoApiKey }; $.ajax({ data: JSON.stringify(data), type: "POST", dataType: "json", contentType: "application/json", url: url, headers: headers, }).done(function (resp) { resolve(resp); }).fail(function (err) { console.warn('Customily Magento: create log failed.'); console.error(err); resolve(''); }); }); } else { return new Promise(function (resolve) { resolve(); }); } }; try { customily.attributes_options = '[{"id":"278","code":"color","label":"Color","selected":"","functions":[{"id":0,"type":"dynamic_image","element_id":"1"},{"id":2,"type":"color","element_id":"8"},{"id":3,"type":"color","element_id":"9"}],"values":[{"id":"251","label":"55 Gold","dynamic_image_id":"1","color_id":"1"},{"id":"254","label":"56 Rose Gold\/Copper","dynamic_image_id":"2","color_id":"2"},{"id":"263","label":"77 Silver \/ Grey","dynamic_image_id":"3","color_id":"3"}]}]'; customily.attributes_options = customily.attributes_options.replace(new RegExp('s_quote;', 'g'), "\\'").replace(new RegExp('d_quote;', 'g'), '\\"'); customily.attributes_options = eval(customily.attributes_options); } catch (ex) { var title = 'Customily Magento: an error occurred when trying to parse product attributes options.'; customily.createLog(title, ex.message).then(function () { console.warn(title); console.error(ex); }); customily.attributes_options = []; } if (customily.isEditMode == '1') { customily.attributes_options.forEach(function (attribute) { if (attribute.selected) { attribute.selected = getAttributeSelectedValue(attribute.code, attribute.selected, true).selected; } }); } try { customily.options = '[{"id":"110453","type":"radio","label":"SELECT FORMAT","price":"0","default":"","selected":"","functions":[],"conditions":[],"is_swatch":"1","is_required":"1","swatch_settings":{"width":"100","height":"35","align":"left","show_tooltip":false,"show_price":false,"border":true,"rounded":false,"paging":false,"rows":2,"cols":3},"text_transform":"none","image_min_width":0,"image_min_height":0,"image_max_width":0,"image_max_height":0,"values":[{"id":"220127","label":"Front Only (No Additional Fee)","positions":[],"color":"","thumbnail":"","sku":"","price":"USD $0.00","color_fee_code":""},{"id":"220130","label":"Front With Back Engraving","positions":[],"color":"","thumbnail":"","sku":"a","price":"USD $0.00","color_fee_code":"1"}],"color_fee":"1"},{"id":"110456","type":"radio","label":"Included","price":"0","default":"","selected":"","functions":[],"conditions":[{"id":0,"action":"show","watch_option":"SELECT FORMAT","expected_value":"Front Only (No Additional Fee"},{"id":1,"action":"show","operator":"or","watch_option":"SELECT FORMAT","expected_value":"Front With Back Engraving"}],"is_swatch":"1","is_required":"0","swatch_settings":[],"text_transform":"none","image_min_width":0,"image_min_height":0,"image_max_width":0,"image_max_height":0,"values":[{"id":"220133","label":"--- FRONT ---","positions":[],"color":"","thumbnail":"","sku":"","price":"USD $0.00","color_fee_code":""}],"color_fee":"0"},{"id":"110459","type":"file","label":"ADD PHOTO","price":"0.000000","default":"","selected":"","functions":[{"id":0,"type":"file","element_id":"3"}],"conditions":[{"id":0,"action":"show","watch_option":"SELECT FORMAT","expected_value":"Front Only (No Additional Fee)"},{"id":1,"action":"show","operator":"or","watch_option":"SELECT FORMAT","expected_value":"Front With Back Engraving"}],"is_swatch":"1","is_required":"1","swatch_settings":[],"text_transform":"none","image_min_width":250,"image_min_height":250,"image_max_width":10000,"image_max_height":10000,"values":[],"color_fee":"0"},{"id":"110462","type":"radio","label":"TEXT PRINT COLOR","price":"0","default":"","selected":"","functions":[{"id":0,"type":"color","element_id":"4"},{"id":1,"type":"color","element_id":"5"}],"conditions":[{"id":0,"action":"show","watch_option":"SELECT FORMAT","expected_value":"Front Only (No Additional Fee)"},{"id":1,"action":"show","operator":"or","watch_option":"SELECT FORMAT","expected_value":"Front With Back Engraving"}],"is_swatch":"1","is_required":"1","swatch_settings":{"width":"36","height":"36","align":"left","show_tooltip":false,"show_price":false,"border":true,"rounded":false,"paging":false,"rows":2,"cols":3},"text_transform":"none","image_min_width":0,"image_min_height":0,"image_max_width":0,"image_max_height":0,"values":[{"id":"220136","label":"Black","positions":[{"id":0,"type":"color","element_id":"4","position":1},{"id":1,"type":"color","element_id":"5","position":1}],"color":"#000000","thumbnail":"","sku":"","price":"USD $0.00","color_fee_code":""},{"id":"220139","label":"White","positions":[{"id":0,"type":"color","element_id":"4","position":2},{"id":1,"type":"color","element_id":"5","position":2}],"color":"#ffffff","thumbnail":"","sku":"","price":"USD $0.00","color_fee_code":""}],"color_fee":"0"},{"id":"110465","type":"field","label":"LINE 1","price":"0.000000","default":"Mr + Mrs","selected":"Mr + Mrs","functions":[{"id":0,"type":"text","element_id":"4"}],"conditions":[{"id":0,"action":"show","watch_option":"SELECT FORMAT","expected_value":"Front Only (No Additional Fee)"},{"id":1,"action":"show","operator":"or","watch_option":"SELECT FORMAT","expected_value":"Front With Back Engraving"}],"is_swatch":"1","is_required":"0","swatch_settings":[],"text_transform":"none","image_min_width":0,"image_min_height":0,"image_max_width":0,"image_max_height":0,"values":[],"color_fee":"0"},{"id":"110468","type":"field","label":"LINE 2","price":"0.000000","default":"","selected":"","functions":[{"id":0,"type":"text","element_id":"5"}],"conditions":[{"id":0,"action":"show","watch_option":"SELECT FORMAT","expected_value":"Front Only (No Additional Fee)"},{"id":1,"action":"show","operator":"or","watch_option":"SELECT FORMAT","expected_value":"Front With Back Engraving"}],"is_swatch":"1","is_required":"0","swatch_settings":[],"text_transform":"uppercase","image_min_width":0,"image_min_height":0,"image_max_width":0,"image_max_height":0,"values":[],"color_fee":"0"},{"id":"110471","type":"radio","label":"Included","price":"0","default":"","selected":"","functions":[],"conditions":[{"id":0,"action":"show","watch_option":"SELECT FORMAT","expected_value":"Front With Back Engraving"}],"is_swatch":"1","is_required":"0","swatch_settings":[],"text_transform":"none","image_min_width":0,"image_min_height":0,"image_max_width":0,"image_max_height":0,"values":[{"id":"220142","label":"--- ENGRAVING ON BACK ---","positions":[],"color":"","thumbnail":"","sku":"","price":"USD $0.00","color_fee_code":""}],"color_fee":"0"},{"id":"110474","type":"field","label":"LINE 1","price":"0.000000","default":"","selected":"","functions":[{"id":0,"type":"text","element_id":"8"}],"conditions":[{"id":0,"action":"show","watch_option":"SELECT FORMAT","expected_value":"Front With Back Engraving"}],"is_swatch":"1","is_required":"0","swatch_settings":[],"text_transform":"none","image_min_width":0,"image_min_height":0,"image_max_width":0,"image_max_height":0,"values":[],"color_fee":"0"},{"id":"110477","type":"field","label":"LINE 2","price":"0.000000","default":"","selected":"","functions":[{"id":0,"type":"text","element_id":"9"}],"conditions":[{"id":0,"action":"show","watch_option":"SELECT FORMAT","expected_value":"Front With Back Engraving"}],"is_swatch":"1","is_required":"0","swatch_settings":[],"text_transform":"none","image_min_width":0,"image_min_height":0,"image_max_width":0,"image_max_height":0,"values":[],"color_fee":"0"},{"id":"110480","type":"checkbox","label":"Confirmation","price":"0","default":"","selected":"","functions":[],"conditions":[],"is_swatch":"1","is_required":"1","swatch_settings":[],"text_transform":"none","image_min_width":0,"image_min_height":0,"image_max_width":0,"image_max_height":0,"values":[{"id":"220145","label":"I confirm the personalization is correct. The print quality will reflect the quality of the image provided. We always recommend the highest quality image available.","positions":[],"color":"","thumbnail":"","sku":"","price":"USD $0.00","color_fee_code":""}],"color_fee":"0"}]'; customily.options = customily.options.replace(new RegExp('s_quote;', 'g'), "\\'").replace(new RegExp('d_quote;', 'g'), '\\"'); customily.options = eval(customily.options); } catch (ex) { var title = 'Customily Magento: an error occurred when trying to parse product customizable options.'; customily.createLog(title, ex.message).then(function () { console.warn(title); console.error(ex); }); customily.options = []; } customily.conditions = []; customily.options.forEach(function (option) { if (option.text_transform && (option.type == 'field' || option.type == 'area')) { const $parent = $('.customily-options [name="options[' + option.id + ']"]').first().parent(); switch (option.text_transform) { case 'capitalize': $parent.addClass('customily-text-capitalize'); break; case 'lowercase': $parent.addClass('customily-text-lowercase'); break; case 'uppercase': $parent.addClass('customily-text-uppercase'); break; } } if (option.selected && (option.type == 'field' || option.type == 'area')) { option.selected = customily.restoreSpecialChars(option.selected); } if (option.conditions.length) { option.conditions.forEach(function (cond) { if (cond.watch_option) { cond.watch_option_sanitized = customily.replaceSpecialChars(cond.watch_option); const attr = _.find(customily.attributes_options, function (a) { return ( a.id == cond.watch_option || a.label == cond.watch_option || a.label == cond.watch_option_sanitized ); }); if (attr && attr.id) { cond.is_attribute_condition = true; cond.id_conditional = attr.id; customily.conditions.push(cond); } else { const op = _.find(customily.options, function (o) { return o.label == cond.watch_option || o.label == cond.watch_option_sanitized; }); if (op && op.id) { cond.is_attribute_condition = false; cond.id_conditional = op.id; customily.conditions.push(cond); } } if (cond.expected_value) { cond.expected_value_sanitized = customily.replaceSpecialChars(cond.expected_value) } } }); } if (customily.isEditMode == '1') { if (option.type == 'drop_down' || option.type == 'radio') { option.selected = getOptionSelectedValue(option.id, option.selected).selected; } else if (option.type == 'file') { if (option.selected.length > 0) { option.functions.forEach(function (f) { addFileInfo(f.element_id, option.selected, option.id, f.type); }); option.selected = true; } else { option.selected = false; } } } else { if (!customily.hasDefaultValues && option.selected) { customily.hasDefaultValues = true; } } }); if (customily.personalization.type == 'modal-preview') { customily.showModalBtnText = customily.showModalBtnText || 'Customize yours'; $('#customily-popup-modal-button span').text(customily.showModalBtnText); $(customily.querySelectors.addToCartButtonContainer).addClass('hidden'); } customily.optionsToShow = []; customily.optionsToHide = []; customily.pendingOperations = []; $('[data-gallery-role=gallery-placeholder]').on('gallery:loaded', function () { $(this).on('fotorama:ready', function () { if (customily.personalization.type == 'page-preview') { if (!customily.preview.ready) { console.log('Customily Magento: fotorama gallery is ready.'); customily.positioningPreview('fotoramaReady'); } } }); $(this).on('fotorama:fullscreenexit', function () { if (customily.template.isLoaded && customily.preview.isVisible) { customily.saveProductImagePosition(); } }); $(this).on('fotorama:show', function () {}); }); $(document).on('click tap', '.fotorama__nav-wrap img, .fotorama__nav-wrap .fotorama__dot', function () { customily.hideCanvas(); }); $(document).on('click tap', '.owl-carousel .item-thumb, .owl-dots, .owl-nav', function () { customily.hideCanvas(); }); $(document).on('click tap', '.MagicToolboxSelectorsContainer a', function () { customily.hideCanvas(); return false; }); $(document).on('click tap', '.swatch-attribute .swatch-option', function (ev, data) { if (customily.personalization.isOptional == '1' && customily.personalization.attachTo == 'child') { var ids = getSelectedProductId(); if (ids.length) { customily.personalization.showCheckbox = getPersonalizationOptional(ids[0]); handleOptionalPersonalizationCheckBox(); } } handleAttributeChange(ev, data, 'click'); }); $(document).on('change', '.swatch-attribute select', function (ev, data) { if (customily.personalization.isOptional == '1' && customily.personalization.attachTo == 'child') { var ids = getSelectedProductId(); if (ids.length) { customily.personalization.showCheckbox = getPersonalizationOptional(ids[0]); handleOptionalPersonalizationCheckBox(); } } handleAttributeChange(ev, data, 'change'); }); $(document).on('change', '#cl-personalization-optional', function () { if (customily.personalization.behavior == 'visible') { customily.personalization.active = !(!!$(this).prop('checked')); } else { customily.personalization.active = !!$(this).prop('checked'); } if (customily.personalization.active) { $(this).parents('.cl-personalization-optional-container').addClass('cl-personalization-active'); window.dispatchEvent(new CustomEvent(CUSTOMILY_PERSONALIZATION_ENABLED)); } else { $(this).parents('.cl-personalization-optional-container').removeClass('cl-personalization-active'); window.dispatchEvent(new CustomEvent(CUSTOMILY_PERSONALIZATION_DISABLED)); } handlePersonalizationOptional(); var s=document.querySelector('#cl-personalization-optional'); if(s.checked) { document.getElementById('cl-personalization-optional').value = "1"; } else{ document.getElementById('cl-personalization-optional').value = "0"; } }); $(document).on('click', '.cl-personalization-optional-span', function () { $('#cl-personalization-optional').click(); }); $( window ).on( "orientationchange", function (event) { if($(window ).width() < 1025 && $(window).width() > 767){ if(jQuery('#fabric-container').siblings().filter(':visible').filter('.fotorama__nav-wrap').length === 1){ parentPadding = $(".fotorama__nav-wrap.fotorama__nav-wrap--vertical").outerWidth(); $('#fabric-container').parent().css({'padding-left': parentPadding+'px'}); } else{ $('#fabric-container').parent().css({'min-width': '100%'}); } $('#fabric-container').css({'left': '0', 'width': '100%'}); } }); /** * Prevent default submission when hitting return key. * Exceptions: textarea elements. * For exceptions, return key will function normally. */ $(customily.querySelectors.addToCartForm).on('keyup keypress', function (e) { var $target = $(e.target); var keyCode = e.keyCode || e.which; if (keyCode === 13 && $target.is('textarea') === false) { e.preventDefault(); return false; } }); function handlePersonalizationOptional() { if (customily.personalization.active) { if (customily.personalization.type == 'modal-preview') { $('.start-configurator-wrapper').removeClass('hidden'); $(customily.querySelectors.addToCartButtonContainer).addClass('hidden'); $(customily.querySelectors.addToCartForm + ' [data-role="swatch-options"]').css('visibility', 'hidden').addClass('hidden'); } else { $(customily.querySelectors.addToCartForm + ' [data-role="customily-options"]').removeClass('hidden').css('visibility', 'visible'); $(customily.querySelectors.addToCartForm + ' [data-role="customily-options"] .customily-file-field').css('visibility', 'visible'); restoreOptionsFields(); } customily.preview.canDisplay = true; if (!customily.initialized) { customily.init(true); } else { customily.displayCanvas(); customily.evalConditions(); } $(".product-prices-fee-wrap .product-setup-fee").removeClass('hidden'); } else { if (customily.personalization.type == 'modal-preview') { $('.start-configurator-wrapper').addClass('hidden'); $(customily.querySelectors.addToCartButtonContainer).removeClass('hidden'); $(customily.querySelectors.addToCartForm + ' [data-role="swatch-options"]').css('visibility', 'visible').removeClass('hidden'); } else { $(customily.querySelectors.addToCartForm + ' [data-role="customily-options"]').addClass('hidden'); } customily.hideCanvas(); customily.preview.canDisplay = false; clearOptionsFields(true); clearCustomilyFields(); } handlePersonalizationOptionalPriceBottom(); } function handleAttributeChange(ev, data, eventTrigger) { if (!ev.isTrigger || (data && data.force)) { var $self = $(ev.target); if (data && data.force) { if (customily.personalization.type == 'modal-preview') { customily.updatePriceElement(); } } else { var $el = $self.parents('.swatch-attribute'); var value = $el.attr('option-selected') || $el.attr('data-option-selected'); if (value !== undefined && value != null) { $('[data-role="swatch-options"].hidden .swatch-attribute #' + $self.attr('data-id')).trigger(eventTrigger, { force: true }); setTimeout(function () { var attributeCode = $el.attr('attribute-code') || $el.attr('data-attribute-code'); var attribute = getAttributeSelectedValue(attributeCode, '' + value, true); attributeChange(attribute); handlePreviewCanvasAttributes(); }, 100); } } } } $(document).on('input', '.customily-options input:text, .customily-options textarea', function (ev, data) { var optionId = getOptionId(this); if ($(this).val()) { $(this).parents('.cl-option').first().addClass('selected'); } else { $(this).parents('.cl-option').first().removeClass('selected'); } customily.checkSelection(ev); optionChange(this, optionId); }); function applyTextTransform(transform, value) { switch (transform) { case 'capitalize': value = value.replace(/(^\w{1})|(\s+\w{1})/g, letter => letter.toUpperCase()); break; case 'lowercase': value = value.toLowerCase(); break; case 'uppercase': value = value.toUpperCase(); break; } return value; } const NOT_ALLOWED_FILE_TYPE_ERROR_MESSAGE = "Wrong file format. We suggest that you upload a new file as .JPG. or .PNG."; const PHOTO_LOW_RESOLUTION_ERROR_MESSAGE = "Image is low resolution and will not print well.\nWe suggest that you either zoom out on your current image or upload a new, larger image."; const PHOTO_TOO_LARGE_ERROR_MESSAGE = "Image is too large.\nWe suggest that you either zoom in on your current image or upload a new, smaller image."; function isImage(file) { if (file) { var fileType = file["type"]; if (fileType.indexOf("image/") !== -1) { return true; } } return false; } function displayErrorMessage(element, messageContent) { var $element = element; var inputName = $element.attr('name'); var errorMessageId = inputName + "-error"; var messageHtml = $t(messageContent).replace("\n", "
"); $(`#${errorMessageId}`).remove(); var errorMessageHtml = `
${messageHtml}
`; $element.after(errorMessageHtml); } $('.customily-options select').change(function (ev, data) { if ($(this).val()) { $(this).parents('.cl-option').first().addClass('selected'); if (!ev.isTrigger || !data || data.allow) { optionChange(this); } } else { $(this).parents('.cl-option').first().removeClass('selected'); if (!ev.isTrigger || !data || data.allow) { unselectOption(this); } } customily.checkSelection(ev); const optionId = this.name.replace('options[', '').replace(']', ''); const hasConditions = _.find(customily.conditions, function (cond) { return cond.id_conditional == optionId; }); if (hasConditions) { customily.evalConditions(); } }); $('.customily-options input:file').change(function (ev) { if (this.files[0]) { var $self = $(this); $self.addClass('cl-file-selected'); $self.parents('.cl-option').first().addClass('selected'); $self.parent().find('.remove-image').removeClass('hidden'); $self.parent().find('.upload-button').prop('disabled', 'disabled'); var fileName = ev.target.value.split('\\').pop(); if (fileName) { $self.parents('.cl-option').first().find('.customily-file-name') .removeClass('hidden').html(fileName); } customily.checkSelection(ev); adjustSpaceForMobileControls(); if (isImage(ev.target.files[0])) { var $form = $('#product_addtocart_form'); var allowedTypes = $form.find('input[type="hidden"][name="'+$self.attr('name')+'_allowed_file_types"]').val(), minX = $form.find('input[type="hidden"][name="'+$self.attr('name')+'_min_size_x"]').val(), minY = $form.find('input[type="hidden"][name="'+$self.attr('name')+'_min_size_y"]').val(), maxX = $form.find('input[type="hidden"][name="'+$self.attr('name')+'_max_size_x"]').val(), maxY = $form.find('input[type="hidden"][name="'+$self.attr('name')+'_max_size_y"]').val(); const file = ev.target.files[0]; var fileName = ev.target.value; var fileExtension = fileName .substring(fileName.lastIndexOf('.') + 1) .toLowerCase(); var allowedExtensions = allowedTypes.split(',').map(type => { var t = type.trim(); return t.toLowerCase(); }); if (allowedExtensions.indexOf(fileExtension) !== -1) { const img = new Image(); img.onload = function() { const width = img.width; const height = img.height; if (img.width >= minX && img.height >= minY) { if (img.width <= maxX && img.height <= maxY) { } else { displayErrorMessage($self, PHOTO_TOO_LARGE_ERROR_MESSAGE); } } else { displayErrorMessage($self, PHOTO_LOW_RESOLUTION_ERROR_MESSAGE); } }; const reader = new FileReader(); reader.onload = function(e) { img.src = e.target.result; }; reader.readAsDataURL(file); } else { displayErrorMessage($self, NOT_ALLOWED_FILE_TYPE_ERROR_MESSAGE); } } optionChange(this); } }); $('.customily-options .upload-button').click(function () { var $input = $(this).parent().find('[type="file"]'); setTimeout(function () { $input.parent().find('.file-action').val('save_new'); $input.val(null).removeAttr('disabled').trigger('click'); }, 200); }); $('.customily-options .remove-image').click(function () { var $self = $(this); $self.addClass('hidden'); var $parent = $self.parents('.cl-option').first(); var $file = $self.parent().find('[type="file"]'); $parent.removeClass('selected'); $parent.removeClass('cl-invalid-image-size'); $parent.find('label').first().find('span').removeClass('customily-invalid-image-size'); $parent.find('.customily-invalid-size-error').addClass('hidden'); $parent.find('.customily-file-name').addClass('hidden').html(''); $self.parent().find('.upload-button').removeAttr('disabled'); var option = _.find(customily.options, function (o) { return o.id == $self.attr('data-option-id'); }); option.functions.forEach(function (f) { if (f.type == 'vector') { engraver.setVector(Number(f.element_id), '').then(function () { engraver.clearSelection(); }); } else { engraver.setImage( Number(f.element_id), 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' ).then(function () { engraver.clearSelection(); }); } }); $parent.find('.field-error').remove(); $file.val(null).removeClass('cl-file-selected'); option.selected = null; customily.lastFiles[option.id] = null; adjustSpaceForMobileControls(); if (customily.personalization.handlePrices == '1') { updatePrice($file, option); } if (customily.personalization.type == 'modal-preview') { customily.updatePriceElement(); } }); $(document).on('click', '.customily-options input[type="checkbox"]', function (ev, data) { const optionId = this.name.replace('options[', '').replace('][]', ''); var $parent = $(this).parents('.cl-option').first(); if ($(this).val() == $parent.attr('data-selected')) { $(this).removeAttr('checked').removeClass('cl-checked-' + optionId); $(this).closest( ".cl-option" ).find('.choose-cat').html(''); $parent.removeClass('selected').attr('data-selected', null); if (!ev.isTrigger || !data || data.allow) { $(this).removeClass('cl-checked-' + optionId) getOptionSelectedValue(optionId, null, true); } } else { $(this).prop('checked', true).addClass('cl-checked-' + optionId); $(this).closest( ".cl-option" ).find('.choose-cat').html(": " + $(this).attr('data-title')); $parent.addClass('selected').attr('data-selected', $(this).val()); if (!ev.isTrigger || !data || data.allow) { $(this).addClass('cl-checked-' + optionId); getOptionSelectedValue(optionId, this.value, true); } } customily.checkSelection(ev); const hasConditions = _.find(customily.conditions, function (cond) { return cond.id_conditional == optionId; }); if (hasConditions) { customily.evalConditions(); } if (customily.personalization.type == 'modal-preview') { customily.updatePriceElement(); } }); $(document).on('click', '.customily-options input[type="radio"]', function (ev) { var $self = $(this); var $parent = $self.parents('.cl-option').first(); if ($self.val() == $parent.attr('data-selected')) { $self.removeAttr('checked'); $('input[name="' + $self.attr('name') + '"].swatch-none-value').prop('checked', true); $parent.removeClass('selected').attr('data-selected', null); $(this).closest( ".cl-option" ).find('.choose-cat').html(''); unselectOption(this); } else { $self.prop('checked', true); $parent.addClass('selected').attr('data-selected', $self.val()); $(this).closest( ".cl-option" ).find('.choose-cat').html(": " + $(this).attr('data-title')); optionChange(this); } customily.checkSelection(ev); const optionId = this.name.replace('options[', '').replace(']', ''); const hasConditions = _.find(customily.conditions, function (cond) { return cond.id_conditional == optionId; }); if (hasConditions) { customily.evalConditions(); } }); $(document).on('click', '.mageworx-swatch-container .mageworx-swatch-option', function () { var $select = $(this).parent().siblings('select').first(); if ($select.length) { $select.trigger('change', { allow: true }); } }); function unselectOption(el) { var optionId = getOptionId(el); var option = _.find(customily.options, function (o) { return o.id == optionId; }); if (option) { option.selected = null; setDefaultOptionValueToPreview(option); reloadProductPriceBottom(option); if (customily.personalization.handlePrices == '1') { updatePrice($(el), option); } if (customily.personalization.type == 'modal-preview') { customily.updatePriceElement(); } } } customily.checkSelection = function (ev) { if (!ev || !ev.isTrigger) { if ($('.customily-options .field.selected').length) { customily.cart.$btn_clone.removeAttr('disabled'); } else { customily.cart.$btn_clone.prop('disabled', 'disabled'); } } }; customily.evalConditions = function () { customily.optionsToShow = []; customily.optionsToHide = []; customily.options.forEach(function (option) { var $el = getOptionParent(option); var show = true; if (option.conditions.length > 0) { var valueMet = false; var valueWasMet = false; var action = false; option.conditions.forEach(function (cond, i) { if (i == 0) { action = cond.action; } valueMet = false; if (cond.watch_option) { if (cond.is_attribute_condition) { var attr = getAttributeOptionById(cond.watch_option); if (attr && attr.code) { var $selectedAttribute = $('[data-role="swatch-options"] [attribute-code="' + attr.code + '"]'); if (!$selectedAttribute.length) { $selectedAttribute = $('[data-role="swatch-options"] [data-attribute-code="' + attr.code + '"]'); } if (attr.selected && $selectedAttribute.length) { valueMet = attr.selected.id == cond.expected_value || attr.selected.id == cond.expected_value_sanitized; } } } else { var op = getOptionByLabel(cond.watch_option); op = op || getOptionByLabel(cond.watch_option_sanitized); if (op && op.id) { var $selectedParent = getOptionParent(op); if (op.selected && $selectedParent.is(':visible')) { valueMet = op.selected.label == cond.expected_value || op.selected.label == cond.expected_value_sanitized; } } } } if (i > 0) { if (cond.operator == 'and') { if (valueWasMet && valueMet) { valueMet = true; } else { valueMet = false; } } if (cond.operator == 'or') { if (valueWasMet || valueMet) { valueMet = true; } else { valueMet = false; } } } valueWasMet = valueMet; }); if (valueMet) { if (action == 'show') { show = true; } if (action == 'hide') { show = false; } } else { if (action == 'show') { show = false; } if (action == 'hide') { show = true; } } } if ($el && $el.length) { if (show) { if (customily.isEditMode == '1' || (!$el.is(':visible') || !engraver.initReady)) { $el.show(); $el.find('[price]').each(function (i, e) { $(e).attr('price', $(e).attr('data-price')); }); if (option.type == 'file' && option.selected) { $el.find('.upload-button'); $el.find('.remove-image').removeClass('hidden'); } } option.isVisible = true; var op = _.find(customily.optionsToShow, function (o) { return o.id == option.id; }); if (!op) { customily.optionsToShow.push(option); } $el.removeClass('cl-exclude'); } else { if ($el.is(':visible')) { $el.hide(); $el.find('[price]').each(function (i, e) { $(e).attr('price', 0); }); if (option.type == 'file') { $el.find('.upload-button').removeAttr('disabled'); } } option.isVisible = false; var op = _.find(customily.optionsToHide, function (o) { return o.id == option.id; }); if (!op) { customily.optionsToHide.push(option); } $el.addClass('cl-exclude'); } } }); if (engraver.initReady) { handlePreviewCanvasConditions(); } customily.imagesLazyLoad(200); }; customily.displayCanvas = function () { if ( customily.personalization.type == 'page-preview' && customily.preview.ready && customily.preview.canDisplay ) { customily.adjustPreview(); $('#fabric-container').siblings().filter(':visible').filter(':not(.fotorama__nav-wrap)') .filter(':not(.MagicToolboxSelectorsContainer)') .filter(':not([data-role="customily-options"])') .data('customily-hidden', true).addClass('hidden'); $('#fabric-container').data('customily-visible', true); $('#fabric-container').fadeIn(); customily.preview.isVisible = true; if (customily.displayCanvasHook && customily.displayCanvasHook.call) { customily.displayCanvasHook.call(); } } }; customily.displayProductImage = function () { var $imagesContainer = customily.getImagesContainer(); if ($imagesContainer && $imagesContainer.length) { $imagesContainer.data('customily-hidden', false).fadeIn(); } } customily.hideCanvas = function () { $('#fabric-container').siblings().filter(function (i, e) { return $(e).data('customily-hidden'); }).data('customily-hidden', false).removeClass('hidden').fadeIn(); $('#fabric-container').data('customily-visible', false); $('#fabric-container').hide(); $('#fabric-container').parent().removeClass('customily-preview-container'); customily.preview.isVisible = false; if (customily.hideCanvasHook && customily.hideCanvasHook.call) { customily.hideCanvasHook.call(); } }; customily.updatePriceElement = function () { setTimeout(function () { var basePrice; if (customily.attributes_options.length > 0) { var attributesConfig = $('[data-role="swatch-options"]').data('mageSwatchRenderer').options.jsonConfig; var selectedAttributes = {}; _.filter(customily.attributes_options, function (attr) { return attr.selected; }).forEach(function (attr) { selectedAttributes[attr.id] = attr.selected.id; }); var index = -1; $.each(attributesConfig.index, function (i, attributes) { if (_.isEqual(attributes, selectedAttributes)) { index = i; } }); if (index != -1) { basePrice = attributesConfig.optionPrices[index] ? attributesConfig.optionPrices[index].finalPrice.amount : 0; } else { basePrice = attributesConfig.prices ? attributesConfig.prices.finalPrice.amount : 0.00; } } else { basePrice = customily.product.price ? parseFloat(customily.product.price) : 0.00; } var personalizationPrice = 0; if (customily.personalization.active) { var floatRegExp = /[+-]?\d+([\,]\d+)*([\.]\d+)?/g; _.filter(customily.options, function (o) { return o.isVisible && o.selected; }).forEach(function (op) { var $el = getOptionParent(op); if ($el.length && $el.is(':visible')) { if (op.type == 'field' || op.type == 'area' || op.type == 'file') { personalizationPrice += op.price ? parseFloat(op.price) : 0.00; } else if (op.type == 'checkbox') { personalizationPrice += op.values && op.values[0].price ? parseFloat(op.values[0].price.match(floatRegExp)[0].replace(',', '')) : 0.00; } else { personalizationPrice += op.selected.price ? parseFloat(op.selected.price.match(floatRegExp)[0].replace(',', '')) : 0.00; } } }); } var finalPrice = basePrice + personalizationPrice; var priceFormat = (customily.priceConfig && customily.priceConfig.priceFormat) || {}; $('.cl-personalization-price-initial .cl-personalization-price-amount').text( priceUtils.formatPrice(basePrice, priceFormat) ); $('.cl-personalization-price-custom .cl-personalization-price-amount').text( priceUtils.formatPrice(personalizationPrice, priceFormat) ); $('.cl-personalization-price-final .cl-personalization-price-amount').text( priceUtils.formatPrice(finalPrice, priceFormat) ); }, 100); }; customily.defaultGetOptionValue = function ($element, optionsConfig, option) { optionsConfig = optionsConfig || customily.optionsPrices.config; if (!option) { var optionId = getOptionId($element); option = _.find(customily.options, function (o) { return o.id == optionId; }); } var changes = {}, optionValue = $element.val(), optionType = $element.prop('type'), optionName = optionType == 'file' ? $element.attr('data-option-name') : $element.attr('name'), optionConfig = optionsConfig[option.id], optionHash = optionName; if ( customily.personalization.active && !$element.hasClass('swatch-none-value') && option && option.isVisible && option.selected ) { switch (optionType) { case 'text': case 'textarea': changes[optionHash] = optionValue ? optionConfig.prices : {}; break; case 'radio': if ($element.is(':checked')) { changes[optionHash] = optionConfig[optionValue] && optionConfig[optionValue].prices || {}; } break; case 'select-one': changes[optionHash] = optionConfig[optionValue] && optionConfig[optionValue].prices || {}; break; case 'select-multiple': _.each(optionConfig, function (row, optionValueCode) { optionHash = optionName + '##' + optionValueCode; changes[optionHash] = _.contains(optionValue, optionValueCode) ? row.prices : {}; }); break; case 'checkbox': optionHash = optionName + '##' + optionValue; changes[optionHash] = $element.is(':checked') ? optionConfig[optionValue].prices : {}; break; case 'file': changes[optionHash] = optionValue || customily.isEditMode == '1' || $element.hasClass('cl-file-selected') ? optionConfig.prices : {}; break; } } else { changes[optionHash] = { basePrice: { adjustments: {}, amount: 0.00 }, finalPrice: { adjustments: {}, amount: 0.00 }, oldPrice: { adjustments: {}, amount: 0.00 } }; } return changes; }; customily.validateRequired = function () { var nonValidatedCount = 0; var firstEmptyRequiredField = null; var $attributeOptions; if (customily.personalization.type == 'modal-preview') { $attributeOptions = $('.customily-options .swatch-attribute-options[aria-required="true"]'); } else { $attributeOptions = $('.swatch-attribute-options[aria-required="true"]'); } $attributeOptions.each(function () { var $self = $(this); var $parent = $self.parent(); var $span = $parent.find('.swatch-attribute-label'); var selected = $parent.attr('option-selected') || $parent.attr('data-option-selected'); if (selected) { $span.removeClass('customily-required'); $self.find('.cl-error').hide(); } else { $span.addClass('customily-required'); $self.find('.cl-error').show(); nonValidatedCount++; if (!firstEmptyRequiredField) { firstEmptyRequiredField = $(this); } } }); $('.customily-options .cl-option.cl-required:not(.cl-exclude)').each(function () { var $self = $(this); var $span = $self.find('label').first().find('span'); if ($self.hasClass('selected') || !$self.is(':visible')) { $span.removeClass('customily-required'); $self.find('.cl-error').hide(); } else { $span.addClass('customily-required'); $self.find('.cl-error').show(); nonValidatedCount++; if (!firstEmptyRequiredField) { firstEmptyRequiredField = $(this); } } }); try { validateCharacter(); } catch(e) { nonValidatedCount++; } customily.firstInvalidField = null; customily.firstInvalidField = firstEmptyRequiredField ? firstEmptyRequiredField : getFirstInvalidField(); return nonValidatedCount; }; function getFirstInvalidField() { var firstInvalidField = null; $('.customily-options .cl-option:not(.cl-exclude)').each(function () { var $self = $(this); var $errors = $self.find('div.cl-error, div.mage-error'); var isErrorVisible = false; /** * Check if error message for that element is visible * as most elements will have their own error message ready but hidden */ $.each($errors, function (key, error) { var $error = $(error); if ($error.is(":visible")) { isErrorVisible = true; } }); if ($errors.length && isErrorVisible) { if (!firstInvalidField) { firstInvalidField = $(this); } } }); return firstInvalidField; } customily.validateImageSize = function () { var nonValidatedCount = 0; $('.customily-options .cl-invalid-image-size').each(function () { var $self = $(this); var $span = $self.find('label').first().find('span'); var $error = $self.find('.customily-invalid-size-error'); if ($self.is(':visible')) { $span.addClass('customily-invalid-image-size'); $error.removeClass('hidden'); nonValidatedCount++; } }); return nonValidatedCount; }; function functionIsUsed(func) { customily.optionsToShow.forEach(function (o) { o.functions.forEach(function (f) { if (f.element_id == func.element_id && f.type == func.type) { return true; } }); }); return false; } function addPendingOperation(func, elId, value, opId) { var index = _.findIndex(customily.pendingOperations, {element_id: elId, function: func}); if (index != -1) { customily.pendingOperations[index].value = value; } else { customily.pendingOperations.push({ function: func, element_id: elId, value: value, optionId: opId }); } } function attributeChange(attribute) { attribute.functions.forEach(function (f) { var elemId = f.element_id, func = f.type; if (func && (elemId || func === 'product')) { if (!customily.preview.isVisible) { customily.displayCanvas(); } var position; switch (func) { case 'font': position = attribute.selected.font_id; if (!engraver.productLoading && position) { setFontType(elemId, position); } break; case 'color': position = attribute.selected.color_id; if (!engraver.productLoading && position) { setFontColor(elemId, position); } break; case 'dynamic_image': position = attribute.selected.dynamic_image_id; if (!engraver.productLoading && position) { setDynamicImage(elemId, position); } break; case 'image_color': position = attribute.selected.image_color_id; if (!engraver.productLoading && position) { setImageColor(elemId, position); } break; case 'dynamic_vector': position = attribute.selected.dynamic_vector_id; if (!engraver.productLoading && position) { setDynamicVector(elemId, position); } break; case 'vector_color': position = attribute.selected.vector_color_id; if (!engraver.productLoading && position) { setVectorColor(elemId, position); } break; case 'product': position = attribute.selected.product_id; if ( !engraver.currentProduct || (position && engraver.currentProduct.id != position && engraver.initReady) ) { setProduct(position); } break; default: console.error('Customily Magento: invalid customily function: "' + func + '"'); break; } if (engraver.productLoading && position && func != 'product') { addPendingOperation(func, elemId, position) } } else { console.error('Customily Magento: invalid customily option: function or element id are empty'); } }); const hasConditions = _.find(customily.conditions, function (cond) { return cond.id_conditional == attribute.id; }); if (hasConditions) { customily.evalConditions(); } } function optionChange(el, optionId) { var value = el.value; if (!optionId) { optionId = getOptionId(el); } var option; if (value !== undefined && value != null) { option = getOptionSelectedValue(optionId, value, true); var positions = option.positions; reloadProductPriceBottom(option); option.functions.forEach(function (f, i) { var position = (positions && positions[i]) ? positions[i].position : null, elemId = f.element_id, func = f.type; if (func && (elemId || func === 'product')) { if (!engraver.productLoading && !customily.preview.isVisible) { customily.displayCanvas(); } switch (func) { case 'text': if (!engraver.productLoading) { setText(elemId, applyTextTransform(option.text_transform, value)); } break; case 'initials': if (!engraver.productLoading) { setInitials(elemId, value, optionId); } break; case 'file': case 'vector': value = el.files && el.files[0] ? el.files[0] : null; if (!engraver.productLoading) { setFile(elemId, value, option.id, func); } break; case 'font': if (!engraver.productLoading && position) { setFontType(elemId, position); } else { value = position; } break; case 'color': if (!engraver.productLoading && position) { setFontColor(elemId, position); } else { value = position; } break; case 'dynamic_image': if (!engraver.productLoading && position) { setDynamicImage(elemId, position); } else { value = position; } break; case 'image_color': if (!engraver.productLoading && position) { setImageColor(elemId, position); } else { value = position; } break; case 'dynamic_vector': if (!engraver.productLoading && position) { setDynamicVector(elemId, position); } else { value = position; } break; case 'vector_color': if (!engraver.productLoading && position) { setVectorColor(elemId, position); } else { value = position; } break; case 'product': if (position) setProduct(position); break; default: console.error('Customily Magento: invalid customily function: "' + func + '"'); break; } if (engraver.productLoading && value && func != 'product') { addPendingOperation(func, elemId, value, optionId); } } else { console.error('Customily Magento: invalid customily option: function or element id are empty'); } }); if (customily.personalization.handlePrices == '1') { updatePrice($(el), option); } if (customily.personalization.type == 'modal-preview') { customily.updatePriceElement(); } } } function updatePrice($el, option) { setTimeout(function () { var prices = customily.defaultGetOptionValue($el, null, option); $(customily.optionsPrices.priceBoxSelector).trigger('updatePrice', prices); }, 200); } function savePlaceholderSettings() { var placeholders = customily.options.filter(function (o) { return _.some(o.functions, function (f) { return (f.type == 'file' || o.type == 'vector') && o.selected; }); }); if (placeholders) { _.filter(placeholders, function (p) { return customily.lastFiles[p.id] && customily.lastFiles[p.id].length && p.functions && p.functions.length }).forEach(function (p) { p.functions.forEach(function (func) { var index = _.findIndex(customily.lastFiles[p.id], { element_id: func.element_id, type: func.type }); if (index != -1) { var object = _.find(engraver.canvas.getObjects(), function (o) { return o.id == customily.lastFiles[p.id][index].elementId; }); if (object) { if (customily.lastFiles[p.id][index].type == 'file') { customily.lastFiles[p.id][index].angle = object.getEditModeImageParameters().angle || 0; customily.lastFiles[p.id][index].scale = object.getEditModeImageParameters().scaleX || 1; customily.lastFiles[p.id][index].offsetX = object.getEditModeImageParameters().offsetX || 0; customily.lastFiles[p.id][index].offsetY = object.getEditModeImageParameters().offsetY || 0; } else { customily.lastFiles[p.id][index].angle = object.getEditModeParameters().angle || 0; customily.lastFiles[p.id][index].scale = object.getEditModeParameters().scaleX || 1; customily.lastFiles[p.id][index].offsetX = object.getEditModeParameters().offsetX || 0; customily.lastFiles[p.id][index].offsetY = object.getEditModeParameters().offsetY || 0; } } } }); }); } } function setText(elemId, value) { if (elemId && value !== undefined && value !== null) { elemId = parseInt(elemId); engraver.setText(elemId, value); } } function setInitials(elemIds, value, optionId) { var length = $('input[name="options[' + optionId + ']"]').attr('maxlength'); if (elemIds && value !== undefined && value !== null && parseInt(length)) { elemIds = elemIds.split(','); elemIds.forEach(function (elemId, i) { elemId = parseInt(elemId.trim()); if (elemId) { if (value[i]) { engraver.setText(elemId, value[i]); } else { engraver.setText(elemId, ''); } } }); } } function setFile(elemId, file, optionId, func) { if (elemId && optionId && func && file && file.name) { elemId = parseInt(elemId); try { if (func == 'vector') { engraver.setVector(elemId, file).then(function () { engraver.clearSelection(); addFileInfo(elemId, file, optionId, func); }); } else { var reader = new FileReader(); reader.onload = function (e) { var dataUrl = e.target.result; var option = _.find(customily.options, function (o) { return o.id == optionId; }); var minWidth = parseInt(option.image_min_width); var minHeight = parseInt(option.image_min_height); var maxWidth = parseInt(option.image_max_width); var maxHeight = parseInt(option.image_max_height); var $parent = getOptionParent(option); var img = new Image(); img.src = dataUrl; img.onload = function () { if ( (minWidth > 0 && img.width < minWidth) || (minHeight > 0 && img.height < minHeight) || (maxWidth > 0 && img.width > maxWidth) || (maxHeight > 0 && img.height > maxHeight) ) { /** * Invalid image - do nothing by now * Was: add and show image error classes */ } else { engraver.setImage(elemId, dataUrl).then(function () { engraver.clearSelection(); addFileInfo(elemId, dataUrl, optionId, func); }); /** * Since no error classes were added, no need to hide them * Was: remove and hide image error classes */ } } }; reader.readAsDataURL(file); } } catch (ex) { console.error(ex); } } } function addFileInfo(elemId, file, optionId, type) { if (!customily.lastFiles[optionId]) { customily.lastFiles[optionId] = []; } var index = _.findIndex(customily.lastFiles[optionId], {element_id: elemId}); if (index != -1) { customily.lastFiles[optionId][index].fileData = file; } else { customily.lastFiles[optionId].push({ type: type, elementId: elemId, fileData: file, angle: 0, scale: 1, offsetX: 0, offsetY: 0 }); } } function setFileByData(elemId, data, func) { if (elemId) { elemId = parseInt(elemId); var promise; if (data && data.fileData) { var object = _.find(engraver.canvas.getObjects(), function (o) { return o.id == elemId; }); if (func == 'vector') { promise = engraver.setVector(elemId, data.fileData); } else { promise = engraver.setImage(elemId, data.fileData); } promise.then(function () { if (object) { if (func == 'vector') { engraver.canvas.setActiveObject(object._controlRectangle); } else { engraver.canvas.setActiveObject(object._maskBoundsRectangle); } engraver.setImagePlaceHolderRotation(data.angle); engraver.setImagePlaceHolderScale(data.scale); engraver.moveImagePlaceholder(data.offsetX, data.offsetY); engraver.canvas.requestRenderAll(); } engraver.clearSelection(); }); } } } function setFontType(elemId, position) { if (elemId && position) { elemId = parseInt(elemId); position = parseInt(position); engraver.setFont(elemId, position); } } function setFontColor(elemId, position) { if (elemId && position) { elemId = parseInt(elemId); position = parseInt(position); engraver.setFontColor(elemId, position); } } function setDynamicImage(elemId, position) { if (elemId && position) { elemId = parseInt(elemId); position = parseInt(position); engraver.setPresetImage(elemId, position); } } function setImageColor(elemId, position) { if (elemId && position) { elemId = parseInt(elemId); position = parseInt(position); engraver.setImageColor(elemId, position); } } function setDynamicVector(elemId, position) { if (elemId && position) { elemId = parseInt(elemId); position = parseInt(position); engraver.setPresetVector(elemId, position); } } function setVectorColor(elemId, position) { if (elemId && position) { elemId = parseInt(elemId); position = parseInt(position); engraver.setPresetVectorColor(elemId, position); } } var lastify = function (fn) { var lastToken = { cancel: function () { } }; return function (...args) { lastToken.cancel(); args.push(lastToken); return fn(...args); }; }; var setProductWithCancellation = lastify(function (id, token) { return new Promise(function (resolve, reject) { if (engraver) { var cancelled = false; token.cancel = function () { cancelled = true; console.warn('Product load cancelled for template id: ' + id); reject(new Error('Product load cancelled for template id: ' + id)); }; engraver.setProduct(id).then(function () { if (!cancelled) { resolve(); } }); } else { reject(); } }); }); function setProduct(productId) { if (productId) { try { if (customily.preview.savePlaceholdersSettings == '1') { savePlaceholderSettings(); } customily.template.id = productId.trim(); engraver.productLoading = true; setProductWithCancellation(customily.template.id).then(function () { console.log('Customily Magento: product: ' + productId + ' has been loaded!'); engraver.productLoading = false; engraver.clearSelection(); customily.template.isLoaded = true; window.dispatchEvent(new CustomEvent(CUSTOMILY_LOADED_EVENT)); }).catch(function (ex) { console.warn('Customily Magento: failed loading product: ' + productId); console.warn(ex); }); } catch (ex) { var title = 'Customily Magento: an error occurred when trying trim templateId: ' + productId + '.'; customily.createLog(title, ex.message).then(function () { console.warn(title); console.warn(ex); }); } } } function adjustSpaceForMobileControls() { setTimeout(function () { var $imagesContainer = customily.getImagesContainer($('#fabric-container').parent()); if ($imagesContainer &&$imagesContainer.length &&!$imagesContainer.hasClass('fotorama__stage') &&!$imagesContainer.attr('id') == 'mtImageContainer') { if ($('.customily-mobile-controls').is(':visible')) { $('#fabric-container').addClass('margin-bottom-60'); } else { $('#fabric-container').removeClass('margin-bottom-60').css('margin-bottom', $imagesContainer.css('margin-bottom')); } } }, 50); } customily.adjustPreview = function () { if (customily.personalization.type == 'page-preview') { try { if (!customily.preview.isVisible) { var $previewContainer = $('#fabric-container').parent(); var $imagesContainer = customily.getImagesContainer($previewContainer); var $activeImage = customily.getActiveImage($previewContainer); if ( $previewContainer && $previewContainer.length && $imagesContainer && $imagesContainer.length && $activeImage && $activeImage.length ) { if ($activeImage.width() > customily.preview.width) { customily.preview.width = $activeImage.width(); } if (customily.preview.width > 1) { var $fabricContainer = $('#fabric-container'), $window = $(window); var barWidth = $fabricContainer.parent().find('.fotorama__nav__frame').width(); $fabricContainer .css('width', customily.preview.width + 'px') .css('min-height', $imagesContainer.height() + 'px') .css('margin-top', $imagesContainer.css('margin-top')); if ($window.width() > 767 && $window.width() < 1366) { if ($window.width() > $window.height()) { $fabricContainer.css('margin', 'auto') .css({'width': 'calc('+ 100 + '% - ' + barWidth + 'px)'}) .css('left', barWidth/2 + 'px'); } else { $fabricContainer.css('margin-right', barWidth + 'px') .css({'width': 'calc('+ 100 + '% - ' + barWidth + 'px)'}) .css('left', barWidth + 'px'); } } window.onresize = function (event) { if ($window.width() > 767 && $window.width() < 1366) { if ($window.width() > $window.height()) { $fabricContainer.css('margin', 'auto') .css({'width': 'calc('+ 100 + '% - ' + barWidth + 'px)'}) .css('left', barWidth/2 + 'px'); } else { $fabricContainer.css('margin-right', barWidth + 'px') .css({'width': 'calc('+ 100 + '% - ' + barWidth + 'px)'}) .css('left', barWidth + 'px'); } } } adjustSpaceForMobileControls(); customily.saveProductImagePosition(); var lPos = parseFloat(customily.preview.position.left) || 0; if ( $window.width() > 767 && $window.width() < 1366 && $window.width() > $window.height() ) { lPos /= 2; } $fabricContainer.css('left', `${lPos}px`); customily.preview.position.top = customily.preview.position.top || 0; var styleHtml = '
'; $('#customily-custom-css').remove(); var d = document.createElement('div'); d.id = 'customily-custom-css'; d.innerHTML = styleHtml; document.head.appendChild(d); $previewContainer.addClass('customily-preview-container'); } } } } catch (ex) { var title = 'Customily Magento: an error occurred when trying to adjust preview, product: ' + customily.product.id + '.'; customily.createLog(title, ex.message).then(function () { console.warn(title); console.error(ex); }); } } }; customily.init = function (force) { customily.initialized = true; console.log(customily.swatches); if (customily.swatches.enabled === '1') { createSwatches(); customily.imagesLazyLoad(); } addInputLengthValidation(); customily.handleCustomilyOptions(true); customily.evalConditions(); window.dispatchEvent(new CustomEvent(CUSTOMILY_OPTIONS_LOADED_EVENT)); if (customily.template.id) { if (!$('#preview-canvas').length) { console.log('Customily Magento: creating hidden canvas'); var $container = $('
').attr('id', 'fabric-container').css('display', 'none'); var $canvas = $('