1/** 2 * Chronopost public utilities namespace 3 */ 4window.ChronopostPublic = window.ChronopostPublic || {}; 5 6/** 7 * Get value from shipping method input, handling both radio and hidden types 8 * WooCommerce switches radio inputs to hidden inputs when only one shipping option is available. 9 * This function handles both cases correctly. 10 * 11 * @param {string} selector - jQuery selector for the input element(s) 12 * @return {string|null} The value of the input, or null if not found 13 */ 14window.ChronopostPublic.getShippingMethodValue = function(selector) { 15 let $input = jQuery(selector); 16 if ($input.length === 0) return null; 17 18 // For radio inputs, get the checked one 19 if ($input.first().attr('type') === 'radio') { 20 return $input.filter(':checked').val(); 21 } 22 // For hidden inputs, just get the value 23 return $input.val(); 24}; 25 26(function ($) { 27 'use strict'; 28 29 $(document).ready(function () { 30 // Function to reset modal states 31 function resetModalStates() { 32 loadingMap = false; 33 loadingRdv = false; 34 $('#container-method-chronorelay').remove(); 35 $('#outer-container-method-chronoprecise').remove(); 36 } 37 38 // Function to detect if we're in Gutenberg block checkout mode 39 function isGutenbergCheckout() { 40 return $('.wc-block-checkout').length > 0 || (window.wp && window.wp.data); 41 } 42 43 // Classic WooCommerce checkout events 44 $('body').on('updated_checkout', function () { 45 if (!$('#saturday_shipping').length) { 46 $('#saturday_shipping_field_enable').val('no'); 47 } 48 // Only reset modal states in Gutenberg mode to prevent fancybox re-opening issues 49 if (isGutenbergCheckout()) { 50 resetModalStates(); 51 } 52 }); 53 54 // Gutenberg blocks checkout - listen for shipping method changes 55 if (isGutenbergCheckout()) { 56 let previousShippingMethods = []; 57 58 const unsubscribe = window.wp.data.subscribe(() => { 59 try { 60 const store = window.wp.data.select('wc/store/cart'); 61 if (store && store.getCartData) { 62 const cartData = store.getCartData(); 63 const currentMethods = cartData.shippingRates ? 64 cartData.shippingRates.flatMap(rateGroup => 65 rateGroup.shipping_rates ? rateGroup.shipping_rates.filter(rate => rate.selected).map(rate => rate.rate_id) : [] 66 ) : []; 67 68 // Compare with previous methods 69 const methodsChanged = JSON.stringify(currentMethods) !== JSON.stringify(previousShippingMethods); 70 71 if (methodsChanged) { 72 console.log('Shipping methods changed in Gutenberg checkout, resetting modal states'); 73 resetModalStates(); 74 previousShippingMethods = currentMethods; 75 } 76 } 77 } catch (error) { 78 // Silently handle any errors accessing WooCommerce store 79 } 80 }); 81 } 82 $(document.body).on('change', '#saturday_shipping', function () { 83 if (!$('form.checkout #saturday_shipping_field_enable').length) { 84 $('form.checkout').append('<input type="hidden" name="saturday_shipping_field_enable" id="saturday_shipping_field_enable">'); 85 } 86 87 $('#saturday_shipping_field_enable').val($(this).prop('checked') ? 'yes' : 'no'); 88 89 $( document.body ).trigger( 'update_checkout', { update_shipping_method: true }); 90 }); 91 92 var loadingMap = false, 93 loadingRdv = false, 94 shipping_method; 95 96 /** 97 * Legacy AJAX function for ChronoPrecise appointment loading 98 * @param {string} shipping_method - Shipping method ID 99 * @param {number} instance_id - Instance ID 100 * @param {string} blockTarget - jQuery selector for blocking target 101 */ 102 function loadChronoPreciseLegacy(shipping_method, instance_id, blockTarget) { 103 $.ajax({ 104 type: 'POST', 105 dataType: 'json', 106 url: Chronomap.ajaxurl, 107 cache: false, 108 data: { 109 'action': 'load_chronoprecise_appointment', 110 'method_id': shipping_method, 111 'instance_id': instance_id, 112 'chrono_nonce': Chronomap.chrono_nonce 113 }, 114 error: function(jqXHR, error, errorThrown) { 115 if (jqXHR.status && jqXHR.status == 400) { 116 alert(jqXHR.responseText); 117 } else { 118 alert(Chronoprecise.error_cant_reach_server); 119 } 120 loadingRdv = false;
121 $(blockTarget).unblock(); 122 } 123 }) 124 .done(function (output) { 125 if (output.status === 'success') { 126 // Create container for the appointment picker 127 let inserted = false; 128 129 if ($('#payment').length) { 130 $(output.data).insertBefore('#payment'); 131 inserted = true; 132 } 133 134 // Initialize the appointment picker if container was successfully inserted 135 if (inserted && $('#outer-container-method-chronoprecise').length) { 136 $('#outer-container-method-chronoprecise').chronoprecise({openRdv: true}); 137 } else if (!inserted) { 138 console.error('Could not find suitable DOM insertion point for appointment container'); 139 $('body').prepend('<div class="pickup-relay-error woocommerce-error">Error displaying appointment selector. Please try again.</div>'); 140 } 141 } else { 142 // Enhanced error display for both checkout types 143 const errorContainer = $('form.checkout').length ? 'form.checkout' : '.wc-block-checkout, body'; 144 $(errorContainer).prepend('<div class="pickup-relay-error woocommerce-error">' + output.data + '</div>'); 145 146 // Scroll to error (if not in body) 147 if (errorContainer !== 'body') { 148 $('html, body').animate({ 149 scrollTop: ($(errorContainer).offset().top - 100) 150 }, 1000); 151 } 152 $(document.body).trigger('checkout_error'); 153 } 154 loadingRdv = false;
155 $(blockTarget).unblock(); 156 }); 157 } 158 159 if ($('.chronorelaismap').length) { 160 $('.chronorelaismap').chronomap(); 161 } 162 if ($('#outer-container-method-chronoprecise').length) { 163 $('#outer-container-method-chronoprecise').chronoprecise(); 164 } 165 166 $(document.body).on('click', '.appointment-link, .chronopost-precise-slot-picker button', function (event) { 167 // (let chronoprecise.plugin.js handle fancybox opening for existing containers) 168 if ($(event.target).is('a') 169 && $(event.target).closest('.appointment-link').length 170 && $('#outer-container-method-chronoprecise').length) { 171 return; 172 } 173 if (!$('#outer-container-method-chronoprecise').length && !loadingRdv) { 174 $('.pickup-relay-error').remove(); 175 loadingRdv = true; 176 177 // Enhanced shipping method detection for Gutenberg + Classic compatibility 178 let shipping_method = null; 179 let instance_id = null; 180 181 // Method 1: Check for data attribute (Gutenberg blocks) 182 if ($(event.target).data('method-id')) { 183 shipping_method = $(event.target).data('method-id'); 184 console.log('Using Gutenberg data attribute:', shipping_method); 185 } 186 187 // Method 2: Original DOM traversal (Classic checkout) 188 if (!shipping_method) { 189 shipping_method = $(event.target).closest('li').find('input[name="shipping_method[0]"]').val(); 190 console.log('Using classic DOM traversal:', shipping_method); 191 } 192 193 // Method 3: Fallback - find any selected shipping method 194 if (!shipping_method) { 195 shipping_method = window.ChronopostPublic.getShippingMethodValue('input[name="shipping_method[0]"]'); 196 console.log('Using fallback selected method:', shipping_method); 197 } 198 199 // Get instance ID from data attribute or closest appointment link 200 instance_id = $(this).data('instance-id') || $('.appointment-link').data('instance-id'); 201 202 // If still no method found, show error 203 if (!shipping_method) { 204 console.error('No shipping method found for appointment selection'); 205 $('form.checkout, .wc-block-checkout').prepend('<div class="pickup-relay-error woocommerce-error">Unable to determine shipping method. Please try again.</div>'); 206 loadingRdv = false;
207 return; 208 } 209 210 // Enhanced blocking for both checkout types 211 const blockTarget = $('.woocommerce-checkout-review-order-table').length ? 212 '.woocommerce-checkout-review-order-table' : '.chronopost-container'; 213 $(blockTarget).block({ 214 message: null, 215 overlayCSS: { 216 background: "#fff", 217 opacity: .6 218 } 219 }); 220 221 // Try to use REST API client if available, otherwise fallback to legacy AJAX 222 if (window.chronoPreciseEnhanced && typeof ChronoPreciseRest !== 'undefined' && ChronoPreciseRest.useRestApi) { 223 console.log('ChronoPrecise: Using REST API approach'); 224 225 window.chronoPreciseEnhanced.loadAppointmentModal(instance_id, shipping_method) 226 .then(() => { 227 // Success - unblock UI 228 $(blockTarget).unblock(); 229 loadingRdv = false; 230 $('#outer-container-method-chronoprecise').remove(); 231 }) 232 .catch((error) => { 233 console.error('ChronoPrecise: REST API failed, using legacy fallback:', error); 234 // Fallback to legacy AJAX 235 loadChronoPreciseLegacy(shipping_method, instance_id, blockTarget); 236 }); 237 } else { 238 console.log('ChronoPrecise: Using legacy AJAX approach'); 239 loadChronoPreciseLegacy(shipping_method, instance_id, blockTarget); 240 } 241 event.preventDefault(); 242 } 243 }); 244 245 $(document.body).on('click', '.pickup-relay-link, .chronopost-button--pickup', function (event) { 246 if (!$('#container-method-chronorelay').length && !loadingMap) { 247 $('.pickup-relay-error').remove(); 248 loadingMap = true; 249 250 // Enhanced shipping method detection for Gutenberg + Classic compatibility 251 let shipping_method = null; 252 253 // Method 1: Check for data attribute (Gutenberg blocks) 254 if ($(event.target).data('method-id')) { 255 shipping_method = $(event.target).data('method-id'); 256 } 257 258 // Method 2: Original DOM traversal (Classic checkout) 259 if (!shipping_method) { 260 shipping_method = $(event.target).closest('li').find('input[name="shipping_method[0]"]').val(); 261 console.log('Using classic DOM traversal:', shipping_method); 262 } 263 264 // Method 3: Fallback - find any selected shipping method 265 if (!shipping_method) { 266 shipping_method = window.ChronopostPublic.getShippingMethodValue('input[name="shipping_method[0]"]'); 267 console.log('Using fallback selected method:', shipping_method); 268 } 269 270 // If still no method found, show error 271 if (!shipping_method) { 272 console.error('No shipping method found for pickup relay selection'); 273 $('form.checkout, .wc-block-checkout').prepend('<div class="pickup-relay-error woocommerce-error">Unable to determine shipping method. Please try again.</div>'); 274 loadingMap = false; 275 $('#container-method-chronorelay').remove(); 276 return; 277 } 278 279 // Try to use REST API client if available, otherwise fallback to legacy AJAX 280 if (window.chronoRelaisEnhanced && typeof ChronoRelaisRest !== 'undefined' && ChronoRelaisRest.useRestApi) { 281 console.log('ChronoRelais: Using REST API approach'); 282 283 window.chronoRelaisEnhanced.loadPickupRelayMap(shipping_method) 284 .then(() => { 285 // Success - unblock UI 286 loadingMap = false; 287 }) 288 .catch((error) => { 289 console.error('ChronoRelais: REST API failed, using legacy fallback:', error); 290 // Fallback to legacy AJAX 291 loadChronoRelaisLegacy(shipping_method); 292 }); 293 } else { 294 console.log('ChronoRelais: Using legacy AJAX approach'); 295 loadChronoRelaisLegacy(shipping_method); 296 } 297 event.preventDefault(); 298 } 299 }); 300 301 }); 302 303 /** 304 * Legacy AJAX function for ChronoRelais map loading 305 * @param {string} shipping_method - Shipping method ID 306 */ 307 function loadChronoRelaisLegacy(shipping_method) { 308 let loadingMap = false; 309 $.ajax({ 310 type: 'POST', 311 dataType: 'json', 312 url: Chronomap.ajaxurl, 313 cache: false, 314 data: { 315 'action': 'load_chronorelais_picker', 316 'method_id': shipping_method, 317 'chrono_nonce': Chronomap.chrono_nonce 318 } 319 }) 320 .done(function (output) { 321 if (output.status == 'success') { 322 // Enhanced DOM insertion for Gutenberg + Classic compatibility 323 let inserted = false;
324 325 // Method 1: Classic checkout - insert before #payment 326 if ($('#payment').length) { 327 $(output.data).insertBefore('#payment'); 328 inserted = true; 329 } 330 331 // Initialize the map if container was successfully inserted 332 if (inserted && $('#container-method-chronorelay').length) { 333 $('.chronorelaismap').chronomap({openMap: true}); 334 } else if (!inserted) { 335 console.error('Could not find suitable DOM insertion point for pickup relay container'); 336 $('body').prepend('<div class="pickup-relay-error woocommerce-error">Error displaying pickup point selector. Please try again.</div>'); 337 } 338 } else { 339 // Enhanced error display for both checkout types 340 const errorContainer = $('form.checkout').length ? 'form.checkout' : '.wc-block-checkout, body'; 341 $(errorContainer).prepend('<div class="pickup-relay-error woocommerce-error">' + output.data + '</div>'); 342 343 // Scroll to error (if not in body) 344 if (errorContainer !== 'body') { 345 $('html, body').animate({ 346 scrollTop: ($(errorContainer).offset().top - 100) 347 }, 1000); 348 } 349 $(document.body).trigger('checkout_error'); 350 } 351 loadingMap = false; 352 }); 353 } 354 355})(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.