1var ready = (callback) => { 2 if (document.readyState != "loading") callback(); 3 else document.addEventListener("DOMContentLoaded", callback); 4} 5ready(() => { 6 var containerClones = {}; 7 8 document.querySelectorAll('[data-repeatable-container][data-is-root]').forEach((rootElement) => { 9 let containerClone = rootElement.cloneNode(true), 10 containerIdentifier = rootElement.dataset['identifier'], 11 formIdentifier = rootElement.closest('form').getAttribute('id'), 12 copyButton = containerClone.querySelector('[data-repeatable-container][data-copy-button]'); 13 14 containerClones[formIdentifier] = containerClones[formIdentifier] || {}; 15 16 for (const copyElement of containerClone.querySelectorAll('[data-repeatable-container][data-is-copy]')) { 17 copyElement.remove(); 18 } 19 if (copyButton !== null) { 20 copyButton.remove(); 21 } 22 for (const alertElement of containerClone.querySelectorAll('[role="alert"]')) { 23 alertElement.remove(); 24 } 25 26 containerClone.querySelectorAll('[data-repeatable-container][data-is-root]').forEach((cloneElement) => { 27 delete cloneElement.dataset.isRoot; 28 cloneElement.dataset.isCopy = ''; 29 cloneElement.dataset.copyMother = cloneElement.dataset['identifier']; 30 }); 31 delete containerClone.dataset.isRoot; 32 containerClone.dataset.isCopy = ''; 33 containerClone.querySelectorAll('*').forEach((cloneChildElement) => { 34 cloneChildElement.classList.remove('has-error'); 35 }); 36 37 let inputs = [...containerClone.querySelectorAll('input')]; 38 inputs.filter((input) => ['checkbox', 'radio', 'hidden'].indexOf(input.getAttribute('type')) == -1).forEach((inputElement) => { 39 inputElement.setAttribute('value', ''); 40 }); 41 inputs.filter((input) => ['file'].indexOf(input.getAttribute('type')) >= 0).forEach((inputElement) => { 42 [...inputElement.parentNode.children].filter((child) => child !== inputElement).forEach((siblingElement) => { 43 siblingElement.remove(); 44 }); 45 }); 46 inputs.filter((input) => ['checkbox', 'radio'].indexOf(input.getAttribute('type')) >= 0).forEach((inputElement) => { 47 inputElement.checked = false; 48 }); 49 containerClone.querySelectorAll('textarea').forEach((textareaElement) => { 50 textareaElement.setAttribute('value', ''); 51 }); 52 containerClone.querySelectorAll('select').forEach((selectElement) => { 53 let selected = selectElement.selectedOptions; 54 for (let i = 0; i < selected.length; i++) { 55 selected[i].removeAttribute('selected'); 56 } 57 selectElement.selectedIndex = -1; 58 }); 59 60 containerClones[formIdentifier][containerIdentifier] = containerClone; 61 }); 62 63 document.dispatchEvent(new CustomEvent('initialize-repeatable-container-copy-buttons', { 'detail': { 'containerClones': containerClones } })); 64 document.dispatchEvent(new CustomEvent('initialize-repeatable-container-remove-buttons')); 65}); 66 67document.addEventListener('initialize-repeatable-container-copy-buttons', (copyEvent) => {
68 let containerClones = copyEvent.detail.containerClones, 69 getNextCopyNumber = (referenceElement, formElement) => { 70 let highestCopyNumber = 0; 71 72 formElement.querySelectorAll('[data-repeatable-container][data-copy-reference="' + referenceElement.dataset['identifier'] + '"]').forEach((copyElement) => { 73 let copyNumber = parseInt(copyElement.dataset['identifier'].split('.').pop()); 74 75 if (copyNumber > highestCopyNumber) { 76 highestCopyNumber = copyNumber; 77 } 78 }); 79 80 return ++highestCopyNumber; 81 }, 82 setRandomIds = (subject) => { 83 let idReplacements = {}; 84 85 subject.querySelectorAll('[id]').forEach((subjectIdElement) => { 86 let id = subjectIdElement.getAttribute('id'), 87 newId = Math.floor(Math.random() * 99999999) + Date.now(); 88 89 subjectIdElement.setAttribute('id', newId); 90 idReplacements[id] = newId; 91 }); 92 93 subject.querySelectorAll('*').forEach((subjectChildElement) => { 94 for (let i = 0, len = subjectChildElement.attributes.length; i < len; i++) { 95 let attributeValue = subjectChildElement.attributes[i].nodeValue; 96 97 if (attributeValue in idReplacements) { 98 subjectChildElement.attributes[i].nodeValue = idReplacements[attributeValue]; 99 } 100 } 101 }); 102 }, 103 escapeRegExp = (subject) => { 104 return subject.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); 105 }; 106 107 document.querySelectorAll('[data-repeatable-container][data-copy-button]').forEach((copyBtnElement) => { 108 let formElement = copyBtnElement.closest('form'), 109 referenceElementIdentifier = copyBtnElement.dataset['copyButtonFor'], 110 referenceElement = formElement.querySelector('[data-repeatable-container][data-identifier="' + referenceElementIdentifier + '"]'), 111 elementCopies = formElement.querySelectorAll('[data-repeatable-container][data-copy-reference="' + referenceElementIdentifier + '"]'), 112 maxCopies = referenceElement.dataset['maxCopies'] || false; 113 114 if (maxCopies && elementCopies.length >= maxCopies) { 115 copyBtnElement.disabled = true; 116 } else { 117 copyBtnElement.disabled = false; 118 /* clone element to remove all event listeners */ 119 let copyBtnElementClone = copyBtnElement.cloneNode(true); 120 copyBtnElement.replaceWith(copyBtnElementClone); 121 copyBtnElementClone.addEventListener('click', (clickEvent) => { 122 clickEvent.preventDefault(); 123 let clickElement = clickEvent.currentTarget, 124 clickFormElement = clickElement.closest('form'), 125 referenceElementIdentifier = clickElement.dataset['copyButtonFor'], 126 formIdentifier = clickFormElement.getAttribute('id'), 127 referenceElement = clickFormElement.querySelector('[data-repeatable-container][data-identifier="' + referenceElementIdentifier + '"]'), 128 referenceElementIsRoot = 'isRoot' in referenceElement.dataset, 129 elementCopies = clickFormElement.querySelectorAll('[data-repeatable-container][data-copy-reference="' + referenceElementIdentifier + '"]'), 130 containerCloneIdentifier = referenceElementIsRoot ? referenceElementIdentifier : referenceElement.dataset['copyMother'], 131 copyMotherIdentifier = containerClones[formIdentifier][containerCloneIdentifier].dataset['identifier'], 132 newIdentifierParts = referenceElement.dataset['identifier'].split('.'), 133 oldIdentifierNameRegex = escapeRegExp('[' + copyMotherIdentifier.split('.').join('][') + ']'), 134 copyMotherIdentifierRegex = '(' + escapeRegExp('data-copy-mother="') + ')?' + escapeRegExp(copyMotherIdentifier), 135 newIdentifier = undefined, 136 newIdentifierNameRegex = undefined, 137 containerClone = undefined, 138 containerCloneHtml = undefined; 139 140 newIdentifierParts.pop(); 141 newIdentifierParts.push(getNextCopyNumber(referenceElement, clickFormElement)); 142 newIdentifier = newIdentifierParts.join('.'); 143 144 containerCloneHtml = containerClones[formIdentifier][containerCloneIdentifier].outerHTML; 145 // leading, negative lookbehind ("?<!") 146 containerCloneHtml = containerCloneHtml.replace(new RegExp(copyMotherIdentifierRegex, 'g'), ($0, $1) => { 147 return $1 ? $0 : newIdentifier; 148 }); 149 150 newIdentifierNameRegex = '[' + newIdentifierParts.join('][') + ']'; 151 containerCloneHtml = containerCloneHtml.replace(new RegExp(oldIdentifierNameRegex, 'g'), newIdentifierNameRegex); 152 153 let containerCloneWrap = document.createElement('div'); 154 containerCloneWrap.innerHTML = containerCloneHtml; 155 containerClone = containerCloneWrap.firstChild; 156 containerClone.dataset.copyReference = referenceElementIdentifier; 157 158 setRandomIds(containerClone); 159 160 if (elementCopies.length === 0) { 161 referenceElement.after(containerClone); 162 } else { 163 [...elementCopies].at(-1).after(containerClone); 164 } 165 166 // document.dispatchEvent(new CustomEvent('after-element-copy', { 'detail': { 'containerClone': containerClone } })); 167 document.dispatchEvent(new CustomEvent('initialize-repeatable-container-copy-buttons', { 'detail': { 'containerClones': containerClones } })); 168 document.dispatchEvent(new CustomEvent('initialize-repeatable-container-remove-buttons')); 169 }); 170 } 171 }); 172}); 173 174document.addEventListener('initialize-repeatable-container-remove-buttons', (removeEvent) => { 175 document.querySelectorAll('[data-repeatable-container][data-remove-button]').forEach((removeBtnElement) => { 176 let formElement = removeBtnElement.closest('form'), 177 referenceElementIdentifier = removeBtnElement.dataset['removeButtonFor'], 178 referenceElement = formElement.querySelector('[data-repeatable-container][data-identifier="' + referenceElementIdentifier + '"]'), 179 referenceElementIsRoot = 'isRoot' in referenceElement.dataset, 180 referenceReferenceElementIdentifier = referenceElementIsRoot ? referenceElementIdentifier : referenceElement.dataset['copyReference'], 181 referenceReferenceElement = formElement.querySelector('[data-repeatable-container][data-identifier="' + referenceReferenceElementIdentifier + '"]'), 182 elementCopies = formElement.querySelectorAll('[data-repeatable-container][data-copy-reference="' + referenceReferenceElementIdentifier + '"]'), 183 minCopies = referenceReferenceElement?.dataset['minCopies'] || false; 184 185 if ((referenceElement.dataset['copyReference'] || false) && referenceElement.dataset['copyReference'] !== '') { 186 if (minCopies && elementCopies.length <= minCopies) { 187 // removeBtnElement.classList.remove('d-none'); 188 removeBtnElement.disabled = true; 189 } else { 190 // removeBtnElement.classList.remove('d-none'); 191 removeBtnElement.disabled = false;
192 } 193 } else { 194 removeBtnElement.remove(); 195 } 196 197 if (removeBtnElement.disabled) { 198 /* clone element to remove all event listeners */ 199 removeBtnElement.replaceWith(removeBtnElement.cloneNode(true)); 200 } else { 201 /* clone element to remove all event listeners */ 202 let removeBtnElementClone = removeBtnElement.cloneNode(true); 203 removeBtnElement.replaceWith(removeBtnElementClone); 204 removeBtnElementClone.addEventListener('click', (clickEvent) => { 205 clickEvent.preventDefault(); 206 207 let clickElement = clickEvent.currentTarget, 208 clickFormElement = clickElement.closest('form'), 209 referenceElementIdentifier = clickElement.dataset['removeButtonFor'], 210 referenceElement = clickFormElement.querySelector('[data-repeatable-container][data-identifier="' + referenceElementIdentifier + '"]'), 211 referenceElementIsRoot = 'isRoot' in referenceElement.dataset, 212 referenceReferenceElementIdentifier = referenceElementIsRoot ? referenceElementIdentifier : referenceElement.dataset['copyReference'], 213 referenceReferenceElement = clickFormElement.querySelector('[data-repeatable-container][data-identifier="' + referenceReferenceElementIdentifier + '"]'), 214 elementCopies = clickFormElement.querySelectorAll('[data-repeatable-container][data-copy-reference="' + referenceReferenceElementIdentifier + '"]'), 215 maxCopies = referenceReferenceElement?.dataset['maxCopies'] || false, 216 copyButton = clickFormElement.querySelector('[data-repeatable-container][data-copy-button-for="' + referenceReferenceElementIdentifier + '"]'); 217 218 if (maxCopies && elementCopies.length - 1 < maxCopies) { 219 copyButton.disabled = false; 220 } 221 222 referenceElement.remove(); 223 document.dispatchEvent(new CustomEvent('initialize-repeatable-container-remove-buttons')); 224 }); 225 } 226 }); 227}); 228 229/* DatePicker is a jQuery UI function and we want to get rid of jQuery... */ 230/* document.addEventListener('after-element-copy', (afterCopyEvent) => {
231 let containerClone = afterCopyEvent.detail.containerClone; 232 document.querySelectorAll('[data-element-type="DatePicker"]').forEach((datePickerElement) => { 233 var dateFormat; 234 235 // if (!datePickerElement.classList.contains('hasDatepicker') && parseInt(datePickerElement.getAttribute('data-element-datepicker-enabled')) === 1) { 236 if (!datePickerElement.classList.contains('hasDatepicker') && parseInt(datePickerElement.dataset['elementDatepickerEnabled']) === 1) { 237 // dateFormat = datePickerElement.getAttribute('data-element-datepicker-date-format'); 238 dateFormat = datePickerElement.dataset['elementDatepickerDateFormat']; 239 240 dateFormat = dateFormat.replace('d', 'dd'); 241 dateFormat = dateFormat.replace('j', 'o'); 242 dateFormat = dateFormat.replace('l', 'DD'); 243 dateFormat = dateFormat.replace('F', 'MM'); 244 dateFormat = dateFormat.replace('m', 'mm'); 245 dateFormat = dateFormat.replace('n', 'm'); 246 dateFormat = dateFormat.replace('Y', 'yy'); 247 248 $('#' + datePickerElement.attr('id')).datepicker({ 249 dateFormat: dateFormat 250 }).on('keydown', function(e) { 251 if(e.keyCode == 8 || e.keyCode == 46) { 252 e.preventDefault(); 253 $.datepicker._clearDate(this); 254 } 255 }); 256 } 257 }); 258}); */
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.