Plugin Directory

Changeset 3452499


Ignore:
Timestamp:
02/03/2026 01:49:05 AM (2 months ago)
Author:
optimal360
Message:

Version 1.1.3 (divi 4.x update)

Location:
optimal-360
Files:
22 added
4 edited

Legend:

Unmodified
Added
Removed
  • optimal-360/trunk/assets/divi-builder.js

    r3452427 r3452499  
    33
    44    var modalOpen = false;
    5     var currentModuleAddress = null;
     5    var DEBUG = typeof optimal360Divi !== 'undefined' && optimal360Divi.debug;
     6
     7    function log() {
     8        if (DEBUG && console && console.log) {
     9            console.log.apply(console, ['[Optimal360 Divi]'].concat(Array.prototype.slice.call(arguments)));
     10        }
     11    }
    612
    713    function sanitizeUUID(uuid) {
     
    1622    }
    1723
    18     function sanitizeStatus(status) {
    19         if (typeof status !== 'string') return 'unknown';
    20         var validStatuses = ['active', 'inactive', 'pending', 'processing', 'published', 'draft'];
    21         return validStatuses.includes(status.toLowerCase()) ? status.toLowerCase() : 'unknown';
    22     }
    23 
    2424    function handleMessage(event) {
    2525        if (event.origin !== 'https://app.optml360.com') {
     
    3030            var sanitizedUUID = sanitizeUUID(event.data.projectuuid);
    3131            var sanitizedName = sanitizeFriendlyName(event.data.friendlyname);
    32             var sanitizedStatus = sanitizeStatus(event.data.status);
    33 
    34             if (!sanitizedUUID || !sanitizedName) {
     32
     33            if (!sanitizedUUID) {
    3534                console.error('Invalid project data received');
    3635                return;
    3736            }
    3837
    39             // Update Divi module settings using ETBuilderBackend or visual builder API
    40             if (typeof ET_Builder !== 'undefined' && currentModuleAddress) {
    41                 // Visual Builder - update the module props
    42                 if (typeof ETBuilderBackend !== 'undefined' && ETBuilderBackend.currentPage) {
    43                     var moduleData = ET_Builder.Frames.app.getModuleByAddress(currentModuleAddress);
    44                     if (moduleData) {
    45                         moduleData.set('project_uuid', sanitizedUUID);
    46                         moduleData.set('project_name', sanitizedName);
    47                     }
    48                 }
    49             }
    50 
    51             // Update hidden inputs if in classic builder
    52             var $projectUuidInput = $('input[data-saved-value][id*="project_uuid"]');
    53             var $projectNameInput = $('input[data-saved-value][id*="project_name"]');
    54            
    55             if ($projectUuidInput.length) {
    56                 $projectUuidInput.val(sanitizedUUID).trigger('change');
    57             }
    58             if ($projectNameInput.length) {
    59                 $projectNameInput.val(sanitizedName).trigger('change');
    60             }
    61 
    62             // Update the info display
    63             updateSelectedInfo(sanitizedName);
     38            log('Project selected:', sanitizedUUID, sanitizedName);
     39
     40            // Find and update the project_uuid input field - try multiple approaches
     41            var $uuidInput = $('input[id*="project_uuid"], textarea[id*="project_uuid"], input[name*="project_uuid"]');
     42           
     43            // Also try in Visual Builder's app frame
     44            if (!$uuidInput.length && window.ET_Builder && ET_Builder.Frames && ET_Builder.Frames.app) {
     45                try {
     46                    var $appFrame = $(ET_Builder.Frames.app.document);
     47                    $uuidInput = $appFrame.find('input[id*="project_uuid"], textarea[id*="project_uuid"]');
     48                } catch(e) {
     49                    log('Could not access app frame:', e);
     50                }
     51            }
     52
     53            if ($uuidInput.length) {
     54                $uuidInput.val(sanitizedUUID).trigger('input').trigger('change').trigger('blur');
     55                log('Updated input field');
     56            } else {
     57                log('Could not find input field');
     58            }
     59
     60            // Update the selected info display
     61            updateSelectedInfo(sanitizedName || sanitizedUUID);
    6462
    6563            closeModal();
     
    7472        var $modal = $('<div class="optimal360-divi-modal">' +
    7573            '<div class="optimal360-modal-header">' +
    76                 '<h2>Showcase Selector</h2>' +
     74                '<h2>Select Showcase</h2>' +
    7775                '<button type="button" class="optimal360-modal-close">&times;</button>' +
    7876            '</div>' +
     
    9694    }
    9795
    98     function updateSelectedInfo(projectName) {
     96    function updateSelectedInfo(name) {
    9997        var $info = $('.optimal360-selected-info');
    100         if (projectName) {
    101             $info.html('<strong>Selected:</strong> ' + $('<div>').text(projectName).html());
    102         } else {
    103             $info.html('<em>No showcase selected</em>');
     98        if ($info.length) {
     99            if (name) {
     100                $info.html('<strong>Selected:</strong> ' + $('<div>').text(name).html());
     101            } else {
     102                $info.html('<em>No showcase selected</em>');
     103            }
    104104        }
    105105    }
    106106
    107107    function injectSelectButton() {
    108         // Check if we're in the Divi Builder settings modal for our module
    109         var $settingsModal = $('.et-pb-option-container');
    110        
    111         if ($settingsModal.length && !$settingsModal.find('.optimal360-select-btn').length) {
    112             // Find the module settings for optimal360_showcase
    113             var $moduleSettings = $('.et_pb_module_settings[data-module_type="et_pb_optimal360_showcase"]');
    114            
    115             if ($moduleSettings.length) {
    116                 // Inject button after the hidden fields
    117                 var $hiddenFields = $moduleSettings.find('[id*="project_uuid"]').closest('.et-pb-option');
    118                
    119                 if ($hiddenFields.length && !$hiddenFields.siblings('.optimal360-select-wrapper').length) {
    120                     var $buttonWrapper = $('<div class="optimal360-select-wrapper et-pb-option">' +
    121                         '<label class="et-pb-option-label">Select Showcase</label>' +
    122                         '<div class="et-pb-option-container">' +
    123                             '<button type="button" class="optimal360-select-btn">Select Showcase</button>' +
    124                             '<div class="optimal360-selected-info"><em>No showcase selected</em></div>' +
    125                             '<div class="optimal360-manual-entry" style="margin-top: 15px;">' +
    126                                 '<label style="display: block; margin-bottom: 5px;">Or enter showcase code manually:</label>' +
    127                                 '<input type="text" id="optimal360-manual-uuid" placeholder="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" style="width: 100%; margin-bottom: 5px;" />' +
    128                                 '<button type="button" id="optimal360-apply-uuid" class="button">Apply</button>' +
    129                             '</div>' +
    130                         '</div>' +
    131                     '</div>');
    132                    
    133                     $hiddenFields.after($buttonWrapper);
    134 
    135                     // Set up manual UUID input
    136                     var currentUuid = $moduleSettings.find('[id*="project_uuid"]').val();
    137                     if (currentUuid) {
    138                         $buttonWrapper.find('#optimal360-manual-uuid').val(currentUuid);
    139                     }
    140                    
    141                     // Get current project name
    142                     var $projectNameInput = $moduleSettings.find('[id*="project_name"]');
    143                     if ($projectNameInput.length && $projectNameInput.val()) {
    144                         updateSelectedInfo($projectNameInput.val());
    145                     }
    146                 }
    147             }
    148         }
    149     }
    150 
    151     // Bind click events using delegation
     108        log('Attempting to inject select button...');
     109
     110        // Divi 4.x Visual Builder selectors
     111        var selectors = [
     112            // Settings modal field containers
     113            '.et-fb-settings-option-input',
     114            '.et-fb-option',
     115            '.et-pb-option',
     116            // By field name/id
     117            '[class*="project_uuid"]',
     118            '[data-option_name="project_uuid"]'
     119        ];
     120
     121        var $containers = $(selectors.join(', '));
     122        log('Found containers:', $containers.length);
     123
     124        // Also search by label text
     125        var $labels = $('label').filter(function() {
     126            var text = $(this).text().toLowerCase();
     127            return text.indexOf('showcase code') !== -1 || text.indexOf('project uuid') !== -1;
     128        });
     129
     130        log('Found labels:', $labels.length);
     131
     132        $labels.each(function() {
     133            var $label = $(this);
     134            var $container = $label.closest('.et-fb-settings-option-input, .et-fb-option, .et-pb-option, [class*="option"]');
     135           
     136            if (!$container.length) {
     137                $container = $label.parent();
     138            }
     139
     140            if ($container.length && !$container.find('.optimal360-select-btn').length) {
     141                log('Injecting button into container');
     142               
     143                var $buttonWrapper = $('<div class="optimal360-select-wrapper" style="margin-top: 10px;">' +
     144                    '<button type="button" class="optimal360-select-btn" style="background: #7c3aed; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 500; width: 100%;">Select Showcase</button>' +
     145                    '<div class="optimal360-selected-info" style="margin-top: 8px; font-size: 13px; color: #888; text-align: center;"><em>Or paste your showcase code above</em></div>' +
     146                '</div>');
     147
     148                $container.append($buttonWrapper);
     149               
     150                // Check for existing value
     151                var $input = $container.find('input, textarea');
     152                if ($input.length && $input.val()) {
     153                    updateSelectedInfo($input.val());
     154                }
     155            }
     156        });
     157
     158        // Also try to find the input directly and inject after it
     159        var $inputs = $('input, textarea').filter(function() {
     160            var id = $(this).attr('id') || '';
     161            var name = $(this).attr('name') || '';
     162            return id.indexOf('project_uuid') !== -1 || name.indexOf('project_uuid') !== -1;
     163        });
     164
     165        log('Found inputs:', $inputs.length);
     166
     167        $inputs.each(function() {
     168            var $input = $(this);
     169            var $wrapper = $input.closest('.et-fb-settings-option-input, .et-fb-option, .et-pb-option').first();
     170           
     171            if (!$wrapper.length) {
     172                $wrapper = $input.parent();
     173            }
     174
     175            if ($wrapper.length && !$wrapper.find('.optimal360-select-btn').length) {
     176                log('Injecting button after input');
     177               
     178                var $buttonWrapper = $('<div class="optimal360-select-wrapper" style="margin-top: 10px;">' +
     179                    '<button type="button" class="optimal360-select-btn" style="background: #7c3aed; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; font-weight: 500; width: 100%;">Select Showcase</button>' +
     180                    '<div class="optimal360-selected-info" style="margin-top: 8px; font-size: 13px; color: #888; text-align: center;"><em>Or paste your showcase code above</em></div>' +
     181                '</div>');
     182
     183                $wrapper.append($buttonWrapper);
     184               
     185                if ($input.val()) {
     186                    updateSelectedInfo($input.val());
     187                }
     188            }
     189        });
     190    }
     191
     192    // Click handler for select button (using delegation)
    152193    $(document).on('click', '.optimal360-select-btn', function(e) {
    153194        e.preventDefault();
    154        
    155         // Try to get module address for visual builder
    156         var $module = $(this).closest('.et_pb_module_settings');
    157         if ($module.length) {
    158             currentModuleAddress = $module.data('address') || null;
    159         }
    160        
     195        e.stopPropagation();
     196        log('Select button clicked');
    161197        openModal();
    162198    });
    163199
    164     // Handle manual UUID apply
    165     $(document).on('click', '#optimal360-apply-uuid', function(e) {
    166         e.preventDefault();
    167         var uuid = $('#optimal360-manual-uuid').val();
    168         var sanitizedUUID = sanitizeUUID(uuid);
    169        
    170         if (sanitizedUUID) {
    171             var $moduleSettings = $(this).closest('.et_pb_module_settings');
    172             var $projectUuidInput = $moduleSettings.find('[id*="project_uuid"]');
    173             var $projectNameInput = $moduleSettings.find('[id*="project_name"]');
    174            
    175             if ($projectUuidInput.length) {
    176                 $projectUuidInput.val(sanitizedUUID).trigger('change');
    177             }
    178             if ($projectNameInput.length) {
    179                 $projectNameInput.val('Manual Entry').trigger('change');
    180             }
    181            
    182             updateSelectedInfo('Manual Entry');
    183         } else {
    184             alert('Invalid showcase code format');
    185         }
     200    // Use MutationObserver to detect when Divi settings panels open
     201    function setupObserver() {
     202        var observer = new MutationObserver(function(mutations) {
     203            var shouldInject = false;
     204           
     205            mutations.forEach(function(mutation) {
     206                if (mutation.addedNodes.length) {
     207                    for (var i = 0; i < mutation.addedNodes.length; i++) {
     208                        var node = mutation.addedNodes[i];
     209                        if (node.nodeType === 1) { // Element node
     210                            var $node = $(node);
     211                            // Check if this looks like a settings panel
     212                            if ($node.is('.et-fb-settings-modal, .et-pb-settings-modal, [class*="settings"]') ||
     213                                $node.find('.et-fb-settings-modal, .et-pb-settings-modal, [class*="project_uuid"]').length) {
     214                                shouldInject = true;
     215                            }
     216                        }
     217                    }
     218                }
     219            });
     220
     221            if (shouldInject) {
     222                setTimeout(injectSelectButton, 200);
     223            }
     224        });
     225
     226        observer.observe(document.body, {
     227            childList: true,
     228            subtree: true
     229        });
     230
     231        log('MutationObserver set up');
     232    }
     233
     234    // Initialize
     235    $(document).ready(function() {
     236        log('Divi builder JS initialized');
     237
     238        // Add message listener for postMessage from iframe
     239        window.addEventListener('message', handleMessage);
     240
     241        // Setup observer for dynamic content
     242        setupObserver();
     243
     244        // Periodic check for the first few seconds (fallback)
     245        var checkCount = 0;
     246        var checkInterval = setInterval(function() {
     247            injectSelectButton();
     248            checkCount++;
     249            if (checkCount > 20) { // Stop after ~10 seconds
     250                clearInterval(checkInterval);
     251            }
     252        }, 500);
    186253    });
    187254
    188     // Watch for settings modal changes
    189     $(document).on('DOMNodeInserted', function(e) {
    190         if ($(e.target).hasClass('et-pb-option') || $(e.target).find('.et-pb-option').length) {
    191             setTimeout(injectSelectButton, 100);
    192         }
    193     });
    194 
    195     // Initial injection attempt
    196     $(document).ready(function() {
    197         setTimeout(injectSelectButton, 500);
    198     });
    199 
    200     // For Visual Builder React component
    201     if (typeof window.ETBuilderBackend !== 'undefined') {
    202         // Hook into the visual builder's module settings
    203         $(document).on('et_fb_module_settings_opened', function(e, module) {
    204             if (module && module.type === 'et_pb_optimal360_showcase') {
    205                 currentModuleAddress = module.address;
    206                 setTimeout(injectSelectButton, 100);
    207             }
    208         });
    209     }
    210 
    211     // Add message listener persistently (like Elementor)
    212     $(function() {
    213         window.addEventListener('message', handleMessage);
    214     });
    215 
    216255})(jQuery);
  • optimal-360/trunk/includes/divi-module.php

    r3452427 r3452499  
    3737        return array(
    3838            'project_uuid' => array(
    39                 'label'       => esc_html__('Project UUID', 'optml360'),
    40                 'type'        => 'hidden',
    41                 'toggle_slug' => 'main_content',
    42             ),
    43             'project_name' => array(
    44                 'label'       => esc_html__('Project Name', 'optml360'),
    45                 'type'        => 'hidden',
    46                 'toggle_slug' => 'main_content',
     39                'label'           => esc_html__('Showcase Code', 'optml360'),
     40                'type'            => 'text',
     41                'option_category' => 'basic_option',
     42                'description'     => esc_html__('Enter your Optimal 360° showcase code (UUID). Find this in your Optimal 360 dashboard under the showcase settings.', 'optml360'),
     43                'toggle_slug'     => 'main_content',
    4744            ),
    4845            'embed_height' => array(
     
    8279
    8380    public function render($attrs, $content = null, $render_slug = '') {
    84         $project_uuid    = isset($this->props['project_uuid']) ? $this->props['project_uuid'] : '';
    85         $project_name    = isset($this->props['project_name']) ? $this->props['project_name'] : '';
    86         $height          = isset($this->props['embed_height']) ? intval($this->props['embed_height']) : 400;
    87         $width           = isset($this->props['embed_width']) ? intval($this->props['embed_width']) : 100;
    88         $width_unit      = isset($this->props['embed_width_unit']) ? $this->props['embed_width_unit'] : '%';
     81        $project_uuid = isset($this->props['project_uuid']) ? trim($this->props['project_uuid']) : '';
     82        $height       = isset($this->props['embed_height']) ? intval($this->props['embed_height']) : 400;
     83        $width        = isset($this->props['embed_width']) ? intval($this->props['embed_width']) : 100;
     84        $width_unit   = isset($this->props['embed_width_unit']) ? $this->props['embed_width_unit'] : '%';
    8985
    9086        if (!empty($project_uuid) && preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i', $project_uuid)) {
  • optimal-360/trunk/optml360-extension.php

    r3452427 r3452499  
    33 * Plugin Name: Optimal 360
    44 * Description: Turn simple 4K videos into 3D 360 showcases for your websites.
    5  * Version: 1.1.2
     5 * Version: 1.1.3
    66 * Author: Optimal 360
    77 * Author URI: https://optml360.com
     
    163163            plugin_dir_url(__FILE__) . 'assets/divi-builder.css',
    164164            array(),
    165             '1.0.0'
     165            '1.1.2'
    166166        );
    167167       
     
    170170            plugin_dir_url(__FILE__) . 'assets/divi-builder.js',
    171171            array('jquery'),
    172             '1.0.0',
    173             true
    174         );
     172            '1.1.2',
     173            true
     174        );
     175       
     176        wp_localize_script('optimal360-divi', 'optimal360Divi', array(
     177            'debug' => defined('WP_DEBUG') && WP_DEBUG
     178        ));
    175179    }
    176180   
     
    192196            plugin_dir_url(__FILE__) . 'assets/divi-builder.css',
    193197            array(),
    194             '1.0.0'
     198            '1.1.2'
    195199        );
    196200       
     
    199203            plugin_dir_url(__FILE__) . 'assets/divi-builder.js',
    200204            array('jquery'),
    201             '1.0.0',
    202             true
    203         );
     205            '1.1.2',
     206            true
     207        );
     208       
     209        wp_localize_script('optimal360-divi', 'optimal360Divi', array(
     210            'debug' => defined('WP_DEBUG') && WP_DEBUG
     211        ));
    204212    }
    205213   
  • optimal-360/trunk/readme.txt

    r3452427 r3452499  
    66Requires at least: 5.0
    77Tested up to: 6.8
    8 Stable tag: 1.1.2
     8Stable tag: 1.1.3
    99Requires PHP: 7.0
    1010License: GPLv3
Note: See TracChangeset for help on using the changeset viewer.