Now highlights answers with green border and subtle glow only, no background fill.

This commit is contained in:
justin committed 2026-01-08 13:12:47 -07:00
1 parent 9b0a63aa37
commit 7b7fdc7c2c
1 file changed
+50 -88
+50 -88
View File
@@ -12,17 +12,11 @@ function injectCustomStyles() {
style.id = 'quiz-helper-styles';
style.textContent = `
.quiz-helper-correct {
background-color: #90EE90 !important;
border: 3px solid #28a745 !important;
box-shadow: 0 0 10px rgba(40, 167, 69, 0.6) !important;
padding: 8px !important;
box-shadow: 0 0 8px rgba(40, 167, 69, 0.5) !important;
border-radius: 4px !important;
transition: all 0.3s ease !important;
}
.quiz-helper-correct * {
background-color: transparent !important;
}
`;
document.head.appendChild(style);
styleInjected = true;
@@ -272,22 +266,17 @@ function findQuestions() {
return questions;
}
// Enhanced answer choice finding
// Enhanced answer choice finding - strictly finds only radio/checkbox options
function findAnswerChoices(questionElement) {
const answers = [];
const seenTexts = new Set();
let inputType = null;
let container = questionElement.closest('[role="group"], fieldset, form, [class*="question"], [class*="answer"], [class*="option"], div');
if (!container || container === questionElement) {
container = questionElement.parentElement;
}
for (let i = 0; i < 4 && container; i++) {
const inputsInContainer = container.querySelectorAll('input[type="radio"], input[type="checkbox"]');
if (inputsInContainer.length > 0) {
console.log(` Found ${inputsInContainer.length} inputs at level ${i}`);
// Find the container with radio/checkbox inputs
let container = questionElement;
for (let i = 0; i < 6 && container; i++) {
const inputs = container.querySelectorAll('input[type="radio"], input[type="checkbox"]');
if (inputs.length > 0) {
break;
}
container = container.parentElement;
@@ -295,93 +284,66 @@ function findAnswerChoices(questionElement) {
if (!container) container = document.body;
let nextSibling = questionElement.nextElementSibling;
let siblingAttempts = 0;
const siblingContainers = [container];
// Get all radio/checkbox inputs - these are the ONLY valid answer choices
const inputs = container.querySelectorAll('input[type="radio"], input[type="checkbox"]');
console.log(` Found ${inputs.length} radio/checkbox inputs`);
while (nextSibling && siblingAttempts < 8) {
siblingContainers.push(nextSibling);
nextSibling = nextSibling.nextElementSibling;
siblingAttempts++;
inputs.forEach((input, idx) => {
if (input.type === 'radio') inputType = 'radio';
else if (input.type === 'checkbox') inputType = 'checkbox';
let text = '';
let labelElement = null;
// Strategy 1: Find label with matching 'for' attribute
if (input.id) {
labelElement = document.querySelector(`label[for="${input.id}"]`);
if (labelElement) {
text = labelElement.textContent.trim();
}
}
const answerSelectors = [
'input[type="radio"]',
'input[type="checkbox"]',
'button[role="radio"]',
'button[role="checkbox"]',
'[role="option"]',
'[class*="answer"]',
'[class*="option"]',
'[class*="choice"]',
'[data-test*="answer"]',
'[data-test*="option"]',
'label',
'li'
];
const excludePatterns = [
/^question\s+\d+\s+of\s+\d+$/i,
/^page\s+\d+/i,
/^(next|previous|submit|skip|back|continue|finish|review)$/i,
/^\d+\s*\/\s*\d+$/,
/^score:/i,
/^time:/i,
/^remaining:/i,
/^points?:/i
];
siblingContainers.forEach(searchContainer => {
answerSelectors.forEach(selector => {
const elements = searchContainer.querySelectorAll(selector);
elements.forEach(el => {
let text = el.textContent.trim();
if (el.tagName === 'INPUT') {
if (el.type === 'radio') {
inputType = 'radio';
} else if (el.type === 'checkbox') {
inputType = 'checkbox';
// Strategy 2: Find parent label
if (!text) {
labelElement = input.closest('label');
if (labelElement) {
text = labelElement.textContent.trim();
}
}
const label = searchContainer.querySelector(`label[for="${el.id}"]`);
if (label) {
text = label.textContent.trim();
} else {
const parentLabel = el.closest('label');
if (parentLabel) {
text = parentLabel.textContent.trim();
} else {
const parent = el.parentElement;
// Strategy 3: Find adjacent sibling text
if (!text) {
const parent = input.parentElement;
if (parent) {
text = parent.textContent.trim();
}
}
// Clone and remove the input to get just the text
const clone = parent.cloneNode(true);
const inputClone = clone.querySelector('input');
if (inputClone) inputClone.remove();
text = clone.textContent.trim();
}
}
if (!text || text.length < 2 || text.length > 800 || seenTexts.has(text)) {
// Strategy 4: Check next sibling
if (!text && input.nextSibling) {
text = input.nextSibling.textContent?.trim() || '';
}
// Skip if no text found or duplicate
if (!text || text.length < 1) {
console.log(` Skipping input ${idx} - no text found`);
return;
}
if (excludePatterns.some(pattern => pattern.test(text))) {
return;
}
const wordCount = text.split(/\s+/).length;
const numberCount = (text.match(/\d+/g) || []).length;
if (wordCount > 2 && numberCount > wordCount / 2) {
if (seenTexts.has(text)) {
console.log(` Skipping input ${idx} - duplicate text`);
return;
}
seenTexts.add(text);
answers.push({
text: text,
element: el,
parentLabel: el.closest('label') || el
});
});
element: input,
parentLabel: labelElement || input.parentElement
});
});
@@ -516,7 +478,7 @@ ANALYSIS STEPS:
Think carefully and provide your answer.
FORMAT: Respond with only "ANSWER: " followed by the letter(s) separated by commas (e.g., "ANSWER: B" or "ANSWER: A,C,D")`;
FORMAT: Always respond with "ANSWER: " followed by the LETTER(s) of the correct option(s) (A, B, C, D, etc.), separated by commas if multiple. Never respond with numbers - always use letters to indicate which option is correct.`;
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',