Changeset 3452499
- Timestamp:
- 02/03/2026 01:49:05 AM (2 months ago)
- Location:
- optimal-360
- Files:
-
- 22 added
- 4 edited
-
tags/1.1.3 (added)
-
tags/1.1.3/LICENSE (added)
-
tags/1.1.3/assets (added)
-
tags/1.1.3/assets/block-editor.css (added)
-
tags/1.1.3/assets/block-editor.js (added)
-
tags/1.1.3/assets/divi-builder.css (added)
-
tags/1.1.3/assets/divi-builder.js (added)
-
tags/1.1.3/assets/elementor-editor.css (added)
-
tags/1.1.3/assets/elementor-editor.js (added)
-
tags/1.1.3/assets/tinymce-plugin.css (added)
-
tags/1.1.3/assets/tinymce-plugin.js (added)
-
tags/1.1.3/assets/woocommerce-admin.css (added)
-
tags/1.1.3/assets/woocommerce-admin.js (added)
-
tags/1.1.3/assets/woocommerce-frontend.css (added)
-
tags/1.1.3/assets/woocommerce-frontend.js (added)
-
tags/1.1.3/includes (added)
-
tags/1.1.3/includes/divi-module.php (added)
-
tags/1.1.3/includes/elementor-widget.php (added)
-
tags/1.1.3/includes/shortcode.php (added)
-
tags/1.1.3/includes/woocommerce-integration.php (added)
-
tags/1.1.3/optml360-extension.php (added)
-
tags/1.1.3/readme.txt (added)
-
trunk/assets/divi-builder.js (modified) (5 diffs)
-
trunk/includes/divi-module.php (modified) (2 diffs)
-
trunk/optml360-extension.php (modified) (5 diffs)
-
trunk/readme.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
optimal-360/trunk/assets/divi-builder.js
r3452427 r3452499 3 3 4 4 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 } 6 12 7 13 function sanitizeUUID(uuid) { … … 16 22 } 17 23 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 24 24 function handleMessage(event) { 25 25 if (event.origin !== 'https://app.optml360.com') { … … 30 30 var sanitizedUUID = sanitizeUUID(event.data.projectuuid); 31 31 var sanitizedName = sanitizeFriendlyName(event.data.friendlyname); 32 var sanitizedStatus = sanitizeStatus(event.data.status); 33 34 if (!sanitizedUUID || !sanitizedName) { 32 33 if (!sanitizedUUID) { 35 34 console.error('Invalid project data received'); 36 35 return; 37 36 } 38 37 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); 64 62 65 63 closeModal(); … … 74 72 var $modal = $('<div class="optimal360-divi-modal">' + 75 73 '<div class="optimal360-modal-header">' + 76 '<h2>S howcase Selector</h2>' +74 '<h2>Select Showcase</h2>' + 77 75 '<button type="button" class="optimal360-modal-close">×</button>' + 78 76 '</div>' + … … 96 94 } 97 95 98 function updateSelectedInfo( projectName) {96 function updateSelectedInfo(name) { 99 97 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 } 104 104 } 105 105 } 106 106 107 107 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) 152 193 $(document).on('click', '.optimal360-select-btn', function(e) { 153 194 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'); 161 197 openModal(); 162 198 }); 163 199 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); 186 253 }); 187 254 188 // Watch for settings modal changes189 $(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 attempt196 $(document).ready(function() {197 setTimeout(injectSelectButton, 500);198 });199 200 // For Visual Builder React component201 if (typeof window.ETBuilderBackend !== 'undefined') {202 // Hook into the visual builder's module settings203 $(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 216 255 })(jQuery); -
optimal-360/trunk/includes/divi-module.php
r3452427 r3452499 37 37 return array( 38 38 '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', 47 44 ), 48 45 'embed_height' => array( … … 82 79 83 80 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'] : '%'; 89 85 90 86 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 3 3 * Plugin Name: Optimal 360 4 4 * Description: Turn simple 4K videos into 3D 360 showcases for your websites. 5 * Version: 1.1. 25 * Version: 1.1.3 6 6 * Author: Optimal 360 7 7 * Author URI: https://optml360.com … … 163 163 plugin_dir_url(__FILE__) . 'assets/divi-builder.css', 164 164 array(), 165 '1. 0.0'165 '1.1.2' 166 166 ); 167 167 … … 170 170 plugin_dir_url(__FILE__) . 'assets/divi-builder.js', 171 171 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 )); 175 179 } 176 180 … … 192 196 plugin_dir_url(__FILE__) . 'assets/divi-builder.css', 193 197 array(), 194 '1. 0.0'198 '1.1.2' 195 199 ); 196 200 … … 199 203 plugin_dir_url(__FILE__) . 'assets/divi-builder.js', 200 204 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 )); 204 212 } 205 213 -
optimal-360/trunk/readme.txt
r3452427 r3452499 6 6 Requires at least: 5.0 7 7 Tested up to: 6.8 8 Stable tag: 1.1. 28 Stable tag: 1.1.3 9 9 Requires PHP: 7.0 10 10 License: GPLv3
Note: See TracChangeset
for help on using the changeset viewer.