1(function () { 2 'use strict'; 3 4 // Mirrors Samurai_Account_Checkout_Fields::NAME_COMBINED_MAX_LENGTH (server 5 // side stays authoritative; this is live inline feedback while typing). 6 var LIMIT = 32; 7 var PAIRS = [ 8 ['billing_first_name', 'billing_last_name'], 9 ['shipping_first_name', 'shipping_last_name'] 10 ]; 11 var STYLE_ID = 'sst-name-length-guard-style'; 12 13 function ensureStyle() { 14 if (document.getElementById(STYLE_ID)) { 15 return; 16 } 17 var style = document.createElement('style'); 18 style.id = STYLE_ID; 19 style.textContent = 20 '.sst-name-too-long input.input-text{border-color:#b32d2e !important;box-shadow:0 0 0 1px #b32d2e !important;}' + 21 '.sst-name-length-warning{display:block;margin-top:6px;font-size:0.82em;line-height:1.4;color:#b32d2e;}'; 22 document.head.appendChild(style); 23 } 24 25 function fieldWrap(input) { 26 return input.closest('.form-row') || input.parentElement; 27 } 28 29 function combinedLength(first, last) { 30 var full = (first.value.trim() + ' ' + last.value.trim()).trim(); 31 if (full === '') { 32 return 0; 33 } 34 // Count code points so multibyte names match the server-side mb_strlen. 35 return Array.from(full).length; 36 } 37 38 function updatePair(pair) { 39 var first = document.getElementById(pair[0]); 40 var last = document.getElementById(pair[1]); 41 if (!first || !last) { 42 return; 43 } 44 45 var len = combinedLength(first, last); 46 var over = len > LIMIT; 47 48 [first, last].forEach(function (input) { 49 var wrap = fieldWrap(input); 50 if (wrap) { 51 wrap.classList.toggle('sst-name-too-long', over); 52 } 53 }); 54 55 var lastWrap = fieldWrap(last); 56 if (!lastWrap) { 57 return; 58 } 59 var note = lastWrap.querySelector('.sst-name-length-warning'); 60 if (over) { 61 if (!note) { 62 note = document.createElement('span'); 63 note.className = 'sst-name-length-warning'; 64 lastWrap.appendChild(note); 65 } 66 note.textContent = 'Name is too long: first and last name combined must be ' + 67 LIMIT + ' characters or fewer including the space (currently ' + len + ').'; 68 } else if (note) { 69 note.parentNode.removeChild(note); 70 } 71 } 72 73 function updateAll() { 74 PAIRS.forEach(updatePair); 75 } 76 77 function isWatched(id) { 78 return PAIRS.some(function (pair) { 79 return pair.indexOf(id) !== -1; 80 }); 81 } 82 83 function init() { 84 ensureStyle(); 85 86 document.addEventListener('input', function (event) { 87 if (event.target && isWatched(event.target.id)) { 88 updateAll(); 89 } 90 }); 91 document.addEventListener('change', function (event) { 92 if (!event.target) { 93 return; 94 } 95 if (isWatched(event.target.id) || event.target.id === 'ship-to-different-address-checkbox') { 96 updateAll(); 97 } 98 }); 99 100 // Re-evaluate after WooCommerce re-renders checkout fragments and when 101 // browsers autofill the fields without firing input events. 102 if (window.jQuery) { 103 window.jQuery(document.body).on('updated_checkout country_to_state_changed', updateAll); 104 } 105 window.setTimeout(updateAll, 800); 106 107 updateAll(); 108 } 109 110 if (document.readyState === 'loading') { 111 document.addEventListener('DOMContentLoaded', init); 112 } else { 113 init(); 114 } 115})();
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.