| | |
| | | $validationAttrs = $this->buildValidationAttributes($field); |
| | | $conditional = array_key_exists('condition', $field) ? $this->handleConditionalField($field) : ''; |
| | | |
| | | $customData = ''; |
| | | if (array_key_exists('data', $field) && !empty($field['data'])) { |
| | | foreach ($field['data'] as $key => $v) { |
| | | $customData .= ($v === '') ? ' data-' . $key : ' data-' . $key . '="' . $v . '"'; |
| | | } |
| | | } |
| | | ?> |
| | | <div class="field <?= esc_attr($field['type']) ?> <?= esc_attr($name) ?>" |
| | | <?= $conditional ?> |
| | |
| | | name="<?= esc_attr($data['name']) ?>" |
| | | value="<?= esc_attr($data['value']) ?>" |
| | | <?= $inputAttrs ?> |
| | | <?= $customData?> |
| | | > |
| | | <span class="validation-icon success" hidden aria-hidden="true"> |
| | | <?= jvbIcon('check-circle') ?> |
| | |
| | | <select |
| | | id="<?= esc_attr($data['id']) ?>" |
| | | name="<?= esc_attr($data['name']) ?>" |
| | | <?= $inputAttrs ?> |
| | | > |
| | | <?= $inputAttrs ?>> |
| | | <?php foreach ($field['options'] as $key => $label) : ?> |
| | | <option value="<?= esc_attr($key) ?>" <?php selected($value, $key); ?>> |
| | | <?= esc_html($label) ?> |
| | |
| | | //Processing Options |
| | | 'max_size' => null, // Override default size limits |
| | | 'convert' => 'webp', // Image conversion format |
| | | 'quality' => 80, // Conversion quality |
| | | 'quality' => 90, // Conversion quality |
| | | 'create_thumbnails' => true, |
| | | ]; |
| | | $config = array_merge($defaultConfig, $field); |
| | |
| | | <?php endif; ?> |
| | | <div class="file-error"></div> |
| | | </div> |
| | | <?php jvbRenderProgressBar(); ?> |
| | | </div> |
| | | |
| | | |
| | |
| | | <div class="selection-controls"> |
| | | <div class="selected"> |
| | | <div class="field"> |
| | | <input type="checkbox" id="select-all-uploads" name="select-all-uploads"> |
| | | <input type="checkbox" id="select-all-uploads" data-select-all data-selects="item-grid" name="select-all-uploads"> |
| | | <label for="select-all-uploads"> |
| | | Select All |
| | | </label> |
| | |
| | | <?php |
| | | } |
| | | |
| | | private function renderExistingAttachment(int $attachmentId, string $subtype): string |
| | | { |
| | | ob_start(); |
| | | |
| | | switch ($subtype) { |
| | | case 'image': |
| | | $this->renderImagePreview($attachmentId); |
| | | break; |
| | | case 'video': |
| | | $this->renderVideoPreview($attachmentId); |
| | | break; |
| | | case 'document': |
| | | case 'file': |
| | | $this->renderFilePreview($attachmentId); |
| | | break; |
| | | default: |
| | | $this->renderImagePreview($attachmentId); |
| | | break; |
| | | } |
| | | |
| | | return ob_get_clean(); |
| | | } |
| | | |
| | | /** |
| | | * Get max file size for subtype |
| | | */ |
| | |
| | | } |
| | | |
| | | ?> |
| | | <div class="field <?= esc_attr($type) ?> <?= esc_attr($name) ?>" |
| | | <div class="field selector <?= esc_attr($type) ?> <?= esc_attr($name) ?>" |
| | | <?= $conditional ?> |
| | | data-field="<?= esc_attr($name) ?>" |
| | | data-type="selector" data-subtype="<?= esc_attr($type)?>" |
| | | <?= $validationAttrs ?> |
| | | <?= $describedBy ?>> |
| | | |
| | |
| | | |
| | | return is_numeric($value) ? [$value] : []; |
| | | } |
| | | /** |
| | | * Render tag list field - inline tag input interface |
| | | */ |
| | | protected function renderTagListField(string $name, mixed $value, array $field): void |
| | | { |
| | | $values = is_array($value) ? $value : []; |
| | | $conditional = $this->handleConditionalField($field); |
| | | $validationAttrs = $this->buildValidationAttributes($field); |
| | | |
| | | if (array_key_exists('group', $field)) { |
| | | $name = $field['group'] . '::' . $name; |
| | | } |
| | | |
| | | $describedBy = (!empty($field['description'])) ? ' aria-describedby="' . $name . '-help"' : ''; |
| | | |
| | | // Tag display format - defaults to first field value |
| | | $tagFormat = $field['tag_format'] ?? 'first_field'; |
| | | ?> |
| | | <div class="field tag-list <?= esc_attr($name) ?>" |
| | | data-field="<?= esc_attr($name) ?>" |
| | | data-tag-format="<?= esc_attr($tagFormat) ?>" |
| | | <?= $describedBy ?> |
| | | <?= $conditional ?> |
| | | <?= $validationAttrs ?>> |
| | | |
| | | <?php if (!empty($field['label'])): ?> |
| | | <h3><?= esc_html($field['label']) ?></h3> |
| | | <?php endif; ?> |
| | | |
| | | <!-- Inline input row --> |
| | | <div class="tag-input-row"> |
| | | <?php foreach ($field['fields'] as $subfield_name => $subfield_config): ?> |
| | | <?php |
| | | $subfield_config['label'] = $subfield_config['label'] ?? ucfirst($subfield_name); |
| | | $input_name = 'new_' . $subfield_name; |
| | | |
| | | // Store required state but don't render it on the input |
| | | // This prevents form submission validation but allows JS validation |
| | | |
| | | if (array_key_exists('required', $subfield_config)) { |
| | | $subfield_config['data']['required'] = true; |
| | | unset($subfield_config['required']); // Remove required for HTML rendering |
| | | } |
| | | $subfield_config['data']['ignore'] = true; |
| | | |
| | | $this->render($input_name, '', $subfield_config, false, false); |
| | | ?> |
| | | <?php endforeach; ?> |
| | | |
| | | <button type="button" class="button add-tag-item"> |
| | | <?= jvbIcon('plus') ?> <?= $field['add_label'] ?? 'Add' ?> |
| | | </button> |
| | | </div> |
| | | |
| | | <!-- Tags display --> |
| | | <div class="tag-items"> |
| | | <?php foreach ($values as $index => $item_data): ?> |
| | | <?php $this->renderTagItem($field['fields'], $item_data, $index, $name, $tagFormat); ?> |
| | | <?php endforeach; ?> |
| | | </div> |
| | | |
| | | <!-- Template for new tags --> |
| | | <template class="tag-template"> |
| | | <?php $this->renderTagItem($field['fields'], [], '', $name, $tagFormat); ?> |
| | | </template> |
| | | |
| | | <?php if (!empty($field['hint'])): ?> |
| | | <?php $this->renderHint($field['hint']); ?> |
| | | <?php endif; ?> |
| | | |
| | | <?php if (!empty($field['description'])): ?> |
| | | <?php $this->renderDescription($field['description'], $name); ?> |
| | | <?php endif; ?> |
| | | </div> |
| | | <?php |
| | | } |
| | | |
| | | /** |
| | | * Render individual tag item |
| | | */ |
| | | protected function renderTagItem(array $fields, array $data, int|string $index, string $base_name, string $format): void |
| | | { |
| | | $tag_text = $this->getTagDisplayText($fields, $data, $format); |
| | | ?> |
| | | <div class="tag-item" data-index="<?= esc_attr($index) ?>"> |
| | | <span class="tag-label"><?= esc_html($tag_text) ?></span> |
| | | |
| | | <!-- Hidden inputs for data --> |
| | | <?php foreach ($fields as $field_name => $field_config): ?> |
| | | <?php |
| | | $value = $data[$field_name] ?? ''; |
| | | $full_name = is_string($index) ? $field_name : "{$base_name}:{$index}:{$field_name}"; |
| | | ?> |
| | | <input type="hidden" |
| | | name="<?= esc_attr($full_name) ?>" |
| | | value="<?= esc_attr($value) ?>" |
| | | data-field="<?= esc_attr($field_name) ?>" /> |
| | | <?php endforeach; ?> |
| | | |
| | | <button type="button" class="remove-tag" aria-label="Remove"> |
| | | <?= jvbIcon('x') ?> |
| | | </button> |
| | | </div> |
| | | <?php |
| | | } |
| | | |
| | | /** |
| | | * Get tag display text based on format |
| | | */ |
| | | protected function getTagDisplayText(array $fields, array $data, string $format): string |
| | | { |
| | | if (empty($data)) { |
| | | return 'New Item'; |
| | | } |
| | | |
| | | switch ($format) { |
| | | case 'first_field': |
| | | // Use the first field's value |
| | | $first_key = array_key_first($fields); |
| | | return $data[$first_key] ?? 'New Item'; |
| | | |
| | | case 'all_fields': |
| | | // Show all field values separated by commas |
| | | $values = array_filter(array_values($data)); |
| | | return implode(', ', $values) ?: 'New Item'; |
| | | |
| | | case 'custom': |
| | | // Custom format - would need callback |
| | | return 'New Item'; |
| | | |
| | | default: |
| | | // Format is a template string like "{name} ({email})" |
| | | if (strpos($format, '{') !== false) { |
| | | $text = $format; |
| | | foreach ($data as $key => $value) { |
| | | $text = str_replace('{' . $key . '}', $value, $text); |
| | | } |
| | | return $text; |
| | | } |
| | | // Use specific field name |
| | | return $data[$format] ?? 'New Item'; |
| | | } |
| | | } |
| | | } |