Explorar o código

theme_m22tc fix

odoo hai 2 meses
pai
achega
0e4f6904ca
Modificáronse 1 ficheiros con 111 adicións e 15 borrados
  1. 111 15
      theme_m22tc/static/src/js/m22_helpdesk_select.js

+ 111 - 15
theme_m22tc/static/src/js/m22_helpdesk_select.js

@@ -116,13 +116,13 @@ publicWidget.registry.M22HelpdeskSelect = publicWidget.Widget.extend({
         };
 
         // Build HTML structure with Tailwind classes
+        // Escape HTML to prevent XSS
+        const selectName = select.name || '';
+        const selectId = select.id || '';
+        const selectRequired = select.required ? 'required' : '';
+        
         wrapper.innerHTML = `
-            <!-- Hidden original select for form submission -->
-            <select name="${select.name}" id="${select.id}" class="hidden" ${select.required ? 'required' : ''}>
-                ${options.map(opt => 
-                    `<option value="${opt.value}" ${opt.value === currentValue ? 'selected' : ''} ${opt.disabled ? 'disabled' : ''}>${opt.label}</option>`
-                ).join('')}
-            </select>
+            <!-- Hidden original select will be moved here, not recreated -->
             
             <!-- Combobox button -->
             <button 
@@ -186,7 +186,9 @@ publicWidget.registry.M22HelpdeskSelect = publicWidget.Widget.extend({
         const placeholderSpan = wrapper.querySelector('.m22-combobox-placeholder');
         const valueSpan = wrapper.querySelector('.m22-combobox-value');
         const arrow = wrapper.querySelector('.m22-combobox-arrow');
-        const hiddenSelect = wrapper.querySelector('select');
+        
+        // The hidden select is the original select element, not a new one
+        // We'll move it into the wrapper after creating the structure
 
         // Methods
         const updateDisplay = () => {
@@ -251,17 +253,39 @@ publicWidget.registry.M22HelpdeskSelect = publicWidget.Widget.extend({
             state.search = '';
             state.open = false;
             
-            // Update hidden select
-            hiddenSelect.value = option.value;
+            // Update the original select (which is now inside the wrapper)
+            select.value = option.value;
             
             // Update display
             updateDisplay();
             renderOptions();
             closeDropdown();
             
-            // Trigger change event
-            const event = new Event('change', { bubbles: true });
-            hiddenSelect.dispatchEvent(event);
+            // Trigger both change and input events for Odoo's conditional visibility system
+            // Odoo listens to 'input.s_website_form' events on .s_website_form_field
+            const changeEvent = new Event('change', { bubbles: true, cancelable: true });
+            select.dispatchEvent(changeEvent);
+            
+            // Find the field container and trigger input event with jQuery namespace
+            // Odoo's listener: this.$el.on('input.s_website_form', '.s_website_form_field', ...)
+            const fieldContainer = select.closest('.s_website_form_field');
+            if (fieldContainer && window.$) {
+                // Use jQuery to trigger the event with the correct namespace
+                // This matches how Odoo listens: 'input.s_website_form'
+                window.$(fieldContainer).trigger('input.s_website_form');
+            } else if (fieldContainer) {
+                // Fallback: native event
+                const inputEvent = new Event('input', { bubbles: true, cancelable: true });
+                fieldContainer.dispatchEvent(inputEvent);
+            }
+            
+            // Also trigger on the select itself
+            if (window.$) {
+                window.$(select).trigger('input.s_website_form');
+            } else {
+                const inputEvent = new Event('input', { bubbles: true, cancelable: true });
+                select.dispatchEvent(inputEvent);
+            }
         };
 
         const openDropdown = () => {
@@ -334,9 +358,81 @@ publicWidget.registry.M22HelpdeskSelect = publicWidget.Widget.extend({
         });
 
         // Replace select with wrapper
-        select.parentNode.insertBefore(wrapper, select);
-        select.style.display = 'none';
-        wrapper.appendChild(select);
+        // Keep the select inside its original field container to maintain Odoo's event listeners
+        const fieldContainer = select.closest('.s_website_form_field');
+        const parentNode = select.parentNode;
+        const nextSibling = select.nextSibling; // Save reference before moving
+        
+        if (!parentNode) {
+            console.warn(_t('Select element has no parent node, skipping combobox transformation'));
+            return;
+        }
+        
+        // Check if select is already inside a wrapper (avoid double transformation)
+        if (select.closest('.m22-combobox-wrapper')) {
+            console.warn(_t('Select is already inside a combobox wrapper, skipping'));
+            return;
+        }
+        
+        try {
+            // First, hide the original select but keep it in the DOM for form submission
+            select.style.display = 'none';
+            
+            // Move the select inside the wrapper BEFORE inserting wrapper into DOM
+            // This prevents DOM hierarchy issues
+            if (wrapper.firstChild) {
+                wrapper.insertBefore(select, wrapper.firstChild);
+            } else {
+                wrapper.appendChild(select);
+            }
+            
+            // Now insert the wrapper (with select inside) where the select was originally
+            // Use the saved nextSibling as reference point
+            if (fieldContainer && fieldContainer === parentNode) {
+                // Select was directly in field container
+                if (nextSibling && nextSibling.parentNode === parentNode) {
+                    parentNode.insertBefore(wrapper, nextSibling);
+                } else {
+                    // No next sibling, append to field container
+                    parentNode.appendChild(wrapper);
+                }
+            } else if (parentNode) {
+                // Select was in a nested structure
+                if (nextSibling && nextSibling.parentNode === parentNode) {
+                    parentNode.insertBefore(wrapper, nextSibling);
+                } else {
+                    // No next sibling, append to parent
+                    parentNode.appendChild(wrapper);
+                }
+            } else {
+                throw new Error(_t('Cannot find valid parent node for wrapper insertion'));
+            }
+        } catch (error) {
+            console.error(_t('Error inserting combobox wrapper:'), error, {
+                select: select,
+                parentNode: parentNode,
+                fieldContainer: fieldContainer,
+                wrapper: wrapper,
+                errorMessage: error.message,
+                errorName: error.name
+            });
+            // Clean up on error - restore select if needed
+            try {
+                if (wrapper.contains(select)) {
+                    // Move select back to original position
+                    if (parentNode) {
+                        parentNode.insertBefore(select, wrapper.nextSibling);
+                    }
+                }
+                if (wrapper.parentNode) {
+                    wrapper.parentNode.removeChild(wrapper);
+                }
+            } catch (cleanupError) {
+                console.error(_t('Error during cleanup:'), cleanupError);
+            }
+            // Don't throw - just skip this select
+            return;
+        }
 
         // Initial render
         updateDisplay();