1jQuery(document).ready(function ($) { 2 if (typeof qcMembershipFormSession === 'undefined') { 3 return; 4 } 5 6 const $form = $('form[data-id="' + qcMembershipFormSession.formId + '"]'); 7 8 if (!$form.length) { 9 return; 10 } 11 12 let saveTimer = null; 13 let isRestoring = false; 14 let lastSavedData = ''; 15 16 function getFormData() { 17 const data = {}; 18 19 $form.find('input[name], textarea[name], select[name]').each(function () { 20 const $field = $(this); 21 const name = $field.attr('name'); 22 const type = ($field.attr('type') || '').toLowerCase(); 23 24 if (!name || type === 'file' || type === 'submit' || type === 'button' || type === 'reset') { 25 return; 26 } 27 28 if (type === 'hidden' && $field.next('select[name="' + name.replace(/"/g, '\\"') + '"]').length) { 29 return; 30 } 31 32 if ($field.is('select')) { 33 if ($field.attr('data-ajax') === '1') { 34 if ($field.is('select[multiple]')) { 35 const values = []; 36 const labels = []; 37 38 $field.find('option:selected').each(function () { 39 values.push($(this).val()); 40 labels.push($(this).text()); 41 }); 42 43 data[name] = { __ajaxSelect: true, values: values, labels: labels }; 44 } else { 45 const $selected = $field.find('option:selected'); 46 47 data[name] = { 48 __ajaxSelect: true, 49 value: $field.val() || '', 50 label: $selected.length ? $selected.text() : ($field.val() || '') 51 }; 52 } 53 54 return; 55 } 56 57 data[name] = $field.is('select[multiple]') ? ($field.val() || []) : ($field.val() || ''); 58 return; 59 } 60 61 if (type === 'checkbox') { 62 if (!$field.is(':checked')) { 63 if (!Object.prototype.hasOwnProperty.call(data, name)) { 64 data[name] = ''; 65 } 66 67 return; 68 } 69 70 if (Object.prototype.hasOwnProperty.call(data, name)) { 71 data[name] = Array.isArray(data[name]) ? data[name] : [data[name]]; 72 data[name].push($field.val()); 73 } else { 74 data[name] = $field.val(); 75 } 76 77 return; 78 } 79 80 if (type === 'radio') { 81 if ($field.is(':checked')) { 82 data[name] = $field.val(); 83 } 84 85 return; 86 } 87 88 data[name] = $field.val() || ''; 89 }); 90 91 return data; 92 } 93 94 function saveFormSession() { 95 if (isRestoring) { 96 return; 97 } 98 99 const formDataJson = JSON.stringify(getFormData()); 100 101 if (formDataJson === lastSavedData) { 102 return; 103 } 104 105 $.ajax({ 106 url: qcMembershipFormSession.ajaxUrl, 107 type: 'POST', 108 dataType: 'json', 109 data: { 110 action: 'qc_save_membership_form_session', 111 nonce: qcMembershipFormSession.nonce, 112 form_data: formDataJson 113 } 114 }).done(function (response) { 115 if (response.success) { 116 lastSavedData = formDataJson; 117 } 118 }); 119 } 120 121 function queueFormSave() { 122 clearTimeout(saveTimer); 123 saveTimer = setTimeout(saveFormSession, parseInt(qcMembershipFormSession.saveDelay, 10) || 700); 124 } 125 126 function getSelectHiddenInput($field) { 127 return $field.siblings('input[type="hidden"][name="' + String($field.attr('name')).replace(/"/g, '\\"') + '"]'); 128 } 129 130 function syncAcfSelectValue($field, value) { 131 const normalizedValue = Array.isArray(value) ? value : String(value ?? ''); 132 const $hiddenInput = getSelectHiddenInput($field); 133 134 $field.val(normalizedValue); 135 136 if ($hiddenInput.length) { 137 $hiddenInput.val(Array.isArray(normalizedValue) ? normalizedValue.join(',') : normalizedValue); 138 } 139 140 if ($field.hasClass('select2-hidden-accessible')) { 141 $field.trigger('change.select2'); 142 } 143 144 $field.trigger('change'); 145 } 146 147 function restoreSelectField($field, value) { 148 const isMultiple = $field.is('select[multiple]'); 149 const isAjax = $field.attr('data-ajax') === '1'; 150 151 if (isAjax && value && typeof value === 'object' && value.__ajaxSelect) { 152 const values = isMultiple ? (value.values || []) : [value.value]; 153 const labels = isMultiple ? (value.labels || []) : [value.label]; 154
155 values.forEach(function (item, idx) { 156 if (item === '' || item === null || typeof item === 'undefined') { 157 return; 158 } 159 160 const stringValue = String(item); 161 const labelText = labels[idx] || stringValue; 162 const $existing = $field.find('option[value="' + stringValue.replace(/"/g, '\\"') + '"]'); 163 164 if (!$existing.length) { 165 $field.append(new Option(labelText, stringValue, true, true)); 166 } else { 167 $existing.text(labelText); 168 } 169 }); 170 171 syncAcfSelectValue($field, isMultiple ? values.map(String) : String(values[0])); 172 return; 173 } 174 175 const plainValue = (value && typeof value === 'object' && value.__ajaxSelect) ? value.value : value; 176 const values = isMultiple ? (Array.isArray(plainValue) ? plainValue : [plainValue]) : [plainValue]; 177 178 if (isAjax) { 179 values.forEach(function (item) { 180 if (item === '' || item === null || typeof item === 'undefined') { 181 return; 182 } 183 184 const stringValue = String(item); 185 186 if (!$field.find('option[value="' + stringValue.replace(/"/g, '\\"') + '"]').length) { 187 $field.append(new Option(stringValue, stringValue, true, true)); 188 } 189 }); 190 } 191 192 syncAcfSelectValue($field, isMultiple ? values : values[0]); 193 } 194 195 function restoreField($field, value) { 196 const type = ($field.attr('type') || '').toLowerCase(); 197 198 if (type === 'file') { 199 return; 200 } 201 202 if (type === 'hidden' && $field.siblings('select[name="' + String($field.attr('name')).replace(/"/g, '\\"') + '"]').length) { 203 return; 204 } 205 206 if ($field.is('select')) { 207 restoreSelectField($field, value); 208 return; 209 } 210 211 if (type === 'checkbox') { 212 $field.prop('checked', Array.isArray(value) ? value.indexOf($field.val()) !== -1 : String(value) === '1' || String(value) === 'true' || String(value) === String($field.val())); 213 return; 214 } 215 216 if (type === 'radio') { 217 $field.prop('checked', String($field.val()) === String(value)); 218 return; 219 } 220 221 $field.val(value); 222 } 223 224 function restoreFormData(savedData) { 225 if (!savedData || typeof savedData !== 'object') { 226 return; 227 } 228 229 isRestoring = true; 230 231 $.each(savedData, function (fieldName, value) { 232 const escapedName = String(fieldName).replace(/\\/g, '\\\\').replace(/"/g, '\\"'); 233 let $fields = $form.find('[name="' + escapedName + '"]'); 234 235 if (!$fields.length) { 236 const fieldKeyMatch = String(fieldName).match(/(field_[a-zA-Z0-9]+)/); 237 238 if (fieldKeyMatch) { 239 $fields = $form.find('[data-key="' + fieldKeyMatch[1] + '"]').find('input, textarea, select'); 240 } 241 } 242 243 const $selectFields = $fields.filter('select'); 244 245 if ($selectFields.length) { 246 $selectFields.each(function () { 247 restoreSelectField($(this), value); 248 }); 249 250 return; 251 } 252 253 $fields.each(function () { 254 restoreField($(this), value); 255 }); 256 }); 257 258 setTimeout(function () { 259 $form.find('select[data-ui="1"]').each(function () { 260 const $select = $(this); 261 const value = $select.val(); 262 const $hiddenInput = getSelectHiddenInput($select); 263 264 if ($hiddenInput.length) { 265 $hiddenInput.val(Array.isArray(value) ? value.join(',') : (value || '')); 266 } 267 268 if ($select.hasClass('select2-hidden-accessible')) { 269 $select.trigger('change.select2'); 270 } 271 }); 272 273 lastSavedData = JSON.stringify(getFormData()); 274 isRestoring = false;
275 }, 100); 276 } 277 278 function loadFormSession() { 279 $.ajax({ 280 url: qcMembershipFormSession.ajaxUrl, 281 type: 'POST', 282 dataType: 'json', 283 data: { 284 action: 'qc_load_membership_form_session', 285 nonce: qcMembershipFormSession.nonce 286 } 287 }).done(function (response) { 288 if (!response.success || !response.data || !response.data.has_data) { 289 return; 290 } 291 292 const savedData = response.data.form_data; 293 294 setTimeout(function () { 295 restoreFormData(savedData); 296 }, 500); 297 298 setTimeout(function () { 299 restoreFormData(savedData); 300 }, 1500); 301 }); 302 } 303 304 function destroyFormSession() { 305 return $.ajax({ 306 url: qcMembershipFormSession.ajaxUrl, 307 type: 'POST', 308 dataType: 'json', 309 data: { 310 action: 'qc_destroy_membership_form_session', 311 nonce: qcMembershipFormSession.nonce 312 } 313 }); 314 } 315 316 $form.on('input', 'input, textarea', function () { 317 if (!isRestoring) { 318 queueFormSave(); 319 } 320 }); 321 322 $form.on('change', 'input, textarea, select', function () { 323 if (!isRestoring) { 324 clearTimeout(saveTimer); 325 saveFormSession(); 326 } 327 }); 328 329 window.qcDestroyMembershipFormSession = destroyFormSession; 330 331 loadFormSession(); 332});
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.