lint: handle js errors

dev
gravel 9 months ago
parent 09c96873a2
commit 31a68403aa
No known key found for this signature in database
GPG Key ID: CA95FFF4E0123903

@ -322,6 +322,7 @@ function createElement(tag, ...args) {
return element;
}
/** @type {Record<string, (...args: any | HTMLElement): HTMLElement>} */
export const element = new Proxy({}, {
get(_, key) {
return (...args) => createElement(key, ...args)

@ -15,7 +15,7 @@
// Import magic numbers and data
import {
dom, COLUMN, COLUMN_LITERAL, COMPARISON, ATTRIBUTES,
dom, COMPARISON, ATTRIBUTES,
columnAscendingByDefault, columnIsSortable, COLUMN_TRANSFORMATION,
element, JOIN_URL_PASTE, communityQRCodeURL, STAFF_ID_PASTE, IDENTIFIER_PASTE, DETAILS_LINK_PASTE, CLASSES, flagToLanguageAscii, RoomInfo, unreachable, workOnMainThread, onInteractive
} from './js/util.js';
@ -64,7 +64,6 @@ let shownCommunityId = "";
/**
* Create an interactive version of the Community join link.
* @param {string} join_link
* @returns {HTMLElement}
*/
const transformJoinURL = () => {
@ -153,6 +152,19 @@ function addInformativeInteractions() {
});
}
function enableEnterClicks() {
Array.from(document.querySelectorAll('.enter-clicks')).forEach(element => {
if (!(element instanceof HTMLElement)) return;
element.addEventListener('keydown', (/** @type {KeyboardEvent} */ ev) => {
if (ev.key == "Enter") {
if (!(ev.currentTarget instanceof HTMLElement)) {
console.error(".enter-clicks could not find its currentTarget");
} else ev.currentTarget.click();
}
})
})
}
async function fetchTableRestFragment() {
if (location.pathname != "/") return;
const request = await fetch("/_fragment/rest/");
@ -182,14 +194,7 @@ async function onLoad() {
preloadImages();
}, 60 * 60E3);
addInformativeInteractions();
Array.from(document.querySelectorAll('.enter-clicks')).forEach(element => {
// @ts-ignore
element.addEventListener('keydown', (/** @type {KeyboardEvent} */ ev) => {
if (ev.key == "Enter") {
ev.currentTarget.click();
}
})
})
enableEnterClicks();
await RoomInfo.fetchRooms();
reactToURLParameters();
addServerIconInteractions();
@ -200,7 +205,7 @@ async function onLoad() {
* Construct room tag DOM from its description.
* @param {Object} param0
* @param {string} param0.text Tag name
* @param {"user"|"reserved"} param0.type Tag classification
* @param {string} param0.type Tag classification
* @param {string} param0.description Tag details
* @returns HTMLElement
*/
@ -253,15 +258,22 @@ function displayQRModal(communityID, pane = 0) {
const tagContainer = dom.details_modal_tag_container();
tagContainer.innerHTML = "";
if (tagContainer) {
tagContainer.append(
...rowInfo.tags.map(tag => tagBody(tag))
);
tagContainer.innerHTML = "";
dom.details_modal_qr_code().src = communityQRCodeURL(communityID);
tagContainer.append(
...rowInfo.tags.map(tag => tagBody(tag))
);
} else console.error(`Could not find tag container for ${communityID}`);
document.getElementById('details-modal-panes').setAttribute('data-pane', pane);
const qrCode = dom.details_modal_qr_code();
if (qrCode instanceof HTMLImageElement) {
qrCode.src = communityQRCodeURL(communityID);
} else console.error(`Could not find QR code <img>`);
document.getElementById('details-modal-panes')?.setAttribute('data-pane', `${pane}`);
location.hash=`#${communityID}`;
@ -272,7 +284,8 @@ function displayQRModal(communityID, pane = 0) {
* Hides the Community details modal.
*/
function hideQRModal() {
dom.details_modal().close();
const detailsModal = dom.details_modal();
if (detailsModal) detailsModal.close(); else console.error("hideQRModal(): detailsModal is null")
shownCommunityId = "";
}
@ -301,7 +314,7 @@ function addQRModalHandlers() {
displayQRModal(communityID);
}
)
row.querySelector('.td_name').addEventListener(
row.querySelector('.td_name')?.addEventListener(
'click',
(e) => {
e.preventDefault();
@ -311,17 +324,20 @@ function addQRModalHandlers() {
}
const closeButton =
dom.details_modal().querySelector('#details-modal-close');
closeButton.addEventListener(
'click',
() => hideQRModal()
);
dom.details_modal().addEventListener('click', function (e) {
if (this == e.target) {
this.close();
}
});
const detailsModal = dom.details_modal();
if (detailsModal) {
const closeButton = detailsModal.querySelector('#details-modal-close');
closeButton?.addEventListener(
'click',
() => hideQRModal()
);
detailsModal.addEventListener('click', function (e) {
if (this == e.target) {
this.close();
}
});
} else console.error("Could not find details modal");
for (const button of document.querySelectorAll('.details-modal-pane-button')) {
button.addEventListener(
@ -333,7 +349,7 @@ function addQRModalHandlers() {
)
}
document.querySelector('#details-modal-copy-button').addEventListener(
document.querySelector('#details-modal-copy-button')?.addEventListener(
'click',
function () {
copyToClipboard(this.getAttribute('data-href'));
@ -391,7 +407,8 @@ function addQRModalHandlers() {
const increment = isLeftArrowKey ? -1 : 1;
const newRowIndex = (shownRowIndex + increment + communityRows.length) % communityRows.length;
const newRowIdentifier = communityRows[newRowIndex].identifier;
displayQRModal(newRowIdentifier);
if (newRowIdentifier === null) console.error("newRowIdentifier is null");
else displayQRModal(newRowIdentifier);
})
}
@ -637,6 +654,7 @@ function compareAscending(fst, snd) {
// Triple equals to avoid "" == 0.
if (fst === "") return COMPARISON.GREATER;
if (snd === "") return COMPARISON.SMALLER;
// @ts-ignore
return (fst > snd) - (fst < snd);
}
@ -699,8 +717,16 @@ function getSortState(table) {
const directionState = table.getAttribute(ATTRIBUTES.SORTING.ASCENDING);
// This is not pretty, but the least annoying.
// Checking for classes would be more idiomatic.
if (directionState === null) {
console.error("directionState was null");
return null;
}
const ascending = directionState.toString() === "true";
const columnState = table.getAttribute(ATTRIBUTES.SORTING.COLUMN);
if (columnState === null) {
console.error("columnState was null");
return null;
}
const column = parseInt(columnState);
if (!Number.isInteger(column)) {
throw new Error(`Invalid column number read from table: ${columnState}`)
@ -715,22 +741,23 @@ function getSortState(table) {
*/
function setSortState(table, { ascending, column }) {
if (!table.hasAttribute(ATTRIBUTES.SORTING.ACTIVE)) {
table.setAttribute(ATTRIBUTES.SORTING.ACTIVE, true);
table.setAttribute(ATTRIBUTES.SORTING.ACTIVE, `${true}`);
}
table.setAttribute(ATTRIBUTES.SORTING.ASCENDING, ascending);
table.setAttribute(ATTRIBUTES.SORTING.COLUMN, column);
table.setAttribute(ATTRIBUTES.SORTING.ASCENDING, `${ascending}`);
table.setAttribute(ATTRIBUTES.SORTING.COLUMN, `${column}`);
// No way around this for brief CSS.
const headers = table.querySelectorAll("th");
headers.forEach((th, colno) => {
th.removeAttribute(ATTRIBUTES.SORTING.ACTIVE);
});
headers[column].setAttribute(ATTRIBUTES.SORTING.ACTIVE, true);
headers[column].setAttribute(ATTRIBUTES.SORTING.ACTIVE, `${true}`);
}
// This is best done in JS, as it would require <noscript> styles otherwise.
function markSortableColumns() {
const table = dom.tbl_communities();
if (!table) throw new Error("markSortableColumns(): could not find table");
const header_cells = table.querySelectorAll('th');
for (let colno = 0; colno < header_cells.length; colno++) {
if (!columnIsSortable(colno)) continue;

Loading…
Cancel
Save