UNPKG

@jinntec/fore

Version:

Fore - declarative user interfaces in plain HTML

90 lines (74 loc) 3.17 kB
export class FxSelect extends HTMLElement { constructor() { super(); // Attach Shadow DOM to encapsulate the component this.attachShadow({ mode: 'open' }); // Create and attach the <select> element this.selectElement = document.createElement('select'); this.shadowRoot.appendChild(this.selectElement); // Set default values this.batchSize = parseInt(this.getAttribute('batch-size')) || 20; this.size = parseInt(this.getAttribute('size')) || 5; this.currentLoadedItems = 0; this.hasMoreItems = true; // Assume there are more items initially // Set the size of the <select> element this.selectElement.setAttribute('size', this.size); // Bind the scroll event handler this.handleScroll = this.handleScroll.bind(this); } connectedCallback() { // Initial load of options this.loadOptions(this.currentLoadedItems, this.batchSize); // Attach scroll event listener this.selectElement.addEventListener('scroll', this.handleScroll); } disconnectedCallback() { // Clean up event listeners when the element is removed this.selectElement.removeEventListener('scroll', this.handleScroll); } // Mock function to simulate fetching more options fetchMoreItems(start, count) { // Simulate an async fetch or data load (replace with real fetch if needed) return new Promise((resolve) => { setTimeout(() => { const items = []; for (let i = start; i < start + count; i++) { if (i < 200) { // Let's say we stop after 200 items (remove this limit for real use) items.push({ value: i, label: `Option ${i + 1}` }); } } resolve(items); }, 500); // Simulate fetch delay }); } // Method to load a batch of options async loadOptions(start, count) { const fragment = document.createDocumentFragment(); const newItems = await this.fetchMoreItems(start, count); if (newItems.length > 0) { newItems.forEach(item => { const option = document.createElement('option'); option.value = item.value; option.textContent = item.label; fragment.appendChild(option); }); this.selectElement.appendChild(fragment); this.currentLoadedItems += newItems.length; } else { // If no more items are returned, stop further loading this.hasMoreItems = false; } } // Scroll event handler to load more items handleScroll() { const { scrollTop, scrollHeight, clientHeight } = this.selectElement; const isNearBottom = scrollTop + clientHeight >= scrollHeight - 10; if (isNearBottom && this.hasMoreItems) { this.loadOptions(this.currentLoadedItems, this.batchSize); } } } // Register the custom element if (!customElements.get('fx-select')) { customElements.define('fx-select', FxSelect); }