1/** 2 * Checkout coupon: apply / remove, live total refresh, and 100%-off payment skip. 3 */ 4(function ($) { 5 'use strict'; 6 7 function currentEmail() { 8 var $email = $('#sec_email, input[name="email"]').filter(':visible').first(); 9 if (!$email.length) { $email = $('input[name="email"]').first(); } 10 return $email.length ? $email.val() : ''; 11 } 12 13 function showMessage($wrapper, text, isError) { 14 var $msg = $wrapper.find('.sec-coupon-msg'); 15 $msg.text(text).toggleClass('sec-coupon-msg-error', !!isError).show(); 16 if (!isError) { 17 setTimeout(function () { $msg.fadeOut(); }, 4000); 18 } 19 } 20 21 /** 22 * Toggle the payment section based on whether the order is now free. 23 * When free we hide the gateway + process button and expose a 24 * "Complete Booking" button that submits the booking form directly. 25 */ 26 function togglePaymentSection(isFree) { 27 var $payWrap = $('.sec-payment-method-wrapper, .sec-payment-method-wrapper-heading'); 28 var $processBtn = $('.sec-payment-process-button'); 29 var $gatewayForm = $('#sec-payment-form .sec-payment-method-wrapper'); 30 31 if (isFree) { 32 $payWrap.hide(); 33 $processBtn.hide(); 34 $('.sec-payment-methods-not-found').hide(); 35 36 if (!$('.sec-coupon-complete-btn').length) { 37 var label = (window.sec_success_error_translations && sec_success_error_translations.sec_submit) 38 ? sec_success_error_translations.sec_submit 39 : 'Complete Booking'; 40 var $btn = $('<button type="button" class="sec-btn sec-primary-btn sec-coupon-complete-btn">' + label + '</button>'); 41 if ($processBtn.length) { 42 $processBtn.after($btn); 43 } else { 44 $('.sec-wizard-buttons, .sec-gwizard-buttons').first().append($btn); 45 } 46 } 47 $('.sec-coupon-complete-btn').show(); 48 } else { 49 $payWrap.show(); 50 $processBtn.show(); 51 $('.sec-coupon-complete-btn').hide(); 52 } 53 } 54 55 function refreshSummary(html, isFree) { 56 if (html) { 57 $('.sec-event-summary').html(html); 58 } 59 togglePaymentSection(isFree); 60 } 61 62 /* ---- Apply ---- */ 63 function applyCoupon($wrapper) { 64 var code = $.trim($wrapper.find('.sec-coupon-input').val()); 65 if (!code) { 66 showMessage($wrapper, (window.sec_success_error_translations && sec_success_error_translations.sec_enter_coupon) || 'Please enter a coupon code.', true); 67 return; 68 } 69 var $btn = $wrapper.find('.sec-coupon-apply-btn'); 70 $btn.prop('disabled', true); 71 72 $.ajax({ 73 url: sec_coupon_object.ajax_url, 74 type: 'POST', 75 dataType: 'json', 76 data: { 77 action: 'sec_apply_coupon', 78 nonce: sec_coupon_object.nonce, 79 code: code, 80 event_id: $wrapper.data('event-id'), 81 qty: $wrapper.data('qty'), 82 sec_btn_id: $wrapper.data('btn-id'), 83 email: currentEmail() 84 }, 85 success: function (res) { 86 $btn.prop('disabled', false); 87 if (res && res.success) { 88 refreshSummary(res.data.summary_html, res.data.is_free); 89 } else { 90 showMessage($wrapper, (res && res.data && res.data.message) || 'Invalid coupon.', true); 91 } 92 }, 93 error: function () { 94 $btn.prop('disabled', false); 95 showMessage($wrapper, 'Request failed. Please try again.', true); 96 } 97 }); 98 } 99 100 /* ---- Remove ---- */ 101 function removeCoupon($wrapper) { 102 $.ajax({ 103 url: sec_coupon_object.ajax_url, 104 type: 'POST', 105 dataType: 'json', 106 data: { 107 action: 'sec_remove_coupon', 108 nonce: sec_coupon_object.nonce, 109 event_id: $wrapper.data('event-id'), 110 qty: $wrapper.data('qty'), 111 sec_btn_id: $wrapper.data('btn-id') 112 }, 113 success: function (res) { 114 if (res && res.success) { 115 refreshSummary(res.data.summary_html, res.data.is_free); 116 } 117 } 118 }); 119 } 120 121 $(function () { 122 $(document).on('click', '.sec-coupon-apply-btn', function () { 123 applyCoupon($(this).closest('.sec-coupon-wrapper')); 124 }); 125 126 $(document).on('keypress', '.sec-coupon-input', function (e) { 127 if (e.which === 13) { 128 e.preventDefault(); 129 applyCoupon($(this).closest('.sec-coupon-wrapper')); 130 } 131 }); 132 133 $(document).on('click', '.sec-coupon-remove', function (e) { 134 e.preventDefault(); 135 removeCoupon($(this).closest('.sec-coupon-wrapper')); 136 }); 137 138 /* Complete a 100%-off booking without payment. */ 139 $(document).on('click', '.sec-coupon-complete-btn', function (e) { 140 e.preventDefault(); 141 var $btn = $(this); 142 $btn.prop('disabled', true).addClass('sec-loading'); 143 if ($('#sec_groupevent_booking').length) { 144 $('#sec_groupevent_booking').trigger('submit'); 145 } else if ($('#sec_event_booking').length) { 146 $('#sec_event_booking').trigger('submit'); 147 } else { 148 $('#sec_submit_custom_form').trigger('click'); 149 } 150 // Re-enable shortly after in case validation blocks submission. 151 setTimeout(function () { $btn.prop('disabled', false).removeClass('sec-loading'); }, 3000); 152 }); 153 154 /* The plugin re-renders the summary on qty / credit changes via its own 155 AJAX. After any request, if a coupon summary is present, re-sync the 156 payment section against the freshly rendered total. */ 157 $(document).ajaxComplete(function () { 158 var $total = $('.sec-cart-total'); 159 if (!$total.length || !$('.sec-coupon-wrapper').length) { return; } 160 var total = parseFloat($total.data('total')); 161 togglePaymentSection(!isNaN(total) && total <= 0); 162 }); 163 }); 164})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.