1init(); 2 3function init() { 4 window.dynamicForms = window.dynamicForms || []; 5 6 // Attempt to dynamically update any already initialised forms (by Formie) 7 // For example forms that are already in the viewport or forms that don't use useObserver 8 refreshForms(); 9 10 // Listen for new forms as they're initialised (if they are using useObserver for example) 11 document.addEventListener("onFormieInit", e => { 12 const form = e.detail.form; 13 const $form = e.detail.$form; 14 15 refreshForm(form, $form); 16 }); 17 18 // Try refreshing Formie initialised forms again if Formie loads in later 19 document.addEventListener("onFormieLoaded", e => { 20 refreshForms(); 21 }); 22} 23 24function refreshForms() { 25 // Check forms are already initialised otherwise they will be initialised using Formie observer 26 if(window.Formie?.forms?.length) { 27 const forms = window.Formie.forms; 28 29 forms.forEach(form => { 30 refreshForm(form, form.$form); 31 }); 32 } 33} 34 35function refreshForm(form, $form) { 36 const dynamicForm = window.dynamicForms.find(dynamicForm => dynamicForm.formHandle === form.config.formHandle); 37 38 updateTokens($form); 39 40 if(dynamicForm) { 41 updateDynamic(dynamicForm); 42 } 43} 44 45function updateTokens(form) { 46 const formConfigRaw = form.getAttribute('data-fui-form'); 47 if (!formConfigRaw) return; 48 const formConfig = JSON.parse(formConfigRaw); 49 if (!formConfig || !formConfig.formHandle) return; 50 // update tokens using built-in Formie function 51 if(typeof window.Formie !== 'undefined') { 52 refreshTokens(form, formConfig, window.Formie); 53 } else { 54 document.addEventListener('onFormieInit', (e) => { 55 refreshTokens(form, formConfig, e.detail.formie); 56 }) 57 } 58 if (formConfig.settings.submitMethod === 'page-reload') { 59 // before submission add a query parameter to break the cache of the success message 60 form.addEventListener('onFormieValidate', e => { 61 const params = new URLSearchParams(location.search) 62 if (params.get('form') === null) params.append('form', '') 63 history.replaceState({}, '', `?${params.toString().replace(/=$|=(?=&)/g, '')}`) 64 }) 65 } 66} 67 68function refreshTokens(form, formConfig, Formie) { 69 // Check refreshForCache exists. It was added in 2.0.39 70 if(typeof Formie.refreshForCache !== 'undefined') { 71 Formie.refreshForCache(formConfig.formHashId) 72 } else { 73 fetch(`/actions/formie/forms/refresh-tokens?form=${formConfig.formHandle}`) 74 .then(result => result.json()) 75 .then(result => { 76 updateCSRF(form, result); 77 updateCaptcha(form, result); 78 }); 79 } 80} 81 82function updateCSRF(form, result) { 83 const csrfEl = form.querySelector('input[name="CRAFT_CSRF_TOKEN"]'); 84 if (!csrfEl) return; 85 csrfEl.outerHTML = result.csrf.input; 86} 87 88function updateCaptcha(form, result) { 89 // Taken from Formie docs 90 // https://verbb.io/craft-plugins/formie/docs/template-guides/cached-forms 91 if (result.captchas && result.captchas.javascript) { 92 let jsCaptcha = result.captchas.javascript; 93 94 form.querySelector('input[name="' + jsCaptcha.sessionKey + '"]').value = jsCaptcha.value; 95 } 96 97 if (result.captchas && result.captchas.duplicate) { 98 let duplicateCaptcha = result.captchas.duplicate; 99 100 form.querySelector('input[name="' + duplicateCaptcha.sessionKey + '"]').value = duplicateCaptcha.value; 101 } 102 103 if (form.form && form.form.formTheme) { 104 form.form.formTheme.updateFormHash(); 105 } 106} 107 108function updateDynamic(form) { 109 for (const field of form.fields) { 110 switch (field.type) { 111 case 'dateUs': 112 updateField( 113 form.parent, 114 field.handle, 115 Intl.DateTimeFormat('en-us', {month: '2-digit', day: '2-digit', year: 'numeric'}).format(new Date()) 116 ); 117 break; 118 case 'dateInt': 119 updateField( 120 form.parent, 121 field.handle, 122 Intl.DateTimeFormat('en-gb', {month: '2-digit', day: '2-digit', year: 'numeric'}).format(new Date()) 123 ); 124 break; 125 case 'currentUrl': 126 updateField(form.parent, field.handle, location.origin + location.pathname + location.search); 127 break; 128 case 'currentUrlNoQueryString': 129 updateField(form.parent, field.handle, location.origin + location.pathname); 130 break; 131 case 'userAgent': 132 updateField(form.parent, field.handle, navigator.userAgent); 133 break; 134 case 'referUrl': 135 updateField(form.parent, field.handle, document.referrer); 136 break; 137 case 'cookie': 138 updateField(form.parent, field.handle, getCookie(field.cookieName)); 139 break; 140 case 'prePopulate': 141 case 'query': 142 const params = new URLSearchParams(location.search); 143 144 switch(field.name) { 145 case 'Checkboxes': 146 updateCheckboxes(form.parent, field.handle, [params.get(`${field.queryParam}`)]); 147 updateCheckboxes(form.parent, field.handle, params.getAll(`${field.queryParam}[]`)); 148 break; 149 150 case 'Radio Buttons': 151 updateRadio(form.parent, field.handle, params.get(field.queryParam)); 152 break; 153 154 case 'Entries': 155 updateElement(form.parent, field.handle, params.get(field.queryParam)); 156 break; 157 158 default: 159 updateField(form.parent, field.handle, params.get(field.queryParam)); 160 } 161 162 break; 163 } 164 } 165} 166 167function updateField(el, handle, value) { 168 const field = el.querySelector(`[name="fields\[${handle}\]"]`); 169 if (!field) return; 170 field.value = value; 171} 172 173function updateElement(el, handle, value) { 174 const field = el.querySelector(`[name="fields\[${handle}\][]"]`); 175 if (!field) return; 176 field.value = value; 177} 178 179function updateCheckboxes(el, handle, values = []) { 180 if (values.length) { 181 // unselect checkboxes 182 el.querySelectorAll(`[name="fields\[${handle}\][]"]`).forEach(checkbox => checkbox.checked = false); 183 184 // select other checkboxes
185 values.forEach(value => { 186 const checkbox = el.querySelector(`[name="fields\[${handle}\][]"][value="${value}"]`); 187 if (!checkbox) return; 188 checkbox.checked = true; 189 }) 190 } 191} 192 193function updateRadio(el, handle, value) { 194 const field = el.querySelector(`[name="fields\[${handle}\]"][value="${value}"]`); 195 if(!field) return; 196 field.checked = true; 197} 198 199function getCookie(name) { 200 const value = `; ${document.cookie}`; 201 const parts = value.split(`; ${name}=`); 202 if (parts.length === 2) return parts.pop().split(';').shift(); 203} 204 205window.dynamicFormsInit = function () { 206 init(); 207}
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.