Files
wp-multisite-waas/assets/js/checkout.js
2024-11-30 18:24:12 -07:00

967 lines
22 KiB
JavaScript

/* global Vue, moment, _, wu_checkout, pwsL10n, wu_checkout_form, wu_create_cookie, wu_listen_to_cookie_change */
(function ($, hooks, _) {
/*
* Remove the pre-flight parameter.
*/
if (window.history.replaceState) {
window.history.replaceState(null, null, wu_checkout.baseurl);
} // end if;
/*
* Sets default template.
*/
hooks.addAction('wu_on_create_order', 'nextpress/wp-ultimo', function (checkout, data) {
if (typeof data.order.extra.template_id !== 'undefined') {
checkout.template_id = data.order.extra.template_id;
} // end if;
});
/*
* Handle auto-submittable fields.
*
* Some fields are auto-submittable if they are the one relevant
* field on a checkout step.
*/
hooks.addAction('wu_checkout_loaded', 'nextpress/wp-ultimo', function (checkout) {
/*
* The checkout sets the auto submittable field as a global variable
*/
if (typeof window.wu_auto_submittable_field !== 'undefined' && window.wu_auto_submittable_field) {
const options = {
deep: true,
};
checkout.$watch(window.wu_auto_submittable_field, function () {
jQuery(this.$el).submit();
}, options);
} // end if;
});
/*
* Sets up the cookie listener for template selection.
*/
hooks.addAction('wu_checkout_loaded', 'nextpress/wp-ultimo', function (checkout) {
/*
* Resets the template selection cookie.
*/
wu_create_cookie('wu_template', '');
/*
* Resets the selected products cookie.
*/
wu_create_cookie('wu_selected_products', '');
/*
* Listens for changes and set the template if one is detected.
*/
wu_listen_to_cookie_change('wu_template', function (value) {
checkout.template_id = value;
});
});
/**
* Allows for cross-sells
*/
$(document).on('click', '[href|="#wu-checkout-add"]', function (event) {
event.preventDefault();
const el = $(this);
const product_slug = el.attr('href').split('#').pop().replace('wu-checkout-add-', '');
if (typeof wu_checkout_form !== 'undefined') {
if (wu_checkout_form.products.indexOf(product_slug) === -1) {
wu_checkout_form.add_product(product_slug);
el.html(wu_checkout.i18n.added_to_order);
} // end if;
} // end if;
});
/**
* Reload page when history back button was pressed
*/
window.addEventListener('pageshow', function (event) {
if (event.persisted && this.window.wu_checkout_form) {
this.window.wu_checkout_form.unblock();
} // end if;
});
/**
* Setup
*/
$(document).ready(function () {
/*
* Prevent app creation when vue is not available.
*/
if (typeof window.Vue === 'undefined') {
return;
} // end if;
Object.defineProperty(Vue.prototype, '$moment', { value: moment });
const maybe_cast_to_int = function (value) {
return isNaN(value) ? value : parseInt(value, 10);
};
const initial_data = {
plan: maybe_cast_to_int(wu_checkout.plan),
errors: [],
order: wu_checkout.order,
products: _.map(wu_checkout.products, maybe_cast_to_int),
template_id: wu_checkout.template_id,
template_category: '',
gateway: wu_checkout.gateway,
request_billing_address: wu_checkout.request_billing_address,
country: wu_checkout.country,
state: '',
city: '',
site_url: wu_checkout.site_url,
site_domain: wu_checkout.site_domain,
is_subdomain: wu_checkout.is_subdomain,
discount_code: '',
toggle_discount_code: 0,
payment_method: '',
username: '',
payment_id: wu_checkout.payment_id,
membership_id: wu_checkout.membership_id,
cart_type: 'new',
auto_renew: 1,
duration: wu_checkout.duration,
duration_unit: wu_checkout.duration_unit,
prevent_submission: false,
valid_password: true,
stored_templates: {},
state_list: [],
city_list: [],
labels: {},
};
hooks.applyFilters('wu_before_form_init', initial_data);
if (!jQuery('#wu_form').length) {
return;
} // end if;
/**
* ColorPicker Component
*/
Vue.component('colorPicker', {
props: ['value'],
template: '<input type="text">',
mounted() {
const vm = this;
$(this.$el)
.val(this.value)
// WordPress color picker
.wpColorPicker({
width: 200,
defaultColor: this.value,
change(event, ui) {
// emit change event on color change using mouse
vm.$emit('input', ui.color.toString());
},
});
},
watch: {
value(value) {
// update value
$(this.$el).wpColorPicker('color', value);
},
},
destroyed() {
$(this.$el).off().wpColorPicker('destroy'); // (!) Not tested
},
});
/**
* Declare the dynamic content for Vue.
*/
const dynamic = {
functional: true,
template: '#dynamic',
props: ['template'],
render(h, context) {
const template = context.props.template;
const component = template ? { template } : '<div>nbsp;</div>';
return h(component);
},
};
// eslint-disable-next-line no-unused-vars
window.wu_checkout_form = new Vue({
el: '#wu_form',
data: initial_data,
directives: {
init: {
bind(el, binding, vnode) {
vnode.context[binding.arg] = binding.value;
},
},
},
components: {
dynamic,
},
computed: {
hooks() {
return wp.hooks;
},
unique_products() {
return _.uniq(this.products, false, (item) => parseInt(item, 10));
},
},
methods: {
debounce(fn) {
return _.debounce(fn, 200, true);
},
open_url(url, target = '_blank') {
window.open(url, target);
},
get_template(template, data) {
if (typeof data.id === 'undefined') {
data.id = 'default';
} // end if;
const template_name = template + '/' + data.id;
if (typeof this.stored_templates[template_name] !== 'undefined') {
return this.stored_templates[template_name];
} // end if;
const template_data = this.hooks.applyFilters('wu_before_template_fetch', {
duration: this.duration,
duration_unit: this.duration_unit,
products: this.products,
...data,
}, this);
this.fetch_template(template, template_data);
return '<div class="wu-p-4 wu-bg-gray-100 wu-text-center wu-my-2 wu-rounded">' + wu_checkout.i18n.loading + '</div>';
},
reset_templates(to_clear) {
if (typeof to_clear === 'undefined') {
this.stored_templates = {};
return;
}
const new_list = {};
_.forEach(this.stored_templates, function (item, key) {
const type = key.toString().substr(0, key.toString().indexOf('/'));
if (_.contains(to_clear, type) === false) {
new_list[key] = item;
} // end if;
});
this.stored_templates = new_list;
},
fetch_template(template, data) {
const that = this;
if (typeof data.id === 'undefined') {
data.id = 'default';
} // end if;
this.request('wu_render_field_template', {
template,
attributes: data,
}, function (results) {
const template_name = template + '/' + data.id;
if (results.success) {
Vue.set(that.stored_templates, template_name, results.data.html);
} else {
Vue.set(that.stored_templates, template_name, '<div>' + results.data[0].message + '</div>');
} // end if;
});
},
go_back() {
// eslint-disable-next-line no-console
console.log('Going back...');
this.block();
window.history.back();
},
set_prevent_submission(value) {
this.$nextTick(function () {
this.prevent_submission = value;
});
},
remove_product(product_id, product_slug) {
this.products = _.filter(this.products, function (item) {
// eslint-disable-next-line eqeqeq
return item != product_id && item != product_slug;
});
},
add_plan(product_id) {
if (this.plan) {
this.remove_product(this.plan);
} // end if;
this.plan = product_id;
this.add_product(product_id);
},
add_product(product_id) {
this.products.push(product_id);
},
has_product(product_id) {
return this.products.indexOf(product_id) > -1 || this.products.indexOf(parseInt(product_id, 10)) > -1;
},
wu_format_money(value) {
return window.wu_format_money(value);
},
filter_for_request(data, request_type = '') {
const filter_list = this.hooks.doAction('wu_filter_for_request', [
'stored_templates',
], data, request_type);
const filtered_list = _.omit(data, filter_list);
return filtered_list;
},
create_order() {
/*
* Bail if there is no order summary to update.
*/
if (!jQuery('#wu-order-summary-content').length) {
return;
} // end if;
this.block();
this.order = false;
const that = this;
const _request = this.debounce(this.request);
const data = { ...this.$data };
delete data.stored_templates;
delete data.state_list;
delete data.city_list;
delete data.labels;
_request('wu_create_order', this.filter_for_request(data, 'wu_create_order'), function (results) {
that.order = results.data.order;
that.state_list = results.data.states;
that.city_list = results.data.cities;
that.labels = results.data.labels;
that.cart_type = results.data.order.type;
that.errors = results.data.order.errors;
that.hooks.doAction('wu_on_create_order', that, results.data);
if (results.data.order.url) {
try {
// history.pushState({}, null, wu_checkout.baseurl + results.data.order.url);
} catch (err) {
// eslint-disable-next-line no-console
console.warn('Browser does not support pushState.', err);
} // end try;
} // ed if;
that.unblock();
}, this.handle_errors);
},
get_errors() {
const result = this.errors.map(function (e) {
return e.message;
});
return result.length > 0 ? result : false;
},
get_error(field) {
const result = this.errors.filter(function (e) {
return e.code === field;
});
return result.length > 0 ? result[0] : false;
},
form_success(results) {
if (!_.isEmpty(results.data)) {
this.hooks.doAction('wu_on_form_success', this, results.data);
const fields = results.data.gateway.data;
fields.payment_id = results.data.payment_id;
fields.membership_id = results.data.membership_id;
fields.cart_type = results.data.cart_type;
// Append the hidden fields
jQuery.each(Object.assign({}, fields), function (index, value) {
const hidden = document.createElement('input');
hidden.type = 'hidden';
hidden.name = index;
hidden.value = value;
jQuery('#wu_form').append(hidden);
});
} // end if;
},
validate_form() {
this.errors = [];
const form_data_obj = jQuery('#wu_form').serializeArray().reduce(function (json, { name, value }) {
// Get products from this
if (name !== 'products[]') {
json[name] = value;
}
return json;
}, {});
const form_data = jQuery.param({
...form_data_obj,
products: this.products,
membership_id: this.membership_id,
payment_id: this.payment_id,
auto_renew: this.auto_renew,
cart_type: this.type,
valid_password: this.valid_password,
duration: this.duration,
duration_unit: this.duration_unit,
});
const that = this;
this.request('wu_validate_form', form_data, function (results) {
if (!that.valid_password) {
that.errors.push({
code: 'password',
message: wu_checkout.i18n.weak_password,
});
} // end if;
if (results.success === false) {
that.errors = [].concat(that.errors, results.data);
that.unblock();
return;
} // end if;
if (!that.errors.length) {
that.form_success(results);
if (that.prevent_submission === false) {
that.resubmit();
} // end if;
} else {
that.unblock();
} // end if;
}, this.handle_errors);
},
resubmit() {
jQuery('#wu_form').get(0).submit();
},
handle_errors(errors) {
this.unblock();
// eslint-disable-next-line no-console
console.error(errors);
},
on_submit(event) {
event.preventDefault();
},
on_change_product(new_value, old_value) {
window.wu_create_cookie('wu_selected_products', new_value.join(','), 0.5) // Save it for 12 hours max.
this.reset_templates(['template-selection']);
hooks.doAction('wu_on_change_product', new_value, old_value, this);
this.create_order();
},
on_change_gateway(new_value, old_value) {
hooks.doAction('wu_on_change_gateway', new_value, old_value, this);
},
on_change_country(new_value, old_value) {
hooks.doAction('wu_on_change_country', new_value, old_value, this);
this.create_order();
},
on_change_state(new_value, old_value) {
hooks.doAction('wu_on_change_state', new_value, old_value, this);
this.create_order();
},
on_change_city(new_value, old_value) {
hooks.doAction('wu_on_change_city', new_value, old_value, this);
this.create_order();
},
on_change_duration(new_value, old_value) {
this.reset_templates();
hooks.doAction('wu_on_change_duration', new_value, old_value, this);
this.create_order();
},
on_change_duration_unit(new_value, old_value) {
this.reset_templates();
hooks.doAction('wu_on_change_duration_unit', new_value, old_value, this);
this.create_order();
},
on_change_discount_code(new_value, old_value) {
hooks.doAction('wu_on_change_discount_code', new_value, old_value, this);
this.create_order();
},
block() {
/*
* Get the first bg color from a parent.
*/
const bg_color = jQuery(this.$el).parents().filter(function () {
return $(this).css('backgroundColor') !== 'rgba(0, 0, 0, 0)';
}).first().css('backgroundColor');
jQuery(this.$el).wu_block({
message: '<div class="spinner is-active wu-float-none" style="float: none !important;"></div>',
overlayCSS: {
backgroundColor: bg_color ? bg_color : '#ffffff',
opacity: 0.6,
},
css: {
padding: 0,
margin: 0,
width: '50%',
fontSize: '14px !important',
top: '40%',
left: '35%',
textAlign: 'center',
color: '#000',
border: 'none',
backgroundColor: 'none',
cursor: 'wait',
},
});
},
unblock() {
jQuery(this.$el).wu_unblock();
},
request(action, data, success_handler, error_handler) {
const actual_ajax_url = action === 'wu_validate_form' ? wu_checkout.late_ajaxurl : wu_checkout.ajaxurl;
jQuery.ajax({
method: 'POST',
url: actual_ajax_url + '&action=' + action,
data,
success: success_handler,
error: error_handler,
});
},
check_pass_strength() {
const pass1_el = '#field-password';
if (!jQuery('#pass-strength-result').length) {
return;
} // end if;
jQuery('#pass-strength-result')
.attr('class', 'wu-py-2 wu-px-4 wu-bg-gray-100 wu-block wu-text-sm wu-border-solid wu-border wu-border-gray-200');
const pass1 = jQuery(pass1_el).val();
if (!pass1) {
jQuery('#pass-strength-result').addClass('empty').html('Enter Password');
return;
} // end if;
this.valid_password = false;
const disallowed_list = typeof wp.passwordStrength.userInputDisallowedList === 'undefined'
? wp.passwordStrength.userInputBlacklist()
: wp.passwordStrength.userInputDisallowedList();
const strength = wp.passwordStrength.meter(pass1, disallowed_list, pass1);
switch (strength) {
case -1:
jQuery('#pass-strength-result').addClass('wu-bg-red-200 wu-border-red-300').html(pwsL10n.unknown);
break;
case 2:
jQuery('#pass-strength-result').addClass('wu-bg-red-200 wu-border-red-300').html(pwsL10n.bad);
break;
case 3:
jQuery('#pass-strength-result').addClass('wu-bg-green-200 wu-border-green-300').html(pwsL10n.good);
this.valid_password = true;
break;
case 4:
jQuery('#pass-strength-result').addClass('wu-bg-green-200 wu-border-green-300').html(pwsL10n.strong);
this.valid_password = true;
break;
case 5:
jQuery('#pass-strength-result').addClass('wu-bg-yellow-200 wu-border-yellow-300').html(pwsL10n.mismatch);
break;
default:
jQuery('#pass-strength-result').addClass('wu-bg-yellow-200 wu-border-yellow-300').html(pwsL10n.short);
} // end switch;
},
},
updated() {
this.$nextTick(function () {
hooks.doAction('wu_on_form_updated', this);
wu_initialize_tooltip();
});
},
mounted() {
const that = this;
jQuery(this.$el).on('click', function (e) {
$(this).data('submited_via', $(e.target));
});
jQuery(this.$el).on('submit', async function (e) {
e.preventDefault();
/**
* Handle button submission.
*/
const submit_el = jQuery(this).data('submited_via');
if (submit_el) {
const new_input = jQuery('<input>');
new_input.attr('type', 'hidden');
new_input.attr('name', submit_el.attr('name'));
new_input.attr('value', submit_el.val());
jQuery(this).append(new_input);
} // end if;
that.block();
try {
const promises = [];
// Here we use filter to return possible promises to await
await Promise.all(hooks.applyFilters("wu_before_form_submitted", promises, that, that.gateway));
} catch (error) {
that.errors = [];
that.errors.push({
code: 'before-submit-error',
message: error.message,
});
that.unblock();
that.handle_errors(error);
return;
} // end try;
that.validate_form();
hooks.doAction('wu_on_form_submitted', that, that.gateway);
});
this.create_order();
hooks.doAction('wu_checkout_loaded', this);
hooks.doAction('wu_on_change_gateway', this.gateway, this.gateway);
jQuery('#field-password').on('input pwupdate', function () {
that.check_pass_strength();
});
wu_initialize_tooltip();
},
watch: {
products(new_value, old_value) {
this.on_change_product(new_value, old_value);
},
toggle_discount_code(new_value) {
if (!new_value) {
this.discount_code = '';
} // end if;
},
discount_code(new_value, old_value) {
this.on_change_discount_code(new_value, old_value);
},
gateway(new_value, old_value) {
this.on_change_gateway(new_value, old_value);
},
country(new_value, old_value) {
this.state = '';
this.on_change_country(new_value, old_value);
},
state(new_value, old_value) {
this.city = '';
this.on_change_state(new_value, old_value);
},
city(new_value, old_value) {
this.on_change_city(new_value, old_value);
},
duration(new_value, old_value) {
this.on_change_duration(new_value, old_value);
},
duration_unit(new_value, old_value) {
this.on_change_duration_unit(new_value, old_value);
},
},
});
});
}(jQuery, wp.hooks, _));