Personalized Photo Printed White Ceramic Indoor Plant Pot with Drainage & Saucer - Home Sweet Home (2024)

PHOTO GUIDELINES

  • Saved as JPG or PNG
  • Minimum size of 515px. X 335px.
  • View all Photo Customization and Editing Tips here

NOTE: Your photo must touch the top and bottom solid dark blue line in order to prevent any unwanted white space.

--- Front ---

--- Back ---

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: '121850', type: 'simple', price: '14.99' }; customily.template = { id: '033f77c7-9725-40a7-8278-f965f64b9d6d', isLoaded: false }; customily.personalization = { type: 'page-preview', isOptional: '0', attachTo: 'child', behavior: 'visible', childrenInfo: JSON.parse('[]'), 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 = '[]'; 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":"109775","type":"radio","label":"SELECT PRINT COLOR","price":"0","default":"","selected":"","functions":[{"id":0,"type":"dynamic_vector","element_id":"2"},{"id":1,"type":"color","element_id":"4"}],"conditions":[],"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":"219482","label":"Black","positions":[{"id":0,"type":"dynamic_vector","element_id":"2","position":"1"},{"id":1,"type":"color","element_id":"4","position":1}],"color":"#000000","thumbnail":"","sku":"","price":"USD $0.00","color_fee_code":""},{"id":"219494","label":"Sand","positions":[{"id":0,"type":"dynamic_vector","element_id":"2","position":"2"},{"id":1,"type":"color","element_id":"4","position":2}],"color":"#c7a78f","thumbnail":"","sku":"","price":"USD $0.00","color_fee_code":""},{"id":"219485","label":"Navy Blue","positions":[{"id":0,"type":"dynamic_vector","element_id":"2","position":"3"},{"id":1,"type":"color","element_id":"4","position":3}],"color":"#3d505a","thumbnail":"","sku":"","price":"USD $0.00","color_fee_code":""},{"id":"219488","label":"Dusty Blue","positions":[{"id":0,"type":"dynamic_vector","element_id":"2","position":"4"},{"id":1,"type":"color","element_id":"4","position":4}],"color":"#a1bbc6","thumbnail":"","sku":"","price":"USD $0.00","color_fee_code":""},{"id":"219491","label":"Terracotta","positions":[{"id":0,"type":"dynamic_vector","element_id":"2","position":"5"},{"id":1,"type":"color","element_id":"4","position":5}],"color":"#cb8362","thumbnail":"","sku":"","price":"USD $0.00","color_fee_code":""},{"id":"219497","label":"Taupe Grey","positions":[{"id":0,"type":"dynamic_vector","element_id":"2","position":"6"},{"id":1,"type":"color","element_id":"4","position":6}],"color":"#a49e9d","thumbnail":"","sku":"","price":"USD $0.00","color_fee_code":""},{"id":"219500","label":"Dusty Rose","positions":[{"id":0,"type":"dynamic_vector","element_id":"2","position":"7"},{"id":1,"type":"color","element_id":"4","position":7}],"color":"#e8bdb6","thumbnail":"","sku":"","price":"USD $0.00","color_fee_code":""}],"color_fee":"0"},{"id":"109778","type":"radio","label":"Included","price":"0","default":"","selected":"","functions":[],"conditions":[],"is_swatch":"1","is_required":"0","swatch_settings":{"width":45,"height":45,"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":"219503","label":"HOME SWEET HOME","positions":[],"color":"","thumbnail":"","sku":"","price":"USD $0.00","color_fee_code":""}],"color_fee":"0"},{"id":"109781","type":"field","label":"LINE 1","price":"0.000000","default":"","selected":"","functions":[{"id":0,"type":"text","element_id":"4"}],"conditions":[],"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":"109784","type":"file","label":"ADD PHOTO","price":"0.000000","default":"","selected":"","functions":[{"id":0,"type":"file","element_id":"3"}],"conditions":[],"is_swatch":"1","is_required":"1","swatch_settings":[],"text_transform":"none","image_min_width":515,"image_min_height":335,"image_max_width":10000,"image_max_height":10000,"values":[],"color_fee":"0"},{"id":"109787","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":"219506","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 = $('

').attr('id', 'preview-canvas'); $container.append($canvas).appendTo('body'); } engraver.productLoading = true; setProductWithCancellation(customily.template.id).then(function () { engraver.productLoading = false; engraver.clearSelection(); customily.template.isLoaded = true; if (customily.personalization.type == 'page-preview') { try { customily.saveProductImagePosition(); if (!customily.preview.ready) { customily.positioningPreview('templateLoaded'); } } catch (ex) { var title = 'Error positioning preview.'; customily.createLog(title, ex.message).then(function () { console.warn(title); console.error(ex); }); } } if (customily.isEditMode == '1' || force) { window.dispatchEvent(new CustomEvent(CUSTOMILY_LOADED_EVENT)); } else { if (customily.hasDefaultValues) { window.dispatchEvent(new CustomEvent(CUSTOMILY_LOADED_DEFAULTS_EVENT)); } else { processPendingOperations(); enableCustomilyBtn(); } } }).catch(function (ex) { var title = 'Customily Magento: failed loading product: ' + customily.template.id; customily.createLog(title, ex.message).then(function () { console.warn(title); console.warn(ex); }); }); } }; customily.imagesLazyLoad = function (timeout = 1000) { setTimeout(function () { var $images = $('.customily-lazy-load').filter(function () { return !$(this).attr('data-loaded'); }); var promises = []; $images.each(function (i, e) { promises.push( new Promise(function (resolve) { var url = $(e).attr('data-src'); var image = new Image(); image.onload = function () { $(e).attr('src', url).attr('data-loaded', true); resolve(); } image.src = url; }) ); }); if (promises.length) { Promise.all(promises).then(function () { console.log('Customily Magento: all images were loaded correctly.'); }); } }, timeout); }; function getAttributeSelectedValue(attributeCode, selected, markAsSelected) { var result = { id: null, label: null, functions: [], selected: null }; var attrIndex = _.findIndex(customily.attributes_options, {code: attributeCode}); if (attrIndex != -1) { result.id = customily.attributes_options[attrIndex].id; result.label = customily.attributes_options[attrIndex].label; result.functions = customily.attributes_options[attrIndex].functions; var valueIndex = _.findIndex(customily.attributes_options[attrIndex].values, {id: selected}); if (valueIndex != -1) { result.selected = customily.attributes_options[attrIndex].values[valueIndex]; if (markAsSelected) { customily.attributes_options[attrIndex].selected = result.selected; } else { customily.attributes_options[attrIndex].selected = false; } } } return result; } function getOptionId(element) { var re, id, name; if (!element) { return id; } name = element.type == 'file' ? $(element).attr('data-option-name') : $(element).attr('name'); if (name.indexOf('[') !== -1) { re = /\[([^\]]+)?\]/; } else { re = /_([^\]]+)?_/; } id = re.exec(name) && re.exec(name)[1]; if (id) { return id; } } function getOptionElement(option) { if (option.type == 'file') { return $('.customily-options [data-option-name="options[' + option.id + ']"]').first(); } if (option.type == 'checkbox') { return $('.customily-options [name="options[' + option.id + '][]"]').first(); } if (option.type == 'radio') { var $radios = $('.customily-options [name="options[' + option.id + ']"]'); var $el = $radios.filter(function () { return $(this).prop('checked'); }); return $el.length ? $el.first() : $radios.first(); } return $('.customily-options [name="options[' + option.id + ']"]').first(); } function getOptionParent(option) { if (option.type == 'file') { return $('.customily-options [data-option-name="options[' + option.id + ']"]').first().parents('.cl-option'); } if (option.type == 'checkbox') { return $('.customily-options [name="options[' + option.id + '][]"]').first().parents('.cl-option'); } return $('.customily-options [name="options[' + option.id + ']"]').first().parents('.cl-option'); } function getOptionSelectedValue(elementId, selected, markAsSelected) { var result = { id: null, label: null, price: null, functions: [], positions: null, selected: null, text_transform: null, isVisible: false, color_fee: null }; var optionIndex = _.findIndex(customily.options, {id: elementId}); if (optionIndex != -1) { result.id = customily.options[optionIndex].id; result.label = customily.options[optionIndex].label; result.price = customily.options[optionIndex].price; result.functions = customily.options[optionIndex].functions; result.text_transform = customily.options[optionIndex].text_transform || 'none'; result.isVisible = customily.options[optionIndex].isVisible; result.color_fee = customily.options[optionIndex].color_fee; if ( customily.options[optionIndex].type == 'field' || customily.options[optionIndex].type == 'area' || customily.options[optionIndex].type == 'file' || customily.options[optionIndex].type == 'checkbox' ) { result.selected = selected; customily.options[optionIndex].selected = selected; } else if ( customily.options[optionIndex].values && customily.options[optionIndex].values.length > 0 ) { var valueIndex = _.findIndex(customily.options[optionIndex].values, {id: selected}); if (valueIndex != -1) { result.positions = customily.options[optionIndex].values[valueIndex].positions; result.selected = { label: customily.options[optionIndex].values[valueIndex].label, value: customily.options[optionIndex].values[valueIndex].id, price: customily.options[optionIndex].values[valueIndex].price, color_fee_code: customily.options[optionIndex].values[valueIndex].color_fee_code }; customily.options[optionIndex].price = result.selected.price; if (markAsSelected) { customily.options[optionIndex].selected = result.selected; } else { customily.options[optionIndex].selected = false; } } } } return result; } function getAttributeOptionById(id) { var attr = _.find(customily.attributes_options, function (a) { return a.id == id; }); return attr; } function getOptionByLabel(label) { var option = _.find(customily.options, function (o) { return o.label == label; }); return option; } function getOptionValueSelected (option, func, optionId) { if (option.type == 'field' || option.type == 'area') { return option.selected; } else if (option.type == 'file' || option.type == 'vector') { if ( customily.lastFiles && customily.lastFiles[option.id] && customily.lastFiles[option.id].length ) { var result = _.find(customily.lastFiles[option.id], function (f) { return f.elementId == func.element_id; }); if (!result) { for (var i = 0; i < customily.lastFiles[option.id].length; i++) { if (!customily.lastFiles[option.id][i].elementId) { customily.lastFiles[option.id][i].elementId = func.element_id; result = customily.lastFiles[option.id][i]; break; } } } return result; } } else { if (option.selected && option.selected.value) { if (func.type == 'product' && option.id != optionId) { return null; } const o = _.find(option.values, function (v) { return v.id == option.selected.value; }); const p = _.find(o.positions, function (pos) { return (pos.element_id == func.element_id || pos.id == func.id) && pos.type == func.type; }); if (p && p.position) { return p.position; } return null; } } } function addInputLengthValidation() { $('.customily-options input:text, .customily-options textarea').each(function () { if ($(this).data('validate') && $(this).data('validate').maxlength) { $(this).attr('maxlength', parseInt($(this).data('validate').maxlength)); } }); } $(document).on('keyup', '.customily-options input:text, .customily-options textarea', function () { var $input = $(this); var max = parseInt($input.attr('maxlength')); if (max && max > 0 && $input.val().length > max) { $input.val($input.val().substr(0, max)); $input.trigger('input'); } }); /** * create swatches by radio button options */ function createSwatches() { _.filter(customily.options, function (o) { return o.type === 'radio' && o.is_swatch === '1' }).forEach(function (option) { var $first = $('input[name="options[' + option.id + ']"][value=""]'); if ($first.length) { $first.parent().addClass('hidden'); $first.addClass('swatch-none-value').attr('price', '0').attr('data-price', '0'); } else { $first = $('

\n' + '\n' + '

'); $('input[name="options[' + option.id + ']"]').first().parent().prepend($first); } var $swatchContainer = $first.parent().parent(); var width = customily.swatches.maxSize; if (option.swatch_settings.width && option.swatch_settings.width > 0) { width = option.swatch_settings.width; } var height = customily.swatches.maxSize; if (option.swatch_settings.height && option.swatch_settings.height > 0) { height = option.swatch_settings.height; } var radius = 0; if (option.swatch_settings.rounded) { radius = (width / 2) + 2; } var align = 'flex-start'; if (option.swatch_settings.align) { if (option.swatch_settings.align == 'left') { align = 'flex-start'; } else if (option.swatch_settings.align == 'right') { align = 'flex-end'; } } $swatchContainer.children('.thread-options').css('justify-content', align); if ($swatchContainer.hasClass('letteringstyle')) { width = 75; height = 75; } if ($swatchContainer.hasClass('logodesign')) { width = 100; height = 100; } if ($swatchContainer.hasClass('logoformat')) { width = 120; height = 89; } $swatchContainer.parent().parent().addClass('swatch-container-wrap'); var containerHeight = '100%'; $swatchContainer.addClass('swatch-container').css('justify-content', align).css('height', containerHeight); option.values.forEach(function (value) { var $radio = $('input[name="options[' + option.id + ']"][value="' + value.id + '"]'); $radio.addClass('cl-option-' + option.id + '-' + value.id); $radio.parent().addClass('swatch').addClass('customily-swatch'); if (option.swatch_settings.show_tooltip || option.swatch_settings.show_info) { var priceHtml = ''; if (option.swatch_settings.show_price) { priceHtml = '' + value.price + ''; } } var $label = $('label[for="' + $radio.attr('id') + '"]'); $label.css('width', width + 'px').css('height', height + 'px').css('border-radius', radius + 'px'); if (option.swatch_settings.border) { $label.css('box-shadow:', '0 0 1px 1px currentColor;'); } if (value.thumbnail) { var thumbnailUrl = value.thumbnail; var pathIndex = thumbnailUrl.indexOf(CUSTOMILY_SWATCH_THUMBNAILS_URL_PATH); if (pathIndex != -1) { thumbnailUrl = customily.magento.baseMediaUrl + thumbnailUrl.substr(pathIndex, thumbnailUrl.length); } var imgWidth = width - 2; var imgHeight = height - 2; var $image = $('Personalized Photo Printed White Ceramic Indoor Plant Pot with Drainage & Saucer - Home Sweet Home (1)'); $image.css('border-radius', radius + 'px'); $label.html('').append($image); } else if (value.color) { $label.css('background-color', value.color).html(''); } $label.append(''); }); }); } function setDefaultOptionValueToPreview(option) { _.filter(option.functions, function (f) { return !functionIsUsed(f); }).forEach(function (f) { var value = getDefaultValue(f); if (value !== undefined && value != null) { updatePreviewCanvas(f.type, f.element_id, value, option.id); } }); } function handlePreviewCanvasAttributes() { _.filter(customily.attributes_options, function (attr) { return attr.selected; }).forEach(function (attribute) { if (attribute.selected) { if (customily.isEditMode == '1') { attributeChange(attribute); } else { var hasChangeProduct = attribute.functions.some(function (f) { return f.type == 'product'; }); if (!hasChangeProduct) { attributeChange(attribute); } } } }); } function handlePreviewCanvasConditions() { customily.optionsToHide.forEach(function (o) { setDefaultOptionValueToPreview(o); if (customily.personalization.handlePrices == '1') { var $el = getOptionElement(o); if ($el.length) { updatePrice($el, o); } } }); var op = customily.optionsToShow.filter(function (o) { return _.find(o.functions, function (f) { return f.type == 'product'; }) }).slice(-1)[0]; op = op && op.id ? op.id : false; customily.optionsToShow.forEach(function (o) { o.functions.forEach(function (f) { const value = getOptionValueSelected(o, f, op); if (value !== undefined && value != null) { reloadProductPriceBottom(o);if (o.type == 'field' || o.type == 'area') { getOptionElement(o).val(value).trigger('change'); } updatePreviewCanvas(f.type, f.element_id, value, o.id); } }); if (customily.personalization.handlePrices == '1') { var $el = getOptionElement(o); if ($el.length) { updatePrice($el, o); } } }); } customily.handleCustomilyOptions = function (handlePrices) { $('.customily-options .field:not(.customily-swatch):not(.choice)').addClass('cl-option'); if (handlePrices) { $('.cl-option').each(function () { $(this).find('[price]').each(function (i, el) { $(el).attr('data-price', $(el).attr('price')); }); }); } if (customily.collapsibleOptions == '1') { var $fields = $('.cl-option').filter(function () { return !$(this).hasClass('is-cl-co-active'); }).addClass('cl-co-no-padding').children().filter(':not(label)'); $fields.each(function () { if ($(this).hasClass('visible')) { $(this).removeClass('visible'); $(this).data('control-visible', true); } $(this).hide(); }); } initOptionsContainers(); if (customily.personalization.type == 'page-preview') { $('.customily-options').css('visibility', 'visible'); $('.customily-file-field').css('visibility', 'visible'); console.log('Customily Magento: options are ready.'); } } function clearOptionsFields(all = false) { if (all) { _.filter(customily.options, function (o) { return o.selected; }).forEach(function (option) { clearOptionField(option); }); } else { _.filter(customily.optionsToHide, function (o) { return o.selected; }).forEach(function (option) { clearOptionField(option); }); } } function restoreOptionsFields() { _.filter(customily.options, function (o) { return o.selected; }).forEach(function (option) { var $el; if (option.type == 'file') { $el = $(customily.querySelectors.addToCartForm + ' [data-role="customily-options"] [data-option-name="options[' + option.id + ']"]'); } else if (option.type == 'checkbox') { $el = $(customily.querySelectors.addToCartForm + ' [data-role="customily-options"] [name="options[' + option.id + '][]"]'); } else { $el = $(customily.querySelectors.addToCartForm + ' [data-role="customily-options"] [name="options[' + option.id + ']"]'); } if ($el.length) { var $parent = $el.first().parents('.cl-option'); switch (option.type) { case 'radio': $el = $('.cl-option-' + option.id + '-' + option.selected.value); $el.prop('checked', true); $parent.attr('data-selected', option.selected.value); break; case 'checkbox': $el = $('.cl-checked-' + option.id); $el.val(option.selected).prop('checked', true); $parent.attr('data-selected', option.selected); break; case 'drop_down': $el.val(option.selected.value); break; case 'field': case 'area': $el.val(option.selected); break; case 'file': var $file = $el.data('cl-restore'); $file.insertAfter($el); $el.remove(); $el = $file; break; default: break; } $parent.addClass('selected'); if (customily.personalization.handlePrices == '1') { updatePrice($el, option); } } }); } function clearOptionField(option, clearFile) { var $el; if (option.type == 'file') { $el = $(customily.querySelectors.addToCartForm + ' [data-role="customily-options"] [data-option-name="options[' + option.id + ']"]'); } else if (option.type == 'checkbox') { $el = $(customily.querySelectors.addToCartForm + ' [data-role="customily-options"] [name="options[' + option.id + '][]"]'); } else { $el = $(customily.querySelectors.addToCartForm + ' [data-role="customily-options"] [name="options[' + option.id + ']"]'); } if ($el.length) { var $parent = $el.first().parents('.cl-option'); switch (option.type) { case 'radio': $el.filter(function () { return $(this).hasClass('swatch-none-value'); }).first().prop('checked', true); $parent.attr('data-selected', null); break; case 'checkbox': $el.filter(function () { return $(this).prop('checked'); }).prop('checked', false); $parent.attr('data-selected', null); break; case 'drop_down': $el.find('option').prop('selected', false); break; case 'field': case 'area': $el.val('').get(0).defaultValue = ''; break; case 'file': if (clearFile) { $el.val(null); } else { var $file = $el.clone(); $file.val(null).insertAfter($el); $file.data('cl-restore', $el.detach()); $el = $file; } break; default: break; } $parent.removeClass('selected'); if (customily.personalization.handlePrices == '1') { updatePrice($el, option); } } } function initOptionsContainers() { customily.options.forEach(function (option) { var $el = getOptionParent(option); if ($el) { if (option.is_required == '1') { $el.addClass('cl-required'); $el.append( '' ); }else{ if($el.hasClass('text_text')){ $el.append(''); } } if ( option.type == 'file' && ( option.image_min_width > 0 || option.image_min_width > 0 || option.image_min_width > 0 || option.image_min_width > 0 ) ) { $el.addClass('cl-validate-size'); } if (option.selected) { $el.addClass('selected'); if (option.type == 'checkbox' || option.type == 'radio') { $el.attr('data-selected', option.selected.value || option.selected); } } } }); } if (customily.collapsibleOptions == '1') { $(document).on('click', '.customily-options .cl-option label:first-child', function (ev) { handleOption(ev); }); function handleOption(ev) { var $option = $(ev.currentTarget).parent(); var optionIsActive = $option.hasClass('is-cl-co-active'); if (!optionIsActive) { if ($option.data('cl-co-visible')) { return false; } $('.customily-options .field').filter(':not(.customily-swatch)').each(function () { hideOption($(this)); }); var $fields = $option.addClass('is-cl-co-active').data('cl-co-visible', true).children().filter(':not(input:radio, label)'); $fields.each(function () { if ($(this).data('control-visible')) { $(this).addClass('visible').data('control-visible', false); } $(this).removeClass('cl-co-hidden').slideDown(300); }); $option.removeClass('cl-co-no-padding').addClass('cl-co-padding'); customily.imagesLazyLoad(100); return true; } else { var $el; switch (ev.target.tagName) { case 'LABEL': case 'SPAN': $el = $(ev.target).parents('.cl-option'); break; case 'DIV': $el = $(ev.target); break; default: break; } if ($el && $el.data('cl-co-visible')) { hideOption($el); ev.preventDefault(); } return false; } } function hideOption($el) { var $fields = $el.removeClass('is-cl-co-active').data('cl-co-visible', false).children().filter(':not(label)'); $fields.each(function () { if ($(this).hasClass('visible')) { $(this).removeClass('visible'); $(this).data('control-visible', true); } $(this).slideUp(300); }); $el.removeClass('cl-co-padding').addClass('cl-co-no-padding'); } } function updatePreviewCanvas(type, elemId, value, optionId) { if (!engraver.productLoading && !customily.preview.isVisible) { customily.displayCanvas(); } if (!engraver.productLoading) { switch (type) { case 'text': setText(elemId, value); break; case 'initials': setInitials(elemId, value, optionId); break; case 'color': setFontColor(elemId, value); break; case 'font': setFontType(elemId, value); break; case 'file': case 'vector': setFileByData(elemId, value, type); break; case 'dynamic_image': setDynamicImage(elemId, value); break; case 'image_color': setImageColor(elemId, value); break; case 'dynamic_vector': setDynamicVector(elemId, value); break; case 'vector_color': setVectorColor(elemId, value); break; case 'product': if (!engraver.currentProduct || (engraver.currentProduct.id != value && engraver.initReady)) { setProduct(value); } break; default: break; } } else { if (type != 'product') addPendingOperation(type, elemId, value, optionId) } } function getDefaultValue(func) { if (func.type == 'text' || func.type == 'initials') { return ''; } else if (['color', 'font', 'dynamic_image', 'image_color', 'dynamic_vector', 'vector_color'].indexOf(func.type) != -1) { return 1; } else if (func.type == 'file') { return { type: 'file', elementId: func.element_id, fileData: 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==', angle: 0, scale: 0, offsetX: 0, offsetY: 0 }; } } customily.addOrUpdateCart = function (ev) { if (customily.personalization.active) { try { ev.preventDefault(); ev.stopPropagation(); if (!customily.preview.isVisible && customily.displayCanvas) { customily.displayCanvas(); } if (engraver) { engraver.clearSelection(); } if (customily.validateRequired() == 0 && customily.validateImageSize() == 0) { $('body').find('.customily-options .cl-error.field-error').hide(); pleaseWaitStart(); var promises = []; var hasThumbnail = customily.cart.customThumbnail == '1'; if (customily.preview.export == '1') { promises.push(uploadPreview(exportPreview(), hasThumbnail)); } else { promises.push(new Promise(function (res) { res({ previewUrl: false, thumbnailUrl: false }); })); } if (customily.productionFile.export == '1') { promises.push(engraver.exportFileDelayed()); } else { promises.push(new Promise(function (res) { res({ Url: false, PersonalizationId: false }); })); } Promise.all(promises).then(function (responses) { console.log('Customily Magento: product added to cart.'); if (responses[0].previewUrl) { $('#url_preview').val(responses[0].previewUrl); console.log('Customily Magento: Preview uploaded successfully.'); } if (responses[0].thumbnailUrl) { $('#url_thumbnail').val(responses[0].thumbnailUrl); console.log('Customily Magento: Preview thumbnail uploaded successfully.'); } if (responses[1].Url) { $('#url_production_file').val(responses[1].Url); } if (responses[1].PersonalizationId) { $('#personalization_id').val(responses[1].PersonalizationId); } $('#magento_product_id').val(customily.product.id); addToCartButtonClick(); }, function (err) { var title = 'Customily Magento: an error occurred when trying to export the preview or when generating the production file for templateId: ' + customily.template.id + '.'; customily.createLog(title, err).then(function () { console.warn(title); console.error(err); }); addToCartButtonClick(); }).catch(function (ex) { var title = 'Customily Magento: an error occurred when trying to export the preview or when generating the production file for templateId: ' + customily.template.id + '.'; customily.createLog(title, ex.message).then(function () { console.warn(title); console.error(ex); }); addToCartButtonClick(); }); } else { /** Trigger form validation without submitting the form */ var dataForm = $(customily.querySelectors.addToCartForm); var ignore = null; dataForm.mage('validation', { ignore: ignore ? ':hidden:not(' + ignore + ')' : ':hidden' }).find('input:text').attr('autocomplete', 'off'); dataForm.validation('isValid'); $('html, body').stop(); /** Scroll to the first invalid required field */ var firstInvalidField = customily.firstInvalidField if (firstInvalidField) { $(firstInvalidField)[0].scrollIntoView({ behavior: "smooth", block: "center" }) } } } catch (ex) { var title = 'Customily Magento: an error occurred when trying to add the personalized product to the cart for templateId: ' + customily.template.id + '.'; customily.createLog(title, ex.message).then(function () { console.warn(title); console.error(ex); }); addToCartButtonClick(); } } else { var optionsToHide = customily.optionsToHide; customily.optionsToHide = customily.options; addToCartButtonClick(); customily.optionsToHide = optionsToHide; setProduct(customily.template.id); } }; function pleaseWaitStart() { if (customily.personalization.type == 'modal-preview') { $('#customily-popup-modal-button span').text('Adding to cart...'); if ($('#customily-popup-modal-button').plswait) {$('#customily-popup-modal-button').plswait();} } else { if (customily.cart.$btn_clone.plswait) { customily.cart.$btn_clone.plswait(); var i = 0; var btnLoadingInterval = setInterval(function () { if (i > 20000) { clearInterval(btnLoadingInterval); } else { $('.loading-btn-overlay').css('top', customily.cart.$btn_clone.position().top + 'px'); i += 25; } }, 25); } } } function pleaseWaitStop() { if (customily.personalization.type == 'modal-preview') { if ($('#customily-popup-modal-button').plswait) $('#customily-popup-modal-button').plswait('stop'); $('#customily-popup-modal-button span').text(customily.showModalBtnText); } else { if (customily.cart.$btn_clone.plswait) customily.cart.$btn_clone.plswait('stop'); } } function addToCartButtonClick() { customily.optionsToHide.forEach(function (o) { if (o.selected || o.type == 'radio' || o.type == 'drop_down') { clearOptionField(o, true); o.selected = null; } }); _.filter(customily.options, function (o) { return (o.type == 'field' || o.type == 'area') && o.isVisible && o.selected }).forEach(function (option) { const $field = getOptionElement(option); if ($field.length) { $field.val(applyTextTransform(option.text_transform, $field.val())); } }); pleaseWaitStop(); customily.cart.$btn.click(); } /** * Convert string base64 to blob * @param base64 * @returns {Blob|false} */ function base64ToBlob(base64) { return new Promise(function (resolve) { fetch(base64).then(function (res) { resolve(res.blob()) }).catch(function (ex) { console.error(ex); resolve(false); }); }); } /** * Generate preview base64 * @param exportSize * @returns {HTMLCanvasElement} */ function exportPreview(exportSize = 800) { if (customily.CanvasRenderingContext2D.drawImage) { CanvasRenderingContext2D.prototype.drawImage = customily.CanvasRenderingContext2D.drawImage; } var cvs = $('.lower-canvas').get(0); var tempcvs = document.createElement('canvas'); var tempctx = tempcvs.getContext('2d'); var size = calculateCanvasSize(cvs.width, cvs.height, exportSize); tempcvs.width = size.width; tempcvs.height = size.height; tempctx.drawImage(cvs, 0, 0, tempcvs.width, tempcvs.height); return tempcvs.toDataURL('image/jpeg', customily.preview.exportQuality); } function calculateCanvasSize(width, height, size) { var ratio = width / height; if (width > height) { return { width: size, height: size / ratio } } else { return { width: size * ratio, height: size } } } /** * Upload preview image * @param dataUrl * @param hasThumbnail * @returns {Promise} */ async function uploadPreview(dataUrl, hasThumbnail) { return new Promise(function (resolve) { var result = { previewUrl: '', thumbnailUrl: '' }; base64ToBlob(dataUrl).then(async function (blob) { var url; var headers; const data = new FormData(); data.append('file', blob); if (customily.saveFilesIn == 'magento') { url = endpoints.magentoApi + '/uploadPreviewAndThumbnail'; data.append('productId', customily.product.id); data.append('hasThumbnail', hasThumbnail); headers = { 'Access-Control-Allow-Origin': '*', 'm-api-key': apiKeys.magentoApiKey }; } else { url = endpoints.customilyApi + '/images/preview/save'; data.append('shop', customily.magento.baseUrl.replace(/^https?:\/\//, '').slice(0,-1)); data.append('cart_token', 'none'); data.append('filename', uuidv4()); headers = { 'Access-Control-Allow-Origin': '*', 'x-access-key': apiKeys.previewApiKey }; if (hasThumbnail) { data.append('file', await base64ToBlob(exportPreview(200))); } } $.ajax({ type: "POST", data: data, url: url, headers: headers, processData: false, contentType: false }).done(function (resp) { var prefix = ''; if (customily.saveFilesIn == 'magento') { resp = JSON.parse(resp); prefix = customily.magento.baseMediaUrl; } if (resp.previewUrl) { result.previewUrl = prefix + resp.previewUrl; } if (resp.thumbnailUrl) { result.thumbnailUrl = prefix + resp.thumbnailUrl; } resolve(result); }).fail(function (err) { var title = 'Customily Magento: an error occurred when trying to upload preview to ' + customily.saveFilesIn + ' server.'; customily.createLog(title, err.message).then(function () { console.warn(title); console.error(err); }); resolve(result); }); }).catch(function (ex) { var title = 'Customily Magento: an error occurred when trying to convert base64 to blob.'; customily.createLog(title, ex.message).then(function () { console.warn(title); console.error(ex); }); resolve(result); }); }); } function uuidv4() { return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c => (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16) ); } function getPersonalizationOptional(id) { var result = _.find(customily.personalization.childrenInfo, function (child) { return child.id == id; }); return result ? result.personalizationIsOptional : '0'; } customily.getPreviewContainer = function ($el) { const $parent = $el || $('body'); for (var i = 0; i < customily.querySelectors.previewContainers.length; i++) { const $result = $parent.find(customily.querySelectors.previewContainers[i]); if ($result && $result.length && !$result.parents('.block.related').length) { return $result.first(); } } return null; }; customily.getImagesContainer = function ($el) { const $parent = $el || $('body'); for (var i = 0; i < customily.querySelectors.imageContainers.length; i++) { const $result = $parent.find(customily.querySelectors.imageContainers[i]); if ($result && $result.length && !$result.parents('.block.related').length) { return $result.first(); } } return null; }; customily.getActiveImage = function ($el) { var $parent = $el || $('body'); return $parent.find(customily.querySelectors.imageActives).first(); }; customily.positioningPreview = function (positionedBy, onLoad = false) { if (customily.preview.positionedOnLoad) { if (onLoad) { doPositioning(); } } else { doPositioning(); } function doPositioning() { setTimeout(function () { var $previewContainer = customily.getPreviewContainer(); if ($previewContainer && $previewContainer.length && !customily.preview.positioned.byFotoramaReady) { $previewContainer.prepend($('#fabric-container')); customily.preview.ready = true; if (customily.hasDefaultValues || customily.isEditMode == '1') { } console.log('Customily Magento: preview positioned successfully by ' + positionedBy + ' inside "' + $previewContainer.get(0).classList.toString() + '".'); } else { console.warn('Customily Magento: preview could not be positioned by ' + positionedBy + '.'); } switch (positionedBy) { case 'contentLoaded': customily.preview.positioned.byContentLoaded = true; break; case 'templateLoaded': customily.preview.positioned.byTemplateLoaded = true; break; case 'fotoramaReady': customily.preview.positioned.byFotoramaReady = true; break; default: break; } }, 2000); } } customily.saveProductImagePosition = function () { try { var $activeImage = customily.getActiveImage(); var $imagesContainer = customily.getImagesContainer(); if ($activeImage && $activeImage.length && $imagesContainer && $imagesContainer.length) { if ($activeImage.first().attr('src').indexOf('images/product/placeholder/') != -1) { customily.preview.position.top = $imagesContainer.position().top; } else { customily.preview.position.top = $activeImage.first().position().top; } customily.preview.position.left = $imagesContainer.position().left; } } catch (ex) { var title = 'Customily Magento: an error occurred when trying to save product image position.' customily.createLog(title, ex.message).then(function () { console.warn(title); console.error(ex); }); } }; customily.initSticky = function () { if (!customily.isMobile() && customily.sticky.enabled == '1') { var $stickyLeft = customily.sticky.leftContainer.length > 0 ? $(customily.sticky.leftContainer) : $('.canvas-wrapper').parent(); var $stickyRight = customily.sticky.rightContainer.length > 0 ? $(customily.sticky.rightContainer) : $('.product-info-main'); $stickyLeft.customily_sticky($stickyRight, {padding: customily.sticky.padding}); $stickyLeft.addClass('margin-bottom-unset'); var margin = (parseInt(customily.sticky.padding) || 40) + 20; $stickyRight.css('margin-bottom', margin + 'px'); } }; customily.cloneAddToCartBtn = function () { customily.cart.$btn = $('#product-addtocart-button'); customily.cart.$btn_clone = customily.cart.$btn.clone(); customily.cart.$btn_clone.attr('type', 'button').attr('id', 'customily-addtocart-button'); if ( customily.personalization.isOptional == '0' || customily.personalization.behavior == 'visible' ) { customily.cart.$btn_clone.prop('disabled', 'disabled'); } customily.cart.$btn_clone.unbind(); customily.cart.$btn_clone.on('click', customily.addOrUpdateCart); if (customily.removeAddToCartBtnClasses) { if (customily.personalization.type == 'modal-preview') { $('.cl-personalization-button').unbind(); $('.cl-personalization-button').removeClass('action').removeClass('tocart'); $('.cl-personalization-button').copyCSS('.action.tocart'); } else { customily.cart.$btn_clone.removeClass('action').removeClass('tocart'); customily.cart.$btn_clone.copyCSS('.action.tocart'); } } customily.cart.$btn.after(customily.cart.$btn_clone); customily.cart.$btn.hide(); }; $(document).ready(function () { (function (t) { return t ? void (t.fn.customily_sticky = function (o, s) { var n = t(this); n.data('st_top', n.offset().top), n.css('transition', 'all 0s'); var a = s || {}; a.padding = a.padding || 0, window.addEventListener('scroll', function (t) { var s = document.documentElement.scrollTop; 0 == s && n.data('st_top', n.offset().top); var i = n.data('st_top'), r = s - i, e = o.outerHeight(), d = o.offset().top, c = n.outerHeight(); e - c > r && r > 0 && d < i + c ? (n.css('margin-top', r + a.padding), n.css('margin-bottom', -1 * c / 2)) : r <= 0 && (n.css('margin-top', 0), n.css('margin-bottom', 0)) }) }) : 0 })(jQuery); (function ($) { $.fn.getStyleObject = function () { var dom = this.get(0); var style; var returns = {}; if (window.getComputedStyle) { var camelize = function (a, b) { return b.toUpperCase(); }; style = window.getComputedStyle(dom, null); for (var i = 0, l = style.length; i < l; i++) { var prop = style[i]; var camel = prop.replace(/\-([a-z])/g, camelize); returns[camel] = style.getPropertyValue(prop); } return returns; } if (style == dom.currentStyle) { for (var p in style) { returns[p] = style[p]; } return returns; } return this.css(); }; $.fn.copyCSS = function (source) { var styles = $(source).getStyleObject(); this.css(styles); }; })(jQuery); function initialize() { var html = ''; $('#product-addtocart-button').parent('.box-tocart .actions').before(html); setTimeout(function () { customily.cloneAddToCartBtn(); }, 300); } initialize(); }); function restoreAttributes() { var selectedAttributes = _.filter(customily.attributes_options, function (attr) { return attr.selected; }); var interval = setInterval(function () { var count = 0; selectedAttributes.forEach(function (attribute) { var $el = customily.magento.version < '2.3.0' ? $('[attribute-code="' + attribute.code + '"]') : $('[data-attribute-code="' + attribute.code + '"]'); var $option = customily.magento.version < '2.3.0' ? $el.find('[option-id="' + attribute.selected.id + '"]') : $el.find('[data-option-id="' + attribute.selected.id + '"]'); var $input = $el.find('[name="super_attribute[' + attribute.id + ']"]'); if (customily.magento.version < '2.3.0') { $el.attr('option-selected', attribute.selected.id); } else { $el.attr('data-option-selected', attribute.selected.id); } if ($el.length && $option.length && $input.length) { if ($option.get(0).tagName == 'OPTION') { $option.parent().val(attribute.selected.id); } else { $option.addClass('selected').attr('aria-checked', true); } $input.val(attribute.selected.id); attributeChange(attribute); count++; } }); if (count == selectedAttributes.length) { clearInterval(interval); console.log('Customily Magento: attributes loaded.') } }, 250); } function processPendingOperations() { customily.pendingOperations.forEach(function (o) { if (o.function == 'file' || o.function == 'vector') { try { setFile(o.element_id, o.value, o.optionId, o.function); } catch (ex) { console.log(ex); updatePreviewCanvas(o.function, o.element_id, o.value, o.optionId); } } else { updatePreviewCanvas(o.function, o.element_id, o.value, o.optionId); } }); customily.pendingOperations = []; } function enableCustomilyBtn() { if (customily.personalization.type == 'modal-preview') { $('#customily-popup-modal-button').removeAttr('disabled'); $('#customily-popup-modal-button img').addClass('hidden'); setTimeout(function () { customily.updatePriceElement(); }, 600); } else { $('#customily-addtocart-button').removeAttr('disabled'); } } function clearCustomilyFields() { $('#url_thumbnail').val(''); $('#url_preview').val(''); $('#url_production_file').val(''); $('#personalization_id').val(''); $('#magento_product_id').val(''); } function getSelectedProductId() { var result = []; var options = {}; $('div.swatch-attribute').each(function (i, e) { var attributeId = $(e).attr('attribute-id'); var option = $(e).attr('option-selected'); if (!attributeId) { attributeId = $(e).attr('data-attribute-id'); } if (!option) { option = $(e).attr('data-option-selected'); } if (!attributeId || !option) { return; } options[attributeId] = option; }); var $swatchOption = $('[data-role=swatch-options]'); if ( $swatchOption.length && $swatchOption.data('mageSwatchRenderer') && $swatchOption.data('mageSwatchRenderer').options && $swatchOption.data('mageSwatchRenderer').options.jsonConfig && $swatchOption.data('mageSwatchRenderer').options.jsonConfig.index ) { var index = $swatchOption.data('mageSwatchRenderer').options.jsonConfig.index; $.each(index, function (id, attributes) { var selected = function (attributes, options) { return _.isEqual(attributes, options); } if (selected(attributes, options)) { result.push(id); } }); } return result; } function handleOptionalPersonalizationCheckBox() { if (customily.personalization.showCheckbox == '1') { $('.cl-personalization-optional-container').removeClass('hidden'); } else { customily.personalization.active = customily.personalization.behavior == 'visible' ? true : false; $('#cl-personalization-optional').prop('checked', false).trigger('change'); $('.cl-personalization-optional-container').addClass('hidden'); } } function handleCheckboxOptions() { _.filter(customily.options, function (o) { return o.type == 'checkbox' && o.selected }).forEach(function (option) { var $checkbox = $('[data-selector="options[' + option.id + '][' + option.selected + ']"]'); var $parent = $checkbox.parents('.cl-option').first(); $parent.attr('data-selected', null); $checkbox.trigger('click', {allow: true}); }); } window.addEventListener(CUSTOMILY_LOADED_EVENT, function () { if (customily.isEditMode == '1') { if (customily.personalization.type == 'modal-preview') { customily.preview.ready = true; setTimeout(function () { $('#customily-popup-modal-button').click(); }, 1000); } restoreAttributes(); } else { handlePreviewCanvasAttributes(); } handlePreviewCanvasConditions(); processPendingOperations(); enableCustomilyBtn(); handleCheckboxOptions(); }); window.addEventListener(CUSTOMILY_LOADED_DEFAULTS_EVENT, function () { if (customily.personalization.type == 'modal-preview') { customily.preview.ready = false; } handlePreviewCanvasAttributes(); handlePreviewCanvasConditions(); processPendingOperations(); enableCustomilyBtn(); if (customily.personalization.type == 'modal-preview') { customily.preview.ready = true; } else { if (!customily.preview.ready) { customily.positioningPreview('templateLoaded'); } } }); window.addEventListener('load', function () { if (!customily.preview.ready && customily.personalization.type == 'page-preview') { customily.positioningPreview('contentLoaded', true); } }); engraver.init('preview-canvas', { hoverZoom: !customily.isMobile() && customily.preview.hoverZoom == '1', keepControlsSize: customily.preview.resize == '1' }); if ( customily.personalization.isOptional == '1' && ( customily.product.type == 'simple' || customily.personalization.attachTo == 'default' ) ) { customily.personalization.showCheckbox = '1'; handleOptionalPersonalizationCheckBox(); } if ( customily.personalization.isOptional == '0' || customily.personalization.behavior == 'visible' ) { $(customily.querySelectors.addToCartForm + ' [data-role="customily-options"]').removeClass('hidden'); customily.personalization.active = true; customily.preview.canDisplay = true; customily.init(); } else { $(document).ready(function () { setTimeout(function () { enableCustomilyBtn(); }, 500); }); } /** * reload product price bottom */ function reloadProductPriceBottom(o){ var priceFormat = (customily.priceConfig && customily.priceConfig.priceFormat) || {}; if(parseInt(o.color_fee) == 1){ var item = o.selected, colorFeeDIV = $('.product-prices-fee-wrap .product-color-fee'), colorFeePriceDIV = $('.product-prices-fee-wrap .product-color-fee > .price'), totalPriceDIV = $('.product-prices-fee-wrap .product-price-total strong > .price'), priceDIV = $('.product-prices-fee-wrap .product-price-total strong > .price > .price'), totalPrice = totalPriceDIV.data('price'); if(!item){ colorFeeDIV.hide(); return; } if(item.color_fee_code !== '' && parseFloat(item.color_fee_code) > 0){ if(colorFeeDIV.length){ var total = parseFloat(totalPrice) + parseFloat(colorFeePriceDIV.data('price')); priceDIV.text(priceUtils.formatPrice(total, priceFormat)); colorFeeDIV.show(); } }else{ if(colorFeeDIV.length){ var total = parseFloat(totalPrice); priceDIV.text(priceUtils.formatPrice(total, priceFormat)); colorFeeDIV.hide(); } } } } function handlePersonalizationOptionalPriceBottom(){ let colorFeeDIV = $('.product-prices-fee-wrap .product-color-fee'); let personFeeDIV = $('.product-prices-fee-wrap .product-setup-fee'); if (customily.personalization.active) { colorFeeDIV.removeClass('hidden'); personFeeDIV.removeClass('hidden'); }else{ colorFeeDIV.addClass('hidden'); personFeeDIV.addClass('hidden'); } } function validateCharacter(){ var optionSelector = ".product-options-bottom"; if($(optionSelector).length){ var fieldSelector = $(optionSelector).find('.text_text'), isValid = false; fieldSelector.each(function (el){ var inputSelector = $(this).find('input'), errorFieldSelector = $(this).find('.cl-error'), val = inputSelector.val() ?? inputSelector.attr('value'), messagesErrorNoSymbol = '', regexValidate = ''; if(val){ if($(this).hasClass('text_uppercase')){ val = val.toUpperCase(); messagesErrorNoSymbol = "Please enter letters A-Z only. Do not enter number or special characters."; } if($(this).hasClass('text_lowercase')){ val = val.toLowerCase(); messagesErrorNoSymbol = "Please enter letters a-z only. Do not enter number or special characters."; } if($(this).hasClass('text_titlecase')){ val = val.split(' ').map(w => w[0].toUpperCase() + w.substr(1).toLowerCase()).join(' '); messagesErrorNoSymbol = "Please enter alphabetic letters only. Do not enter number or special characters."; } inputSelector.val(val); if($(this).hasClass('number_symbol')){ var valid = /^[0-9\s]*$/g.test(val); if(!valid){ errorFieldSelector.text("Please enter a number only. Do not enter letters or special characters."); errorFieldSelector.show(); isValid = true; }else{ errorFieldSelector.hide(); } return; } if($(this).hasClass('base_character')){ var valid = /^[a-zA-Z0-9`!#$^&'()*\/+@\[\]:;,.\-=?\s]*$/g.test(val); if(!valid){ errorFieldSelector.text("Your personalization contains invalid characters. Please adjust your entry."); errorFieldSelector.show(); isValid = true; return; }else{ if($(this).hasClass('nosymbol')){ var valid; if ($(this).hasClass('text_uppercase')) { valid = /^[A-Z\s]*$/g.test(val); } else if ($(this).hasClass('text_lowercase')) { valid = /^[a-z\s]*$/g.test(val); } else { valid = /^[a-zA-Z\s]*$/g.test(val); } if(!valid){ errorFieldSelector.text(messagesErrorNoSymbol); errorFieldSelector.show(); isValid = true; }else{ errorFieldSelector.hide(); } return; }else{ errorFieldSelector.hide(); } return; } }else if($(this).hasClass('international_character')){ var valid = /^[a-zA-Z0-9àèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝâêîôûðÂÊÎÔÛÐãñõÃÑÕäëïöüÿÄËÏÖÜŸåÅæœÆŒßçÇðÐøØ¿¡ß`‘’“”~!#$^&'()*\/+@\[\]:;,.\-"%<=>?|•–—_\s]*$/g.test(val); if(!valid){ errorFieldSelector.text("Your personalization contains invalid characters. Please adjust your entry."); errorFieldSelector.show(); isValid = true; return; }else{ if($(this).hasClass('nosymbol')){ var valid; if ($(this).hasClass('text_uppercase')) { valid = /^[A-ZÀÈÌÒÙÁÉÍÓÚÝÂÊÎÔÛÐÃÑÕÄËÏÖÜŸÅÆŒßÇØ¿¡\s]*$/g.test(val); } else if ($(this).hasClass('text_lowercase')) { valid = /^[a-zàèìòùáéíóúýâêîôûðãñõäëïöüÿåæœçø¿¡\s]*$/g.test(val); } else { valid = /^[a-zA-ZàèìòùÀÈÌÒÙáéíóúýÁÉÍÓÚÝâêîôûðÂÊÎÔÛÐãñõÃÑÕäëïöüÿÄËÏÖÜŸåÅæœÆŒßçÇøØ¿¡\s]*$/g.test(val); } if(!valid){ errorFieldSelector.text(messagesErrorNoSymbol); errorFieldSelector.show(); isValid = true; }else{ errorFieldSelector.hide(); } return; }else{ errorFieldSelector.hide(); } return; } } }else{ if($(this).hasClass('cl-required')){ errorFieldSelector.text("This is a required field."); errorFieldSelector.show(); return; } } }) if(isValid){ throw "error validate"; } } } });

When will I receive it?See Arrival Dates

: USD $14.99

Personalized Photo Printed White Ceramic Indoor Plant Pot with Drainage & Saucer - Home Sweet Home (2024)

References

Top Articles
Latest Posts
Article information

Author: Wyatt Volkman LLD

Last Updated:

Views: 5851

Rating: 4.6 / 5 (66 voted)

Reviews: 89% of readers found this page helpful

Author information

Name: Wyatt Volkman LLD

Birthday: 1992-02-16

Address: Suite 851 78549 Lubowitz Well, Wardside, TX 98080-8615

Phone: +67618977178100

Job: Manufacturing Director

Hobby: Running, Mountaineering, Inline skating, Writing, Baton twirling, Computer programming, Stone skipping

Introduction: My name is Wyatt Volkman LLD, I am a handsome, rich, comfortable, lively, zealous, graceful, gifted person who loves writing and wants to share my knowledge and understanding with you.