Update 5 files
- /assets/index-0e5924d3.css - /app/index.js - /app/index.html - /index.html - /assets/style.css
This commit is contained in:
parent
16100dc229
commit
a7059d3929
4 changed files with 657 additions and 444 deletions
477
app/index.html
477
app/index.html
File diff suppressed because one or more lines are too long
552
app/index.js
Normal file
552
app/index.js
Normal file
|
@ -0,0 +1,552 @@
|
|||
let questionid="";
|
||||
window.onload = () => resetState();
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
resetState();
|
||||
jsonDataFetched = false;
|
||||
});
|
||||
|
||||
|
||||
function toggleModal(){document.getElementById("modal").classList.toggle("hidden")}
|
||||
function toggleMS(){document.getElementById("markscheme").classList.toggle("hidden")}
|
||||
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;
|
||||
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";
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const darkModeStatus = localStorage.getItem("darkMode");
|
||||
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||
|
||||
if (darkModeStatus === "enabled") {
|
||||
document.body.classList.add("dark-mode");
|
||||
document.head.classList.add("dark-mode");
|
||||
document.getElementById("darkmodebtn").innerText = "Light Mode";
|
||||
} else if (darkModeStatus === "disabled") {
|
||||
document.body.classList.remove("dark-mode");
|
||||
document.head.classList.remove("dark-mode");
|
||||
document.getElementById("darkmodebtn").innerText = "Dark Mode";
|
||||
} else if (prefersDarkScheme) {
|
||||
document.body.classList.add("dark-mode");
|
||||
document.head.classList.add("dark-mode");
|
||||
document.getElementById("darkmodebtn").innerText = "Light Mode";
|
||||
localStorage.setItem("darkMode", "enabled");
|
||||
} else {
|
||||
document.body.classList.remove("dark-mode");
|
||||
document.head.classList.remove("dark-mode");
|
||||
document.getElementById("darkmodebtn").innerText = "Dark Mode";
|
||||
localStorage.setItem("darkMode", "disabled");
|
||||
}
|
||||
});
|
||||
|
||||
function startRandomTimerLoop() {
|
||||
var randomTime = Math.floor(11 * Math.random()) + 20;
|
||||
setTimeout(() => {
|
||||
alert("Provided by pirateIB\nhttps://pirateib.xyz");
|
||||
startRandomTimerLoop();
|
||||
}, 60 * randomTime * 1000);
|
||||
}
|
||||
window.onload = function() {
|
||||
setTimeout(() => {
|
||||
startRandomTimerLoop();
|
||||
}, 300000);
|
||||
};
|
||||
|
||||
/*function generatePDF() {
|
||||
const selectedQuestionIds = JSON.parse(sessionStorage.getItem("selectedQuestionIds")) || [];
|
||||
if (0 === selectedQuestionIds.length) return alert("Select some questions first!");
|
||||
const printWindow = window.open("", "_blank");
|
||||
printWindow.document.write('\n <html>\n <head>\n <title>QuestionBank Test</title>\n <link rel="stylesheet" href="../assets/style.css">\n <style>\n @media print { body { overflow: hidden; } ::-webkit-scrollbar { display: none; } }\n </style>\n </head>\n <body>\n ');
|
||||
let concatenatedHTML = "";
|
||||
let markschemesHTML = '';
|
||||
selectedQuestionIds.forEach((questionId => {
|
||||
const questionDiv = document.getElementById(questionId),
|
||||
h3 = questionDiv.querySelector("h3"),
|
||||
squareContainer = questionDiv.querySelector(".square-container");
|
||||
concatenatedHTML += h3.outerHTML + squareContainer.outerHTML
|
||||
const msDiv = document.querySelector(`[id*="markscheme-${questionId}"]`);
|
||||
const cloneMsDiv = msDiv.cloneNode(true);
|
||||
cloneMsDiv.classList.remove('hidden');
|
||||
markschemesHTML += h3.outerHTML + cloneMsDiv.outerHTML;
|
||||
})), printWindow.document.write(`<h2>Questions</h2><br>${concatenatedHTML}<div style="page-break-after: always;"></div><h2>Markschemes</h2><br>${markschemesHTML}`), printWindow.document.write("\n </body>\n </html>\n "), printWindow.document.close();
|
||||
setTimeout(() => {
|
||||
printWindow.print(), printWindow.onafterprint = () => printWindow.close();
|
||||
}, 1000);}*/
|
||||
|
||||
function generatePDF() {
|
||||
const selectedQuestionIds = JSON.parse(sessionStorage.getItem("selectedQuestionIds")) || [];
|
||||
if (0 === selectedQuestionIds.length) return alert("Select some questions first!");
|
||||
|
||||
// Prompt the user for including markschemes
|
||||
let includeMarkschemes = null;
|
||||
while (includeMarkschemes !== "yes" && includeMarkschemes !== "no") {
|
||||
includeMarkschemes = prompt("Do you want to include markschemes? (yes/no)").toLowerCase();
|
||||
if (includeMarkschemes !== "yes" && includeMarkschemes !== "no") {
|
||||
alert("Please answer 'yes' or 'no'.");
|
||||
}
|
||||
}
|
||||
|
||||
const printWindow = window.open("", "_blank");
|
||||
printWindow.document.write('\n <html>\n <head>\n <title>QuestionBank Test</title>\n <link rel="stylesheet" href="../assets/style.css">\n <style>\n @media print { body { overflow: hidden; } ::-webkit-scrollbar { display: none; } }\n </style>\n </head>\n <body>\n ');
|
||||
|
||||
let concatenatedHTML = "";
|
||||
let markschemesHTML = '';
|
||||
|
||||
selectedQuestionIds.forEach((questionId) => {
|
||||
const questionDiv = document.getElementById(questionId),
|
||||
h3 = questionDiv.querySelector("h3"),
|
||||
squareContainer = questionDiv.querySelector(".square-container");
|
||||
concatenatedHTML += h3.outerHTML + squareContainer.outerHTML;
|
||||
|
||||
if (includeMarkschemes === "yes") {
|
||||
const msDiv = document.querySelector(`[id*="markscheme-${questionId}"]`);
|
||||
const cloneMsDiv = msDiv.cloneNode(true);
|
||||
cloneMsDiv.classList.remove('hidden');
|
||||
markschemesHTML += h3.outerHTML + cloneMsDiv.outerHTML;
|
||||
}
|
||||
});
|
||||
|
||||
printWindow.document.write(`<h2>Questions</h2><br>${concatenatedHTML}`);
|
||||
|
||||
if (includeMarkschemes === "yes") {
|
||||
printWindow.document.write(`<div style="page-break-after: always;"></div><h2>Markschemes</h2><br>${markschemesHTML}`);
|
||||
}
|
||||
|
||||
printWindow.document.write("\n </body>\n </html>\n ");
|
||||
printWindow.document.close();
|
||||
|
||||
setTimeout(() => {
|
||||
printWindow.print();
|
||||
printWindow.onafterprint = () => printWindow.close();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
|
||||
function addalltoPDF() {
|
||||
const buttons = document.querySelectorAll('.btn-secondary');
|
||||
buttons.forEach(button => {
|
||||
if (button.textContent.trim() === "Add to PDF" && !button.parentElement.parentElement.classList.contains('hidden')) {
|
||||
button.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let jsonDataFetched = false;
|
||||
let jsonData = null;
|
||||
let currentFileName = null;
|
||||
let topics = [];
|
||||
|
||||
const domCache = {
|
||||
rightCol: document.getElementById("right-col"),
|
||||
msbox: document.getElementById("markscheme-box"),
|
||||
reportbox: document.getElementById("report-box"),
|
||||
msbox2: document.getElementById("markscheme-box2"),
|
||||
repbox2: document.getElementById("report-box2"),
|
||||
leftCol: document.getElementById('left-col')
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Escape') {
|
||||
const modal = document.getElementById('modal');
|
||||
const helpmenu = document.getElementById('helpmenu');
|
||||
if (modal && !modal.classList.contains('hidden')) {
|
||||
toggleModal();
|
||||
} else if (helpmenu && !helpmenu.classList.contains('hidden')) {
|
||||
toggleHelp();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const fileNameMap = {
|
||||
'bioqb': 'Biology QB.json',
|
||||
'bmqb': 'Business Management QB.json',
|
||||
'chemqb': 'Chemistry QB.json',
|
||||
'compsciqb': 'Computer Science QB.json',
|
||||
'destechqb': 'Design Technology QB.json',
|
||||
'digsocqb': 'Digital Society QB.json',
|
||||
'econqb': 'Economics QB.json',
|
||||
'essqb': 'ESS QB.json',
|
||||
'geoqb': 'Geography QB.json',
|
||||
'histqb': 'History QB.json',
|
||||
'mathaaqb': 'Math AA QB.json',
|
||||
'mathaiqb': 'Math AI QB.json',
|
||||
'phyqb': 'Physics QB.json',
|
||||
'psychqb': 'Psychology QB.json',
|
||||
'sehsqb': 'SEHS QB.json'
|
||||
};
|
||||
|
||||
function createSVGElement(questionid) {
|
||||
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
||||
const attributes = {
|
||||
"width": "2rem",
|
||||
"height": "2rem",
|
||||
"viewBox": "0 0 24 24",
|
||||
"fill": "none",
|
||||
"stroke": "currentColor",
|
||||
"stroke-width": "2",
|
||||
"stroke-linecap": "round",
|
||||
"stroke-linejoin": "round"
|
||||
};
|
||||
|
||||
Object.entries(attributes).forEach(([key, value]) => {
|
||||
svg.setAttribute(key, value);
|
||||
});
|
||||
|
||||
svg.classList.add("cursor-pointer", "text-primary", "hidden");
|
||||
svg.innerHTML = `
|
||||
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
||||
<line x1="9" y1="9" x2="15" y2="15"></line>
|
||||
<line x1="15" y1="9" x2="9" y2="15"></line>
|
||||
`;
|
||||
return svg;
|
||||
}
|
||||
|
||||
function showLoading() {
|
||||
document.getElementById('loadingBanner').style.display = 'block';
|
||||
}
|
||||
|
||||
function hideLoading() {
|
||||
document.getElementById('loadingBanner').style.display = 'none';
|
||||
}
|
||||
|
||||
function openDatabase() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = indexedDB.open('myDatabase', 1);
|
||||
|
||||
request.onupgradeneeded = (event) => {
|
||||
const db = event.target.result;
|
||||
if (!db.objectStoreNames.contains('myStore')) {
|
||||
db.createObjectStore('myStore');
|
||||
}
|
||||
};
|
||||
|
||||
request.onsuccess = (event) => {
|
||||
resolve(event.target.result);
|
||||
};
|
||||
|
||||
request.onerror = (event) => {
|
||||
reject('Error opening database:', event.target.error);
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async function loadJSON(filename) {
|
||||
showLoading();
|
||||
const db = await openDatabase();
|
||||
|
||||
const cachedData = await new Promise((resolve, reject) => {
|
||||
const transaction = db.transaction('myStore', 'readonly');
|
||||
const store = transaction.objectStore('myStore');
|
||||
const request = store.get(filename);
|
||||
|
||||
request.onsuccess = (event) => {
|
||||
resolve(event.target.result);
|
||||
};
|
||||
|
||||
request.onerror = (event) => {
|
||||
reject('Error fetching data from IndexedDB:', event.target.error);
|
||||
};
|
||||
});
|
||||
|
||||
if (cachedData) {
|
||||
hideLoading();
|
||||
processData(cachedData, filename);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`https://pub-59370068cd854c158959e7ca4578e5bd.r2.dev/${filename}`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
const data = await response.json();
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
const transaction = db.transaction('myStore', 'readwrite');
|
||||
const store = transaction.objectStore('myStore');
|
||||
const request = store.put(data, filename);
|
||||
|
||||
request.onsuccess = () => {
|
||||
resolve();
|
||||
};
|
||||
|
||||
request.onerror = (event) => {
|
||||
reject('Error storing data in IndexedDB:', event.target.error);
|
||||
};
|
||||
});
|
||||
sessionStorage.setItem('selectedQuestionIds', '[]');
|
||||
|
||||
setTimeout(() => {
|
||||
processData(data, filename);
|
||||
hideLoading();
|
||||
sessionStorage.setItem('selectedQuestionIds', '[]');
|
||||
}, 0);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error fetching JSON:', error);
|
||||
hideLoading();
|
||||
sessionStorage.setItem('selectedQuestionIds', '[]');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function processData(data, filename) {
|
||||
jsonDataFetched = true;
|
||||
currentFileName = filename;
|
||||
|
||||
topics = [...new Set(data.flatMap(item => item.topics))].sort();
|
||||
renderTopics();
|
||||
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
data.forEach(item => {
|
||||
const {
|
||||
Question: question,
|
||||
question_id: questionid,
|
||||
Markscheme: markscheme,
|
||||
'Examiners report': report,
|
||||
topics,
|
||||
subtopics
|
||||
} = item;
|
||||
|
||||
const bigQuestionBox = document.createElement("div");
|
||||
bigQuestionBox.id = questionid;
|
||||
|
||||
const allClasses = [...topics.map(t => t.trim()),
|
||||
...subtopics.map(s => s.trim()),
|
||||
"hidden"];
|
||||
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;
|
||||
}
|
||||
|
||||
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 buttons = [
|
||||
{ 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));
|
||||
|
||||
const content = `
|
||||
<h3>${questionid}</h3>
|
||||
<h4><b>Topics:</b> ${topics.join(', ')}</h4>
|
||||
<h4><b>Subtopics:</b> ${subtopics.join(', ')}</h4>
|
||||
<div class="square-container">${question}</div>
|
||||
`;
|
||||
|
||||
bigQuestionBox.innerHTML = content;
|
||||
bigQuestionBox.querySelector('h3').after(btnContainer);
|
||||
|
||||
if (markscheme) {
|
||||
createContainer('markscheme', questionid, filename, markscheme, domCache.msbox);
|
||||
}
|
||||
|
||||
if (report) {
|
||||
createContainer('report', questionid, filename, 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 (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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/******** 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();
|
||||
renderTopics();
|
||||
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
data.forEach(item => {});
|
||||
|
||||
domCache.rightCol.appendChild(fragment);
|
||||
updateSquareContainers();
|
||||
})
|
||||
.catch(error => console.error('Error fetching JSON:', error));
|
||||
}*/
|
||||
|
||||
function createButton({ text, handler, className = 'btn-secondary' }) {
|
||||
const button = document.createElement("button");
|
||||
button.classList.add(className);
|
||||
button.textContent = text;
|
||||
button.addEventListener('click', handler);
|
||||
return button;
|
||||
}
|
||||
|
||||
function createPDFButtonHandler(questionid) {
|
||||
return function () {
|
||||
let selectedQuestionIds = JSON.parse(sessionStorage.getItem('selectedQuestionIds')) || [];
|
||||
const index = selectedQuestionIds.indexOf(questionid);
|
||||
if (index !== -1) {
|
||||
selectedQuestionIds.splice(index, 1);
|
||||
this.style.backgroundColor = 'rgb(66 165 245)';
|
||||
this.textContent = 'Add to PDF';
|
||||
} else {
|
||||
selectedQuestionIds.push(questionid);
|
||||
this.style.backgroundColor = '#e03b3b';
|
||||
this.textContent = 'Added!';
|
||||
}
|
||||
sessionStorage.setItem('selectedQuestionIds', JSON.stringify(selectedQuestionIds));
|
||||
};
|
||||
}
|
||||
|
||||
function createContainer(type, questionid, filename, content, parent) {
|
||||
const container = document.createElement("div");
|
||||
container.classList.add("square-container", "hidden");
|
||||
container.id = `${type}-${questionid} ${filename}`;
|
||||
container.innerHTML = content;
|
||||
parent.appendChild(container);
|
||||
}
|
||||
|
||||
function renderTopics() {
|
||||
const fragment = document.createDocumentFragment();
|
||||
|
||||
topics.forEach(topic => {
|
||||
const label = document.createElement('label');
|
||||
label.classList.add('topic-label');
|
||||
|
||||
const checkbox = document.createElement('input');
|
||||
checkbox.type = 'checkbox';
|
||||
checkbox.name = 'topic';
|
||||
checkbox.value = topic;
|
||||
|
||||
checkbox.addEventListener('change', () => {
|
||||
document.querySelectorAll(`div[class*="${topic}"]`)
|
||||
.forEach(div => div.classList.toggle('hidden'));
|
||||
});
|
||||
|
||||
label.append(checkbox, topic);
|
||||
fragment.appendChild(label);
|
||||
});
|
||||
|
||||
domCache.leftCol.appendChild(fragment);
|
||||
}
|
||||
|
||||
function updateSquareContainers() {
|
||||
document.querySelectorAll('.square-container').forEach(container => {
|
||||
const firstChild = container.children[0];
|
||||
if (firstChild?.classList.contains('question')) {
|
||||
firstChild.classList.replace('question', 'specification');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
document.addEventListener('click', event => {
|
||||
const filename = fileNameMap[event.target.id];
|
||||
if (!filename) return;
|
||||
|
||||
if (jsonDataFetched && filename !== currentFileName) {
|
||||
resetState();
|
||||
loadJSON(filename);
|
||||
//} else if (jsonDataFetched && filename === currentFileName) {
|
||||
//resetState();
|
||||
//jsonDataFetched = false;
|
||||
} else if (!jsonDataFetched) {
|
||||
loadJSON(filename);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function resetState() {
|
||||
domCache.rightCol.innerHTML = '';
|
||||
document.querySelectorAll('.topic-label').forEach(label => label.remove());
|
||||
sessionStorage.setItem('selectedQuestionIds', '[]');
|
||||
}
|
|
@ -254,6 +254,10 @@ video {
|
|||
display: none
|
||||
}
|
||||
|
||||
.mainpage {
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
body,
|
||||
html,
|
||||
#root {
|
||||
|
@ -311,15 +315,15 @@ h4 {
|
|||
|
||||
.btn-secondary {
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(3 54 40 / var(--tw-text-opacity));
|
||||
background-color: #55ad95
|
||||
color: rgb(248 248 248 / var(--tw-text-opacity));
|
||||
background-color: rgb(66 165 245 / var(--tw-text-opacity)); /*55ad95*/
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
--tw-bg-opacity: 1;
|
||||
background-color: rgb(85 173 149 / var(--tw-bg-opacity));
|
||||
background-color: #42a2f5;
|
||||
--tw-text-opacity: 1;
|
||||
color: rgb(248 248 248 / var(--tw-text-opacity))
|
||||
color: rgb(0 0 0 / var(--tw-text-opacity))
|
||||
}
|
||||
|
||||
#left-col {
|
||||
|
@ -343,6 +347,10 @@ h4 {
|
|||
position: relative;
|
||||
}
|
||||
|
||||
#markscheme, #report, #modal {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
#markscheme-box, #report-box{
|
||||
min-height: 100%;
|
||||
overflow-y: scroll;
|
50
index.html
50
index.html
|
@ -1,43 +1,41 @@
|
|||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="./favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Mortar & Pestle</title>
|
||||
<link rel="stylesheet" href="./assets/index-0e5924d3.css">
|
||||
<script>
|
||||
function toggleDarkMode() {
|
||||
const body = document.body;
|
||||
const button = document.querySelector('.btn-primary');
|
||||
body.classList.toggle('dark-mode');
|
||||
|
||||
if (body.classList.contains('dark-mode')) {
|
||||
button.style.position = 'static';
|
||||
button.style.zIndex = 'auto';
|
||||
} else {
|
||||
button.style.position = 'fixed';
|
||||
button.style.zIndex = '9999';
|
||||
button.style.right = '0';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="icon" type="image/svg+xml" href="./favicon.svg">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Mortar & Pestle | The Next Generation of Question Grinding</title>
|
||||
<link rel="stylesheet" href="./assets/style.css">
|
||||
<meta name="robots" content="index,follow">
|
||||
<meta name="copyright" content="Public Domain">
|
||||
<meta name="keywords" content="pestle, mortar, mortar & pestle, ib questionbank, pirateib">
|
||||
<meta name="description" content="Practice IB Exam-Style Questions, create topic-wise tests, and much more!">
|
||||
<meta property="og:locale" content="en_US">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:title" content="Mortar & Pestle | The Next Generation of Question Grinding">
|
||||
<meta property="og:description" content="Practice IB Exam-Style Questions, create topic-wise tests, and much more!">
|
||||
<meta property="og:url" content="https://pestle.pages.dev/">
|
||||
<meta property="og:site_name" content="Mortar & Pestle">
|
||||
<meta name="twitter:title" content="Mortar & Pestle | The Next Generation of Question Grinding">
|
||||
<meta name="twitter:description" content="Practice IB Exam-Style Questions, create topic-wise tests, and much more!">
|
||||
<script>function toggleDarkMode(){var e=document.body,d=document.head,t=document.getElementById("darkmodebtn");"disabled"===(localStorage.getItem("darkMode")||"disabled")?(e.classList.add("dark-mode"),d.classList.add("dark-mode"),localStorage.setItem("darkMode","enabled"),t.innerText="Light Mode"):(e.classList.remove("dark-mode"),d.classList.remove("dark-mode"),localStorage.setItem("darkMode","disabled"),t.innerText="Dark Mode")}document.addEventListener("DOMContentLoaded",(()=>{const e=localStorage.getItem("darkMode"),d=window.matchMedia("(prefers-color-scheme: dark)").matches;"enabled"===e?(document.body.classList.add("dark-mode"),document.head.classList.add("dark-mode"),document.getElementById("darkmodebtn").innerText="Light Mode"):"disabled"===e?(document.body.classList.remove("dark-mode"),document.head.classList.remove("dark-mode"),document.getElementById("darkmodebtn").innerText="Dark Mode"):d?(document.body.classList.add("dark-mode"),document.head.classList.add("dark-mode"),document.getElementById("darkmodebtn").innerText="Light Mode",localStorage.setItem("darkMode","enabled")):(document.body.classList.remove("dark-mode"),document.head.classList.remove("dark-mode"),document.getElementById("darkmodebtn").innerText="Dark Mode",localStorage.setItem("darkMode","disabled"))}));</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root">
|
||||
<div class="me-auto ms-auto flex flex-col items-center p-4 pt-3" id="landingPage">
|
||||
<header class="flex w-full items-start" style="position: fixed">
|
||||
<div style="position: fixed; right: 15px; z-index: 9999;"><button class="btn-primary" onclick="toggleDarkMode()">Dark Mode</button></div>
|
||||
<div style="position: fixed; right: 15px; z-index: 9999;"><button id="darkmodebtn" class="btn-primary" onclick="toggleDarkMode()">Dark Mode</button></div>
|
||||
</header>
|
||||
<div>
|
||||
<div style="text-align:center;"><h1><b>Mortar & Pestle</b></h1><br></div>
|
||||
<h1>The <em>Next Generation</em> of Question Grinding</h1>
|
||||
<h1 style="text-align:center;">The <em>Next Generation</em> of Question Grinding</h1>
|
||||
</div><br>
|
||||
<div class="mt-4" style="text-align:center;">
|
||||
<h2>Practice IB Exam-Style Questions, create topic-wise tests, and much more!</h2><br>
|
||||
<h2 style="color:orangered">Warning: This site is on early beta release, and it is <b>NOT</b> optimized for mobile.</h2>
|
||||
<h2 style="color:orangered">Warning: This site is <b>NOT</b> optimized for mobile.</h2>
|
||||
</div>
|
||||
<br>
|
||||
<div class="p-3" style="text-align:center;"><a href="app/index.html"><button class="btn-primary"><h1>Start Grinding!</h1></button></a></div>
|
||||
|
@ -45,7 +43,7 @@
|
|||
<div class="mt-8 font-medium text-neutralVariant">
|
||||
<h2>Features</h2>
|
||||
</div>
|
||||
<section class="flex w-full justify-evenly pt-5">
|
||||
<section class="flex w-full justify-evenly pt-5 text-center">
|
||||
<div class="flex shrink grow basis-0 flex-col items-center">
|
||||
<div class="rounded-full bg-secondary/30 p-2"><svg xmlns="http://www.w3.org/2000/svg" width="24"
|
||||
height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
|
@ -80,7 +78,7 @@
|
|||
</div>
|
||||
|
||||
<footer class="mt-16 flex flex-col text-center">
|
||||
<p><a href="http://pirateib.net">Made by pirateIB</a></p>
|
||||
<p><a href="https://pirateib.xyz">Made by pirateIB</a></p>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue