1function toggleAccordion(header) { 2 var accordionItem = header.parentElement; 3 var content = accordionItem.querySelector('.cr_learn_inside_content'); 4 5 if (accordionItem.classList.contains('up-arrow')) { 6 // Close the accordion item 7 content.style.maxHeight = 0; 8 accordionItem.classList.remove('up-arrow'); 9 } else { 10 // Open the accordion item 11 content.style.maxHeight = content.scrollHeight + 'px'; 12 accordionItem.classList.add('up-arrow'); 13 14 // Close other accordion items 15 var accordionItems = document.querySelectorAll('.cr_learn_more_tabs-main'); 16 accordionItems.forEach(function (item) { 17 if (item !== accordionItem && item.classList.contains('up-arrow')) { 18 var otherContent = item.querySelector('.cr_learn_inside_content'); 19 otherContent.style.maxHeight = 0; 20 item.classList.remove('up-arrow'); 21 } 22 }); 23 } 24} 25// Get all elements with the class "cr_learn_more_tabs-link" 26var elements = document.querySelectorAll('.cr_learn_more_tabs-main'); 27 28// Iterate over the elements 29elements.forEach(function(element) { 30 // Find the <a> tag within each container 31 var anchor = element.querySelector('a'); 32 33 if (anchor) { 34 // Add onclick attribute to the <a> tag 35 anchor.setAttribute('onclick', 'toggleAccordion(this)'); 36 37 // Find the h3 element within each container 38 var heading = element.querySelector('a h3'); 39 40 if (heading) { 41 // Create a new span element 42 var spanElement = document.createElement('span'); 43 spanElement.className = 'arrow'; // Add the 'arrow' class to the span 44 45 // Insert the span element after the h3 element 46 heading.parentNode.insertBefore(spanElement, heading.nextSibling); 47 } 48 } 49}); 50 51/************************************ 52 * GLOBAL PHONE FORMATTER 53 ************************************/ 54window.GrandPhoneHelper = (function () { 55 56 function formatDigitsToDisplay(digits) { 57 // digits is just numeric chars, max 10 58 if (!digits) return ""; 59 if (digits.length <= 3) return "(" + digits; 60 if (digits.length <= 6) return "(" + digits.substring(0, 3) + ") " + digits.substring(3); 61 return "(" + digits.substring(0, 3) + ") " + digits.substring(3, 6) + "-" + digits.substring(6, 10); 62 } 63 64 function normalizeToDigits(raw) { 65 if (!raw) return ""; 66 return raw.replace(/\D/g, "").substring(0, 10); // strictly max 10 digits 67 } 68 69 // Map raw caret position to number-of-digits-before-caret 70 function countDigitsBeforeCaret(value, caretPos) { 71 let count = 0; 72 for (let i = 0; i < caretPos && i < value.length; i++) { 73 if (/\d/.test(value[i])) count++; 74 } 75 return count; 76 } 77 78 // Map digit index back to caret position in formatted string 79 function caretPosFromDigits(formatted, digitsBefore) { 80 if (digitsBefore <= 0) return 0; 81 let count = 0; 82 for (let i = 0; i < formatted.length; i++) { 83 if (/\d/.test(formatted[i])) { 84 count++; 85 if (count === digitsBefore) return i + 1; // place after this digit 86 } 87 } 88 return formatted.length; 89 } 90 91 function formatPhoneInput(input) { 92 const raw = input.value; 93 // Save caret and number-of-digits-before-caret 94 const selStart = input.selectionStart || 0; 95 const digitsBefore = countDigitsBeforeCaret(raw, selStart); 96 97 // Make normalized digits and formatted value 98 const digits = normalizeToDigits(raw); 99 const formatted = formatDigitsToDisplay(digits); 100 101 // Only update if changed (avoids unnecessary DOM writes) 102 if (formatted !== raw) { 103 input.value = formatted; 104 105 // Recalculate caret position based on digitsBefore 106 const newCaret = caretPosFromDigits(formatted, digitsBefore); 107 try { 108 input.setSelectionRange(newCaret, newCaret); 109 } catch (e) { 110 // ignore if input isn't focusable etc. 111 } 112 113 // For frameworks that listen to "input" event (Vue), dispatch one 114 const ev = new Event('input', { bubbles: true }); 115 input.dispatchEvent(ev); 116 } 117 } 118 119 function attachFormatting() { 120 // Attach with delegation for dynamic inputs too 121 document.addEventListener('input', function (e) { 122 const target = e.target; 123 if (!target) return; 124 if (target.tagName !== 'INPUT') return; 125 if (!target.classList.contains('format-phone')) return; 126
127 // Avoid interfering with composition (IME) for languages like Japanese 128 if (target.composing) return; 129 130 formatPhoneInput(target); 131 }, true); 132 } 133 134 document.addEventListener("DOMContentLoaded", attachFormatting); 135 136 return { 137 // public API to format a string or a specific input element 138 formatString: function (s) { return formatDigitsToDisplay(normalizeToDigits(s)); }, 139 formatElement: function (el) { if (el && el.tagName === 'INPUT') formatPhoneInput(el); } 140 }; 141 142})(); 143
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.