Plugin Directory

Changeset 3454517


Ignore:
Timestamp:
02/05/2026 11:07:46 AM (5 weeks ago)
Author:
codeandcore
Message:

Added Settings page for better plugin management.

Location:
image-preview-for-acf-field
Files:
32 added
5 edited

Legend:

Unmodified
Added
Removed
  • image-preview-for-acf-field/trunk/assets/js/admin.js

    r3302824 r3454517  
    1 (function($) {
     1(function ($) {
    22    'use strict';
    33
    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    }
    58
    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 () {
    871
    972        // Create modal HTML if it doesn't exist
     
    1780                </div>
    1881            `);
    19             console.log('Image Preview for ACF Field modal HTML added');
    2082        }
    2183
     
    2587        const $modalClose = $modal.find('.image-preview-for-acf-field-modal-close');
    2688
    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();
    3091
    3192        // 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) {
    3394            e.preventDefault();
    34             console.log('Help icon clicked!');
     95            e.stopPropagation();
     96
    3597            const imageUrl = $(this).data('image-url');
    36             console.log('Image URL:', imageUrl);
     98
    3799            if (imageUrl) {
    38100                $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 () {
    41102                    $('body').addClass('image-preview-for-acf-field-modal-open');
    42                     console.log('Modal shown, body class added.');
    43103                });
    44             } else {
    45                 console.log('Image URL is empty, not showing modal.');
    46104            }
    47105        });
     
    49107        // Function to close modal and remove body class
    50108        function close_modal() {
    51             console.log('Closing modal...');
    52             $modal.fadeOut(200, function() {
     109            $modal.fadeOut(200, function () {
    53110                $('body').removeClass('image-preview-for-acf-field-modal-open');
    54111                $modal.removeClass('is-visible');
    55                 console.log('Modal hidden, body class removed.');
    56112            });
    57113        }
    58114
    59         // Handle modal close
     115        // Handle modal close button click
    60116        $modalClose.on('click', close_modal);
    61117
    62118        // Close modal when clicking outside
    63         $(window).on('click', function(e) {
     119        $(window).on('click', function (e) {
    64120            if ($(e.target).is($modal)) {
    65                 console.log('Clicked outside modal');
    66121                close_modal();
    67122            }
     
    69124
    70125        // Close modal on escape key
    71         $(document).on('keydown', function(e) {
     126        $(document).on('keydown', function (e) {
    72127            if (e.key === 'Escape' && $modal.is(':visible')) {
    73                 console.log('Escape key pressed');
    74128                close_modal();
    75129            }
    76130        });
    77131
    78         // Ensure modal is hidden on load (redundant safety check)
     132        // Ensure modal is hidden on load
    79133        $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        }
    81141
    82142    }); // End document ready
    83143
    84 })(jQuery); 
     144})(jQuery);
  • image-preview-for-acf-field/trunk/image-preview-for-acf-field.php

    r3302824 r3454517  
    33 * Plugin Name: Image Preview for ACF Field
    44 * Description: Enhances ACF fields with visual help images that appear in a modal popup when clicking a help icon.
    5  * Version: 1.0.0
     5 * Version: 1.1.0
    66 * Author: Code and Core
    77 * Author URI: https://codeandcore.com/
     
    1717
    1818// Define plugin constants
    19 define('IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_VERSION', '1.0.0');
     19define('IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_VERSION', '1.1.0');
    2020define('IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_PLUGIN_DIR', plugin_dir_path(__FILE__));
    2121define('IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_PLUGIN_URL', plugin_dir_url(__FILE__));
    2222
    2323// Check if ACF is active
    24 function imagprfo_image_preview_for_acf_field_check_acf() {
     24function imagprfo_image_preview_for_acf_field_check_acf()
     25{
    2526    if (!class_exists('ACF')) {
    2627        add_action('admin_notices', 'imagprfo_image_preview_for_acf_field_acf_notice');
     
    3031
    3132// Admin notice if ACF is not active
    32 function imagprfo_image_preview_for_acf_field_acf_notice() {
     33function imagprfo_image_preview_for_acf_field_acf_notice()
     34{
    3335    ?>
    3436    <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>
    3639    </div>
    3740    <?php
     
    4043// Include required files
    4144require_once IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_PLUGIN_DIR . 'includes/class-image-preview-for-acf-field.php';
     45require_once IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_PLUGIN_DIR . 'includes/tracking.php';
     46require_once IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_PLUGIN_DIR . 'includes/settings-page.php';
     47require_once IMAGPRFO_IMAGE_PREVIEW_FOR_ACF_FIELD_PLUGIN_DIR . 'includes/deactivation.php';
    4248
    4349// Initialize the plugin
    44 function imagprfo_image_preview_for_acf_field_init() {
     50function imagprfo_image_preview_for_acf_field_init()
     51{
    4552    if (class_exists('ACF')) {
    4653        new Imagprfo_Image_Preview_For_ACF_Field();
    4754    }
    4855}
    49 add_action('plugins_loaded', 'imagprfo_image_preview_for_acf_field_init');
     56add_action('plugins_loaded', 'imagprfo_image_preview_for_acf_field_init');
     57
     58// Register hooks
     59register_activation_hook(__FILE__, 'imagprfo_plugin_activation');
     60register_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  
    11<?php
     2// Exit if accessed directly
     3if (!defined('ABSPATH')) {
     4    exit;
     5}
    26/**
    37 * Main plugin class
    48 */
    5 class Imagprfo_Image_Preview_For_ACF_Field  {
     9class Imagprfo_Image_Preview_For_ACF_Field
     10{
    611    /**
    712     * Constructor
    813     */
    9     public function __construct() {
     14    public function __construct()
     15    {
    1016        $this->imagprfo_init_hooks();
    1117    }
     
    1420     * Initialize hooks
    1521     */
    16     private function imagprfo_init_hooks() {
     22    private function imagprfo_init_hooks()
     23    {
    1724        // Add field settings
    1825        add_action('acf/render_field_settings', array($this, 'imagprfo_add_field_settings'), 10, 1);
    19        
     26
    2027        // Add field display - Use a filter to modify the field array before rendering
    2128        add_filter('acf/prepare_field', array($this, 'imagprfo_prepare_field_with_help_icon'), 10, 1);
    22        
     29
    2330        // Add admin scripts and styles
    2431        add_action('admin_enqueue_scripts', array($this, 'imagprfo_enqueue_admin_assets'));
     
    2835     * Add field settings
    2936     */
    30     public function imagprfo_add_field_settings($field) {
     37    public function imagprfo_add_field_settings($field)
     38    {
    3139        // Add enable/disable toggle
    3240        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,
    3846        ));
    3947
    4048        // Add image upload field
    4149        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',
    4654            'return_format' => 'array',
    4755            'preview_size' => 'medium',
     
    4957                array(
    5058                    array(
    51                         'field'    => 'enable_preview_image',
     59                        'field' => 'enable_preview_image',
    5260                        'operator' => '==',
    53                         'value'    => '1',
     61                        'value' => '1',
    5462                    ),
    5563                ),
     
    6169     * Prepare field to include help icon in label
    6270     */
    63     public function imagprfo_prepare_field_with_help_icon($field) {
     71    public function imagprfo_prepare_field_with_help_icon($field)
     72    {
    6473        // Check if preview image is enabled and exists
    6574        if (!empty($field['enable_preview_image']) && !empty($field['preview_image'])) {
     
    9099     * Enqueue admin scripts and styles
    91100     */
    92     public function imagprfo_enqueue_admin_assets() {
     101    public function imagprfo_enqueue_admin_assets()
     102    {
    93103        // Load assets on any admin page where ACF is active
    94104        if (is_admin() && class_exists('ACF')) {
     
    110120            wp_localize_script('imagprfo-image-preview-for-acf-field-admin', 'imagprfo_acfImagePreview', array(
    111121                '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'),
    113123            ));
    114124        }
  • image-preview-for-acf-field/trunk/includes/class-image-preview-for-acf-field.php

    r3302824 r3454517  
    11<?php
     2// Exit if accessed directly
     3if (!defined('ABSPATH')) {
     4    exit;
     5}
    26/**
    37 * Main plugin class
    48 */
    5 class Imagprfo_Image_Preview_For_ACF_Field {
     9class Imagprfo_Image_Preview_For_ACF_Field
     10{
    611    /**
    712     * Constructor
    813     */
    9     public function __construct() {
     14    public function __construct()
     15    {
    1016        $this->init_hooks();
    1117    }
     
    1420     * Initialize hooks
    1521     */
    16     private function init_hooks() {
     22    private function init_hooks()
     23    {
    1724        // Add field settings
    1825        add_action('acf/render_field_settings', array($this, 'add_field_settings'), 10, 1);
    19        
     26
    2027        // Add field display - Use a filter to modify the field array before rendering
    2128        add_filter('acf/prepare_field', array($this, 'prepare_field_with_help_icon'), 10, 1);
    22        
     29
    2330        // Add admin scripts and styles
    2431        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
     
    2835     * Add field settings
    2936     */
    30     public function add_field_settings($field) {
     37    public function add_field_settings($field)
     38    {
    3139        // Add enable/disable toggle
    3240        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,
    3846        ));
    3947
    4048        // Add image upload field
    4149        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',
    4654            'return_format' => 'array',
    4755            'preview_size' => 'medium',
     
    4957                array(
    5058                    array(
    51                         'field'    => 'enable_preview_image',
     59                        'field' => 'enable_preview_image',
    5260                        'operator' => '==',
    53                         'value'    => '1',
     61                        'value' => '1',
    5462                    ),
    5563                ),
     
    6169     * Prepare field to include help icon in label
    6270     */
    63     public function prepare_field_with_help_icon($field) {
     71    public function prepare_field_with_help_icon($field)
     72    {
    6473        // Check if preview image is enabled and exists
    6574        if (!empty($field['enable_preview_image']) && !empty($field['preview_image'])) {
     
    7786            }
    7887
    79             // Add help icon to the label if image URL is available
     88            // Add data attributes and class to the wrapper instead of modifying the label directly
    8089            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) . '">&#8505;</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
    83101            }
    84102        }
     
    90108     * Enqueue admin scripts and styles
    91109     */
    92     public function enqueue_admin_assets() {
     110    public function enqueue_admin_assets()
     111    {
    93112        // Load assets on any admin page where ACF is active
    94113        if (is_admin() && class_exists('ACF')) {
     
    110129            wp_localize_script('imagprfo-image-preview-for-acf-field-admin', 'imagprfo_acfImagePreview', array(
    111130                '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'),
    113132            ));
    114133        }
    115134    }
    116 } 
     135}
  • image-preview-for-acf-field/trunk/readme.txt

    r3302831 r3454517  
    33Tags: acf, advanced custom fields, image preview, help images, modal popup
    44Requires at least: 5.0
    5 Tested up to: 6.8
     5Tested up to: 6.9
    66Requires PHP: 7.0
    7 Stable tag: 1.0.0
     7Stable tag: 1.1.0
    88License: GPLv2 or later
    99License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    3737* Advanced Custom Fields (ACF) plugin
    3838
     39= Privacy & Data Collection =
     40
     41**Your Privacy Matters**
     42
     43This 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
     58When 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
    3964== Installation ==
    4065
     
    5681== Changelog ==
    5782
     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
    5890= 1.0.0 =
    5991* Initial release
Note: See TracChangeset for help on using the changeset viewer.