145 lines
4.0 KiB
JavaScript
145 lines
4.0 KiB
JavaScript
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 `<div class="flex items-center p-2">
|
|
<span>${escape(data.text)}</span>
|
|
</div>`
|
|
},
|
|
item: function(data, escape) {
|
|
return `<div class="flex items-center text-sm">
|
|
<span>${escape(data.text)}</span>
|
|
</div>`
|
|
}
|
|
},
|
|
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()
|
|
}
|
|
}
|
|
} |