Changeset 3454517
- Timestamp:
- 02/05/2026 11:07:46 AM (5 weeks ago)
- Location:
- image-preview-for-acf-field
- Files:
-
- 32 added
- 5 edited
-
tags/1.1.0 (added)
-
tags/1.1.0/assets (added)
-
tags/1.1.0/assets/css (added)
-
tags/1.1.0/assets/css/admin.css (added)
-
tags/1.1.0/assets/css/deactivation.css (added)
-
tags/1.1.0/assets/css/settings.css (added)
-
tags/1.1.0/assets/images (added)
-
tags/1.1.0/assets/images/code-and-core-remove-empty-p-tags.png (added)
-
tags/1.1.0/assets/images/speedy-go.gif (added)
-
tags/1.1.0/assets/js (added)
-
tags/1.1.0/assets/js/admin.js (added)
-
tags/1.1.0/assets/js/deactivation.js (added)
-
tags/1.1.0/assets/js/settings.js (added)
-
tags/1.1.0/image-preview-for-acf-field.php (added)
-
tags/1.1.0/includes (added)
-
tags/1.1.0/includes/class-acf-image-preview.php (added)
-
tags/1.1.0/includes/class-image-preview-for-acf-field.php (added)
-
tags/1.1.0/includes/deactivation.php (added)
-
tags/1.1.0/includes/settings-page.php (added)
-
tags/1.1.0/includes/tracking.php (added)
-
tags/1.1.0/readme.txt (added)
-
tags/1.1.0/uninstall.php (added)
-
trunk/assets/css/deactivation.css (added)
-
trunk/assets/css/settings.css (added)
-
trunk/assets/images (added)
-
trunk/assets/images/code-and-core-remove-empty-p-tags.png (added)
-
trunk/assets/images/speedy-go.gif (added)
-
trunk/assets/js/admin.js (modified) (5 diffs)
-
trunk/assets/js/deactivation.js (added)
-
trunk/assets/js/settings.js (added)
-
trunk/image-preview-for-acf-field.php (modified) (4 diffs)
-
trunk/includes/class-acf-image-preview.php (modified) (7 diffs)
-
trunk/includes/class-image-preview-for-acf-field.php (modified) (8 diffs)
-
trunk/includes/deactivation.php (added)
-
trunk/includes/settings-page.php (added)
-
trunk/includes/tracking.php (added)
-
trunk/readme.txt (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
image-preview-for-acf-field/trunk/assets/js/admin.js
r3302824 r3454517 1 (function ($) {1 (function ($) { 2 2 'use strict'; 3 3 4 console.log('Image Preview for ACF Field admin.js loaded'); 4 // Helper to create icon HTML 5 function create_icon_html(id, url) { 6 return '<span class="image-preview-for-acf-field-help" data-image-id="' + id + '" data-image-url="' + url + '">ℹ</span>'; 7 } 5 8 6 $(document).ready(function() { 7 console.log('Document ready.'); 9 // Function to inject help icons 10 function inject_help_icons() { 11 $('.acf-field-with-image-preview').each(function () { 12 var $field = $(this); 13 var imageId = $field.data('preview-image-id'); 14 var imageUrl = $field.data('preview-image-url'); 15 16 if (!imageUrl) return; 17 18 // Scenario 1: Standard Field (Label is inside the field wrapper) 19 var $label = $field.find('.acf-label label'); 20 if ($label.length) { 21 // Check if icon is already added to avoid duplicates in this specific label 22 if ($label.find('.image-preview-for-acf-field-help').length === 0) { 23 $label.append(create_icon_html(imageId, imageUrl)); 24 } 25 } 26 // Scenario 2: Repeater Table View (Field is a TD, Label is in the Table Header) 27 else if ($field.is('td')) { 28 // Prefer the robust key we added, fallback to standard key 29 var key = $field.data('field-key') || $field.data('key'); 30 var $table = $field.closest('.acf-table'); 31 32 if (key && $table.length) { 33 // Find the corresponding header 34 var $th = $table.find('thead th[data-key="' + key + '"]'); 35 36 if ($th.length) { 37 // Try to find the best place to append the icon 38 // Priority 1: Label inside .acf-label (Standard ACF) 39 var $target = $th.find('.acf-label label'); 40 41 // Priority 2: .acf-label container itself 42 if ($target.length === 0) { 43 $target = $th.find('.acf-label'); 44 } 45 46 // Priority 3: A span (Common in some older ACF versions or modified headers) 47 if ($target.length === 0) { 48 $target = $th.find('span').first(); 49 } 50 51 // Priority 4: The TH itself (Last resort) 52 if ($target.length === 0) { 53 $target = $th; 54 } 55 56 // If we found a place to append 57 if ($target.length) { 58 // Check if icon is already in the header to prevent duplicates 59 // We check the target AND the whole TH to be safe 60 if ($th.find('.image-preview-for-acf-field-help').length === 0) { 61 $target.append(create_icon_html(imageId, imageUrl)); 62 } 63 } 64 } 65 } 66 } 67 }); 68 } 69 70 $(document).ready(function () { 8 71 9 72 // Create modal HTML if it doesn't exist … … 17 80 </div> 18 81 `); 19 console.log('Image Preview for ACF Field modal HTML added');20 82 } 21 83 … … 25 87 const $modalClose = $modal.find('.image-preview-for-acf-field-modal-close'); 26 88 27 console.log('Modal element found:', $modal.length > 0); 28 console.log('Modal image element found:', $modalImage.length > 0); 29 console.log('Modal close element found:', $modalClose.length > 0); 89 // Initial injection 90 inject_help_icons(); 30 91 31 92 // Handle help icon click 32 $(document).on('click', '.image-preview-for-acf-field-help', function (e) {93 $(document).on('click', '.image-preview-for-acf-field-help', function (e) { 33 94 e.preventDefault(); 34 console.log('Help icon clicked!'); 95 e.stopPropagation(); 96 35 97 const imageUrl = $(this).data('image-url'); 36 console.log('Image URL:', imageUrl); 98 37 99 if (imageUrl) { 38 100 $modalImage.attr('src', imageUrl); 39 console.log('Attempting to show modal...'); 40 $modal.addClass('is-visible').fadeIn(200, function() { 101 $modal.addClass('is-visible').fadeIn(200, function () { 41 102 $('body').addClass('image-preview-for-acf-field-modal-open'); 42 console.log('Modal shown, body class added.');43 103 }); 44 } else {45 console.log('Image URL is empty, not showing modal.');46 104 } 47 105 }); … … 49 107 // Function to close modal and remove body class 50 108 function close_modal() { 51 console.log('Closing modal...'); 52 $modal.fadeOut(200, function() { 109 $modal.fadeOut(200, function () { 53 110 $('body').removeClass('image-preview-for-acf-field-modal-open'); 54 111 $modal.removeClass('is-visible'); 55 console.log('Modal hidden, body class removed.');56 112 }); 57 113 } 58 114 59 // Handle modal close 115 // Handle modal close button click 60 116 $modalClose.on('click', close_modal); 61 117 62 118 // Close modal when clicking outside 63 $(window).on('click', function (e) {119 $(window).on('click', function (e) { 64 120 if ($(e.target).is($modal)) { 65 console.log('Clicked outside modal');66 121 close_modal(); 67 122 } … … 69 124 70 125 // Close modal on escape key 71 $(document).on('keydown', function (e) {126 $(document).on('keydown', function (e) { 72 127 if (e.key === 'Escape' && $modal.is(':visible')) { 73 console.log('Escape key pressed');74 128 close_modal(); 75 129 } 76 130 }); 77 131 78 // Ensure modal is hidden on load (redundant safety check)132 // Ensure modal is hidden on load 79 133 $modal.removeClass('is-visible').hide(); 80 console.log('Initial modal state set to hidden.'); 134 135 // Hook into ACF append action (for repeater fields, etc.) 136 if (typeof acf !== 'undefined') { 137 acf.addAction('append', function ($el) { 138 inject_help_icons(); 139 }); 140 } 81 141 82 142 }); // End document ready 83 143 84 })(jQuery); 144 })(jQuery); -
image-preview-for-acf-field/trunk/image-preview-for-acf-field.php
r3302824 r3454517 3 3 * Plugin Name: Image Preview for ACF Field 4 4 * Description: Enhances ACF fields with visual help images that appear in a modal popup when clicking a help icon. 5 * Version: 1. 0.05 * Version: 1.1.0 6 6 * Author: Code and Core 7 7 * Author URI: https://codeandcore.com/ … … 17 17 18 18 // Define plugin constants 19 define('IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_VERSION', '1. 0.0');19 define('IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_VERSION', '1.1.0'); 20 20 define('IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_PLUGIN_DIR', plugin_dir_path(__FILE__)); 21 21 define('IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_PLUGIN_URL', plugin_dir_url(__FILE__)); 22 22 23 23 // Check if ACF is active 24 function imagprfo_image_preview_for_acf_field_check_acf() { 24 function imagprfo_image_preview_for_acf_field_check_acf() 25 { 25 26 if (!class_exists('ACF')) { 26 27 add_action('admin_notices', 'imagprfo_image_preview_for_acf_field_acf_notice'); … … 30 31 31 32 // Admin notice if ACF is not active 32 function imagprfo_image_preview_for_acf_field_acf_notice() { 33 function imagprfo_image_preview_for_acf_field_acf_notice() 34 { 33 35 ?> 34 36 <div class="notice notice-error"> 35 <p><?php esc_html_e('Image Preview for ACF Field requires Advanced Custom Fields to be installed and activated.', 'image-preview-for-acf-field'); ?></p> 37 <p><?php esc_html_e('Image Preview for ACF Field requires Advanced Custom Fields to be installed and activated.', 'image-preview-for-acf-field'); ?> 38 </p> 36 39 </div> 37 40 <?php … … 40 43 // Include required files 41 44 require_once IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_PLUGIN_DIR . 'includes/class-image-preview-for-acf-field.php'; 45 require_once IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_PLUGIN_DIR . 'includes/tracking.php'; 46 require_once IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_PLUGIN_DIR . 'includes/settings-page.php'; 47 require_once IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_PLUGIN_DIR . 'includes/deactivation.php'; 42 48 43 49 // Initialize the plugin 44 function imagprfo_image_preview_for_acf_field_init() { 50 function imagprfo_image_preview_for_acf_field_init() 51 { 45 52 if (class_exists('ACF')) { 46 53 new Imagprfo_Image_Preview_For_ACF_Field(); 47 54 } 48 55 } 49 add_action('plugins_loaded', 'imagprfo_image_preview_for_acf_field_init'); 56 add_action('plugins_loaded', 'imagprfo_image_preview_for_acf_field_init'); 57 58 // Register hooks 59 register_activation_hook(__FILE__, 'imagprfo_plugin_activation'); 60 register_deactivation_hook(__FILE__, 'imagprfo_plugin_deactivation'); 61 // Note: Uninstall hook is best handled via uninstall.php or verified callback availability -
image-preview-for-acf-field/trunk/includes/class-acf-image-preview.php
r3302824 r3454517 1 1 <?php 2 // Exit if accessed directly 3 if (!defined('ABSPATH')) { 4 exit; 5 } 2 6 /** 3 7 * Main plugin class 4 8 */ 5 class Imagprfo_Image_Preview_For_ACF_Field { 9 class Imagprfo_Image_Preview_For_ACF_Field 10 { 6 11 /** 7 12 * Constructor 8 13 */ 9 public function __construct() { 14 public function __construct() 15 { 10 16 $this->imagprfo_init_hooks(); 11 17 } … … 14 20 * Initialize hooks 15 21 */ 16 private function imagprfo_init_hooks() { 22 private function imagprfo_init_hooks() 23 { 17 24 // Add field settings 18 25 add_action('acf/render_field_settings', array($this, 'imagprfo_add_field_settings'), 10, 1); 19 26 20 27 // Add field display - Use a filter to modify the field array before rendering 21 28 add_filter('acf/prepare_field', array($this, 'imagprfo_prepare_field_with_help_icon'), 10, 1); 22 29 23 30 // Add admin scripts and styles 24 31 add_action('admin_enqueue_scripts', array($this, 'imagprfo_enqueue_admin_assets')); … … 28 35 * Add field settings 29 36 */ 30 public function imagprfo_add_field_settings($field) { 37 public function imagprfo_add_field_settings($field) 38 { 31 39 // Add enable/disable toggle 32 40 acf_render_field_setting($field, array( 33 'label' => __('Enable Preview Image', 'image-preview-for-acf-field'),34 'instructions' => __('Enable to add a help image for this field', 'image-preview-for-acf-field'),35 'name' => 'enable_preview_image',36 'type' => 'true_false',37 'ui' => 1,41 'label' => __('Enable Preview Image', 'image-preview-for-acf-field'), 42 'instructions' => __('Enable to add a help image for this field', 'image-preview-for-acf-field'), 43 'name' => 'enable_preview_image', 44 'type' => 'true_false', 45 'ui' => 1, 38 46 )); 39 47 40 48 // Add image upload field 41 49 acf_render_field_setting($field, array( 42 'label' => __('Preview Image', 'image-preview-for-acf-field'),43 'instructions' => __('Upload an image to show as help/preview', 'image-preview-for-acf-field'),44 'name' => 'preview_image',45 'type' => 'image',50 'label' => __('Preview Image', 'image-preview-for-acf-field'), 51 'instructions' => __('Upload an image to show as help/preview', 'image-preview-for-acf-field'), 52 'name' => 'preview_image', 53 'type' => 'image', 46 54 'return_format' => 'array', 47 55 'preview_size' => 'medium', … … 49 57 array( 50 58 array( 51 'field' => 'enable_preview_image',59 'field' => 'enable_preview_image', 52 60 'operator' => '==', 53 'value' => '1',61 'value' => '1', 54 62 ), 55 63 ), … … 61 69 * Prepare field to include help icon in label 62 70 */ 63 public function imagprfo_prepare_field_with_help_icon($field) { 71 public function imagprfo_prepare_field_with_help_icon($field) 72 { 64 73 // Check if preview image is enabled and exists 65 74 if (!empty($field['enable_preview_image']) && !empty($field['preview_image'])) { … … 90 99 * Enqueue admin scripts and styles 91 100 */ 92 public function imagprfo_enqueue_admin_assets() { 101 public function imagprfo_enqueue_admin_assets() 102 { 93 103 // Load assets on any admin page where ACF is active 94 104 if (is_admin() && class_exists('ACF')) { … … 110 120 wp_localize_script('imagprfo-image-preview-for-acf-field-admin', 'imagprfo_acfImagePreview', array( 111 121 'ajaxurl' => admin_url('admin-ajax.php'), 112 'nonce' => wp_create_nonce('image_preview_for_acf_field_nonce'),122 'nonce' => wp_create_nonce('image_preview_for_acf_field_nonce'), 113 123 )); 114 124 } -
image-preview-for-acf-field/trunk/includes/class-image-preview-for-acf-field.php
r3302824 r3454517 1 1 <?php 2 // Exit if accessed directly 3 if (!defined('ABSPATH')) { 4 exit; 5 } 2 6 /** 3 7 * Main plugin class 4 8 */ 5 class Imagprfo_Image_Preview_For_ACF_Field { 9 class Imagprfo_Image_Preview_For_ACF_Field 10 { 6 11 /** 7 12 * Constructor 8 13 */ 9 public function __construct() { 14 public function __construct() 15 { 10 16 $this->init_hooks(); 11 17 } … … 14 20 * Initialize hooks 15 21 */ 16 private function init_hooks() { 22 private function init_hooks() 23 { 17 24 // Add field settings 18 25 add_action('acf/render_field_settings', array($this, 'add_field_settings'), 10, 1); 19 26 20 27 // Add field display - Use a filter to modify the field array before rendering 21 28 add_filter('acf/prepare_field', array($this, 'prepare_field_with_help_icon'), 10, 1); 22 29 23 30 // Add admin scripts and styles 24 31 add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets')); … … 28 35 * Add field settings 29 36 */ 30 public function add_field_settings($field) { 37 public function add_field_settings($field) 38 { 31 39 // Add enable/disable toggle 32 40 acf_render_field_setting($field, array( 33 'label' => __('Enable Preview Image', 'image-preview-for-acf-field'),34 'instructions' => __('Enable to add a help image for this field', 'image-preview-for-acf-field'),35 'name' => 'enable_preview_image',36 'type' => 'true_false',37 'ui' => 1,41 'label' => __('Enable Preview Image', 'image-preview-for-acf-field'), 42 'instructions' => __('Enable to add a help image for this field', 'image-preview-for-acf-field'), 43 'name' => 'enable_preview_image', 44 'type' => 'true_false', 45 'ui' => 1, 38 46 )); 39 47 40 48 // Add image upload field 41 49 acf_render_field_setting($field, array( 42 'label' => __('Preview Image', 'image-preview-for-acf-field'),43 'instructions' => __('Upload an image to show as help/preview', 'image-preview-for-acf-field'),44 'name' => 'preview_image',45 'type' => 'image',50 'label' => __('Preview Image', 'image-preview-for-acf-field'), 51 'instructions' => __('Upload an image to show as help/preview', 'image-preview-for-acf-field'), 52 'name' => 'preview_image', 53 'type' => 'image', 46 54 'return_format' => 'array', 47 55 'preview_size' => 'medium', … … 49 57 array( 50 58 array( 51 'field' => 'enable_preview_image',59 'field' => 'enable_preview_image', 52 60 'operator' => '==', 53 'value' => '1',61 'value' => '1', 54 62 ), 55 63 ), … … 61 69 * Prepare field to include help icon in label 62 70 */ 63 public function prepare_field_with_help_icon($field) { 71 public function prepare_field_with_help_icon($field) 72 { 64 73 // Check if preview image is enabled and exists 65 74 if (!empty($field['enable_preview_image']) && !empty($field['preview_image'])) { … … 77 86 } 78 87 79 // Add help icon to the label if image URL is available88 // Add data attributes and class to the wrapper instead of modifying the label directly 80 89 if (!empty($image_url)) { 81 $help_icon_html = '<span class="image-preview-for-acf-field-help" data-image-id="' . esc_attr($image_id) . '" data-image-url="' . esc_url($image_url) . '">ℹ</span>'; 82 $field['label'] .= $help_icon_html; 90 if (empty($field['wrapper'])) { 91 $field['wrapper'] = array(); 92 } 93 if (empty($field['wrapper']['class'])) { 94 $field['wrapper']['class'] = ''; 95 } 96 97 $field['wrapper']['class'] .= ' acf-field-with-image-preview'; 98 $field['wrapper']['data-preview-image-id'] = esc_attr($image_id); 99 $field['wrapper']['data-preview-image-url'] = esc_url($image_url); 100 $field['wrapper']['data-field-key'] = esc_attr($field['key']); // Explicitly pass key for JS lookup 83 101 } 84 102 } … … 90 108 * Enqueue admin scripts and styles 91 109 */ 92 public function enqueue_admin_assets() { 110 public function enqueue_admin_assets() 111 { 93 112 // Load assets on any admin page where ACF is active 94 113 if (is_admin() && class_exists('ACF')) { … … 110 129 wp_localize_script('imagprfo-image-preview-for-acf-field-admin', 'imagprfo_acfImagePreview', array( 111 130 'ajaxurl' => admin_url('admin-ajax.php'), 112 'nonce' => wp_create_nonce('image_preview_for_acf_field_nonce'),131 'nonce' => wp_create_nonce('image_preview_for_acf_field_nonce'), 113 132 )); 114 133 } 115 134 } 116 } 135 } -
image-preview-for-acf-field/trunk/readme.txt
r3302831 r3454517 3 3 Tags: acf, advanced custom fields, image preview, help images, modal popup 4 4 Requires at least: 5.0 5 Tested up to: 6. 85 Tested up to: 6.9 6 6 Requires PHP: 7.0 7 Stable tag: 1. 0.07 Stable tag: 1.1.0 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 37 37 * Advanced Custom Fields (ACF) plugin 38 38 39 = Privacy & Data Collection = 40 41 **Your Privacy Matters** 42 43 This plugin respects your privacy and operates with full transparency: 44 45 * **No Automatic Data Collection** - The plugin does not collect or transmit any data without your explicit consent 46 * **Opt-In Telemetry** - You can optionally enable anonymous usage tracking from Settings > ACF WYSIWYG Limit to help improve the plugin 47 * **Deactivation Feedback** - When deactivating, you can choose to share feedback to help us improve. This is completely optional 48 * **No Personal Content** - We never collect your post content, user passwords, or sensitive information 49 * **What We Collect (Only if you opt-in)**: 50 - Plugin version and settings 51 - WordPress and PHP versions 52 - Theme information 53 - Site language and multisite status 54 - Anonymous site URL (for duplicate detection only) 55 56 **Deactivation Feedback** 57 58 When you deactivate the plugin, a feedback modal appears asking for your reason. This helps us improve the plugin: 59 60 * **Completely Optional** - You can skip and deactivate immediately 61 * **Contact Consent** - Check the consent box only if you want us to follow up with support 62 * **Your Choice** - Your name and email are only sent if you check the consent checkbox 63 39 64 == Installation == 40 65 … … 56 81 == Changelog == 57 82 83 = 1.1.0 = 84 * New: Added Settings page for better plugin management. 85 * New: Added Tracking system to understand plugin usage (opt-in). 86 * New: Added Deactivation feedback popup to gather user feedback. 87 * Enhancement: Improved UI/UX for settings page. 88 * Fix: Minor bug fixes and improvements. 89 58 90 = 1.0.0 = 59 91 * Initial release
Note: See TracChangeset
for help on using the changeset viewer.