mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-06-06 03:34:40 +00:00
fix: more reliable zoom buttons on timetable page
This commit is contained in:
@@ -39,43 +39,14 @@ const zoomHandlers = new WeakMap<
|
|||||||
>();
|
>();
|
||||||
|
|
||||||
function resetTimetableStyles(): void {
|
function resetTimetableStyles(): void {
|
||||||
const firstDayColumn = document.querySelector(
|
// Reset entry opacity (for assessment hide feature)
|
||||||
".dailycal .content .days td",
|
|
||||||
) as HTMLElement;
|
|
||||||
if (!firstDayColumn) return;
|
|
||||||
|
|
||||||
const baseContainerHeight =
|
|
||||||
parseInt(firstDayColumn.style.height) || firstDayColumn.offsetHeight;
|
|
||||||
|
|
||||||
const dayColumns = document.querySelectorAll(".dailycal .content .days td");
|
|
||||||
dayColumns.forEach((td: Element) => {
|
|
||||||
(td as HTMLElement).style.height = `${baseContainerHeight}px`;
|
|
||||||
});
|
|
||||||
|
|
||||||
const timeColumn = document.querySelector(".times");
|
|
||||||
if (timeColumn) {
|
|
||||||
const times = timeColumn.querySelectorAll(".time");
|
|
||||||
const timeHeight = baseContainerHeight / times.length;
|
|
||||||
times.forEach((time: Element) => {
|
|
||||||
(time as HTMLElement).style.height = `${timeHeight}px`;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const lessons = document.querySelectorAll(".dailycal .lesson");
|
|
||||||
lessons.forEach((lesson: Element) => {
|
|
||||||
const lessonEl = lesson as HTMLElement;
|
|
||||||
const originalHeight = lessonEl.getAttribute("data-original-height");
|
|
||||||
if (originalHeight) {
|
|
||||||
lessonEl.style.height = `${originalHeight}px`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const entries = document.querySelectorAll(".entry");
|
const entries = document.querySelectorAll(".entry");
|
||||||
entries.forEach((entry: Element) => {
|
entries.forEach((entry: Element) => {
|
||||||
const entryEl = entry as HTMLElement;
|
const entryEl = entry as HTMLElement;
|
||||||
entryEl.style.opacity = "1";
|
entryEl.style.opacity = "1";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Clean up zoom control event handlers
|
||||||
const zoomControls = document.querySelector(".timetable-zoom-controls");
|
const zoomControls = document.querySelector(".timetable-zoom-controls");
|
||||||
if (zoomControls) {
|
if (zoomControls) {
|
||||||
const handlers = zoomHandlers.get(zoomControls);
|
const handlers = zoomHandlers.get(zoomControls);
|
||||||
@@ -94,17 +65,7 @@ function resetTimetableStyles(): void {
|
|||||||
async function handleTimetable(): Promise<void> {
|
async function handleTimetable(): Promise<void> {
|
||||||
await waitForElm(".time", true, 10);
|
await waitForElm(".time", true, 10);
|
||||||
|
|
||||||
// Store original heights when timetable loads
|
// Convert time format if needed
|
||||||
const lessons = document.querySelectorAll(".dailycal .lesson");
|
|
||||||
lessons.forEach((lesson: Element) => {
|
|
||||||
const lessonEl = lesson as HTMLElement;
|
|
||||||
lessonEl.setAttribute(
|
|
||||||
"data-original-height",
|
|
||||||
lessonEl.offsetHeight.toString(),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Existing time format code
|
|
||||||
if (settingsState.timeFormat == "12") {
|
if (settingsState.timeFormat == "12") {
|
||||||
const times = document.querySelectorAll(".timetablepage .times .time");
|
const times = document.querySelectorAll(".timetablepage .times .time");
|
||||||
for (const time of times) {
|
for (const time of times) {
|
||||||
@@ -120,14 +81,6 @@ async function handleTimetable(): Promise<void> {
|
|||||||
function handleTimetableZoom(): void {
|
function handleTimetableZoom(): void {
|
||||||
console.log("Initializing timetable zoom controls");
|
console.log("Initializing timetable zoom controls");
|
||||||
|
|
||||||
// Lazy initialize state variables only when function is first called
|
|
||||||
let timetableZoomLevel = 1;
|
|
||||||
let baseContainerHeight: number | null = null;
|
|
||||||
const originalEntryPositions = new Map<
|
|
||||||
Element,
|
|
||||||
{ topRatio: number; heightRatio: number }
|
|
||||||
>();
|
|
||||||
|
|
||||||
// Create zoom controls
|
// Create zoom controls
|
||||||
const zoomControls = document.createElement("div");
|
const zoomControls = document.createElement("div");
|
||||||
zoomControls.className = "timetable-zoom-controls";
|
zoomControls.className = "timetable-zoom-controls";
|
||||||
@@ -148,16 +101,16 @@ function handleTimetableZoom(): void {
|
|||||||
|
|
||||||
// Store event listener references
|
// Store event listener references
|
||||||
const zoomInHandler = () => {
|
const zoomInHandler = () => {
|
||||||
if (timetableZoomLevel < 2) {
|
const seqtaZoomIn = document.querySelector('.uiButton.zoom.in') as HTMLElement;
|
||||||
timetableZoomLevel += 0.2;
|
if (seqtaZoomIn) {
|
||||||
updateZoom();
|
seqtaZoomIn.click();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const zoomOutHandler = () => {
|
const zoomOutHandler = () => {
|
||||||
if (timetableZoomLevel > 0.6) {
|
const seqtaZoomOut = document.querySelector('.uiButton.zoom.out') as HTMLElement;
|
||||||
timetableZoomLevel -= 0.2;
|
if (seqtaZoomOut) {
|
||||||
updateZoom();
|
seqtaZoomOut.click();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -169,84 +122,6 @@ function handleTimetableZoom(): void {
|
|||||||
zoomIn: zoomInHandler,
|
zoomIn: zoomInHandler,
|
||||||
zoomOut: zoomOutHandler,
|
zoomOut: zoomOutHandler,
|
||||||
});
|
});
|
||||||
|
|
||||||
const initializePositions = () => {
|
|
||||||
// Get the base container height from the first TD
|
|
||||||
const firstDayColumn = document.querySelector(
|
|
||||||
".dailycal .content .days td",
|
|
||||||
) as HTMLElement;
|
|
||||||
if (!firstDayColumn) return false;
|
|
||||||
|
|
||||||
baseContainerHeight =
|
|
||||||
parseInt(firstDayColumn.style.height) || firstDayColumn.offsetHeight;
|
|
||||||
|
|
||||||
// Store original ratios
|
|
||||||
const entries = document.querySelectorAll(".entriesWrapper .entry");
|
|
||||||
entries.forEach((entry: Element) => {
|
|
||||||
const entryEl = entry as HTMLElement;
|
|
||||||
|
|
||||||
// Calculate ratios relative to detected base height
|
|
||||||
if (baseContainerHeight === null) return;
|
|
||||||
const topRatio = parseInt(entryEl.style.top) / baseContainerHeight;
|
|
||||||
const heightRatio = parseInt(entryEl.style.height) / baseContainerHeight;
|
|
||||||
|
|
||||||
originalEntryPositions.set(entry, { topRatio, heightRatio });
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
const updateZoom = () => {
|
|
||||||
// Initialize positions if not already done
|
|
||||||
if (baseContainerHeight === null && !initializePositions()) {
|
|
||||||
console.error("Failed to initialize positions");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.debug(`Updating zoom level to: ${timetableZoomLevel}`);
|
|
||||||
|
|
||||||
// Calculate new container height
|
|
||||||
if (baseContainerHeight === null) return;
|
|
||||||
const newContainerHeight = baseContainerHeight * timetableZoomLevel;
|
|
||||||
|
|
||||||
// Update all day columns (TDs)
|
|
||||||
const dayColumns = document.querySelectorAll(".dailycal .content .days td");
|
|
||||||
dayColumns.forEach((td: Element) => {
|
|
||||||
(td as HTMLElement).style.height = `${newContainerHeight}px`;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update all entries using stored ratios
|
|
||||||
const entries = document.querySelectorAll(".entriesWrapper .entry");
|
|
||||||
entries.forEach((entry: Element) => {
|
|
||||||
const entryEl = entry as HTMLElement;
|
|
||||||
const originalRatios = originalEntryPositions.get(entry);
|
|
||||||
|
|
||||||
if (originalRatios) {
|
|
||||||
// Calculate new positions from original ratios
|
|
||||||
const newTop = originalRatios.topRatio * newContainerHeight;
|
|
||||||
const newHeight = originalRatios.heightRatio * newContainerHeight;
|
|
||||||
|
|
||||||
// Apply new values
|
|
||||||
entryEl.style.top = `${Math.round(newTop)}px`;
|
|
||||||
entryEl.style.height = `${Math.round(newHeight)}px`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update time column to match
|
|
||||||
const timeColumn = document.querySelector(".times");
|
|
||||||
if (timeColumn) {
|
|
||||||
const times = timeColumn.querySelectorAll(".time");
|
|
||||||
const timeHeight = newContainerHeight / times.length;
|
|
||||||
times.forEach((time: Element) => {
|
|
||||||
(time as HTMLElement).style.height = `${timeHeight}px`;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
entries[Math.round((entries.length - 1) / 2)].scrollIntoView({
|
|
||||||
behavior: "instant",
|
|
||||||
block: "center",
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleTimetableAssessmentHide(): void {
|
function handleTimetableAssessmentHide(): void {
|
||||||
|
|||||||
Reference in New Issue
Block a user