Jake Vanderwerf
2026-01-01 c06013234d16ab3889bd7fce09f6606b45fd2b9f
assets/js/concise/PopulateForm.js
@@ -28,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':
@@ -100,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'
@@ -114,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) {
@@ -138,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
@@ -159,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
@@ -413,76 +419,184 @@
   }
   /**
    * 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');
      fieldWrapper.querySelector('.progress')?.remove();
      if (grid) {
         window.removeChildren(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);
            }
            // 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 = {}) {
   populateRepeaterField(fieldWrapper, fieldName, fieldValue) {
      if (!fieldValue || !Array.isArray(fieldValue)) {
         return;
      }