var phoneInstance = null; var phoneInput = null; var phoneInstanceUtils = null; var selectedProductOption = null; var selectedShippingMethod = null; var noteAnswer = null; function animateCSS(element, animationName, callback) { const node = document.querySelector(element) node.classList.add('animated', animationName) function handleAnimationEnd() { node.classList.remove('animated', animationName) node.removeEventListener('animationend', handleAnimationEnd) if (typeof callback === 'function') callback() } node.addEventListener('animationend', handleAnimationEnd) } function setupShippingForm() { console.log('setupShippingForm(): invoked!'); var form = document.getElementById('shippingForm'); setupOptionsForm(); initializeTelInputField(); initializeCountryStateSelect(); hideAlertsWhenFieldLosesFocus(); if (parent.IS_CHIRINGO_CART) { form.addEventListener('submit', function onSubmit(event) { event.preventDefault(); event.stopPropagation(); if (validateShippingForm()) { composeChiringoConfirmationScreen(); slideToNext(); } }, false); return; } // ShopWindow stuff if (form) { form.addEventListener('submit', function onSubmit(event) { event.preventDefault(); event.stopPropagation(); if ( shippingOptions ) { showShippingOptionsForm(); // The options form will call sendShippingDetails(); return; } sendShippingDetails(); }, false); console.log('setupShippingForm(): listener invoked!'); } } function hideAlertsWhenFieldLosesFocus() { // Hide alerts when focus goes to field $('.validate-form .input100').each(function(){ $(this).focus(function(){ console.log('setupShippingForm(): form validated!'); hideValidate(this); }); }); } function setupOptionsForm() { var submitOptionsButton = document.getElementById('shippingWithOptionsButton'); submitOptionsButton.addEventListener('click', function onSubmit(event) { event.stopPropagation(); if (setSelectedOptionsIfValid()) { sendShippingDetails(); hideShippingOptionsForm(); } }); $(function() { if (true) { if (productOptions) { setupProductMethodSelect(); } if (shippingOptions) { setupShippingMethodSelect(); } } document.getElementById('productShippingOptionsLayer').style.bottom = (new Number($('#productShippingOptionsLayer').css('bottom').replace('px', '')) + 0) + 'px'; }); } function isNoteFieldAnswered() { var noteAnswerField = document.getElementById('noteAnswer'); var noteAnswerValid = true; if ($('#noteAnswerContainer').is(':visible')) { if ( ! noteAnswerField.value ) { noteAnswerValid = false; showValidateSelect('noteAnswer'); } else { noteAnswer = noteAnswerField.value } } return noteAnswerValid } function isProductOptionSelected() { var productSelect = document.getElementById('productOption'); var productOptionValid = true; if ($('#productOptionSelectContainer').is(':visible')) { // Options to select there if (((productSelect.options[productSelect.selectedIndex].text) == 'Select product option')) { productOptionValid = false; showValidateSelect('productOption'); } else { selectedProductOption = productSelect.options[productSelect.selectedIndex].getAttribute('data-productOption-Name'); } } return productOptionValid; } function isShippingOptionSelected() { var shippingSelect = document.getElementById('shippingOption'); var shippingOptionValid = true; if ($('#shippingOptionSelectContainer').is(':visible')) { // Options to select there if ((shippingSelect.options[shippingSelect.selectedIndex].text) == 'Select shipping method') { shippingOptionValid = false; showValidateSelect('shippingOption'); } else { selectedShippingMethod = shippingSelect.options[shippingSelect.selectedIndex].getAttribute('data-shippingMethod-Name'); } } return shippingOptionValid; } function goToProductForm() { if (( productOptions ) || ( notes )) { showProductOptionForm(); } else { if (singleProductCheckout) { setButtonAsLoading("confirmButton"); updateFunnelState(label, customerId, FUNNEL_STATES.PRODUCT_OPTION_SELECTED).end(); showOverlayOn(0); } else { updateMultiFunnelState(customerId, FUNNEL_STATES.PRODUCT_OPTION_SELECTED); setButtonAsLoading("confirmButton"); setPriceFromShoppingCart(); showOverlayOn(0); } } } function goToShippingForm() { if ( productOptionController() ) { setButtonAsLoading("confirmButton"); hideProductOptionForm(); updateFunnelState(label, customerId, FUNNEL_STATES.PRODUCT_OPTION_SELECTED).end(); showOverlayOn(0); } } function productOptionController() { var productOptionController = isProductOptionSelected(); var noteController = isNoteFieldAnswered(); return ( productOptionController && noteController ) } function setSelectedOptionsIfValid() { return (isShippingOptionSelected() && isProductOptionSelected() && isNoteFieldAnswered()); } function setupShippingMethodSelect() { console.log(shippingOptions); if (!shippingOptions) { console.log('setupShippingMethodSelect(): no shipping method'); return; } var shippingOptionsAsObject = JSON.parse(shippingOptions); var shippingOptionObjects = Object.keys(shippingOptionsAsObject); if (shippingOptionObjects.length == 0) { console.log('setupShippingMethodSelect(): no shipping method'); return; } var shippingOptionContainer = document.getElementById('shippingOptionContainer'); var shippingSelect = document.getElementById('shippingOption'); shippingSelect.length = 0; // Fixed by Julian Woods shippingSelect.options[0] = new Option('Select shipping method',''); shippingSelect.selectedIndex = 0; for (option of shippingOptionObjects) { var aux = shippingOptionsAsObject[option]; //var shippingPrice = applyDiscountToStringValue(aux.price); var shippingPrice = shiftCommaForDecimals((Math.round(Number(aux.price) * (100 - discountValue)/100)).toString()) // "SEUR" : { // "name" : "SEUR", // "regions" : [ // "Europe" // ], // "ETA" : "1 week", // "price" : "1111" // } for (region of aux.regions) { //var text = aux.ETA + ' to ' + region + ' for ' + shiftCommaForDecimals(aux.price) + currency + ' (' + aux.ETA + ')'; var text = aux.ETA_translated + ' to ' + region + ' for ' + shippingPrice + currency + ' (' + aux.ETA_translated + ')'; var newShippingOption = new Option(text, aux.price); newShippingOption.setAttribute('data-shippingMethod-Name', aux.name); shippingSelect.options[shippingSelect.length] = newShippingOption; } } //document.getElementById('productShippingOptionsLayer').style.bottom = (new Number($('#productShippingOptionsLayer').css('bottom').replace('px', '')) + 62) + 'px'; shippingOptionContainer.style.display = 'block'; } function applyDiscountToStringValue(stringValue) { if ((discountValue > 0) && (discountType == "percentage")) { var numberString = Math.round(Number(stringValue) * (100 - discountValue)/100).toString(); var lengthString = numberString.length if (lengthString > 2) { return shiftCommaForDecimals(numberString); } else { return (lengthString == 1) ? shiftCommaForDecimals('00' + numberString) : shiftCommaForDecimals('0' + numberString); } } else { return shiftCommaForDecimals(stringValue) } } function setupProductMethodSelect() { var productOptionsAsObject = JSON.parse(productOptions); var productOptionObjects = Object.keys(productOptionsAsObject); if (productOptionObjects.length == 0) { console.log('setupProductMethodSelect(): no product options'); return; } var productOptionContainer = document.getElementById('productOptionContainer'); var productSelect = document.getElementById('productOption'); productSelect.length = 0; // Fixed by Julian Woods productSelect.options[0] = new Option('Select product option',''); productSelect.selectedIndex = 0; for (option of productOptionObjects) { var aux = productOptionsAsObject[option]; // "productOptions" : { // "XL" : { // "name" : "XL", // "stock" : "10" // }, // "M" : { // "name" : "M", // "stock" : "10" // }, // "S" : { // "name" : "S", // "stock" : "0" // } // } var availableStock = new Number(aux.stock); console.log('setupProductMethodSelect(): available stock is ' + availableStock); if ((availableStock > 0) // Stock limited but available ||(availableStock == -1)) // Infinite stock or overselling allowed { var newProductOption = new Option(aux.name, aux.name); newProductOption.setAttribute('data-productOption-Name', aux.name); productSelect.options[productSelect.length] = newProductOption; } } //document.getElementById('productShippingOptionsLayer').style.bottom = (new Number($('#productShippingOptionsLayer').css('bottom').replace('px', '')) + 82) + 'px'; productOptionContainer.style.display = 'block'; } function showShippingOptionsForm() { // $('#productShippingOptionsLayer').toggleClass('slideInUp'); animateCSS('#productShippingOptionsLayer', 'slideInUp', function() { // Do something after animation }); $('#productShippingOptionsLayer').fadeIn(); } function hideShippingOptionsForm() { // $('#productShippingOptionsLayer').toggleClass('slideOutDown'); animateCSS('#productShippingOptionsLayer', 'slideOutDown', function() { // Do something after animation $('#productShippingOptionsLayer').hide(); }); } function showProductOptionForm() { // $('#productShippingOptionsLayer').toggleClass('slideInUp'); animateCSS('#productOptionsLayer', 'slideInUp', function() { // Do something after animation }); $('#productOptionsLayer').fadeIn(); } function hideProductOptionForm() { // $('#productShippingOptionsLayer').toggleClass('slideOutDown'); animateCSS('#productOptionsLayer', 'slideOutDown', function() { // Do something after animation $('#productOptionsLayer').hide(); }); } function initializeCountryStateSelect() { // TODO: filter countries not configured in the project populateCountries("country", "state"); } function initializeTelInputField() { phoneInput = document.getElementById('phone'); var countryCode = 'US'; phoneInstance = window.intlTelInput(phoneInput, { separateDialCode: true, initialCountry: "auto", geoIpLookup: function(callback) { request.get('/beta/customer/location?customerIp=' + customerIp) .set('X-Request-ID', correlationId) .then((successResponse) => { console.log('initializeTelInputField(): located client as in country ' + JSON.stringify(successResponse.body)); countryCode = successResponse.body.countryCode; automaticallyPopulateCountry(successResponse.body.countryCode) }) .catch((errorResponse) => { console.log('initializeTelInputField(): could not locate client because of ' + errorResponse); }) .finally(() => { callback(countryCode); }); }, // TODO: onlyCountries (Twilio requires a phone per country) preferredCountries: [ "us", "ca", "gb" ], utilsScript: 'https://d2tzi4yayp7s6t.cloudfront.net/beta/static/shippingForm/js/intlTelInput-utils.js' }); phoneInstanceUtils = window.intlTelInputGlobals.loadUtils("https://d2tzi4yayp7s6t.cloudfront.net/beta/static/shippingForm/js/intlTelInput-utils.js"); var theSpan = document.createElement('span'); theSpan.setAttribute('class', 'focus-input100'); theSpan.setAttribute('style', 'top: 9px'); var theWrapperDiv = document.getElementsByClassName('intl-tel-input')[0]; theWrapperDiv.appendChild(theSpan); } function defaultDoneActions() { console.log('defaultDoneActions(): SHOPPING CART purchase complete, now actions...'); //sendMessageStackToUser(customerId, 'post'); closeWebView(); if (!singleProductCheckout) { removePurchasedProductsFromShoppingCart(); } } function registerDoneActions() { DONE_ACTIONS['default'] = defaultDoneActions; } function validateShippingForm() { // "use strict"; /*================================================================== [ Focus Contact2 ]*/ $('.input100').each(function(){ $(this).on('blur', function(){ if($(this).val().trim() != "") { $(this).addClass('has-val'); } else { $(this).removeClass('has-val'); } }) }) /*================================================================== [ Validate ]*/ var name = $('.validate-input input[name="firstName"]'); var lastname = $('.validate-input input[name="lastName"]'); var email = $('.validate-input input[name="email"]'); // var phoneInputField = $('.validate-input input[name="phone"]'); var phoneInputField = $('#phone'); var address1 = $('.validate-input input[name="address1"]'); var address2 = $('.validate-input input[name="address2"]'); var city = $('.validate-input input[name="city"]'); var country = $('#country option:selected'); var state = $('#state option:selected'); var zipcode = $('.validate-input input[name="zipcode"]'); var check = true; if($(name).val().trim() == ''){ showValidate(name); check=false; } if((shippingFormObject.lastname) && ($(lastname).val().trim() == '')){ showValidate(lastname); check=false; } if($(email).val().trim().match(/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{1,5}|[0-9]{1,3})(\]?)$/) == null) { showValidate(email); check=false; } if(!phoneInstance.isValidNumber()){ showValidatePhone(phoneInputField); check=false; } if((shippingFormObject.address) && ($(address1).val().trim() == '')){ showValidate(address1); check=false; } // if($(address2).val().trim() == ''){ // showValidate(address2); // check=false; // } if((shippingFormObject.address) && ($(city).val().trim() == '')){ showValidate(city); check=false; } if((shippingFormObject.address) && ($(zipcode).val().trim() == '')){ showValidate(zipcode); check=false; } if((shippingFormObject.address) && ($(country).text() == 'Select Country')){ showValidateSelect('country'); check=false; } if((shippingFormObject.address) && ($(state).text() == 'Select State')){ showValidateSelect('state'); check=false; } return check; } function showValidate(input) { var thisAlert = $(input).parent(); $(thisAlert).addClass('alert-validate'); } function showValidateSelect(selectElementId) { $('#' + selectElementId).css('border', '1px solid #cc1414'); } function showValidatePhone(phoneInputField) { var validationWrapper = $('#phoneInputWrapper'); var determineTipText = getTipForPhoneInput(phoneInputField, validationWrapper); $(validationWrapper).addClass('alert-validate'); } function hideValidate(input) { var thisAlert = $(input).parent(); if($(input).is('select')) { $(input).css('border', '1px solid #8cb2e9'); } else if($(input).attr('type') == 'tel') { thisAlert = $('#phoneInputWrapper'); $(thisAlert).removeClass('alert-validate'); } else { $(thisAlert).removeClass('alert-validate'); } } function getTipForPhoneInput(phoneTelInputFiel, validationWrapper) { console.log('getTipForPhoneInput(): validation error ' + phoneInstance.getValidationError()); // Custom errors // console.log('getTipForPhoneInput(): selected country data ' + JSON.stringify(phoneInstance.getSelectedCountryData(), null, 2)); if ($.isEmptyObject(phoneInstance.getSelectedCountryData())) { validationWrapper.attr('data-validate', '👈 Pick a country'); // document.getElementsByClassName('selected-flag')[0].click(); return; } // Errors from lib // Values for cases from https://github.com/jackocnr/intl-tel-input/blob/master/src/js/utils.js#L153 switch(phoneInstance.getValidationError()) { case 0: console.log('getTipForPhoneInput(): what does it mean it is possible?'); // validationWrapper.attr('data-validate', 'The phone number is possible'); break; case 1: console.log('getTipForPhoneInput(): The country code is not valid'); validationWrapper.attr('data-validate', '👈 Select a valid country code'); break; case 2: console.log('getTipForPhoneInput(): The phone number is too short'); validationWrapper.attr('data-validate', 'The phone number is too short'); break; case 3: console.log('getTipForPhoneInput(): The phone number is too long'); validationWrapper.attr('data-validate', 'The phone number is too long'); break; case 4: console.log('getTipForPhoneInput(): The phone number is not a number'); validationWrapper.attr('data-validate', 'The phone number is not a number'); break; } } function getShippingAddressDatastructure() { var shippingAddressFields = [ $('.validate-input input[name="firstName"]'), $('.validate-input input[name="lastName"]'), $('.validate-input input[name="email"]'), // $('.validate-input input[name="phone"]'), $('#phone'), $('.validate-input input[name="address1"]'), $('.validate-input input[name="address2"]'), $('.validate-input input[name="city"]'), $('#country option:selected'), $('#state option:selected'), $('.validate-input input[name="zipcode"]') ]; var addressBufferObject = { shippingAddress: { } }; shippingAddressFields.forEach(addressField => { if (addressField.attr('type') == 'tel') { // Parameter 0 as per https://github.com/jackocnr/intl-tel-input/blob/c398e8ca17d848107109e044437796a6c8ff272a/src/js/utils.js#L104 addressBufferObject.shippingAddress[addressField.attr('id')] = phoneInstance.getNumber(0) } else { //if(addressField.val()) { // Regular input Select input id var fieldId = (addressField.attr('id')) ? addressField.attr('id') : addressField.parent().attr('id'); addressBufferObject.shippingAddress[fieldId] = addressField.val().trim(); } }); // Tell the backend to replace the customer id // addressBufferObject['MS_replaceId'] = false; console.log(addressBufferObject); return addressBufferObject; } function composeChiringoConfirmationScreen() { var firstName = document.getElementById('firstName').value; var lastName = document.getElementById('lastName').value; var email = document.getElementById('email').value; // Parameter 0 as per https://github.com/jackocnr/intl-tel-input/blob/c398e8ca17d848107109e044437796a6c8ff272a/src/js/utils.js#L104 var phone = phoneInstance.getNumber(0); var address1 = document.getElementById('address1').value; var address2 = document.getElementById('address2').value; var city = document.getElementById('city').value; var country = document.getElementById('country').value; var state = document.getElementById('state').value; var zipcode = document.getElementById('zipcode').value; document.getElementById('nameEmailPhone').innerHTML = firstName + ' ' + lastName + '
' + email + '
' + phone + '
'; document.getElementById('composedShippingAddress').innerHTML = address1 + ' ' + address2 + '
' + city + ' (' + state + ')
' + country + '
' + phone + '
' + 'Change address'; const [ productTotal, shippingTotal, total ] = parent.calculateTotals(); console.log('The locale: ' + parent.LOCALE); document.getElementById('totalAmountToPay').innerHTML = 'Price: ' + parent.formatPriceToLocale(parent.shiftCommaForDecimals(productTotal + ''), parent.CURRENCY) + '
' + 'Shipping cost: ' + parent.formatPriceToLocale(parent.shiftCommaForDecimals(shippingTotal + ''), parent.CURRENCY) + '
' + 'Total: ' + parent.formatPriceToLocale(parent.shiftCommaForDecimals(total + ''), parent.CURRENCY) + '' + '
' //+ //'' + getPODNotice() + ''; } function composeConfirmationScreen() { var firstName = document.getElementById('firstName').value; var lastName = document.getElementById('lastName').value; var email = document.getElementById('email').value; // Parameter 0 as per https://github.com/jackocnr/intl-tel-input/blob/c398e8ca17d848107109e044437796a6c8ff272a/src/js/utils.js#L104 var phone = phoneInstance.getNumber(0); var address1 = document.getElementById('address1').value; var address2 = document.getElementById('address2').value; var city = document.getElementById('city').value; var country = document.getElementById('country').value; var state = document.getElementById('state').value; var zipcode = document.getElementById('zipcode').value; // console.log('composeConfirmationScreen(): name ' + name + ' lastname ' + lastname + ' email ' + email + ' phone ' + phone + ' address1 ' + address1 + ' address2' + address2 + ' city ' + city + ' country ' + country + ' state ' + state + ' zipcode ' + zipcode); costBreakdown = getCostBreakdown(); switchPaymentBlock(costBreakdown.total) document.getElementById('nameEmailPhone').innerHTML = firstName + ' ' + lastName + '
' + email + '
' + phone + '
'; document.getElementById('composedShippingAddress').innerHTML = address1 + ' ' + address2 + '
' + city + ' (' + state + ')
' + country + '
' + phone + '
' + 'Change address'; document.getElementById('totalAmountToPay').innerHTML = 'Price: ' + Number(applyDiscountToStringValue(costBreakdown.price)).toLocaleString(undefined, { style: "currency", currency: currency }) + '
' + 'Shipping cost: ' + Number(applyDiscountToStringValue(costBreakdown.shippingCost)).toLocaleString(undefined, { style: "currency", currency: currency }) + '
' + 'Total: ' + Number(applyDiscountToStringValue(costBreakdown.total + '')) .toLocaleString(undefined, { style: "currency", currency: currency }) + '' + '
' //+ //'' + getPODNotice() + ''; } function getCostBreakdown() { var costDatastructure = { }; var shippingCostElement = document.getElementById('shippingOption'); var shippingCostElementValue = (shippingCostElement.options.length > 0) ? (shippingCostElement.options[shippingCostElement.selectedIndex].value) : '0'; selectedShippingMethod = (shippingCostElement.options.length > 0) ? (shippingCostElement.options[shippingCostElement.selectedIndex].getAttribute('data-shippingMethod-Name')) : null; costDatastructure['price'] = price; costDatastructure['shippingCost'] = shippingCostElementValue; var totalCost = 0.00; for (concept of Object.keys(costDatastructure)) { totalCost += new Number(costDatastructure[concept]); } if (!singleProductCheckout) { SetPayButtonsTextFromShoppingCart(totalCost); } costDatastructure['total'] = totalCost; console.log('getCostBreakdown(): cost datastructure is ' + JSON.stringify(costDatastructure, null, 2)); return costDatastructure; } function sendShippingDetails() { console.log('sendShippingDetails(): customerId is ' + customerId + ' and label is ' + label); if(validateShippingForm()) { $('#shippingButton').toggleClass('button--loading'); $('#shippingButton').prop("disabled",true); // pay(goToLastStep); // 1) Update funnel state if ( singleProductCheckout ) { updateCustomer(getShippingAddressDatastructure()) .then(updateCustomerSuccess => { if(updateCustomerSuccess.body.updateId) { console.log('setupShippingForm(): updating customerId ' + customerId + ' with ' + updateCustomerSuccess.body.customerId); customerId = updateCustomerSuccess.body.customerId; } updateFunnelState(label, customerId, FUNNEL_STATES.SHIPPING_ADDRESS_COMPLETED) .then(updateFunnelSuccess => { composeConfirmationScreen(); // 4) slide to next window standardNote.defineStandardNoteProcess(slideToNext, enableShippingButton); }).catch(updateFunnelError => { // Send error logs!!! }); }) .catch(updateCustomerError => { // Inform the user the operation cannot continue! // Send the error logs!!! }); } else { updateCustomer(getShippingAddressDatastructure()) .then(updateCustomerSuccess => { if(updateCustomerSuccess.body.updateId) { console.log('setupShippingForm(): updating customerId ' + customerId + ' with ' + updateCustomerSuccess.body.customerId); customerId = updateCustomerSuccess.body.customerId; } if (updateMultiFunnelState( customerId, FUNNEL_STATES.SHIPPING_ADDRESS_COMPLETED)) { composeConfirmationScreen(); // 4) slide to next window standardNote.defineStandardNoteProcess(slideToNext, enableShippingButton); } }) .catch(updateCustomerError => { // Inform the user the operation cannot continue! // Send the error logs!!! }); } } } function shiftCommaForDecimals(nonDecimalAmount) { if ((!nonDecimalAmount) || (nonDecimalAmount == '0')) return '0.00'; if ((nonDecimalAmount.length < 2)) { return '0.' + nonDecimalAmount; } var position = nonDecimalAmount.length - 2; var decimalPrice = [nonDecimalAmount.slice(0, position), '.', nonDecimalAmount.slice(position)].join(''); // CONSTANTS.LOGGER.info('getPriceWithDecimals(): converting ' + nonDecimalAmount + ' into ' + decimalPrice); // console.log('shiftCommaForDecimals(): turned ' + nonDecimalAmount + ' into ' + decimalPrice); return decimalPrice; } function getPODNotice() { if (selectedPaymentMethod == 'POD') { return '(Cash pay on delivery)'; } return ''; } function removePurchasedProductsFromShoppingCart() { window.parent.shoppingCart.updateShoppingCartAftherPayment(); } function insertappointmentLink() { if (appointmentproduct) { document.getElementById("appointmentIframe").src = appointmentLink; }; return; } function setPriceFromShoppingCart() { price = window.parent.shoppingCart.getTotalProductPrice().toString(); } $(document).ready(function() { insertappointmentLink(); setupShippingForm(); registerDoneActions(); });