@@ -5,8 +5,7 @@
|
||||
*/
|
||||
function initialiseFacilityData(data, force = false) {
|
||||
// Only prevent multiple initializations if not forcing
|
||||
if (!force && isInitialized) {
|
||||
console.debug('Facility data already initialized, skipping...');
|
||||
if (!force && isinitialised) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -21,11 +20,9 @@ function initialiseFacilityData(data, force = false) {
|
||||
// Check if we're on the map page
|
||||
const isMapPage = window.location.pathname.includes('map.php');
|
||||
if (!isMapPage) {
|
||||
// Only try to initialize table if we're not on the map page
|
||||
// Only try to initialise table if we're not on the map page
|
||||
const table = document.querySelector('#facilityTable');
|
||||
if (!table) {
|
||||
console.error('Table not found in DOM. Available elements:',
|
||||
Array.from(document.querySelectorAll('table')).map(t => t.id || 'no-id'));
|
||||
throw new Error('Facility table not found in DOM');
|
||||
}
|
||||
// Clear existing table content
|
||||
@@ -33,27 +30,30 @@ function initialiseFacilityData(data, force = false) {
|
||||
if (tbody) {
|
||||
tbody.innerHTML = '';
|
||||
} else {
|
||||
console.warn('No tbody found in table, creating one');
|
||||
const newTbody = document.createElement('tbody');
|
||||
table.appendChild(newTbody);
|
||||
}
|
||||
|
||||
// Initialize filteredData with all data
|
||||
// initialise filteredData with all data
|
||||
filteredData = data;
|
||||
// Calculate total pages
|
||||
totalPages = Math.ceil(filteredData.length / itemsPerPage);
|
||||
// Set current page to 1
|
||||
currentPage = 1;
|
||||
|
||||
// Update table with paginated data
|
||||
updateTable();
|
||||
|
||||
// Reset sorting state
|
||||
currentSortField = null;
|
||||
currentSortOrder = null;
|
||||
|
||||
// Set up table controls (sorting and filtering)
|
||||
setupTableControls();
|
||||
|
||||
// Update table with paginated data
|
||||
updateTableWithPagination();
|
||||
}
|
||||
|
||||
// Mark as initialized
|
||||
isInitialized = true;
|
||||
// Mark as initialised
|
||||
isinitialised = true;
|
||||
} catch (error) {
|
||||
console.error('Error initialising facility data:', error);
|
||||
// Don't throw error if we're on map page, as table errors are expected
|
||||
@@ -79,7 +79,52 @@ function renderFacilityTable(data) {
|
||||
|
||||
// Check if user is admin
|
||||
const userIsAdmin = isAdmin();
|
||||
console.log('renderFacilityTable - userIsAdmin:', userIsAdmin);
|
||||
|
||||
// Set up table headers first
|
||||
const tableHeaderRow = document.getElementById('tableHeaderRow');
|
||||
if (tableHeaderRow) {
|
||||
// Define header configuration
|
||||
const headers = [
|
||||
{ field: 'title', label: 'Title', width: '17%' },
|
||||
{ field: 'category', label: 'Category', width: '11%', center: true },
|
||||
{ field: 'description', label: 'Description', width: '27%' },
|
||||
{ field: 'address', label: 'Address', width: '20%' },
|
||||
{ field: 'coordinates', label: 'Coordinates', width: '10%', center: true },
|
||||
{ field: 'contributor', label: 'Contributor', width: '7%', center: true },
|
||||
{ field: 'actions', label: 'Actions', width: '8%', center: true, sortable: false }
|
||||
];
|
||||
|
||||
// Clear existing headers
|
||||
tableHeaderRow.innerHTML = '';
|
||||
|
||||
// Create header cells
|
||||
headers.forEach(header => {
|
||||
const th = document.createElement('th');
|
||||
th.className = 'fw-semibold' + (header.center ? ' text-center' : '');
|
||||
th.style.width = header.width;
|
||||
|
||||
if (header.sortable !== false) {
|
||||
th.classList.add('sortable');
|
||||
th.style.cursor = 'pointer';
|
||||
th.dataset.field = header.field;
|
||||
|
||||
// Create header content with sort indicator
|
||||
th.innerHTML = `
|
||||
<div class="d-flex align-items-center gap-1 ${header.center ? 'justify-content-center' : ''}">
|
||||
<span>${header.label}</span>
|
||||
<i class="bi bi-arrow-down-up sort-icon"></i>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Add click handler
|
||||
th.addEventListener('click', () => handleHeaderClick(header.field));
|
||||
} else {
|
||||
th.textContent = header.label;
|
||||
}
|
||||
|
||||
tableHeaderRow.appendChild(th);
|
||||
});
|
||||
}
|
||||
|
||||
// Render each row
|
||||
data.forEach((facility, index) => {
|
||||
@@ -98,19 +143,9 @@ function renderFacilityTable(data) {
|
||||
// Start building the row HTML
|
||||
let rowHtml = '';
|
||||
|
||||
// Only show ID column for admins
|
||||
if (userIsAdmin) {
|
||||
console.log('Adding ID column for facility:', facility.id);
|
||||
rowHtml += `
|
||||
<td class="fw-medium align-middle text-center" style="width: 40px;">
|
||||
${escapeHtml(facility.id)}
|
||||
</td>
|
||||
`;
|
||||
}
|
||||
|
||||
// Add the rest of the columns
|
||||
rowHtml += `
|
||||
<td class="fw-medium align-middle" style="${userIsAdmin ? 'width: 15%;' : 'width: 17%;'}">
|
||||
<td class="fw-medium align-middle" style="width: 17%;">
|
||||
<div class="d-flex align-items-center h-100">
|
||||
<div class="facility-icon me-2 rounded-circle bg-light d-flex align-items-center justify-content-center" style="width: 28px; height: 28px; min-width: 28px;">
|
||||
<i class="${getFacilityIcon(facility.category)} text-${categoryClass}"></i>
|
||||
@@ -118,14 +153,14 @@ function renderFacilityTable(data) {
|
||||
<span class="text-truncate" style="max-width: calc(100% - 35px);">${escapeHtml(facility.title)}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center align-middle" style="${userIsAdmin ? 'width: 10%;' : 'width: 11%;'}">
|
||||
<td class="text-center align-middle" style="width: 11%;">
|
||||
<div class="d-flex align-items-center justify-content-center h-100">
|
||||
<span class="badge bg-${categoryClass} bg-opacity-10 text-${categoryClass} px-2 py-1 rounded-pill">
|
||||
${escapeHtml(facility.category)}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-middle" style="${userIsAdmin ? 'width: 25%;' : 'width: 27%;'}">
|
||||
<td class="align-middle" style="width: 27%;">
|
||||
<div class="description-container d-flex flex-column justify-content-center">
|
||||
<div class="cell-content" data-full-text="${escapeHtml(facility.description)}">
|
||||
${escapeHtml(facility.description)}
|
||||
@@ -144,13 +179,13 @@ function renderFacilityTable(data) {
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="small text-nowrap text-center align-middle" style="${userIsAdmin ? 'width: 12%;' : 'width: 12%;'}">
|
||||
<td class="small text-nowrap text-center align-middle" style="width: 10%;">
|
||||
<span class="badge bg-light text-dark border">
|
||||
${escapeHtml(coordinates)}
|
||||
</span>
|
||||
</td>
|
||||
<td class="small text-center align-middle" style="width: 8%;">${escapeHtml(facility.contributor)}</td>
|
||||
<td class="text-center align-middle" style="${userIsAdmin ? 'width: 10%;' : 'width: 5%;'}">
|
||||
<td class="small text-center align-middle" style="width: 5%;">${escapeHtml(facility.contributor)}</td>
|
||||
<td class="text-center align-middle" style="width: 8%;">
|
||||
<div class="d-flex justify-content-center gap-1">
|
||||
${userIsAdmin ? `
|
||||
<button type="button" class="btn btn-sm btn-outline-primary update-btn rounded-circle d-flex align-items-center justify-content-center" style="width: 30px; height: 30px;" data-bs-toggle="modal" data-bs-target="#updateModal" data-facility-id="${facility.id}" title="Edit">
|
||||
@@ -185,6 +220,9 @@ function renderFacilityTable(data) {
|
||||
`;
|
||||
tbody.appendChild(emptyRow);
|
||||
}
|
||||
|
||||
// Update sort indicators
|
||||
updateSortIndicators();
|
||||
} catch (error) {
|
||||
error_log('Error in renderFacilityTable:', error);
|
||||
}
|
||||
@@ -283,15 +321,19 @@ let filteredData = [];
|
||||
let paginationHandler = null;
|
||||
|
||||
// Add initialization state tracking
|
||||
let isInitialized = false;
|
||||
let isinitialised = false;
|
||||
|
||||
// Initialize modals once
|
||||
// initialise modals once
|
||||
let updateModal, deleteModal, createModal;
|
||||
let formHandlersInitialized = false;
|
||||
let formHandlersinitialised = false;
|
||||
|
||||
// Add sorting state variables
|
||||
let currentSortField = null;
|
||||
let currentSortOrder = null; // null = unsorted, 'asc' = ascending, 'desc' = descending
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// Initialize modals once
|
||||
// initialise modals once
|
||||
const modals = document.querySelectorAll('.modal');
|
||||
modals.forEach((modal, index) => {
|
||||
if (modal.id === 'updateModal') {
|
||||
@@ -388,15 +430,15 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// Set up form handlers with a small delay to ensure DOM is fully loaded
|
||||
setTimeout(() => {
|
||||
if (!formHandlersInitialized) {
|
||||
if (!formHandlersinitialised) {
|
||||
console.log('Setting up form handlers...');
|
||||
setupFormHandlers();
|
||||
formHandlersInitialized = true;
|
||||
formHandlersinitialised = true;
|
||||
}
|
||||
}, 100);
|
||||
|
||||
// Initialize facility data if not already initialized
|
||||
if (!isInitialized) {
|
||||
// initialise facility data if not already initialised
|
||||
if (!isinitialised) {
|
||||
const storedData = sessionStorage.getItem('facilityData');
|
||||
if (storedData) {
|
||||
try {
|
||||
@@ -407,6 +449,23 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add CSS styles for sort indicators
|
||||
const style = document.createElement('style');
|
||||
style.textContent = `
|
||||
.sortable:hover {
|
||||
background-color: rgba(25, 135, 84, 0.1);
|
||||
}
|
||||
.sort-icon {
|
||||
opacity: 0.5;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.sortable:hover .sort-icon,
|
||||
.text-success .sort-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
});
|
||||
|
||||
// Handle create form submission
|
||||
@@ -435,6 +494,8 @@ function setupFormHandlers() {
|
||||
const formData = new FormData(this);
|
||||
// Set the contributor to the current user's username
|
||||
formData.set('contCreate', JSON.parse(localStorage.getItem('user'))?.username);
|
||||
// Set the action to 'create'
|
||||
formData.set('action', 'create');
|
||||
try {
|
||||
// Use simpleAuth.fetchAuth for authenticated requests
|
||||
const response = await simpleAuth.fetchAuth('/facilitycontroller.php', {
|
||||
@@ -517,20 +578,30 @@ function setupFormHandlers() {
|
||||
const formData = new FormData(this);
|
||||
|
||||
// Create a new FormData with the correct field names for the server
|
||||
// This is due to the contributor field being disabled in the form
|
||||
// disallowing it to be included in the form data
|
||||
const serverFormData = new FormData();
|
||||
serverFormData.append('action', 'update');
|
||||
|
||||
// Copy all fields from the form to the server form data
|
||||
for (const [key, value] of formData.entries()) {
|
||||
serverFormData.append(key, value);
|
||||
}
|
||||
// Map form fields to server field names
|
||||
const fieldMappings = {
|
||||
'idUpdate': 'id',
|
||||
'titlUpdate': 'title',
|
||||
'cateUpdate': 'category',
|
||||
'descUpdate': 'description',
|
||||
'hnumUpdate': 'houseNumber',
|
||||
'strtUpdate': 'streetName',
|
||||
'cntyUpdate': 'county',
|
||||
'townUpdate': 'town',
|
||||
'postUpdate': 'postcode',
|
||||
'lngUpdate': 'lng',
|
||||
'latUpdate': 'lat',
|
||||
'contUpdate': 'contributor'
|
||||
};
|
||||
|
||||
// Ensure the contributor field is included (it might be disabled in the form)
|
||||
const contUpdateField = document.getElementById('contUpdate');
|
||||
if (contUpdateField) {
|
||||
serverFormData.append('contUpdate', contUpdateField.value);
|
||||
// Copy and transform fields from the form to the server form data
|
||||
for (const [key, value] of formData.entries()) {
|
||||
if (fieldMappings[key]) {
|
||||
serverFormData.append(fieldMappings[key], value);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -801,12 +872,6 @@ function updatePaginationControls() {
|
||||
paginationInfo.querySelector('span').textContent = `Showing ${startItem}-${endItem} of ${filteredData.length} facilities`;
|
||||
}
|
||||
}
|
||||
|
||||
// Update facility count badge
|
||||
const facilityCount = document.getElementById('facilityCount');
|
||||
if (facilityCount) {
|
||||
facilityCount.textContent = `${filteredData.length} facilities`;
|
||||
}
|
||||
}
|
||||
|
||||
function createPageNumberElement(pageNum, isActive) {
|
||||
@@ -862,6 +927,8 @@ function updateTableWithPagination() {
|
||||
const pageData = getCurrentPageData();
|
||||
renderFacilityTable(pageData);
|
||||
updatePaginationControls();
|
||||
// Update sort indicators after rendering table
|
||||
updateSortIndicators();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -930,14 +997,13 @@ function updateTable() {
|
||||
}
|
||||
|
||||
// Get current filter values
|
||||
const sortBy = document.getElementById('sort').value;
|
||||
const sortDir = document.getElementById('dir').value;
|
||||
const filterCategory = document.getElementById('filterCat').value;
|
||||
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
|
||||
const searchTerm = document.getElementById('searchInput').value;
|
||||
|
||||
// Apply filters and sorting
|
||||
filteredData = filterData(data, filterCategory, searchTerm);
|
||||
filteredData = sortData(filteredData, sortBy, sortDir);
|
||||
filteredData = filterData(data, searchTerm);
|
||||
if (currentSortField && currentSortOrder) {
|
||||
filteredData = sortData(filteredData, currentSortField, currentSortOrder);
|
||||
}
|
||||
|
||||
// Update pagination
|
||||
totalPages = Math.ceil(filteredData.length / itemsPerPage);
|
||||
@@ -962,12 +1028,9 @@ function setupTableControls() {
|
||||
}
|
||||
|
||||
// Get control elements
|
||||
const filterControls = document.querySelectorAll('.filter-control');
|
||||
const sortControls = document.querySelectorAll('.sort-control');
|
||||
const searchInput = document.getElementById('searchInput');
|
||||
|
||||
if (!filterControls.length || !sortControls.length || !searchInput) {
|
||||
error_log('Missing filter or sort controls');
|
||||
if (!searchInput) {
|
||||
error_log('Missing search input');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -978,66 +1041,142 @@ function setupTableControls() {
|
||||
updateTable();
|
||||
});
|
||||
|
||||
// Add event listeners for immediate updates
|
||||
// Add event listener for search input
|
||||
searchInput.addEventListener('input', updateTable);
|
||||
|
||||
// Add change event listeners for select elements
|
||||
filterControls.forEach(control => {
|
||||
control.addEventListener('change', updateTable);
|
||||
});
|
||||
|
||||
sortControls.forEach(control => {
|
||||
control.addEventListener('change', updateTable);
|
||||
});
|
||||
|
||||
// Set up table headers for sorting
|
||||
setupSortableHeaders();
|
||||
|
||||
// Set up pagination controls
|
||||
setupPaginationControls();
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the facility data based on current filter values
|
||||
* Sets up sortable table headers
|
||||
*/
|
||||
function setupSortableHeaders() {
|
||||
const tableHeaderRow = document.getElementById('tableHeaderRow');
|
||||
if (!tableHeaderRow) return;
|
||||
|
||||
// Define header configuration
|
||||
const headers = [
|
||||
{ field: 'title', label: 'Title', width: '17%' },
|
||||
{ field: 'category', label: 'Category', width: '11%', center: true },
|
||||
{ field: 'description', label: 'Description', width: '27%' },
|
||||
{ field: 'address', label: 'Address', width: '20%' },
|
||||
{ field: 'coordinates', label: 'Coordinates', width: '12%', center: true },
|
||||
{ field: 'contributor', label: 'Contributor', width: '8%', center: true },
|
||||
{ field: 'actions', label: 'Actions', width: '5%', center: true, sortable: false }
|
||||
];
|
||||
|
||||
// Clear existing headers
|
||||
tableHeaderRow.innerHTML = '';
|
||||
|
||||
// Create header cells
|
||||
headers.forEach(header => {
|
||||
const th = document.createElement('th');
|
||||
th.className = 'fw-semibold' + (header.center ? ' text-center' : '');
|
||||
th.style.width = header.width;
|
||||
|
||||
if (header.sortable !== false) {
|
||||
th.classList.add('sortable');
|
||||
th.style.cursor = 'pointer';
|
||||
th.dataset.field = header.field;
|
||||
|
||||
// Create header content with sort indicator
|
||||
th.innerHTML = `
|
||||
<div class="d-flex align-items-center gap-1 ${header.center ? 'justify-content-center' : ''}">
|
||||
<span>${header.label}</span>
|
||||
<i class="bi bi-arrow-down-up sort-icon"></i>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Add click handler
|
||||
th.addEventListener('click', () => handleHeaderClick(header.field));
|
||||
} else {
|
||||
th.textContent = header.label;
|
||||
}
|
||||
|
||||
tableHeaderRow.appendChild(th);
|
||||
});
|
||||
|
||||
// initialise sort indicators
|
||||
updateSortIndicators();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles click on sortable header
|
||||
* @param {string} field - The field to sort by
|
||||
*/
|
||||
function handleHeaderClick(field) {
|
||||
console.log('Header clicked:', field); // Debug log
|
||||
|
||||
// Rotate through sort orders: none -> asc -> desc -> none
|
||||
if (currentSortField === field) {
|
||||
if (currentSortOrder === 'asc') {
|
||||
currentSortOrder = 'desc';
|
||||
} else if (currentSortOrder === 'desc') {
|
||||
currentSortField = null;
|
||||
currentSortOrder = null;
|
||||
}
|
||||
} else {
|
||||
currentSortField = field;
|
||||
currentSortOrder = 'asc';
|
||||
}
|
||||
|
||||
console.log('New sort state:', { field: currentSortField, order: currentSortOrder }); // Debug log
|
||||
|
||||
// Update table
|
||||
updateTable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates sort indicators in table headers
|
||||
*/
|
||||
function updateSortIndicators() {
|
||||
const headers = document.querySelectorAll('#tableHeaderRow th.sortable');
|
||||
headers.forEach(header => {
|
||||
const icon = header.querySelector('.sort-icon');
|
||||
if (header.dataset.field === currentSortField) {
|
||||
icon.classList.remove('bi-arrow-down-up');
|
||||
icon.classList.add(currentSortOrder === 'asc' ? 'bi-arrow-up' : 'bi-arrow-down');
|
||||
header.classList.add('text-success');
|
||||
} else {
|
||||
icon.classList.remove('bi-arrow-up', 'bi-arrow-down');
|
||||
icon.classList.add('bi-arrow-down-up');
|
||||
header.classList.remove('text-success');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the facility data based on search term
|
||||
* @param {Array} data - Array of facility objects
|
||||
* @param {string} category - Filter category
|
||||
* @param {string} searchTerm - Search term
|
||||
* @returns {Array} Filtered array of facility objects
|
||||
*/
|
||||
function filterData(data, category, searchTerm) {
|
||||
function filterData(data, searchTerm) {
|
||||
const filtered = data.filter(facility => {
|
||||
if (!facility) return false;
|
||||
|
||||
// If no category selected or no search term, show all results
|
||||
if (!category || !searchTerm) return true;
|
||||
// If no search term, show all results
|
||||
if (!searchTerm) return true;
|
||||
|
||||
// Get the value to search in based on the selected category
|
||||
let searchValue = '';
|
||||
switch(category) {
|
||||
case 'title':
|
||||
searchValue = (facility.title || '').toLowerCase();
|
||||
break;
|
||||
case 'category':
|
||||
searchValue = (facility.category || '').toLowerCase();
|
||||
break;
|
||||
case 'description':
|
||||
searchValue = (facility.description || '').toLowerCase();
|
||||
break;
|
||||
case 'streetName':
|
||||
searchValue = (facility.streetName || '').toLowerCase();
|
||||
break;
|
||||
case 'county':
|
||||
searchValue = (facility.county || '').toLowerCase();
|
||||
break;
|
||||
case 'town':
|
||||
searchValue = (facility.town || '').toLowerCase();
|
||||
break;
|
||||
case 'postcode':
|
||||
searchValue = (facility.postcode || '').toLowerCase();
|
||||
break;
|
||||
case 'contributor':
|
||||
searchValue = (facility.contributor || '').toLowerCase();
|
||||
break;
|
||||
}
|
||||
// Convert search term to lowercase for case-insensitive search
|
||||
searchTerm = searchTerm.toLowerCase();
|
||||
|
||||
return searchValue.includes(searchTerm.toLowerCase());
|
||||
// Search across all relevant fields
|
||||
return (
|
||||
(facility.title || '').toLowerCase().includes(searchTerm) ||
|
||||
(facility.category || '').toLowerCase().includes(searchTerm) ||
|
||||
(facility.description || '').toLowerCase().includes(searchTerm) ||
|
||||
(facility.streetName || '').toLowerCase().includes(searchTerm) ||
|
||||
(facility.county || '').toLowerCase().includes(searchTerm) ||
|
||||
(facility.town || '').toLowerCase().includes(searchTerm) ||
|
||||
(facility.postcode || '').toLowerCase().includes(searchTerm) ||
|
||||
(facility.contributor || '').toLowerCase().includes(searchTerm) ||
|
||||
(facility.houseNumber || '').toLowerCase().includes(searchTerm)
|
||||
);
|
||||
});
|
||||
return filtered;
|
||||
}
|
||||
@@ -1051,51 +1190,50 @@ function filterData(data, category, searchTerm) {
|
||||
*/
|
||||
function sortData(data, sortBy, sortDir) {
|
||||
if (!sortBy) return data;
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
|
||||
|
||||
console.log('Sorting by:', sortBy, 'Direction:', sortDir); // Debug log
|
||||
|
||||
return [...data].sort((a, b) => {
|
||||
if (!a || !b) return 0;
|
||||
|
||||
let valueA = '';
|
||||
let valueB = '';
|
||||
let valueA, valueB;
|
||||
|
||||
// Get the values to compare based on the selected field
|
||||
switch (sortBy) {
|
||||
case 'title':
|
||||
valueA = (a.title || '').toLowerCase();
|
||||
valueB = (b.title || '').toLowerCase();
|
||||
break;
|
||||
case 'category':
|
||||
valueA = (a.category || '').toLowerCase();
|
||||
valueB = (b.category || '').toLowerCase();
|
||||
break;
|
||||
case 'description':
|
||||
valueA = (a.description || '').toLowerCase();
|
||||
valueB = (b.description || '').toLowerCase();
|
||||
break;
|
||||
case 'streetName':
|
||||
valueA = (a.streetName || '').toLowerCase();
|
||||
valueB = (b.streetName || '').toLowerCase();
|
||||
break;
|
||||
case 'county':
|
||||
valueA = (a.county || '').toLowerCase();
|
||||
valueB = (b.county || '').toLowerCase();
|
||||
break;
|
||||
case 'town':
|
||||
valueA = (a.town || '').toLowerCase();
|
||||
valueB = (b.town || '').toLowerCase();
|
||||
break;
|
||||
case 'postcode':
|
||||
valueA = (a.postcode || '').toLowerCase();
|
||||
valueB = (b.postcode || '').toLowerCase();
|
||||
break;
|
||||
case 'contributor':
|
||||
valueA = (a.contributor || '').toLowerCase();
|
||||
valueB = (b.contributor || '').toLowerCase();
|
||||
break;
|
||||
// Special handling for address field which is composed of multiple fields
|
||||
if (sortBy === 'address') {
|
||||
valueA = [
|
||||
a.houseNumber || '',
|
||||
a.streetName || '',
|
||||
a.town || '',
|
||||
a.county || '',
|
||||
a.postcode || ''
|
||||
].filter(Boolean).join(', ').toLowerCase();
|
||||
|
||||
valueB = [
|
||||
b.houseNumber || '',
|
||||
b.streetName || '',
|
||||
b.town || '',
|
||||
b.county || '',
|
||||
b.postcode || ''
|
||||
].filter(Boolean).join(', ').toLowerCase();
|
||||
}
|
||||
// Special handling for coordinates field
|
||||
else if (sortBy === 'coordinates') {
|
||||
// Sort by latitude first, then longitude
|
||||
valueA = `${parseFloat(a.lat || 0)},${parseFloat(a.lng || 0)}`;
|
||||
valueB = `${parseFloat(b.lat || 0)},${parseFloat(b.lng || 0)}`;
|
||||
}
|
||||
// Default handling for other fields
|
||||
else {
|
||||
valueA = (a[sortBy] || '').toString().toLowerCase();
|
||||
valueB = (b[sortBy] || '').toString().toLowerCase();
|
||||
}
|
||||
|
||||
const comparison = valueA.localeCompare(valueB);
|
||||
return sortDir === 'asc' ? comparison : -comparison;
|
||||
console.log('Comparing:', valueA, valueB); // Debug log
|
||||
|
||||
// Compare the values
|
||||
if (valueA < valueB) return sortDir === 'asc' ? -1 : 1;
|
||||
if (valueA > valueB) return sortDir === 'asc' ? 1 : -1;
|
||||
return 0;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1154,4 +1292,4 @@ function getCategoryColorClass(category) {
|
||||
}
|
||||
|
||||
// Export the initialization function
|
||||
window.initializeFacilityData = initialiseFacilityData;
|
||||
window.initialiseFacilityData = initialiseFacilityData;
|
Reference in New Issue
Block a user