1( function( $ ) { 2 3 4 $(document).ready( function() { 5 $('.manage-billing-link a').click(function(e) { 6 e.preventDefault(); 7 8 $('.manage-billing-link').hide(); 9 10 if ( $('#update-authorizenet-card-form').length > 0 ) { 11 $('#update-authorizenet-card-form').show(); 12 } else { 13 $('#update-card-form').show(); 14 } 15 16 }); 17 }); 18 19 20 21 $(window).on('load', function() { 22 23 if ( $('.leaky-paywall-profile-subscription-details').length > 0 || $('#leaky-paywall-account-wrapper').length > 0 ) { 24 25 console.log('on account'); 26 27 lpWaitForElm('#leaky-paywall-cancel-modal').then((elm) => { 28 29 const $modal = $('#leaky-paywall-cancel-modal'); 30 const retentionEnabled = $modal.attr('data-retention-enabled') === '1'; 31 let selectedReason = ''; 32 let retentionOfferShown = false; 33 34 // Stop clicks inside the container from bubbling up to MicroModal's 35 // overlay close handler. Clicks on the backdrop still close the modal. 36 $modal.on('click', '.modal__container', function(e) { 37 if ( ! $(e.target).closest('[data-micromodal-close]').length ) { 38 e.stopPropagation(); 39 } 40 }); 41 42 function showStep(stepName) { 43 $modal.find('.leaky-paywall-cancel-step').hide(); 44 $modal.find('.leaky-paywall-cancel-step[data-step="' + stepName + '"]').show(); 45 } 46 47 // Toggle the "Other" free text field. 48 $modal.on('change', '.cancel-reason-select', function() { 49 if ( $(this).val() === '__other__' ) { 50 $modal.find('.cancel-reason-other-row').show(); 51 } else { 52 $modal.find('.cancel-reason-other-row').hide(); 53 } 54 }); 55 56 // Step 1 "Continue" -> go to offer or confirm. 57 $modal.on('click', '.leaky-paywall-cancel-continue-button', function(e) { 58 e.preventDefault(); 59 60 const $select = $modal.find('.cancel-reason-select'); 61 if ( $select.length > 0 ) { 62 let value = $select.val() || ''; 63 if ( value === '__other__' ) { 64 const otherText = ($modal.find('.cancel-reason-other').val() || '').trim(); 65 value = otherText || 'Other'; 66 } 67 selectedReason = value; 68 } else { 69 selectedReason = ''; 70 } 71 72 // Store the reason on the final form for submission. 73 $modal.find('.cancel-reason-input').val(selectedReason); 74 75 if ( retentionEnabled ) { 76 retentionOfferShown = true; 77 showStep('offer'); 78 } else { 79 showStep('confirm'); 80 } 81 }); 82 83 // Retention offer: Accept. 84 $modal.on('click', '.leaky-paywall-retention-accept-button', function(e) { 85 e.preventDefault(); 86 const $btn = $(this); 87 const originalText = $btn.text(); 88 $btn.attr('disabled', true).text('Processing...'); 89 $('#leaky-paywall-retention-errors').html('').hide(); 90 91 $.post(leaky_paywall_recurring.ajaxurl, { 92 action: 'leaky_paywall_retention_offer_accept', 93 _ajax_nonce: leaky_paywall_recurring._ajax_nonce, 94 }, function(resp) { 95 if ( resp.status === 'success' ) { 96 $('#leaky-paywall-cancel-modal .modal__container').html(resp.html); 97 } else { 98 $btn.attr('disabled', false).text(originalText); 99 $('#leaky-paywall-retention-errors').html('<p>' + (resp.message || 'An error occurred.') + '</p>').show(); 100 } 101 }); 102 }); 103 104 // Retention offer: Decline -> proceed to confirm. 105 $modal.on('click', '.leaky-paywall-retention-decline-button', function(e) { 106 e.preventDefault(); 107 showStep('confirm'); 108 }); 109 110 // Final cancel form submission. 111 $modal.on('submit', '#leaky-paywall-cancel-form', function(e) { 112 e.preventDefault(); 113 114 $('#leaky-paywall-cancel-errors').html('').hide(); 115 $('#leaky-paywall-cancel-form input[type="submit"]').attr('disabled', true).val('Processing...'); 116 117 let data = { 118 action: 'leaky_paywall_cancel_form_process', 119 reason: selectedReason, 120 retention_offer_shown: retentionOfferShown ? '1' : '0', 121 _ajax_nonce: leaky_paywall_recurring._ajax_nonce, 122 }; 123 124 $.post(leaky_paywall_recurring.ajaxurl, data, function(resp) { 125 if ( resp.message == 'success' ) { 126 $('#leaky-paywall-cancel-modal .modal__container').html(resp.html); 127 } else { 128 $('#leaky-paywall-cancel-form input[type="submit"]').attr('disabled', false).val('Please cancel my subscription'); 129 $('#leaky-paywall-cancel-errors').html(resp.html).show(); 130 } 131 }); 132 }); 133 134 }); 135
136 let stripe = Stripe(leaky_paywall_script_ajax.stripe_pk); 137 var elements = stripe.elements(); 138 var cardElement = elements.create('card'); 139 140 if ( $('#update-card-element').length > 0 ) { 141 cardElement.mount('#update-card-element'); 142 143 var form = document.getElementById('update-card-form'); 144 form.addEventListener('submit', function(event) { 145 event.preventDefault(); 146 147 var $errorBox = $('#lp-card-errors'); 148 var $submitBtn = $(form).find('button[type="submit"], input[type="submit"]').first(); 149 var isButtonEl = $submitBtn.is('button'); 150 var originalBtnText = isButtonEl ? $submitBtn.html() : $submitBtn.val(); 151 152 function restoreButton() { 153 if ( isButtonEl ) { 154 $submitBtn.prop('disabled', false).html(originalBtnText); 155 } else { 156 $submitBtn.prop('disabled', false).val(originalBtnText); 157 } 158 } 159 160 function showError(message) { 161 $errorBox.html('<p class="leaky_paywall_message error">' + $('<div/>').text(message).html() + '</p>'); 162 } 163 164 // Reset previous error + lock the submit button while in flight. 165 $errorBox.html(''); 166 if ( isButtonEl ) { 167 $submitBtn.prop('disabled', true).html('Processing...'); 168 } else { 169 $submitBtn.prop('disabled', true).val('Processing...'); 170 } 171 172 stripe.createPaymentMethod({ 173 type: 'card', 174 card: cardElement, 175 }).then(function(result) { 176 if (result.error) { 177 // Surface Stripe's error message to the user (declined 178 // card, expired card, missing CVC, test card in live 179 // mode, etc.). Without this the form silently swallows 180 // the error and the user gets no feedback â they think 181 // the button is broken. 182 showError(result.error.message || 'Your card could not be processed. Please try again.'); 183 restoreButton(); 184 return; 185 } 186 187 var paymentMethodId = result.paymentMethod.id; 188 var hiddenInput = document.createElement('input'); 189 hiddenInput.setAttribute('type', 'hidden'); 190 hiddenInput.setAttribute('name', 'payment_method_id'); 191 hiddenInput.setAttribute('value', paymentMethodId); 192 form.appendChild(hiddenInput); 193 194 // Hand off to the server. The browser navigates away, 195 // so no need to restore the button here. 196 form.submit(); 197 }).catch(function(err) { 198 // Network failure or Stripe.js exception. Same UX as a 199 // card error so the user has a path forward. 200 showError('Something went wrong while processing your card. Please try again.'); 201 restoreButton(); 202 if ( window.console && console.error ) { 203 console.error(err); 204 } 205 }); 206 }); 207 } 208 209 210 } 211 212 213 214 }); 215 216 function lpWaitForElm(selector) { 217 return new Promise(resolve => { 218 if (document.querySelector(selector)) { 219 return resolve(document.querySelector(selector)); 220 } 221 222 const observer = new MutationObserver(mutations => { 223 if (document.querySelector(selector)) { 224 resolve(document.querySelector(selector)); 225 observer.disconnect(); 226 } 227 }); 228 229 observer.observe(document.body, { 230 childList: true, 231 subtree: true 232 }); 233 }); 234} 235 236})( 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.