From afdc1b396e3e88146006cd707a15b9da4843e1c2 Mon Sep 17 00:00:00 2001
From: Jake Vanderwerf <get@jakevanderwerf.ca>
Date: Sun, 04 Jan 2026 18:34:21 +0000
Subject: [PATCH] Merge branch 'main' of https://github.com/jakevdwerf/jvb
---
assets/js/concise/PopulateForm.js | 235 +++++++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 175 insertions(+), 60 deletions(-)
diff --git a/assets/js/concise/PopulateForm.js b/assets/js/concise/PopulateForm.js
index 4a56a10..f9335db 100644
--- a/assets/js/concise/PopulateForm.js
+++ b/assets/js/concise/PopulateForm.js
@@ -3,10 +3,6 @@
**********************************************/
class PopulateForm {
constructor(form, fieldData = {}, imageData = {}, options = {}) {
- console.log('Populating field... ', form);
- console.log('fieldData: ', fieldData);
- console.log('imageData: ', imageData);
- console.log('options: ', options);
for (let [fieldName, fieldValue] of Object.entries(fieldData)) {
let wrapper = form.querySelector(`[data-field="${fieldName}"]`);
if (wrapper) {
@@ -32,12 +28,10 @@
const fieldType = this.getFieldType(fieldWrapper);
switch (fieldType) {
- case 'image':
- this.populateImageField(fieldWrapper, fieldName, fieldValue, imagesData);
- break;
-
+ case 'upload':
case 'gallery':
- this.populateGalleryField(fieldWrapper, fieldName, fieldValue, imagesData);
+ case 'image':
+ this.populateUploadField(fieldWrapper, fieldName, fieldValue, imagesData);
break;
case 'repeater':
@@ -104,9 +98,18 @@
* @returns {string} Field type
*/
getFieldType(fieldWrapper) {
+ // Check dataset first (most reliable for our use case)
+ if (fieldWrapper.dataset.fieldType) {
+ return fieldWrapper.dataset.fieldType;
+ }
+
+ if (fieldWrapper.dataset.type) {
+ return fieldWrapper.dataset.type;
+ }
+
// Check for specific field classes
const typeClasses = [
- 'image', 'gallery', 'repeater', 'taxonomy', 'user', 'location',
+ 'upload', 'repeater', 'taxonomy', 'user', 'location',
'set', 'checkbox', 'select', 'radio', 'true_false', 'date',
'time', 'datetime', 'editor', 'number', 'text', 'textarea',
'email', 'url', 'tel', 'phone'
@@ -118,11 +121,6 @@
}
}
- // Check for data attribute
- if (fieldWrapper.dataset.type) {
- return fieldWrapper.dataset.type;
- }
-
// Check input type
const input = fieldWrapper.querySelector('input, select, textarea');
if (input) {
@@ -142,7 +140,12 @@
*/
populateTextField(fieldWrapper, fieldName, fieldValue) {
const input = fieldWrapper.querySelector(`[name="${fieldName}"], input, textarea`);
+ // Skip file inputs - browsers don't allow setting their values programmatically
+ if (input && input.type === 'file') {
+ return;
+ }
if (input) {
+
input.value = String(fieldValue || '');
// Update character counter if present
@@ -163,7 +166,6 @@
fieldWrapper.querySelector('textarea:not([data-editor="true"])');
if (textarea) {
- const oldValue = textarea.value;
textarea.value = String(fieldValue || '');
// Trigger change event to update any dependencies
@@ -389,7 +391,8 @@
} else if (typeof fieldValue === 'string') {
try {
const parsed = JSON.parse(fieldValue);
- termIds = Array.isArray(parsed) ? parsed.map(v => String(v)) : [String(parsed)];
+ termIds = Array.isArray(parsed) ?
+ parsed.map(v => String(v)) : [String(parsed)];
} catch (e) {
termIds = fieldValue.split(',').map(v => v.trim());
}
@@ -405,6 +408,12 @@
const hiddenInput = fieldWrapper.querySelector(`input[type="hidden"][name="${fieldName}"]`);
if (hiddenInput) {
hiddenInput.value = termIds.join(',');
+
+ // Trigger TaxonomySelector to update visual display
+ const toggle = fieldWrapper.querySelector('.taxonomy-toggle');
+ if (toggle && toggle.dataset.fieldId && window.jvbTaxonomy) {
+ window.jvbTaxonomy.updateFieldFromInput(toggle.dataset.fieldId);
+ }
}
}
@@ -417,80 +426,186 @@
}
/**
- * Populate image fields
+ * Populate upload fields (images, videos, files)
*/
- populateImageField(fieldWrapper, fieldName, fieldValue, imagesData = {}) {
+ populateUploadField(fieldWrapper, fieldName, fieldValue, imagesData = {}) {
+ // Check if this is a timeline gallery
+ const isTimeline = fieldWrapper.dataset.subtype === 'timeline' || fieldName === 'timeline';
+
+ if (isTimeline) {
+ this.populateTimelineGallery(fieldWrapper, fieldName, fieldValue, imagesData);
+ return;
+ }
+
if (!fieldValue) {
return;
}
// Handle comma-separated IDs or single ID
- const imageIds = String(fieldValue).split(',').filter(id => parseInt(id.trim()));
- if (imageIds.length === 0) {
+ const itemIds = String(fieldValue).split(',').filter(id => parseInt(id.trim()));
+ if (itemIds.length === 0) {
return;
}
// Update hidden input
const hiddenInput = fieldWrapper.querySelector(`input[type="hidden"][name="${fieldName}"]`);
if (hiddenInput) {
- hiddenInput.value = imageIds.join(',');
+ hiddenInput.value = itemIds.join(',');
}
- // Update image display
+ // Update display grid
+ const grid = fieldWrapper.querySelector('.item-grid');
+ const uploadContainer = fieldWrapper.querySelector('.file-upload-container');
+
+ // Clear existing items first
+ if (grid) {
+ window.removeChildren(grid);
+ }
+
+ fieldWrapper.querySelector('.progress')?.remove();
+
+ if (grid) {
+ itemIds.forEach(itemId => {
+ const template = window.getTemplate('uploadItem');
+
+ if (!template) {
+ console.warn('uploadItem template not found');
+ return;
+ }
+
+ let input = template.querySelector('input[name="select-item"]');
+ let label = template.querySelector('label[for="select-item"]');
+
+ template.dataset.id = itemId;
+ input.name = input.name + `-${itemId}`;
+ input.id = input.name;
+ label.htmlFor = input.name;
+
+ const img = template.querySelector('img');
+ template.querySelector('video')?.remove();
+ const details = template.querySelector('details');
+
+ // Populate with data
+ if (imagesData[itemId]) {
+ const data = imagesData[itemId];
+ if (img) {
+ img.src = data.medium || data.small || data.large || '';
+ img.alt = data['image-alt-text'] || data.alt || '';
+ }
+
+ // Populate metadata fields
+ const titleInput = template.querySelector('[name="image-title"]');
+ const altInput = template.querySelector('[name="image-alt-text"]');
+ const captionInput = template.querySelector('[name="image-caption"]');
+
+ if (titleInput) titleInput.value = data['image-title'] || data.title || '';
+ if (altInput) altInput.value = data['image-alt-text'] || data.alt || '';
+ if (captionInput) captionInput.value = data['image-caption'] || data.caption || '';
+ } else {
+ console.warn('No image data found for ID:', itemId, 'Available data:', Object.keys(imagesData));
+ }
+
+ // Remove hint if present
+ details?.querySelector('.upload-meta > .hint')?.remove();
+
+ grid.append(template);
+ });
+
+ // Hide upload container if items exist
+ if (itemIds.length > 0 && uploadContainer) {
+ uploadContainer.hidden = true;
+ }
+ }
+ }
+
+ populateTimelineGallery(fieldWrapper, fieldName, fieldValue, imagesData) {
+ console.log('populating Timeline Gallery');
+ if (!fieldValue || typeof fieldValue !== 'object') {
+ return;
+ }
+
+ const imageIds = Object.values(fieldValue);
+ if (imageIds.length === 0) {
+ return;
+ }
+
+ // Update display
const grid = fieldWrapper.querySelector('.item-grid');
const uploadContainer = fieldWrapper.querySelector('.file-upload-container');
fieldWrapper.querySelector('.progress')?.remove();
+
if (grid) {
window.removeChildren(grid);
- imageIds.forEach(imageId => {
- let image = window.getTemplate('uploadItem');
- let img = image.querySelector('img');
+ console.log(imageIds);
+ for (let data of Object.entries(fieldValue)) {
+ let imageId = data['post_thumbnail'];
+ const template = window.getTemplate('timelineItem');
+ if (!template) return;
- let details = image.querySelector('details');
- let meta = window.getTemplate('uploadMeta')
- details.append(meta);
- [
- img.src,
- img.alt,
- image.querySelector('[name="image-title"]').value,
- image.querySelector('[name="image-alt-text"]').value,
- image.querySelector('[name="image-caption"]').value,
- ] = [
- imagesData[imageId].medium,
- imagesData[imageId].alt,
- imagesData[imageId].title,
- imagesData[imageId].alt,
- imagesData[imageId].caption,
- ];
+ const img = template.querySelector('img');
- details.querySelector('.upload-meta > .hint')?.remove();
+ // Remove unnecessary elements
+ template.querySelector('video')?.remove();
+ template.querySelector('.select-item span')?.remove();
- grid.append(image);
- });
+ let input = template.querySelector('input[name="select-item"]');
+ let label = template.querySelector('label[for="select-item"]');
+ template.dataset.id = imageId;
+ template.dataset.postId = data.id;
+ input.name = input.name + `-${imageId}`;
+ input.id = input.name;
+ label.htmlFor = input.name;
- if (imageIds.length > 0) {
- if (uploadContainer) {
- uploadContainer.hidden = true;
+ const imgData = imagesData[imageId];
+
+ // Set image source
+ if (img && imgData) {
+ img.src = imgData.medium || imgData.small || imgData.large || '';
+ img.title = imgData['image-title'];
}
+
+ // Merge data
+ const mergedData = { ...data, ...imgData };
+
+ // Populate fields
+ const fields = template.querySelectorAll('.field');
+ fields.forEach(field => {
+ if (field.classList.contains('group')) {
+ return;
+ }
+
+ const input = field.querySelector('input:not([type="file"]), textarea');
+ if (!input) return;
+
+ const label = field.querySelector('label');
+ const name = input.name.replace('upload_data::', '');
+ const value = mergedData[name];
+
+ // Populate the field
+ this.populateField(field, name, value, imagesData);
+
+ // Update field identifiers
+ const id = data.id;
+ const newName = `[${id}]${name}`;
+ input.name = newName;
+ input.id = newName;
+ if (label) label.htmlFor = newName;
+ });
+
+ grid.append(template);
+ }
+
+ // Hide upload container if items exist
+ if (imageIds.length > 0 && uploadContainer) {
+ uploadContainer.hidden = true;
}
}
}
/**
- * Populate gallery fields
- */
- populateGalleryField(fieldWrapper, fieldName, fieldValue, imagesData = {}) {
- this.populateImageField(fieldWrapper, fieldName, fieldValue, imagesData);
- }
-
- /**
* Populate repeater fields
*/
- populateRepeaterField(fieldWrapper, fieldName, fieldValue, options = {}) {
- console.log('fieldWrapper', fieldWrapper);
- console.log('fieldName', fieldName);
- console.log('fieldValue', fieldValue);
- console.log('options', options);
+ populateRepeaterField(fieldWrapper, fieldName, fieldValue) {
if (!fieldValue || !Array.isArray(fieldValue)) {
return;
}
--
Gitblit v1.10.0