import { Controller } from "@hotwired/stimulus" export default class extends Controller { static targets = [ "select" ] static values = { options: Array, placeholder: String } connect() { // Check if the element is visible, if not, wait for it to become visible if (this.isHidden()) { // Element is hidden, set up a MutationObserver to watch for visibility changes this.observer = new MutationObserver(() => { if (!this.isHidden()) { this.initializeTomSelect() this.observer.disconnect() } }) this.observer.observe(this.element, { attributes: true, attributeFilter: ['class'] }) // Also check periodically as a fallback this.checkInterval = setInterval(() => { if (!this.isHidden()) { this.initializeTomSelect() this.cleanup() } }, 500) } else { // Element is already visible, initialize immediately this.initializeTomSelect() } } isHidden() { return this.element.offsetParent === null || this.element.classList.contains('hidden') } cleanup() { if (this.observer) { this.observer.disconnect() this.observer = null } if (this.checkInterval) { clearInterval(this.checkInterval) this.checkInterval = null } } initializeTomSelect() { if (!this.hasSelectTarget) { console.log('No select target found') return } // Check if Tom Select is available if (typeof TomSelect === 'undefined') { console.log('Tom Select is not loaded') return } // If TomSelect is already initialized, destroy it first if (this.tomSelect) { this.tomSelect.destroy() } console.log('Initializing Tom Select with options:', this.optionsValue.length, 'countries') console.log('First few country options:', this.optionsValue.slice(0, 3)) // Prepare options for Tom Select const options = this.optionsValue.map(([display, value]) => ({ value: value, text: display, // Add searchable fields for better search search: display + ' ' + value })) // Get currently selected values from the hidden select const selectedValues = Array.from(this.selectTarget.selectedOptions).map(option => option.value) try { // Initialize Tom Select this.tomSelect = new TomSelect(this.selectTarget, { options: options, items: selectedValues, plugins: ['remove_button'], maxItems: null, maxOptions: 1000, create: false, placeholder: this.placeholderValue || "Search and select countries...", searchField: ['text', 'search'], searchConjunction: 'or', onItemAdd: function() { // Clear the search input after selecting an item this.setTextboxValue(''); this.refreshOptions(); }, render: { option: function(data, escape) { return `
${escape(data.text)}
` }, item: function(data, escape) { return `
${escape(data.text)}
` } }, dropdownParent: 'body', copyClassesToDropdown: false }) console.log('Tom Select successfully initialized for country selector') // Make sure the wrapper is visible setTimeout(() => { if (this.tomSelect && this.tomSelect.wrapper) { this.tomSelect.wrapper.style.visibility = 'visible' this.tomSelect.wrapper.style.display = 'block' console.log('Tom Select wrapper made visible') } }, 100) } catch (error) { console.error('Error initializing Tom Select:', error) } } // Public method to reinitialize if needed reinitialize() { this.initializeTomSelect() } disconnect() { this.cleanup() if (this.tomSelect) { this.tomSelect.destroy() } } }