1(function () { 2 'use strict'; 3 4 // Mirrors Samurai_Account_Checkout_Fields::CITY_MAX_LENGTH (server side 5 // stays authoritative; this is live inline feedback while typing). 6 // FedEx rejects labels whose city field exceeds 35 characters 7 // (CITY.TOO.LONG) - shoppers in KR/CN often paste "district, city, 8 // province, country" into the city box. 9 var LIMIT = 35; 10 var FIELDS = ['billing_city', 'shipping_city']; 11 var STYLE_ID = 'sst-city-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-city-too-long input.input-text{border-color:#b32d2e !important;box-shadow:0 0 0 1px #b32d2e !important;}' + 21 '.sst-city-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 cityLength(input) { 30 var value = input.value.trim(); 31 if (value === '') { 32 return 0; 33 } 34 // Count code points so multibyte input matches the server-side mb_strlen. 35 return Array.from(value).length; 36 } 37 38 function updateField(id) { 39 var input = document.getElementById(id); 40 if (!input) { 41 return; 42 } 43 var wrap = fieldWrap(input); 44 if (!wrap) { 45 return; 46 } 47 48 var len = cityLength(input); 49 var over = len > LIMIT; 50 wrap.classList.toggle('sst-city-too-long', over); 51 52 var note = wrap.querySelector('.sst-city-length-warning'); 53 if (over) { 54 if (!note) { 55 note = document.createElement('span'); 56 note.className = 'sst-city-length-warning'; 57 wrap.appendChild(note); 58 } 59 note.textContent = 'City is too long: ' + LIMIT + ' characters or fewer (currently ' + len + 60 '). Enter the city name only (e.g. "Goyang-si") - put the district in the address lines; ' + 61 'the province and country are covered by the other fields.'; 62 } else if (note) { 63 note.parentNode.removeChild(note); 64 } 65 } 66 67 function updateAll() { 68 FIELDS.forEach(updateField); 69 } 70 71 function isWatched(id) { 72 return FIELDS.indexOf(id) !== -1; 73 } 74 75 function init() { 76 ensureStyle(); 77 78 document.addEventListener('input', function (event) { 79 if (event.target && isWatched(event.target.id)) { 80 updateAll(); 81 } 82 }); 83 document.addEventListener('change', function (event) { 84 if (!event.target) { 85 return; 86 } 87 if (isWatched(event.target.id) || event.target.id === 'ship-to-different-address-checkbox') { 88 updateAll(); 89 } 90 }); 91 92 // Re-evaluate after WooCommerce re-renders checkout fragments and when 93 // browsers autofill the fields without firing input events. 94 if (window.jQuery) { 95 window.jQuery(document.body).on('updated_checkout country_to_state_changed', updateAll); 96 } 97 window.setTimeout(updateAll, 800); 98 99 updateAll(); 100 } 101 102 if (document.readyState === 'loading') { 103 document.addEventListener('DOMContentLoaded', init); 104 } else { 105 init(); 106 } 107})();
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.