1/** 2/** * Estimated Delivery - Front Office Feature 3 * 4 * NOTICE OF LICENSE 5 * 6 * @author Pol Rué 7 * @copyright Smart Modules 2015 8 * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0) 9 * @category Transport & Logistics 10 * Registered Trademark & Property of smart-modules.com 11 * 12 * *************************************************** 13 * * Estimated Delivery * 14 * * http://www.smart-modules.com * 15 * * * 16 * *************************************************** 17*/ 18 19var dynamic_refresh = false; 20 21function reverseString(str) { 22 return str.split("").reverse().join(""); 23} 24 25jQuery(document).ready(function($) { 26 let curr_ele = ''; 27 let t = 0; 28 29 const EDCheckoutMonitor = { 30 init: function() { 31 setTimeout(() => this.checkAndInit('page-load'), 100); 32 33 $(document).ajaxComplete((event, xhr, settings) => { 34 if (this.isCheckoutRelated(settings.url, xhr.responseText)) { 35 setTimeout(() => this.checkAndInit('ajax'), 300); 36 } 37 }); 38 39 new MutationObserver((mutations) => { 40 if (mutations.some(m => this.hasDeliveryInMutation(m))) { 41 setTimeout(() => this.checkAndInit('dom'), 100); 42 } 43 }).observe(document.body, { childList: true, subtree: true }); 44 }, 45 46 checkAndInit: function(reason) { 47 if ($('#estimateddelivery-cart').length > 0 && this.hasDeliveryOptions()) { 48 init_do(5, 100); 49 } 50 }, 51 52 isCheckoutRelated: function(url, content) { 53 const keywords = ['checkout', 'carrier', 'delivery', 'shipping', 'order', 'cart']; 54 const text = ((url || '') + (content || '')).toLowerCase(); 55 return keywords.some(k => text.includes(k)); 56 }, 57 58 hasDeliveryOptions: function() { 59 const deliveryOptionSelectors = [ 60 '.delivery_options', 61 '.delivery-options', 62 '.opc_shipping_method', 63 '#shipping-method', 64 '.js-delivery-option' 65 ]; 66 67 const selector = deliveryOptionSelectors 68 .map(sel => sel + ' input[type=radio]') 69 .join(', '); 70 71 return $(selector).length > 0; 72 }, 73 74 hasDeliveryInMutation: function(mutation) { 75 return Array.from(mutation.addedNodes).some(node => 76 node.nodeType === 1 && 77 ($(node).find('[class*="delivery"], [class*="carrier"]').length > 0 || 78 $(node).is('[class*="delivery"], [class*="carrier"]')) 79 ); 80 } 81 }; 82 83 EDCheckoutMonitor.init(); 84 85 init_do(8, 200); 86 setTimeout( function() {init_submit_refresh(); }, 800); 87 setTimeout( function() { init_do(8, 200); }, 3000); 88 89 function restart_ed() { 90 clearTimeout(t); 91 t = setTimeout(function() { 92 init_do(200, 50); 93 }, 500); 94 } 95 96 function init_submit_refresh() 97 { 98 var elements = ['#onepagecheckoutps', '#opc_checkout', '#supercheckout', '#velsof_supercheckout_form', '#module-steasycheckout-default', '#module-thecheckout-order', '#tc-container', '#checkout', '#opc_checkot']; 99 if ($(elements.join(', ')).length > 0) { 100 for (i = 0; i < elements.length; i++) { 101 if ($(elements[i]).length > 0) { 102 $(document).on('change', elements[i] + ' input, ' + elements[i] + ' select', restart_ed); 103 $(document).on('focusout', elements[i] + ' input, ' + elements[i] + ' select', restart_ed); 104 $(document).on('click', elements[i] + ' a, ' + elements[i] + ' button, ' + elements[i] + ' img', restart_ed); 105 $(document).on('mousedown', elements[i] + ' button', restart_ed); 106 break; 107 } 108 } 109 } else { 110 $(document).on('mousedown', '.step-title, button.continue, button[type=submit], a.cart_quantity_delete, .cart_quantity a', restart_ed); 111 $(document).on('focusout', '.cart_quantity_input', restart_ed); 112 $(document).on('change', 'select', restart_ed); 113 } 114 } 115 116 function init_do(tries, ms) { 117 let new_ele = []; 118 if (curr_ele.length > 0) { 119 new_ele = curr_ele.filter(function () { 120 return $(this).parent().length && $(this).is(':visible'); 121 }); 122 } 123 // Array of Selector, version, delay 124 let sels = [ 125 ['.delivery_options input[type=radio], .delivery_options_address input[type=radio]', '1.6', 0], 126 ['.delivery-options input[type=radio]', '1.7', 0], 127 ['.js-delivery-option input[type=radio]', '1.7', 0], 128 ['.opc_shipping_method input[type=radio]', 'new-supercheckout', 1200], 129 ['#shipping-method input[type=radio]', 'supercheckout', 1200], 130 ['#opc_delivery_methods .carrier_infos', '1.6', 1200], 131 ]; 132 let moved = false;
133 if ($('#estimateddelivery-cart').length > 0 && (curr_ele.length == 0 || curr_ele.length != new_ele.length)) { 134 for (let sel of sels) { 135 if ($(sel[0]).length > 0) { 136 137 // Remove any ID duplicate, just in case content is generated more than once 138 let txt = []; 139 let s = $(sel[0]).filter(function() { 140 if (typeof txt[$(this).prop('id')] === 'undefined') { 141 txt[$(this).prop('id')] = true; 142 return true; 143 } 144 }); 145 curr_ele = s; 146 s.each(function(i) { 147 move_options($(this), sel[1]); 148 if (s.length == i + 1) { 149 $('#estimateddelivery-cart').remove(); 150 moved = true; 151 } 152 }); 153 break; 154 } 155 } 156 } 157 if (tries > 0) { 158 if (ms <= 333) { 159 ms *= 1.1; 160 } 161 setTimeout(function() { init_do(tries-1, ms); }, ms); 162 return false; 163 } 164 } 165 166 function getNewId(e) { 167 const val = e.val(); 168 if (!val) return false; 169 170 // Case: multiple carrier IDs (CSV format) 171 if (val.includes(',')) { 172 const ids = val.split(','); 173 ids.pop(); 174 return ids.length ? ids : false; 175 } 176 177 // Desintifier check: first char is a digit, and the following string starts with N+1 zeros 178 const firstChar = val[0]; 179 const zeroCheck = parseInt(firstChar, 10); 180 181 if (!isNaN(zeroCheck)) { 182 const expectedZeros = '0'.repeat(zeroCheck + 1); 183 if (val.slice(1).startsWith(expectedZeros)) { 184 let carrId = val.slice(1); 185 carrId = reverseString(carrId); 186 carrId = carrId.split(expectedZeros); 187 carrId = carrId.reverse(); 188 carrId = reverseString(carrId[0]); 189 return [carrId]; 190 } 191 } 192 // Otherwise, assume ID is clean 193 return [val]; 194 } 195 196 function getTargetAndElements(e, version, i, carrier_id, is_multiple, wrapper) { 197 // Default values 198 let target = null; 199 let append_pre = '<div id="ed-item-'; 200 let append_post = '"></div>'; 201 202 // PRIORITY 1: Table-based layouts (PS 1.6 and some OPC modules) 203 if (e.closest('td').length > 0) { 204 // Check if rowspan scenario 205 if (e.closest('td')[0].hasAttribute('rowspan') && e.closest('td').attr('rowspan') > 1) { 206 if (version == '1.6') { 207 var tmp = e.closest('table').find('tr').eq(i).find('td'); 208 var repo = 2; 209 if (!(tmp[i].hasAttribute('rowspan') && tmp.eq(i).attr('rowspan') > 1)) { 210 repo = 1; 211 } 212 target = tmp.eq(tmp.length - repo); 213 } else if (version == '1.7') { 214 target = e.closest('.row'); 215 append_pre = '<div class="row ed_row"><div class="col-sm-1 col-1"></div><div class="col-sm-11 col-11"><div class="col-xs-12" id="ed-item-'; 216 append_post = '"></div></div></div>'; 217 } 218 } else { 219 // Normal table scenario 220 if (version == '1.6') { 221 if (e.closest('td').siblings().length > 1) { 222 target = e.closest('td').next().next(); 223 } else if (e.closest('td').siblings().length == 1) { 224 target = e.closest('tr').find('.delivery_option_delay'); 225 } 226 } else if (version == '1.7') { 227 target = e.closest('.row'); 228 append_pre = '<div class="row ed_row"><div class="col-sm-1 col-1"></div><div class="col-sm-11 col-11"><div class="col-xs-12" id="ed-item-'; 229 append_post = '"></div></div></div>'; 230 } else if (version == 'supercheckout') { 231 var e2 = e.closest('tr').find('td.shipping_info'); 232 e2.append('<div class="ed_delay"></div>'); 233 target = e2.find('.ed_delay'); 234 } 235 } 236 } 237 // PRIORITY 2: PrestaShop 1.5 legacy layout 238 else if (e.next().find('.delivery_option_delay').length > 0) { 239 var e2 = (e.next().find('.delivery_option_delay').next().length > 0 ? e.next().find('.delivery_option_delay').next() : e.next().find('.delivery_option_delay')); 240 target = e2; 241 append_pre = '<div class="col-xs-12" id="ed-item-'; 242 append_post = '"></div>'; 243 } 244 // PRIORITY 3: Standard .delivery-option with .carrier-delay 245 else if (e.closest('.delivery-option').find('.carrier-delay').first().length > 0) { 246 target = e.closest('.delivery-option').find('.carrier-delay').first().parent(); 247 } 248 // PRIORITY 4: Standard .delivery-option without .carrier-delay 249 else if (e.closest('.delivery-option').length > 0 && e.closest('.delivery-option').find('.delivery_option_delay').length > 0) { 250 target = e.closest('.delivery-option').find('.delivery_option_delay'); 251 } 252 // PRIORITY 5: List-based layouts (some OPC modules) 253 else if (e.closest('li').find('.shippingInfo').length > 0) { 254 var li_elem = e.closest('li'); 255 if (li_elem.find('#ed-item-' + carrier_id).length == 0) { 256 li_elem.find('.shippingInfo').html(''); 257 } 258 target = li_elem.find('.shippingInfo'); 259 } 260 // PRIORITY 6: Row-based layouts with carrier_delay 261 else if (e.closest('.row').length > 0 && e.closest('.row').find('.carrier_delay').length > 0) { 262 var row = e.closest('.row'); 263 if (e.closest('.delivery_options_address').length > 0) { 264 target = row.find('.delivery_option_delay'); 265 append_pre = '<div class="col-xs-12" id="ed-item-'; 266 append_post = '"></div>'; 267 } else if (row.find('.carrier_delay').length > 0) { 268 target = row.find('.carrier_delay'); 269 } else if (row.next().hasClass('carrier-extra-content')) { 270 var nextRow = row.next(); 271 nextRow.show(); 272 target = nextRow; 273 append_pre = '<div class="col-xs-1 col-1"></div><div class="col-xs-11 col-11" id="ed-item-'; 274 append_post = '"></div>'; 275 } else { 276 target = row; 277 append_pre = '<div class="col-xs-3"></div><div class="col-xs-9" id="ed-item-'; 278 append_post = '"></div>'; 279 } 280 } 281 // PRIORITY 7: Modern .js-delivery-option (newer themes/OPC) 282 else if (e.closest('.js-delivery-option').length > 0) { 283 target = e.closest('.js-delivery-option').find('.delivery-option__center'); 284 if (target.length === 0) { 285 target = e.closest('.js-delivery-option').find('[class*="delay"], [class*="center"]').first(); 286 } 287 append_pre = '<div class="col-xs-12" id="ed-item-'; 288 append_post = '"></div>'; 289 } 290 291 return { target: target, append_pre: append_pre, append_post: append_post }; 292 } 293 294 function move_ed_to_line(e, append_pre, append_post, carrier_id) { 295 const shouldHideDelay = typeof ed_hide_delay !== 'undefined' ? ed_hide_delay : false;
296 297 // List of possible delay message selectors 298 const delay_msg_selectors = [ 299 '.carrier-delay', 300 '.delivery_option_delay', 301 '.carrier_delay', 302 '.delivery-option__center' 303 ]; 304 305 let targetElement = e; 306 if (shouldHideDelay) { 307 let isDelayElement = false; 308 for (let selector of delay_msg_selectors) { 309 if (e.is(selector)) { 310 targetElement = e; 311 isDelayElement = true; 312 break; 313 } 314 } 315 316 if (!isDelayElement) { 317 for (let selector of delay_msg_selectors) { 318 const delayElement = e.find(selector); 319 if (delayElement.length > 0) { 320 targetElement = delayElement; 321 break; 322 } 323 } 324 } 325 } 326 327 const edContent = $('#estimateddelivery-cart #ed-cart-' + carrier_id); 328 const edItemExists = $('#ed-item-' + carrier_id).length > 0; 329 330 if (edContent.length > 0) { 331 if (!edItemExists) { 332 if (shouldHideDelay) { 333 targetElement.empty(); 334 } 335 336 targetElement.append(append_pre + carrier_id + append_post); 337 edContent.appendTo($('#ed-item-' + carrier_id)).addClass('ed_order_list').show(); 338 } else { 339 edContent.remove(); 340 } 341 } else { 342 if (!edItemExists) { 343 if (shouldHideDelay) { 344 targetElement.empty(); 345 } 346 347 let new_id = carrier_id + '-1'; 348 while ($('#estimateddelivery-cart #ed-cart-' + new_id).length > 0) { 349 const id = parseInt(new_id.slice(-1)) + 1; 350 new_id = new_id.slice(0, -1) + id; 351 } 352 353 targetElement.append(append_pre + new_id + append_post); 354 $('#ed-item-' + carrier_id).clone().appendTo($('#ed-item-' + new_id)).addClass('ed_order_list').show(); 355 } 356 } 357 } 358 359 function move_options(e, version) { 360 const new_id = getNewId(e); 361 if (new_id === false) { 362 return false; 363 } 364 365 const is_multiple = new_id.length > 1; 366 const show_message = typeof ed_multiple_carriers_message !== 'undefined' && ed_multiple_carriers_message; 367 368 const wrapper = is_multiple && ed_multiple_carriers_display === 'all' && show_message 369 ? $('<div class="estimateddelivery"></div>').append('<span>' + ed_multiple_carriers_message + '</span>') 370 : null; 371 372 let longest_delivery = null; 373 let longest_delivery_data = null; 374 375 new_id.forEach((carrier_id, i) => { 376 const elements = getTargetAndElements(e, version, i, carrier_id, is_multiple, wrapper); 377 if (!elements.target) return; 378 379 if (wrapper && wrapper.parent().length === 0) { 380 elements.target.append(wrapper); 381 } 382 383 const insertionPoint = wrapper || elements.target; 384 385 if (!is_multiple || ed_multiple_carriers_display === 'all') { 386 move_ed_to_line(insertionPoint, elements.append_pre, elements.append_post, carrier_id); 387 } else if (ed_multiple_carriers_display === 'longest') { 388 const current_delivery_data = $(`#ed-item-${carrier_id} .ed-cart-${carrier_id}`).data(); 389 if (!longest_delivery || 390 current_delivery_data.delivery_min > longest_delivery.delivery_min || 391 (current_delivery_data.delivery_min === longest_delivery.delivery_min && 392 current_delivery_data.delivery_max > longest_delivery.delivery_max)) { 393 longest_delivery = current_delivery_data; 394 longest_delivery_data = { 395 insertionPoint, 396 append_pre: elements.append_pre, 397 append_post: elements.append_post, 398 carrier_id 399 }; 400 } 401 } 402 403 // Update summary-selected-carrier if necessary 404 const selectedCarrier = $('.summary-selected-carrier'); 405 if (selectedCarrier.find('.carrier-delay').length > 0) { 406 const closestOption = e.closest('.delivery-option'); 407 if (closestOption.find('.ed-cart-selected').length > 0) { 408 closestOption.find('.ed-cart-selected').clone().appendTo(selectedCarrier.find('.row div
408:eq(3)')); 409 closestOption.find('.carrier-delay').hide(); 410 selectedCarrier.find('.carrier-delay').remove(); 411 } 412 } 413 }); 414 415 if (is_multiple) { 416 if (ed_multiple_carriers_display === 'longest' && longest_delivery_data) { 417 const data = longest_delivery_data; 418 move_ed_to_line(data.insertionPoint, data.append_pre, data.append_post, data.carrier_id); 419 } 420 } 421 } 422});
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.