|
|
|
@ -17,7 +17,7 @@
|
|
|
|
|
import {
|
|
|
|
|
dom, COLUMN, COLUMN_LITERAL, COMPARISON, ATTRIBUTES,
|
|
|
|
|
columnAscendingByDefault, columnIsSortable, COLUMN_TRANSFORMATION,
|
|
|
|
|
element, JOIN_URL_PASTE, communityQRCodeURL, STAFF_ID_PASTE, IDENTIFIER_PASTE, DETAILS_LINK_PASTE
|
|
|
|
|
element, JOIN_URL_PASTE, communityQRCodeURL, STAFF_ID_PASTE, IDENTIFIER_PASTE, DETAILS_LINK_PASTE, CLASSES
|
|
|
|
|
} from './js/constants.js';
|
|
|
|
|
|
|
|
|
|
// Hidden communities for transparency.
|
|
|
|
@ -129,16 +129,26 @@ function onLoad() {
|
|
|
|
|
hideBadCommunities();
|
|
|
|
|
// Sort by server to show off new feature & align colors.
|
|
|
|
|
sortTable(COLUMN.SERVER_ICON);
|
|
|
|
|
initializeSearch();
|
|
|
|
|
createJoinLinkButtons();
|
|
|
|
|
markSortableColumns();
|
|
|
|
|
addQRModalHandlers();
|
|
|
|
|
addServerIconInteractions();
|
|
|
|
|
addSearchInteractions();
|
|
|
|
|
preloadImages();
|
|
|
|
|
setInterval(() => {
|
|
|
|
|
preloadImages();
|
|
|
|
|
}, 60 * 60E3);
|
|
|
|
|
reactToURLParameters();
|
|
|
|
|
addInformativeInteractions();
|
|
|
|
|
Array.from(document.querySelectorAll('.enter-clicks')).forEach(element => {
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
element.addEventListener('keydown', (/** @type {KeyboardEvent} */ ev) => {
|
|
|
|
|
if (ev.key == "Enter") {
|
|
|
|
|
ev.currentTarget.click();
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -200,7 +210,7 @@ function displayQRModal(communityID, pane = 0) {
|
|
|
|
|
tagContainer.innerHTML = "";
|
|
|
|
|
|
|
|
|
|
tagContainer.append(
|
|
|
|
|
...JSON.parse(rowInfo.tags).map(tag => tagBody(tag))
|
|
|
|
|
...rowInfo.tags.map(tag => tagBody(tag))
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
dom.details_modal_qr_code().src = communityQRCodeURL(communityID);
|
|
|
|
@ -438,6 +448,29 @@ function addServerIconInteractions() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function addSearchInteractions() {
|
|
|
|
|
dom.toggle_search_checkbox()?.addEventListener('click', function (ev) {
|
|
|
|
|
if (this.checked) {
|
|
|
|
|
dom.search_bar()?.focus();
|
|
|
|
|
} else {
|
|
|
|
|
useSearchTerm("");
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
dom.search_bar()?.addEventListener('keydown', function () {
|
|
|
|
|
setTimeout(() => useSearchTerm(this.value), 0);
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
dom.search_bar()?.addEventListener('keyup', function () {
|
|
|
|
|
useSearchTerm(this.value);
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
dom.btn_clear_search()?.addEventListener('click', function () {
|
|
|
|
|
useSearchTerm("");
|
|
|
|
|
dom.search_bar().value = "";
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Function comparing two elements.
|
|
|
|
|
*
|
|
|
|
@ -562,25 +595,73 @@ function markSortableColumns() {
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @type {HTMLTableRowElement[]}
|
|
|
|
|
*/
|
|
|
|
|
const communityFullRowCache = [];
|
|
|
|
|
|
|
|
|
|
function initializeSearch() {
|
|
|
|
|
communityFullRowCache.push(...dom.tbl_communities_content_rows());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* @param {string} [rawTerm]
|
|
|
|
|
*/
|
|
|
|
|
function useSearchTerm(rawTerm) {
|
|
|
|
|
if (!rawTerm) {
|
|
|
|
|
replaceRowsWith(communityFullRowCache);
|
|
|
|
|
} else {
|
|
|
|
|
const term = rawTerm.toLowerCase();
|
|
|
|
|
const termTags = Array.from(rawTerm.matchAll(/#[^#\s]+/g)).map(match => match[0].slice(1).toLowerCase());
|
|
|
|
|
const newRows = communityFullRowCache.filter(
|
|
|
|
|
row => {
|
|
|
|
|
const rowInfo = dom.row_info(row);
|
|
|
|
|
const rowTags = rowInfo.tags.map(({text}) => text);
|
|
|
|
|
return rowInfo.name.toLowerCase().includes(term) ||
|
|
|
|
|
rowInfo.description.toLowerCase().includes(term) ||
|
|
|
|
|
(termTags.length >= 1 && termTags.some(tag => rowTags.some(rowTag => rowTag.includes(tag))))
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
if (newRows.length === 0) {
|
|
|
|
|
dom.search_bar()?.classList.add(CLASSES.SEARCH.NO_RESULTS);
|
|
|
|
|
} else {
|
|
|
|
|
dom.search_bar()?.classList.remove(CLASSES.SEARCH.NO_RESULTS);
|
|
|
|
|
}
|
|
|
|
|
replaceRowsWith(newRows);
|
|
|
|
|
}
|
|
|
|
|
sortTable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function replaceRowsWith(rows) {
|
|
|
|
|
dom.tbl_communities_content_rows().forEach(row => row.remove());
|
|
|
|
|
dom.tbl_communities().querySelector("tbody").append(...rows);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Sorts the default communities table according the given column.
|
|
|
|
|
* Sort direction is determined by defaults; successive sorts
|
|
|
|
|
* on the same column reverse the sort direction.
|
|
|
|
|
* @param {number} column - Numeric ID of column being sorted.
|
|
|
|
|
* @param {number} [column] - Numeric ID of column being sorted. Re-applies last sort if absent.
|
|
|
|
|
*/
|
|
|
|
|
function sortTable(column) {
|
|
|
|
|
const table = dom.tbl_communities();
|
|
|
|
|
const sortState = getSortState(table);
|
|
|
|
|
const sortingAsBefore = column === undefined;
|
|
|
|
|
const sortingNewColumn = column !== sortState?.column;
|
|
|
|
|
const ascending = sortingNewColumn
|
|
|
|
|
? columnAscendingByDefault(column)
|
|
|
|
|
: !sortState.ascending;
|
|
|
|
|
const compare = makeRowComparer(column, ascending);
|
|
|
|
|
const sortedColumn = column ?? sortState?.column;
|
|
|
|
|
const ascending =
|
|
|
|
|
sortingAsBefore ?
|
|
|
|
|
sortState.ascending : (
|
|
|
|
|
sortingNewColumn
|
|
|
|
|
? columnAscendingByDefault(column)
|
|
|
|
|
: !sortState.ascending
|
|
|
|
|
);
|
|
|
|
|
const compare = makeRowComparer(sortedColumn, ascending);
|
|
|
|
|
const rows = Array.from(table.rows).slice(1);
|
|
|
|
|
rows.sort(compare);
|
|
|
|
|
rows.forEach((row) => row.remove());
|
|
|
|
|
table.querySelector("tbody").append(...rows);
|
|
|
|
|
setSortState(table, { ascending, column });
|
|
|
|
|
replaceRowsWith(rows);
|
|
|
|
|
setSortState(table, { ascending, column: sortedColumn });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// `html.js` selector for styling purposes
|
|
|
|
|