function createEstimateShippingPopUp(settings) { var defaultSettings = { opener: false, form: false, requestDelay: 300, urlFactory: false, handlers: {}, localizedData: false, contentEl: false, countryEl: false, stateProvinceEl: false, zipPostalCodeEl: false, useCity: false, cityEl: false, errorMessageBoxClass: 'message-failure', }; return { settings: $.extend({}, defaultSettings, settings), params: { jqXHR: false, displayErrors: false, delayTimer: false, selectedShippingOption: false }, init: function () { var self = this; var $content = $(this.settings.contentEl); $('.apply-shipping-button', $content).on('click', function () { var option = self.getActiveShippingOption(); if (option && option.provider && option.price) { self.selectShippingOption(option); self.closePopup(); } }); $(this.settings.opener).magnificPopup({ type: 'inline', removalDelay: 500, callbacks: { beforeOpen: function () { this.st.mainClass = this.st.el.attr('data-effect'); }, open: function () { if (self.settings.handlers.openPopUp) self.settings.handlers.openPopUp(); self.params.displayErrors = true; } } }); var addressChangedHandler = function () { self.clearShippingOptions(); var address = self.getShippingAddress(); self.getShippingOptions(address); }; $(this.settings.countryEl, $content).on('change', function () { $(self.settings.stateProvinceEl, $content).val(0); addressChangedHandler(); }); $(this.settings.stateProvinceEl, $content).on('change', addressChangedHandler); if (this.settings.useCity) { $(this.settings.cityEl, $content).on('input propertychange paste', addressChangedHandler); } else { $(this.settings.zipPostalCodeEl, $content).on('input propertychange paste', addressChangedHandler); } }, closePopup: function () { $.magnificPopup.close(); }, getShippingOptions: function (address) { if (!this.validateAddress(address)) return; var self = this; self.setLoadWaiting(); if (self.settings.handlers.load) self.settings.handlers.load(); clearTimeout(self.params.delayTimer); self.params.delayTimer = setTimeout(function () { if (self.params.jqXHR && self.params.jqXHR.readyState !== 4) self.params.jqXHR.abort(); var url = self.settings.urlFactory(address); if (url) { self.params.jqXHR = $.ajax({ cache: false, url: url, data: $(self.settings.form).serialize(), type: 'POST', success: function (response) { self.successHandler(address, response); }, error: function (jqXHR, textStatus, errorThrown) { self.errorHandler(jqXHR, textStatus, errorThrown); }, complete: function (jqXHR, textStatus) { if (self.settings.handlers.complete) self.settings.handlers.complete(jqXHR, textStatus); } }); } }, self.settings.requestDelay); }, setLoadWaiting: function () { this.clearErrorMessage(); $('.shipping-options-body', $(this.settings.contentEl)).html($('
').addClass('shipping-options-loading')); }, successHandler: function (address, response) { $('.shipping-options-body', $(this.settings.contentEl)).empty(); if (response.Success) { var activeOption; var options = response.ShippingOptions; if (options && options.length > 0) { var self = this; var selectedShippingOption = this.params.selectedShippingOption; $.each(options, function (i, option) { // try select the shipping option with the same provider and address if (option.Selected || (selectedShippingOption && selectedShippingOption.provider === option.Name && self.addressesAreEqual(selectedShippingOption.address, address))) { activeOption = { provider: option.Name, price: option.Price, address: address, deliveryDate: option.DeliveryDateFormat }; } self.addShippingOption(option.Name, option.DeliveryDateFormat, option.Price); }); // select the first option if (!activeOption) { activeOption = { provider: options[0].Name, price: options[0].Price, deliveryDate: options[0].DeliveryDateFormat, address: address }; } // if we have the already selected shipping options with the same address, reload it if (!$.magnificPopup.instance.isOpen && selectedShippingOption && this.addressesAreEqual(selectedShippingOption.address, address)) this.selectShippingOption(activeOption); this.setActiveShippingOption(activeOption); } else { this.clearShippingOptions(); } } else { this.params.displayErrors = true; this.clearErrorMessage(); this.clearShippingOptions(); this.showErrorMessage(response.Errors); } if (this.settings.handlers.success) this.settings.handlers.success(address, response); }, errorHandler: function (jqXHR, textStatus, errorThrown) { if (textStatus === 'abort') return; this.clearShippingOptions(); if (this.settings.handlers.error) this.settings.handlers.error(jqXHR, textStatus, errorThrown); }, clearErrorMessage: function () { $('.' + this.settings.errorMessageBoxClass, $(this.settings.contentEl)).empty(); }, showErrorMessage: function (errors) { if (this.params.displayErrors) { var errorMessagesContainer = $('.' + this.settings.errorMessageBoxClass, $(this.settings.contentEl)); $.each(errors, function (i, error) { errorMessagesContainer.append($('
').text(error)); }); } }, selectShippingOption: function (option) { if (option && option.provider && option.price && this.validateAddress(option.address)) this.params.selectedShippingOption = option; if (this.settings.handlers.selectedOption) this.settings.handlers.selectedOption(option); }, addShippingOption: function (name, deliveryDate, price) { if (!name || !price) return; var shippingOption = $('
').addClass('estimate-shipping-row shipping-option'); shippingOption .append($('
').addClass('estimate-shipping-row-item-radio') .append($('').addClass('estimate-shipping-radio').attr({ 'type': 'radio', 'name': 'shipping-option' + '-' + this.settings.contentEl })) .append($('