o3 mini high just came out today, used it and it solved the issue for me. This is one big hunk of code. Great advertisement haha

Here is the code for everyone interested
Frontside
<script>
// Debug logger (optional)
var logDiv = null;
function log(s) {
if (logDiv === null) {
logDiv = document.createElement("div");
logDiv.id = 'log_debug';
logDiv.style = 'position:absolute;left:0;top:0;z-index:-2;color:grey;font-size:small';
document.body.append(logDiv);
}
logDiv.insertAdjacentHTML('beforeend', s + '<br/>');
}
// Get the card number from the body class (e.g. "card1", "card2", etc.)
function getCardNumber() {
var clz = document.body.className;
const regex = /card(\d+)/gm;
let m;
if ((m = regex.exec(clz)) !== null) {
return m[1];
} else {
console.error("Cannot find cardN class of body element!");
return "0";
}
}
/*
Updated getClozes:
This regex captures:
- Group 1: The answer text.
- Group 2: An optional hint (everything until the closing "}}")
If no hint is provided, the hint defaults to "[...]".
*/
function getClozes(str, cardNumber) {
const regex = new RegExp(`\\{\\{c${cardNumber}::(.*?)(?:::([^}]*))?\\}\\}`, 'gm');
let m;
const clozes = [];
while ((m = regex.exec(str)) !== null) {
clozes.push({
answer: m[1].trim(),
hint: (typeof m[2] !== "undefined" && m[2].trim() !== "") ? m[2].trim() : "[...]"
});
}
return clozes;
}
// Global variables holding DOM elements, cloze objects, and their revealed state.
var elements; // All elements with the class "cloze"
var clozes; // Array of objects: { answer, hint }
var revealed = []; // Array of booleans: true means the answer is revealed.
// --- STYLING HELPER FUNCTION ---
// Sets the visual style of a cloze element based on whether it is revealed and on which side.
function styleCloze(el, isRevealed) {
if (getCardNumber() === "1") {
// Front side.
if (!isRevealed) {
el.style.color = "#BD00FD";
el.style.backgroundColor = "transparent";
} else {
el.style.color = "white";
el.style.backgroundColor = "black";
}
} else {
// Back side.
if (isRevealed) {
el.style.color = "white";
el.style.backgroundColor = "black";
} else {
el.style.color = "gold";
el.style.backgroundColor = "transparent";
}
}
}
// Update the display of all cloze elements according to the revealed array.
function applyRevealedState() {
elements.forEach((el, i) => {
if (revealed[i]) {
el.innerHTML = clozes[i].answer;
} else {
el.innerHTML = clozes[i].hint;
}
styleCloze(el, revealed[i]);
});
}
// Save the revealed state to localStorage so that it persists.
function saveRevealedState() {
localStorage.setItem("cloze_revealed_c" + getCardNumber(), JSON.stringify(revealed));
}
// Load the saved revealed state (if available) or initialize a new state.
function loadRevealedState() {
let stored = localStorage.getItem("cloze_revealed_c" + getCardNumber());
if (stored) {
try {
let arr = JSON.parse(stored);
if (Array.isArray(arr) && arr.length === elements.length) {
return arr;
}
} catch(e) {
console.error("Error parsing saved cloze state:", e);
}
}
return new Array(elements.length).fill(false);
}
// Toggle the state of a single cloze and update the display and storage.
function revealCloze(i) {
if (!revealed[i]) {
elements[i].innerHTML = clozes[i].answer;
revealed[i] = true;
} else {
elements[i].innerHTML = clozes[i].hint;
revealed[i] = false;
}
styleCloze(elements[i], revealed[i]);
saveRevealedState();
}
// Optionally, reveal the first unrevealed cloze.
function revealNextCloze() {
const firstUnrevealed = revealed.findIndex(el => !el);
if (firstUnrevealed !== -1) {
revealCloze(firstUnrevealed);
}
}
// A click handler to reveal the next cloze if certain elements are clicked.
function clickHandler(e) {
const tt = e.target;
if (tt instanceof HTMLElement &&
(tt.id === 'qa' || tt.tagName === 'HTML' || tt.tagName === 'LI' || tt.tagName === 'I')) {
revealNextCloze();
}
}
// Set up everything when the card front is updated.
onUpdateHook.push(function() {
var cardNumber = getCardNumber();
var text = document.getElementById("rawText").innerHTML;
clozes = getClozes(text, cardNumber);
elements = document.querySelectorAll(".cloze");
if (clozes.length != elements.length) {
console.error("Inconsistent count of clozes found in original note text and in the card!");
return;
}
// Attach click listeners to each cloze for individual toggling.
elements.forEach((el, i) => {
el.addEventListener('click', e => {
revealCloze(i);
});
});
// Load any previously saved state and apply it.
revealed = loadRevealedState();
applyRevealedState();
// Attach a global click handler for revealing the next cloze (if desired).
window.addEventListener('click', clickHandler);
// Create the buttons.
createClozeButtons();
});
// Create two buttons:
// 1. Reset Clozes button: Bottom center with a magenta background.
// 2. Reveal All Clozes button: Bottom right with a green background.
function createClozeButtons() {
// Create Reset Clozes button on bottom center.
if (!document.getElementById('resetCloze')) {
var resetBtn = document.createElement('button');
resetBtn.id = 'resetCloze';
resetBtn.textContent = 'Reset Clozes';
resetBtn.style.position = 'fixed';
resetBtn.style.bottom = '10px';
resetBtn.style.left = '50%';
resetBtn.style.transform = 'translateX(-50%)';
resetBtn.style.zIndex = '9999';
resetBtn.style.padding = '10px 20px';
resetBtn.style.backgroundColor = 'magenta';
resetBtn.style.color = 'white';
resetBtn.style.border = 'none';
resetBtn.style.cursor = 'pointer';
document.body.appendChild(resetBtn);
resetBtn.addEventListener('click', function() {
revealed = new Array(elements.length).fill(false);
applyRevealedState();
saveRevealedState();
});
}
// Create Reveal All Clozes button on bottom right.
if (!document.getElementById('revealAllClozes')) {
var revealBtn = document.createElement('button');
revealBtn.id = 'revealAllClozes';
revealBtn.textContent = 'Reveal All Clozes';
revealBtn.style.position = 'fixed';
revealBtn.style.bottom = '10px';
revealBtn.style.right = '10px';
revealBtn.style.zIndex = '9999';
revealBtn.style.padding = '10px 20px';
revealBtn.style.backgroundColor = 'green';
revealBtn.style.color = 'white';
revealBtn.style.border = 'none';
revealBtn.style.cursor = 'pointer';
document.body.appendChild(revealBtn);
revealBtn.addEventListener('click', function() {
revealed = new Array(elements.length).fill(true);
applyRevealedState();
saveRevealedState();
});
}
}
// Attach a keydown listener in the capture phase to reset clozes when the "g" key is pressed.
var resetKeyListenerAdded;
if (!resetKeyListenerAdded) {
document.addEventListener(
"keydown",
function (e) {
// Do nothing if the user is typing in an input or textarea.
if (e.target.tagName === "INPUT" || e.target.tagName === "TEXTAREA") {
return;
}
if (e.key && e.key.toLowerCase() === "g") {
console.log("Reset cloze state via keyboard shortcut (g).");
if (elements && elements.length) {
revealed = new Array(elements.length).fill(false);
applyRevealedState();
saveRevealedState();
e.preventDefault();
e.stopPropagation();
}
}
},
true
);
resetKeyListenerAdded= true;
}
</script>
<!-- The raw text is stored here. This should be your note field containing the cloze markers. -->
<script id="rawText" type="text/plain">
{{Text}}
</script>
Backside
<script>
window.removeEventListener('click', clickHandler);
</script>
PROBLEMS
Problem 1: Keymapping
- I have just one problem. I made the o3 make a reset cloze button and it works just fine. I tried mapping it to a key and it does not work. I tried mapping it to “g”. It is in the following part of the code. Could you please have a look at it

// Attach a keydown listener in the capture phase to reset clozes when the "h" key is pressed.
document.addEventListener("keydown", function(e) {
// Do nothing if the user is typing in an input or textarea.
if (e.target.tagName === "INPUT" || e.target.tagName === "TEXTAREA") {
return;
}
if (e.key && e.key.toLowerCase() === "g") {
if (elements && elements.length) {
revealed = new Array(elements.length).fill(false);
applyRevealedState();
saveRevealedState();
e.preventDefault();
e.stopPropagation();
console.log("Reset cloze state via keyboard shortcut (g).");
}
}
}, true);
Problem 2: Nested Cloze - Answer Displayed on Frontside (Regex problem?)
- EDIT: Second Problem → The code does not work well the nested cloze. It is making the answer appear on the front side fo the card. For a cloze card {{c1::{{c2::A}}}}, c2 is displayed normally (answer is only displayed on the backside, and can be revealed upon click on the front side as per the code).
For c1 however, the answer is displayed on both the front and the backside. Clicking on the cloze makes the answer then disappear “opposite to what is happening for cloze 2”.
So following up on this trying to know more about the error, it seems the code stops displaying the card till the c number of the nested cloze.
I decided I should downgrade back to the non-persistence incremental cloze code (this post Suggestion: Persistent Incremental Cloze Reveal)
Old Code
Frontside:

Reveal Front side. Notice where it stopped the answer at.

Backside:

Edit view

With the new code above
Frontside (Unwanted behaviour)

Reveal Frontside (Same)

Backside (Same)

I want to stop it from displaying the answer on the frontside.