Spaces:
No application file
No application file
| // Global variables for sorting and filtering | |
| let currentSortColumn = -1; | |
| let isAscending = true; | |
| let columnFilters = {}; | |
| let columnValues = {}; | |
| // Function to update the table based on filters | |
| async function updateTable() { | |
| const navigation = document.getElementById('navigation').value; | |
| const embdType = document.getElementById('embdType').value; | |
| const similarity = document.getElementById('similarity').value; | |
| // Get all checked embedding dimensions | |
| const embdDims = Array.from(document.querySelectorAll('input[name="embdDim"]:checked')) | |
| .map(checkbox => checkbox.value); | |
| // Prepare filter data | |
| const filters = { | |
| navigation: navigation, | |
| embd_type: embdType, | |
| embd_dims: embdDims, | |
| similarity: similarity | |
| }; | |
| try { | |
| const response = await fetch('/api/filter', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json' | |
| }, | |
| body: JSON.stringify(filters) | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| const data = await response.json(); | |
| updateTableContent(data); | |
| } catch (error) { | |
| console.error('Error updating table:', error); | |
| alert('Failed to update table. Please try again.'); | |
| } | |
| } | |
| // Function to update table content | |
| function updateTableContent(data) { | |
| const tbody = document.querySelector('#leaderboardTable tbody'); | |
| tbody.innerHTML = ''; | |
| data.forEach(row => { | |
| const tr = document.createElement('tr'); | |
| row.forEach(cell => { | |
| const td = document.createElement('td'); | |
| td.innerHTML = cell; // Use innerHTML instead of textContent to handle HTML content | |
| tr.appendChild(td); | |
| }); | |
| tbody.appendChild(tr); | |
| }); | |
| } | |
| // Initialize when document is ready | |
| document.addEventListener('DOMContentLoaded', () => { | |
| initializeColumnValues(); | |
| document.addEventListener('click', handleClickOutside); | |
| }); | |
| // Initialize unique values for each column | |
| function initializeColumnValues() { | |
| const table = document.getElementById('leaderboardTable'); | |
| const headers = Array.from(table.querySelectorAll('th')); | |
| const rows = Array.from(table.querySelectorAll('tbody tr')); | |
| headers.forEach((header, columnIndex) => { | |
| const columnName = header.querySelector('span').textContent; | |
| const values = new Set(); | |
| rows.forEach(row => { | |
| const cell = row.cells[columnIndex]; | |
| const value = cell.textContent.trim(); | |
| if (value) values.add(value); | |
| }); | |
| columnValues[columnName] = Array.from(values).sort(); | |
| }); | |
| } | |
| // Handle clicking outside filter dropdowns | |
| function handleClickOutside(event) { | |
| const dropdowns = document.querySelectorAll('.filter-dropdown'); | |
| dropdowns.forEach(dropdown => { | |
| const filterBtn = dropdown.parentElement.querySelector('.filter-btn'); | |
| if (!dropdown.contains(event.target) && !filterBtn.contains(event.target)) { | |
| dropdown.style.display = 'none'; | |
| } | |
| }); | |
| } | |
| // Toggle filter dropdown | |
| function toggleFilter(event, columnName) { | |
| event.stopPropagation(); | |
| const dropdown = document.getElementById(`filter-${columnName}`); | |
| const options = document.getElementById(`options-${columnName}`); | |
| // Close other dropdowns | |
| document.querySelectorAll('.filter-dropdown').forEach(d => { | |
| if (d !== dropdown) d.style.display = 'none'; | |
| }); | |
| if (dropdown.style.display === 'none') { | |
| dropdown.style.display = 'block'; | |
| if (!options.children.length) { | |
| populateFilterOptions(columnName); | |
| } | |
| } else { | |
| dropdown.style.display = 'none'; | |
| } | |
| } | |
| // Populate filter options | |
| function populateFilterOptions(columnName) { | |
| const options = document.getElementById(`options-${columnName}`); | |
| options.innerHTML = ''; | |
| columnValues[columnName].forEach(value => { | |
| const option = document.createElement('div'); | |
| option.className = 'filter-option'; | |
| const checkbox = document.createElement('input'); | |
| checkbox.type = 'checkbox'; | |
| checkbox.value = value; | |
| checkbox.checked = columnFilters[columnName]?.includes(value) || false; | |
| const label = document.createElement('span'); | |
| label.textContent = value; | |
| option.appendChild(checkbox); | |
| option.appendChild(label); | |
| options.appendChild(option); | |
| }); | |
| } | |
| // Filter options based on search input | |
| function filterOptions(columnName) { | |
| const searchInput = document.querySelector(`#filter-${columnName} .filter-search`); | |
| const searchTerm = searchInput.value.toLowerCase(); | |
| const options = document.getElementById(`options-${columnName}`); | |
| Array.from(options.children).forEach(option => { | |
| const text = option.textContent.toLowerCase(); | |
| option.style.display = text.includes(searchTerm) ? '' : 'none'; | |
| }); | |
| } | |
| // Apply filter | |
| function applyFilter(columnName) { | |
| const options = document.getElementById(`options-${columnName}`); | |
| const checkedValues = Array.from(options.querySelectorAll('input[type="checkbox"]:checked')) | |
| .map(cb => cb.value); | |
| columnFilters[columnName] = checkedValues; | |
| updateTableVisibility(); | |
| document.getElementById(`filter-${columnName}`).style.display = 'none'; | |
| } | |
| // Clear filter | |
| function clearFilter(columnName) { | |
| const options = document.getElementById(`options-${columnName}`); | |
| options.querySelectorAll('input[type="checkbox"]').forEach(cb => cb.checked = false); | |
| delete columnFilters[columnName]; | |
| updateTableVisibility(); | |
| document.getElementById(`filter-${columnName}`).style.display = 'none'; | |
| } | |
| // Update table visibility based on filters | |
| function updateTableVisibility() { | |
| const table = document.getElementById('leaderboardTable'); | |
| const rows = Array.from(table.querySelectorAll('tbody tr')); | |
| const headers = Array.from(table.querySelectorAll('th')); | |
| rows.forEach(row => { | |
| let visible = true; | |
| Object.entries(columnFilters).forEach(([columnName, selectedValues]) => { | |
| if (!selectedValues.length) return; | |
| const columnIndex = headers.findIndex(header => | |
| header.querySelector('span').textContent === columnName | |
| ); | |
| const cellValue = row.cells[columnIndex].textContent.trim(); | |
| if (!selectedValues.includes(cellValue)) { | |
| visible = false; | |
| } | |
| }); | |
| row.style.display = visible ? '' : 'none'; | |
| }); | |
| } | |
| // Sort table | |
| function sortTable(columnIndex) { | |
| const table = document.getElementById('leaderboardTable'); | |
| const tbody = table.querySelector('tbody'); | |
| const rows = Array.from(tbody.querySelectorAll('tr')); | |
| // Update sort direction | |
| if (currentSortColumn === columnIndex) { | |
| isAscending = !isAscending; | |
| } else { | |
| currentSortColumn = columnIndex; | |
| isAscending = true; | |
| } | |
| // Sort rows | |
| rows.sort((a, b) => { | |
| let aValue = a.cells[columnIndex].textContent; | |
| let bValue = b.cells[columnIndex].textContent; | |
| // Remove HTML tags for comparison | |
| aValue = aValue.replace(/<[^>]*>/g, '').trim(); | |
| bValue = bValue.replace(/<[^>]*>/g, '').trim(); | |
| // Check if the values are numbers | |
| const aNum = parseFloat(aValue); | |
| const bNum = parseFloat(bValue); | |
| if (!isNaN(aNum) && !isNaN(bNum)) { | |
| return isAscending ? aNum - bNum : bNum - aNum; | |
| } | |
| // Sort as strings | |
| return isAscending | |
| ? aValue.localeCompare(bValue) | |
| : bValue.localeCompare(aValue); | |
| }); | |
| // Update table | |
| tbody.innerHTML = ''; | |
| rows.forEach(row => tbody.appendChild(row)); | |
| // Update sort indicators | |
| const headers = table.querySelectorAll('.sort-icon'); | |
| headers.forEach((icon, index) => { | |
| icon.textContent = index === columnIndex | |
| ? (isAscending ? '↑' : '↓') | |
| : '↕'; | |
| }); | |
| } | |
| // Initialize table sorting and filtering | |
| document.addEventListener('DOMContentLoaded', () => { | |
| // Add event listener for checkboxes | |
| const checkboxes = document.querySelectorAll('input[name="embdDim"]'); | |
| checkboxes.forEach(checkbox => { | |
| checkbox.addEventListener('change', updateTable); | |
| }); | |
| }); | |