initial commit
This commit is contained in:
229
static/js/modules/study-mode.js
Normal file
229
static/js/modules/study-mode.js
Normal file
@@ -0,0 +1,229 @@
|
||||
// Study Mode Module
|
||||
class StudyMode extends BaseModule {
|
||||
constructor() {
|
||||
super();
|
||||
this.showingAnswer = false;
|
||||
this.navigator = null;
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.setupEventListeners();
|
||||
this.loadQuestions();
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
// Filter controls
|
||||
document.getElementById('apply-filters')?.addEventListener('click', () => {
|
||||
this.loadQuestions();
|
||||
});
|
||||
|
||||
document.getElementById('reset-filters')?.addEventListener('click', () => {
|
||||
document.getElementById('start-question').value = 1;
|
||||
document.getElementById('end-question').value = 200;
|
||||
this.loadQuestions();
|
||||
});
|
||||
|
||||
// Navigation controls
|
||||
document.getElementById('prev-btn')?.addEventListener('click', () => {
|
||||
this.previousQuestion();
|
||||
});
|
||||
|
||||
document.getElementById('next-btn')?.addEventListener('click', () => {
|
||||
this.nextQuestion();
|
||||
});
|
||||
|
||||
// Answer controls
|
||||
document.getElementById('show-answer')?.addEventListener('click', () => {
|
||||
this.showAnswer();
|
||||
});
|
||||
|
||||
document.getElementById('hide-answer')?.addEventListener('click', () => {
|
||||
this.hideAnswer();
|
||||
});
|
||||
|
||||
// Keyboard navigation
|
||||
document.addEventListener('keydown', (e) => {
|
||||
this.handleKeyboard(e);
|
||||
});
|
||||
}
|
||||
|
||||
async loadQuestions() {
|
||||
this.showLoading();
|
||||
BaseModule.hide('study-content');
|
||||
BaseModule.hide('no-questions');
|
||||
|
||||
const start = document.getElementById('start-question').value;
|
||||
const end = document.getElementById('end-question').value;
|
||||
|
||||
try {
|
||||
const data = await this.fetchQuestions({
|
||||
mode: 'range',
|
||||
start: start,
|
||||
end: end
|
||||
});
|
||||
|
||||
this.questions = data;
|
||||
this.currentIndex = 0;
|
||||
|
||||
if (this.questions.length === 0) {
|
||||
this.hideLoading();
|
||||
BaseModule.show('no-questions');
|
||||
return;
|
||||
}
|
||||
|
||||
document.getElementById('total-questions').textContent = this.questions.length;
|
||||
|
||||
// Initialize navigator
|
||||
this.initializeNavigator(start, end);
|
||||
|
||||
this.displayQuestion();
|
||||
this.updateProgress('study-progress');
|
||||
|
||||
this.hideLoading();
|
||||
BaseModule.show('study-content');
|
||||
|
||||
} catch (error) {
|
||||
this.hideLoading();
|
||||
console.error('Error in loadQuestions:', error);
|
||||
}
|
||||
}
|
||||
|
||||
initializeNavigator(start, end) {
|
||||
if (!this.navigator) {
|
||||
this.navigator = new QuestionNavigator('question-navigator', {
|
||||
onQuestionSelect: (index) => {
|
||||
this.currentIndex = index;
|
||||
this.displayQuestion();
|
||||
this.hideAnswer();
|
||||
},
|
||||
storagePrefix: `study_${start}_${end}`
|
||||
});
|
||||
}
|
||||
|
||||
this.navigator.setQuestions(this.questions);
|
||||
}
|
||||
|
||||
displayQuestion() {
|
||||
if (this.questions.length === 0) return;
|
||||
|
||||
const question = this.questions[this.currentIndex];
|
||||
|
||||
let html = this.createQuestionHTML(question, this.currentIndex, this.questions.length);
|
||||
html += this.createOptionsHTML(question.options, question.correct);
|
||||
|
||||
document.getElementById('question-container').innerHTML = html;
|
||||
|
||||
// Animate options
|
||||
this.animateOptions();
|
||||
|
||||
this.updateNavigation('prev-btn', 'next-btn', 'current-question');
|
||||
this.updateProgress('study-progress');
|
||||
|
||||
if (this.navigator) {
|
||||
this.navigator.setCurrentIndex(this.currentIndex);
|
||||
}
|
||||
}
|
||||
|
||||
animateOptions() {
|
||||
const options = document.querySelectorAll('.option-btn');
|
||||
options.forEach((option, index) => {
|
||||
option.style.opacity = '0';
|
||||
option.style.transform = 'translateY(20px)';
|
||||
setTimeout(() => {
|
||||
option.style.transition = 'all 0.3s ease';
|
||||
option.style.opacity = '1';
|
||||
option.style.transform = 'translateY(0)';
|
||||
}, index * 100);
|
||||
});
|
||||
}
|
||||
|
||||
showAnswer() {
|
||||
const correctOption = document.querySelector('.option-btn[data-correct="true"]');
|
||||
if (correctOption) {
|
||||
correctOption.classList.add('correct', 'correct-option');
|
||||
correctOption.style.background = 'rgba(39, 174, 96, 0.3)';
|
||||
correctOption.style.borderColor = '#27ae60';
|
||||
correctOption.style.color = '#ffffff';
|
||||
correctOption.style.fontWeight = 'bold';
|
||||
|
||||
const indicator = correctOption.querySelector('.answer-indicator');
|
||||
if (indicator) {
|
||||
indicator.style.display = 'inline';
|
||||
}
|
||||
}
|
||||
|
||||
// Dim incorrect options
|
||||
const incorrectOptions = document.querySelectorAll('.option-btn[data-correct="false"]');
|
||||
incorrectOptions.forEach(option => {
|
||||
option.classList.add('text-muted');
|
||||
option.style.opacity = '0.6';
|
||||
});
|
||||
|
||||
BaseModule.hide('show-answer');
|
||||
BaseModule.show('hide-answer');
|
||||
this.showingAnswer = true;
|
||||
}
|
||||
|
||||
hideAnswer() {
|
||||
const allOptions = document.querySelectorAll('.option-btn');
|
||||
allOptions.forEach(option => {
|
||||
option.classList.remove('correct', 'correct-option', 'text-muted');
|
||||
option.style.background = '';
|
||||
option.style.borderColor = '';
|
||||
option.style.color = '';
|
||||
option.style.fontWeight = '';
|
||||
option.style.opacity = '';
|
||||
});
|
||||
|
||||
const indicators = document.querySelectorAll('.answer-indicator');
|
||||
indicators.forEach(indicator => {
|
||||
indicator.style.display = 'none';
|
||||
});
|
||||
|
||||
BaseModule.show('show-answer');
|
||||
BaseModule.hide('hide-answer');
|
||||
this.showingAnswer = false;
|
||||
}
|
||||
|
||||
previousQuestion() {
|
||||
if (this.currentIndex > 0) {
|
||||
this.currentIndex--;
|
||||
this.displayQuestion();
|
||||
this.hideAnswer();
|
||||
}
|
||||
}
|
||||
|
||||
nextQuestion() {
|
||||
if (this.currentIndex < this.questions.length - 1) {
|
||||
this.currentIndex++;
|
||||
this.displayQuestion();
|
||||
this.hideAnswer();
|
||||
}
|
||||
}
|
||||
|
||||
handleKeyboard(e) {
|
||||
if (e.key === 'ArrowLeft' && this.currentIndex > 0) {
|
||||
this.previousQuestion();
|
||||
} else if (e.key === 'ArrowRight' && this.currentIndex < this.questions.length - 1) {
|
||||
this.nextQuestion();
|
||||
} else if (e.key === ' ') {
|
||||
e.preventDefault();
|
||||
if (this.showingAnswer) {
|
||||
this.hideAnswer();
|
||||
} else {
|
||||
this.showAnswer();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-initialize when DOM is ready
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (document.getElementById('study-content')) {
|
||||
window.studyMode = new StudyMode();
|
||||
}
|
||||
});
|
||||
|
||||
// Export for global use
|
||||
window.StudyMode = StudyMode;
|
||||
Reference in New Issue
Block a user