Skip to content

Instantly share code, notes, and snippets.

@light-flight
Created March 17, 2024 12:14
Show Gist options
  • Save light-flight/411262a6cec99ab52c9bf35cd751932a to your computer and use it in GitHub Desktop.
Save light-flight/411262a6cec99ab52c9bf35cd751932a to your computer and use it in GitHub Desktop.
list filtering
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
static targets = ['filterOption', 'filterList'];
#compareOptions(searchText, a, b) {
const aText = a.textContent.toLowerCase();
const bText = b.textContent.toLowerCase();
const aIndex = aText.indexOf(searchText);
const bIndex = bText.indexOf(searchText);
if (aIndex === -1) return 1;
if (bIndex === -1) return -1;
if (aIndex === bIndex) return aText.localeCompare(bText);
return aIndex - bIndex;
}
filter(event) {
const searchText = event.target.value.toLowerCase();
const listItems = this.filterOptionTargets;
// Prepare a document fragment to minimize direct DOM manipulation
const fragment = document.createDocumentFragment();
// Filter and sort relevant items
const relevantItems = listItems.filter((li) => li.textContent.toLowerCase().includes(searchText));
relevantItems.sort((a, b) => this.#compareOptions(searchText, a, b));
// Append relevant items to the fragment
relevantItems.forEach((li) => {
li.style.display = '';
fragment.appendChild(li);
});
// Hide non-relevant items and adjust display without removing them from the DOM
listItems.forEach((li) => {
if (!relevantItems.includes(li)) {
li.style.display = 'none';
}
});
// Append the fragment to the list, minimizing direct DOM updates
this.filterListTarget.appendChild(fragment);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment