1(function($) { 2 'use strict'; 3 4 /** 5 * All of the code for your public-facing JavaScript source 6 * should reside in this file. 7 * 8 * Note: It has been assumed you will write jQuery code here, so the 9 * $ function reference has been prepared for usage within the scope 10 * of this function. 11 * 12 * This enables you to define handlers, for when the DOM is ready: 13 * 14 * $(function() { 15 * 16 * }); 17 * 18 * When the window is loaded: 19 * 20 * $( window ).on('load', function() { 21 * 22 * }); 23 * 24 * ...and/or other possibilities. 25 * 26 * Ideally, it is not considered best practise to attach more than a 27 * single DOM-ready or window-load handler for a particular page. 28 * Although scripts in the WordPress core, Plugins and Themes may be 29 * practising this, we should strive to set a better example in our own work. 30 31 */ 32 33 $(document).ready(function () { 34 function afrsmUpdateFreeShippingNoticeFragments(fragments) { 35 if (!fragments || !fragments['#afrsm-free-shipping-notices']) { 36 return; 37 } 38 39 var $noticeWrapper = $('#afrsm-free-shipping-notices'); 40 if ($noticeWrapper.length) { 41 $noticeWrapper.replaceWith(fragments['#afrsm-free-shipping-notices']); 42 } else { 43 var $target = $('.woocommerce-cart-form, form.checkout, .woocommerce-checkout').first(); 44 if ($target.length) { 45 $target.before(fragments['#afrsm-free-shipping-notices']); 46 } else { 47 $('.woocommerce').first().prepend(fragments['#afrsm-free-shipping-notices']); 48 } 49 } 50 } 51 52 $(document.body).on('updated_wc_div updated_checkout', function (event, data) { 53 if (data && data.fragments) { 54 afrsmUpdateFreeShippingNoticeFragments(data.fragments); 55 } 56 }); 57 58 $('body').on('change', 'input[name="payment_method"]', function () { 59 $('body').trigger('update_checkout'); 60 }); 61 62 /** Checkout WC compatibility Start */ 63 $( document.body ).on( 'updated_checkout', function(){ 64 var move_element; 65 $('.cfw-shipping-methods-list').addClass('afrsm_shipping'); 66 $('.cfw-shipping-methods-list li').each( function(){ 67 if( $(this).find('.extra-flate-tool-tip').length > 0){ 68 move_element = $(this).find('.extra-flate-tool-tip'); 69 $(move_element).appendTo( $(this).find('.cfw-shipping-method-inner') ); 70 } 71 if( $(this).find('.forceall-tooltip').length > 0){ 72 move_element = $(this).find('.forceall-tooltip'); 73 $(move_element).appendTo( $(this).find('.cfw-shipping-method-inner') ); 74 } 75 }); 76 }); 77 /** Checkout WC compatibility End */ 78 79 /** 80 * Block Checkout Compatibility - Tooltip Feature 81 * Tooltips should appear only in Order Summary (totals section) for selected shipping method 82 * Following the same pattern as fees plugin 83 */ 84 var isUpdatingTooltip = false; // Flag to prevent infinite loops 85 var tooltipUpdateTimeout = null; // Debounce timeout 86 87 init_shipping_tooltip(); 88 89 // Function to update the shipping method tooltip in Order Summary 90 updateShippingLabel(); 91 92 // Also run it whenever the DOM updates (e.g., when shipping methods are updated) 93 // But make it more specific to avoid infinite loops 94 const observer = new MutationObserver(function(mutations) { 95 // Only trigger if the mutation is not from our tooltip additions 96 var shouldUpdate = false; 97 mutations.forEach(function(mutation) { 98 if (mutation.addedNodes.length > 0) { 99 for (var i = 0; i < mutation.addedNodes.length; i++) { 100 var node = mutation.addedNodes[i]; 101 // Skip if it's our tooltip being added 102 if (node.nodeType === 1 && !$(node).hasClass('wc-afrsm-help-tip') && !$(node).find('.wc-afrsm-help-tip').length) { 103 // Check if it's a relevant change (totals item or shipping method) 104 if ($(node).closest('.wc-block-components-totals-item, .wc-block-components-shipping-rates-control').length > 0) { 105 shouldUpdate = true; 106 break; 107 } 108 } 109 } 110 } 111 }); 112 113 if (shouldUpdate && !isUpdatingTooltip) { 114 // Debounce to prevent rapid fire 115 clearTimeout(tooltipUpdateTimeout); 116 tooltipUpdateTimeout = setTimeout(updateShippingLabel, 300); 117 } 118 }); 119 observer.observe(document.body, { childList: true, subtree: true }); 120 121 function updateShippingLabel() { 122 // Remove all existing tooltips only if we need to update 123 $('.wc-afrsm-help-tip').remove(); 124 $('.afrsm-shipping-subtitle').remove(); 125 126 // Prevent re-entry 127 if (isUpdatingTooltip) { 128 return; 129 } 130 131 if (typeof afrsm_public_vars === 'undefined' || !afrsm_public_vars.shipping_tooltip_data) { 132 return; 133 } 134 135 isUpdatingTooltip = true; // Set flag to prevent re-entry 136 137 // Check if tooltip already exists for current selected method 138 var $existingTooltip = $('.wc-afrsm-help-tip'); 139 var needsUpdate = true; 140 141 // Get the selected shipping method and its label 142 var selectedMethodLabel = ''; 143 var $selectedInput = $('.wc-block-components-shipping-rates-control .wc-block-components-radio-control__option-checked'); 144 145 if ($selectedInput.length > 0) { 146 var $methodLabel = $selectedInput.find('.wc-block-components-radio-control__label'); 147 if ($methodLabel.length > 0) { 148 selectedMethodLabel = $methodLabel.text().trim(); 149 } 150 } else { 151 selectedMethodLabel = $('.wc-block-components-totals-shipping .wc-block-components-totals-item__label').text().trim(); 152 } 153 154 // If no selected method, don't show any tooltips 155 if (!selectedMethodLabel) { 156 isUpdatingTooltip = false;
157 return; 158 } 159 160 // Create slug from selected method label (same way PHP creates slug) 161 var selectedMethodSlug = selectedMethodLabel.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, ''); 162 163 // If we have an existing tooltip, check if it's for the current method 164 if ($existingTooltip.length > 0) { 165 var existingSlug = $existingTooltip.first().attr('class').match(/afrsm-help-tip-([^\s]+)/); 166 if (existingSlug && existingSlug[1] === selectedMethodSlug) { 167 // Tooltip already exists for current method, no need to update 168 needsUpdate = false; 169 } 170 } 171 172 if (!needsUpdate) { 173 isUpdatingTooltip = false; 174 return; 175 } 176 177 // Find the tooltip data for the selected shipping method 178 var tooltip_html = null; 179 var shipping_slug = null; 180 var tooltip_type = null; 181 182 $.each( afrsm_public_vars.shipping_tooltip_data, function( slug, tooltip ){ 183 // Match by slug 184 if (slug === selectedMethodSlug) { 185 tooltip_html = tooltip.text; 186 tooltip_type = tooltip.type; 187 shipping_slug = slug; 188 return false; // break the loop 189 } 190 }); 191 192 // If no tooltip found for selected method, don't show anything 193 if (!tooltip_html || !shipping_slug) { 194 isUpdatingTooltip = false; 195 return; 196 } 197 198 // Now find the selected shipping method in Order Summary totals and add tooltip 199 $('.wc-block-components-totals-item').each(function() { 200 var $item = $(this); 201 var $label = $item.find('.wc-block-components-totals-item__label'); 202 var labelText = $label.text().trim(); 203 204 // Skip if it's subtotal, fees, or total 205 if ($item.hasClass('wc-block-components-totals-item--subtotal') || 206 $item.closest('.wc-block-components-totals-fees').length > 0 || 207 $item.closest('.wc-block-components-totals-footer-item').hasClass('wc-block-components-totals-footer-item--total')) { 208 return true; // continue 209 } 210 211 // Create slug from Order Summary label text for comparison 212 var labelSlug = labelText.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, ''); 213 214 var matches = false; 215 if (labelSlug === shipping_slug || labelSlug === selectedMethodSlug) { 216 matches = true; 217 } else if (labelText === selectedMethodLabel) { 218 matches = true; 219 } else if (labelText.indexOf(selectedMethodLabel) !== -1) { 220 // Partial match - Order Summary label contains selected method name 221 matches = true; 222 } 223 224 if (matches) { 225 var $valueElement = $item.find('.wc-block-components-totals-item__value'); 226 227 if ($valueElement.length > 0 && $('.afrsm-help-tip-' + shipping_slug).length === 0) { 228 // Temporarily disconnect observer to prevent loop 229 observer.disconnect(); 230 231 if (tooltip_type === 'tooltip') { 232 let $tooltip = $('<span class="wc-afrsm-help-tip wc-block-components-tooltip afrsm-help-tip-' + shipping_slug + '" data-tip="' + tooltip_html + '"></span>'); 233 $valueElement.after($tooltip); 234 } else { 235 var $description = $valueElement.next('.wc-block-components-totals-item__description'); 236 let $subtitle = $('<span class="afrsm-shipping-subtitle afrsm-subtitle-' + shipping_slug + '">'+ tooltip_html +'</span>'); 237 $description.html($subtitle); 238 } 239 240 // Reconnect observer after a short delay 241 setTimeout(function() { 242 observer.observe(document.body, { childList: true, subtree: true }); 243 }, 100); 244 } 245 } 246 }); 247 248 init_shipping_tooltip(); 249 250 // Reset flag after a short delay to allow DOM to settle 251 setTimeout(function() { 252 isUpdatingTooltip = false;
253 }, 200); 254 } 255 256 function init_shipping_tooltip() { 257 setTimeout( function(){ 258 $('.wc-afrsm-help-tip').each(function () { 259 // Check if tipTip is already initialized 260 if (!$(this).data('tiptip-initialized')) { 261 $(this).tipTip({ 262 content: $(this).data('tip'), 263 keepAlive: true, 264 edgeOffset: 2 265 }); 266 $(this).data('tiptip-initialized', true); 267 } 268 }); 269 }, 1000 ); 270 } 271 }); 272 273 $(window).on('load', function () { 274 if ($('.forceall_shipping_method').length) { 275 if ($('.forceall_shipping_method').is(':hidden')) { 276 updateCartButton(); 277 } 278 } 279 280 function updateCartButton() { 281 $('.forceall_shipping_method').attr('checked', true).trigger('change'); 282 var checked = $('.forceall_shipping_method').is(':checked'); 283 if (checked === 'true') { 284 $('[name="update_cart"]').trigger('click'); 285 } 286 } 287 }); 288 289})(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.