| | |
| | | const handlers = { |
| | | 'repeater': this.populateRepeater.bind(this), |
| | | 'tag-list': this.populateTagList.bind(this), |
| | | 'group': this.populateGroup.bind(this), |
| | | 'location': this.populateLocation.bind(this), |
| | | 'selector': this.populateTaxonomy.bind(this), |
| | | 'user': this.populateUser.bind(this), |
| | | 'upload': this.populateUpload.bind(this), |
| | | 'gallery': this.populateUpload.bind(this), |
| | | 'image': this.populateUpload.bind(this), |
| | | 'set': this.populateMultiValue.bind(this), |
| | | 'checkbox': this.populateMultiValue.bind(this), |
| | | 'select': this.populateSingleValue.bind(this), |
| | | 'radio': this.populateSingleValue.bind(this), |
| | | 'true-false': this.populateBoolean.bind(this), |
| | | 'toggle-text': this.populateBoolean.bind(this), |
| | | 'date': this.populateDate.bind(this), |
| | | 'time': this.populateDate.bind(this), |
| | | 'datetime': this.populateDate.bind(this), |
| | | 'number': this.populateNumber.bind(this), |
| | | 'textarea': this.populateTextarea.bind(this) |
| | | 'textarea': this.populateTextarea.bind(this), |
| | | 'quantity': this.populateNumber.bind(this), |
| | | }; |
| | | |
| | | if (Object.hasOwn(handlers, type)) { |
| | |
| | | if (!value || !Array.isArray(value)) return; |
| | | |
| | | const container = field.querySelector('.repeater-items'); |
| | | let template = field.querySelector('template')?.className??false; |
| | | let template = field.querySelector('template')?.className ?? false; |
| | | if (!container || !template) return; |
| | | |
| | | window.removeChildren(container); |
| | | |
| | | value.forEach((data, index) => { |
| | | data.index = index; |
| | | const row = this.templates.create(template, data); |
| | | let fields = row.querySelectorAll('.field'); |
| | | this.populate(fields, data); |
| | | const templateData = { ...data, index, repeater: field }; |
| | | |
| | | const row = this.templates.create(template, templateData); |
| | | if (!row) return; |
| | | |
| | | container.append(row); |
| | | |
| | | const formConfig = this.formHelper.getForm(row); |
| | | if (formConfig) { |
| | | this.formHelper.initializeFields(row, formConfig); |
| | | } |
| | | |
| | | for (let [fieldName, fieldValue] of Object.entries(data)) { |
| | | let subField = row.querySelector(`[data-field="${fieldName}"]`); |
| | | if (subField) { |
| | | this.populateField(subField, fieldName, fieldValue); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | populateTagList(field, name, value) { |
| | | if (!value || !Array.isArray(value)) return; |
| | | |
| | | const container = field.querySelector('.tag-items'); |
| | | let template = field.querySelector('template')?.className??false; |
| | | let template = field.querySelector('template')?.className ?? false; |
| | | if (!container || !template) return; |
| | | |
| | | window.removeChildren(container); |
| | | |
| | | value.forEach((data, index) => { |
| | | data.index = index; |
| | | const row = this.templates.create(template, data); |
| | | let fields = row.querySelectorAll('.field'); |
| | | this.populate(fields, data); |
| | | const row = this.templates.create(template, { |
| | | label: this.getTagLabel(data, field.dataset.tagFormat ?? 'first_field'), |
| | | fieldName: name, |
| | | ...data |
| | | }); |
| | | if (!row) return; |
| | | |
| | | // Set hidden input values directly |
| | | row.querySelectorAll('input[type="hidden"]').forEach(input => { |
| | | const key = input.dataset.field; |
| | | if (key && data[key] !== undefined) { |
| | | input.value = data[key]; |
| | | } |
| | | }); |
| | | |
| | | container.append(row); |
| | | }); |
| | | } |
| | | /** |
| | | * Build tag label from data - mirrors addTagListItem logic |
| | | */ |
| | | getTagLabel(data, format) { |
| | | const values = Object.values(data).filter(v => !this.isEmptyValue(v)); |
| | | switch (format) { |
| | | case 'first_field': |
| | | return values[0] ?? 'New Item'; |
| | | case 'all_fields': |
| | | return values.join(', ') || 'New Item'; |
| | | default: |
| | | if (format.includes('{')) { |
| | | let label = format; |
| | | for (const [key, value] of Object.entries(data)) { |
| | | label = label.replace(`{${key}}`, value); |
| | | } |
| | | return label; |
| | | } |
| | | return data[format] ?? values[0] ?? 'New Item'; |
| | | } |
| | | } |
| | | populateGroup(field, name, value) { |
| | | if (!value || typeof value !== 'object') return; |
| | | |
| | | for (let [subName, subValue] of Object.entries(value)) { |
| | | let subField = field.querySelector(`[data-field="${subName}"]`); |
| | | if (subField) { |
| | | this.populateField(subField, subName, subValue); |
| | | } |
| | | } |
| | | } |
| | | populateLocation(field, name, value) { |
| | | const subFields = ['address', 'lat', 'lng', 'street', 'city', 'province', 'postal_code', 'country']; |
| | | subFields.forEach(subField => { |
| | |
| | | } |
| | | |
| | | const grid = field.querySelector('.item-grid'); |
| | | let uploadContainer = field.querySelector('.file-upload-container'); |
| | | let uploadContainer = field.querySelector('.file-upload-wrapper'); |
| | | uploadContainer.hidden = ids.length > 0; |
| | | field.querySelector('.progress')?.remove(); |
| | | if (grid) { |
| | | window.removeChildren(grid); |
| | | ids.forEach(id => { |
| | | let data = this.data.images[id]??{}; |
| | | data.field = { |
| | | config: { |
| | | showMeta: true |
| | | } |
| | | }; |
| | | data.id = id; |
| | | grid.append(this.templates.create('uploadItem', data)); |
| | | }); |
| | |
| | | for (const m of meta) { |
| | | const input = imageDataField.querySelector(`[data-field="${m}"] input, [data-field="${m}"] textarea`); |
| | | if (input && data[m]!=='') { |
| | | input.value = data[m]; |
| | | input.value = window.decodeHTMLEntities(data[m]); |
| | | } |
| | | } |
| | | } |
| | |
| | | if (!value || !Array.isArray(value) || value.length === 0) return; |
| | | |
| | | let grid = field.querySelector('.item-grid'); |
| | | let uploadContainer = field.querySelector('.file-upload-container'); |
| | | let uploadContainer = field.querySelector('.file-upload-wrapper'); |
| | | uploadContainer.hidden = value.length > 0; |
| | | if (grid) { |
| | | window.removeChildren(grid); |
| | |
| | | } |
| | | return; |
| | | } |
| | | field.querySelectorAll(`[type="checkbox"][name=${name}]`).forEach(checkbox => { |
| | | field.querySelectorAll(`input[type="checkbox"][name="${name}[]"], input[type="checkbox"][name="${name}"]`).forEach(checkbox => { |
| | | checkbox.checked = value.includes(checkbox.value); |
| | | }); |
| | | |
| | |
| | | } |
| | | } |
| | | populateTextarea(field, name, value) { |
| | | let textarea = field.querySelector('textarea'); |
| | | if (!textarea.dataset.editor) { |
| | | this.populateText(field, name, value) |
| | | return; |
| | | let textarea = field.querySelector('textarea[data-editor], textarea'); |
| | | this.populateText(field, name, value); |
| | | |
| | | if (textarea?.dataset.editor) { |
| | | const editor = field.querySelector('.ql-editor'); |
| | | if (editor) { |
| | | editor.innerHTML = value; |
| | | } else { |
| | | textarea.dispatchEvent(new Event('change', { bubbles: true })); |
| | | } |
| | | } |
| | | textarea.value = String(value || ''); |
| | | textarea.dispatchEvent(new Event('change', {bubbles: true})); |
| | | } |
| | | populateText(field, name, value) { |
| | | let input = field.querySelector(`[name="${name}"], input, textarea`); |
| | | if (input && input.type !== 'file') { |
| | | input.value = String(value || ''); |
| | | let input = field.querySelector(`[name="${name}"]`) |
| | | || field.querySelector('textarea[data-editor]') |
| | | || field.querySelector('input:not([type="hidden"]):not([type="file"]), textarea, select'); |
| | | if (input) { |
| | | input.value = window.decodeHTMLEntities(value??''); |
| | | } |
| | | } |
| | | /******************************************************************** |