diff --git a/app/index.js b/app/index.js
index 8402f09..8484a42 100644
--- a/app/index.js
+++ b/app/index.js
@@ -3,8 +3,18 @@ window.onload = () => resetState();
document.addEventListener('DOMContentLoaded', () => {
resetState();
jsonDataFetched = false;
- });
+});
+function handleYearSort() {
+ const yearButton = document.getElementById('sort-by-year');
+ if (yearButton.textContent === 'Year ▼') {
+ sortQuestionsByYear('asc');
+ yearButton.textContent = 'Year ▲';
+ } else {
+ sortQuestionsByYear('desc');
+ yearButton.textContent = 'Year ▼';
+ }
+}
function toggleModal(){document.getElementById("modal").classList.toggle("hidden")}
function toggleMS(){document.getElementById("markscheme").classList.toggle("hidden")}
@@ -12,7 +22,6 @@ function toggleR(){document.getElementById("report").classList.toggle("hidden")}
function toggleHelp(){document.getElementById("helpmenu").classList.toggle("hidden")}
function toggleDownAllQs(){document.getElementById("addalltoPDFbtn").classList.remove('hidden');document.getElementById("generatePDFbtn").classList.remove('hidden')}
-
function toggleDarkMode() {
var body = document.body;
var head = document.head;
@@ -152,6 +161,8 @@ let jsonDataFetched = false;
let jsonData = null;
let currentFileName = null;
let topics = [];
+let subtopics = [];
+let sortOrder = null;
const domCache = {
rightCol: document.getElementById("right-col"),
@@ -312,36 +323,101 @@ async function loadJSON(filename) {
}
}
+// Extract year from question ID (e.g., "23M.1A.SL.TZ2.39" -> 2023)
+function extractYear(questionId) {
+ if (!questionId || typeof questionId !== 'string') return 0;
+
+ // Extract the first two digits
+ const match = questionId.match(/^(\d{2})/);
+ if (!match) return 0;
+
+ let year = parseInt(match[1], 10);
+
+ // Convert to four-digit year
+ if (year >= 0 && year <= 99) {
+ if (year >= 0 && year <= 25) {
+ year += 2000; // 00-25 -> 2000-2025
+ } else {
+ year += 1900; // 26-99 -> 1926-1999
+ }
+ }
+
+ return year;
+}
+// Function to sort questions by year
+function sortQuestionsByYear(direction = 'asc') {
+ if (!jsonData || !Array.isArray(jsonData)) return;
+
+ sortOrder = direction;
+
+ const sortedData = [...jsonData].sort((a, b) => {
+ const yearA = extractYear(a.question_id);
+ const yearB = extractYear(b.question_id);
+
+ return direction === 'asc' ? yearA - yearB : yearB - yearA;
+ });
+
+ // Clear the existing questions
+ clearDisplayedQuestions();
+
+ // Re-render with sorted data
+ renderQuestions(sortedData);
+
+ // Maintain topic filter states
+ document.querySelectorAll('input[name="topic"]:checked').forEach(checkbox => {
+ document.querySelectorAll(`div[class*="${checkbox.value}"]`)
+ .forEach(div => div.classList.remove('hidden'));
+ });
+}
-function processData(data, filename) {
- jsonDataFetched = true;
- currentFileName = filename;
+// Function to reset sorting and show questions in original order
+function resetSorting() {
+ if (!jsonData || !Array.isArray(jsonData)) return;
+
+ sortOrder = null;
+ document.getElementById('sort-by-year').textContent = 'Year ▼';
+
+ // Clear the existing questions
+ clearDisplayedQuestions();
+
+ // Re-render with original data
+ renderQuestions(jsonData);
+
+ // Maintain topic filter states
+ document.querySelectorAll('input[name="topic"]:checked').forEach(checkbox => {
+ document.querySelectorAll(`div[class*="${checkbox.value}"]`)
+ .forEach(div => div.classList.remove('hidden'));
+ });
+}
- topics = [...new Set(data.flatMap(item => item.topics))].sort();
- subtopics = [...new Set(data.flatMap(item => item.subtopics))].sort();
- renderTopics();
+// Function to clear displayed questions but keep filters
+function clearDisplayedQuestions() {
+ domCache.rightCol.innerHTML = '';
+ document.querySelectorAll('#markscheme-box > div').forEach(el => el.remove());
+ document.querySelectorAll('#report-box > div').forEach(el => el.remove());
+ document.querySelectorAll('#markscheme-box2 > svg').forEach(el => el.remove());
+ document.querySelectorAll('#report-box2 > svg').forEach(el => el.remove());
+}
- const fragment = document.createDocumentFragment();
+// Function to render questions (extracted from processData)
+function renderQuestions(data) {
+ const fragment = document.createDocumentFragment();
- data.forEach(item => {
+ data.forEach(item => {
const {
- Question: question,
- question_id: questionid,
- Markscheme: markscheme,
- 'Examiners report': report,
- topics,
- subtopics
+ Question: question,
+ question_id: questionid,
+ Markscheme: markscheme,
+ 'Examiners report': report,
+ topics,
+ subtopics,
+ year
} = item;
const bigQuestionBox = document.createElement("div");
bigQuestionBox.id = questionid;
- /*const allClasses = [...topics.map(t => t.trim()),
- subtopics,
- "hidden"];
- bigQuestionBox.classList.add(...allClasses);*/
-
const allClasses = [
...topics.map(t => t.trim()).filter(t => t),
...(typeof subtopics === "string" ? [subtopics] : []),
@@ -350,133 +426,112 @@ function processData(data, filename) {
bigQuestionBox.classList.add(...allClasses);
-
const btnContainer = document.createElement("div");
btnContainer.classList.add("btn-container");
function toggleMScont(questionid) {
- const markschemeContainer = document.getElementById(`markscheme-${questionid} ${currentFileName}`);
- toggleMSSvg.classList.toggle('hidden');
- markschemeContainer.classList.toggle('hidden');
- activeQuestionId = markschemeContainer.classList.contains('hidden') ? null : questionid;
+ const markschemeContainer = document.getElementById(`markscheme-${questionid} ${currentFileName}`);
+ const toggleMSSvg = document.querySelector(`#markscheme-box2 svg`); // Simplified selector
+ toggleMSSvg.classList.toggle('hidden');
+ markschemeContainer.classList.toggle('hidden');
+ activeQuestionId = markschemeContainer.classList.contains('hidden') ? null : questionid;
}
function toggleRepcont(questionid) {
- const reportContainer = document.getElementById(`report-${questionid} ${currentFileName}`);
- toggleRepSvg.classList.toggle('hidden');
- reportContainer.classList.toggle('hidden');
- activeQuestionId = reportContainer.classList.contains('hidden') ? null : questionid;
+ const reportContainer = document.getElementById(`report-${questionid} ${currentFileName}`);
+ const toggleRepSvg = document.querySelector(`#report-box2 svg`); // Simplified selector
+ toggleRepSvg.classList.toggle('hidden');
+ reportContainer.classList.toggle('hidden');
+ activeQuestionId = reportContainer.classList.contains('hidden') ? null : questionid;
}
const buttons = [
- { text: "Markscheme", handler: () => { toggleMS(); toggleMScont(questionid); } },
- { text: "Examiners report", handler: () => { toggleR(); toggleRepcont(questionid); } },
- { text: "Add to PDF", handler: createPDFButtonHandler(questionid) }
+ { text: "Markscheme", handler: () => { toggleMS(); toggleMScont(questionid); } },
+ { text: "Examiners report", handler: () => { toggleR(); toggleRepcont(questionid); } },
+ { text: "Add to PDF", handler: createPDFButtonHandler(questionid) }
].map(createButton);
buttons.forEach(button => btnContainer.appendChild(button));
+ // Add full year from extracted two-digit year
+ const extractedYear = extractYear(questionid);
+ const yearText = extractedYear ? `
Year: ${extractedYear}
` : '';
+
const content = `
-
${questionid}
-
Topics: ${topics.join(', ')}
-
Subtopics: ${subtopics.join(', ')}
-
${question}
- `;
+
${questionid}
+ ${yearText}
+
Topics: ${topics.join(', ')}
+
Subtopics: ${subtopics.join(', ')}
+
${question}
+ `;
bigQuestionBox.innerHTML = content;
bigQuestionBox.querySelector('h3').after(btnContainer);
if (markscheme) {
- createContainer('markscheme', questionid, filename, markscheme, domCache.msbox);
+ createContainer('markscheme', questionid, currentFileName, markscheme, domCache.msbox);
}
if (report) {
- createContainer('report', questionid, filename, report, domCache.reportbox);
+ createContainer('report', questionid, currentFileName, report, domCache.reportbox);
}
- /********** Removed ID appending method since it was slowing down interaction with the X svg *********/
-
const toggleMSSvg = createSVGElement(questionid);
- //toggleMSSvg.id = `toggleMSSvg-${questionid}`;
-
const toggleRepSvg = createSVGElement(questionid);
- //toggleRepSvg.id = `toggleRepSvg-${questionid}`;
domCache.msbox2.appendChild(toggleMSSvg);
domCache.repbox2.appendChild(toggleRepSvg);
- /*toggleMSSvg.addEventListener('click', () => {
- toggleMScont(questionid);
- toggleMS();
- });*/
-
- /********** Identifying by active question instead **********/
let activeQuestionId = null;
const handleToggle = () => {
- if (activeQuestionId) {
- const markschemeContainer = document.getElementById(`markscheme-${activeQuestionId} ${currentFileName}`);
- const reportContainer = document.getElementById(`report-${activeQuestionId} ${currentFileName}`);
+ if (activeQuestionId) {
+ const markschemeContainer = document.getElementById(`markscheme-${activeQuestionId} ${currentFileName}`);
+ const reportContainer = document.getElementById(`report-${activeQuestionId} ${currentFileName}`);
- if (markschemeContainer && !markschemeContainer.classList.contains('hidden')) {
- toggleMSSvg.classList.toggle('hidden');
- toggleMS();
- markschemeContainer.classList.toggle('hidden');
- activeQuestionId = null;
-
- } else if (reportContainer && !reportContainer.classList.contains('hidden')) {
- toggleRepSvg.classList.toggle('hidden');
- toggleR();
- reportContainer.classList.toggle('hidden');
- activeQuestionId = null;
- }
+ if (markschemeContainer && !markschemeContainer.classList.contains('hidden')) {
+ toggleMSSvg.classList.toggle('hidden');
+ toggleMS();
+ markschemeContainer.classList.toggle('hidden');
+ activeQuestionId = null;
+ } else if (reportContainer && !reportContainer.classList.contains('hidden')) {
+ toggleRepSvg.classList.toggle('hidden');
+ toggleR();
+ reportContainer.classList.toggle('hidden');
+ activeQuestionId = null;
+ }
}
- }
+ };
toggleMSSvg.addEventListener('click', handleToggle);
toggleRepSvg.addEventListener('click', handleToggle);
- document.addEventListener('keydown', (event) => {
- if (event.key === 'Escape') {
- handleToggle();
- }
- });
-
-
- /*toggleRepSvg.addEventListener('click', () => {
- toggleRepcont(questionid);
- toggleR();
- });*/
fragment.appendChild(bigQuestionBox);
- });
-
- domCache.rightCol.appendChild(fragment);
- updateSquareContainers();
- toggleDownAllQs();
+ });
+ domCache.rightCol.appendChild(fragment);
+ updateSquareContainers();
+ toggleDownAllQs();
}
+function processData(data, filename) {
+ jsonData = data; // Store the data for sorting
+ jsonDataFetched = true;
+ currentFileName = filename;
-/******** Old function for fetching JSON, deprecated in favor of IndexedDB ********/
-/*function loadJSON(filename) {
- fetch(`https://pub-59370068cd854c158959e7ca4578e5bd.r2.dev/${filename}`) // ../assets/jsonqb/
- .then(response => response.json())
- .then(data => {
- jsonDataFetched = true;
- currentFileName = filename;
+ topics = [...new Set(data.flatMap(item => item.topics))].sort();
+ subtopics = [...new Set(data.flatMap(item => item.subtopics))].sort();
+ renderTopics();
- topics = [...new Set(data.flatMap(item => item.topics))].sort();
- renderTopics();
-
- const fragment = document.createDocumentFragment();
-
- data.forEach(item => {});
-
- domCache.rightCol.appendChild(fragment);
- updateSquareContainers();
- })
- .catch(error => console.error('Error fetching JSON:', error));
-}*/
+ // Reset sort button state
+ const yearButton = document.getElementById('sort-by-year');
+ if (yearButton) {
+ yearButton.textContent = 'Year ▼';
+ }
+
+ // Render questions
+ renderQuestions(data);
+}
function createButton({ text, handler, className = 'btn-secondary' }) {
const button = document.createElement("button");
@@ -552,9 +607,6 @@ document.addEventListener('DOMContentLoaded', () => {
if (jsonDataFetched && filename !== currentFileName) {
resetState();
loadJSON(filename);
- //} else if (jsonDataFetched && filename === currentFileName) {
- //resetState();
- //jsonDataFetched = false;
} else if (!jsonDataFetched) {
loadJSON(filename);
}
@@ -564,5 +616,28 @@ document.addEventListener('DOMContentLoaded', () => {
function resetState() {
domCache.rightCol.innerHTML = '';
document.querySelectorAll('.topic-label').forEach(label => label.remove());
+ const yearButton = document.getElementById('sort-by-year');
+ if (yearButton) {
+ yearButton.textContent = 'Year ▼';
+ }
sessionStorage.setItem('selectedQuestionIds', '[]');
+ sortOrder = null;
+}
+
+function toggleDarkMode() {
+ var body = document.body;
+ var head = document.head;
+ var toggleButton = document.getElementById("darkmodebtn");
+
+ if (localStorage.getItem("darkMode") === "disabled") {
+ body.classList.add("dark-mode");
+ head.classList.add("dark-mode");
+ localStorage.setItem("darkMode", "enabled");
+ toggleButton.innerText = "Light Mode";
+ } else {
+ body.classList.remove("dark-mode");
+ head.classList.remove("dark-mode");
+ localStorage.setItem("darkMode", "disabled");
+ toggleButton.innerText = "Dark Mode";
+ }
}
\ No newline at end of file
diff --git a/assets/style.css b/assets/style.css
index feb26e3..33c7579 100644
--- a/assets/style.css
+++ b/assets/style.css
@@ -356,6 +356,23 @@ h4 {
overflow-y: scroll;
}
+#sorting-container {
+ margin-bottom: 15px;
+ padding: 10px;
+ background-color: #f5f5f5;
+ border-radius: 5px;
+ border: 1px solid #ddd;
+}
+
+#sorting-container label {
+ font-weight: bold;
+ margin-right: 10px;
+}
+
+#sorting-container button {
+ margin-right: 5px;
+}
+
.square-container {
display: flex;
flex-direction: column;