Find/demos/Quiz/index.js
2026-04-14 15:25:02 +04:00

339 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const questions = [
{
image: "image.avif",
question: "Мой вопрос",
variants: [
"Вариант 1",
"Вариант 2",
"Вариант 3"
],
correct: 0
},
{
question: "Мой вопрос",
variants: [
"Вариант 1",
"Вариант 2",
"Вариант 3"
],
correct: [0, 1]
}
];
class Quiz extends Find.createApp() {
constructor(questions) {
const root = Find.search('root');
super(root);
this.question_type = undefined;
this.questions = questions;
this.question = null;
this.correctCount = 0;
}
init() {
this.select('com.find.demos.quiz');
this.setMeta();
this.setCard();
this.stable();
this.createQuestions();
}
setCard() {
this.add([
Find.content('<div id="message"></div>'),
Find.content(
`<div class="card">
<div class="card-header">
<p class="card-header-title">
<span id="title">
Загрузка...
</span>
</p>
</div>
<div class="card-content">
<div class="content" id="content"></div>
<button
class="button"
style="width: 100%;"
id="test_select"
>Проверить</button>
</div>
</div>`
)
]);
}
setMeta() {
this.meta([
Find.content('<meta name="viewport" content="width=device-width, initial-scale=1">'),
Find.content(`<style>#${this.rootId()} { margin: 20px; } </style>`),
Find.content(
`<style>
.fit-image {
object-fit: contain;
width: 100%;
height: 100%;
}
</style>`
)
]);
}
createQuestions() {
this.number = 0;
this.questionsWaiter(null);
}
questionsWaiter(status) {
const results = [
{
source: "no_select",
text: "Не выбран не один вариант!",
type: "error"
},
{
source: "incorrect",
text: "Неправильный ответ!",
type: "error"
},
{
source: "correct",
text: "Правильный ответ!",
type: "success"
}
];
const isEnd = (this.questions.length === this.number);
if (!isEnd) this.question = this.questions[this.number];
this.select('question' + this.number);
this.setTitle();
this.render();
this.setStatus(status);
this.setForms(isEnd);
this.attachDeleteButton();
if (isEnd) return;
this.setEvents().then((result) => {
if (result !== 'no_select') {
this.number ++;
}
let obj = undefined;
for (obj of results) {
if (obj.source == result) break;
}
this.questionsWaiter(obj);
});
}
setStatus(status) {
const root = this.component();
const message = root.id('message');
if (status !== null) {
const elem = status.type === 'error' ?
'is-danger' :
'is-success';
message.html(
Find.content(
`<div
class="notification ${elem}"
style="margin-bottom: 10px;">
<button class="delete" id="delete-info"></button>
${status.text}
</div>`
)
);
}
}
attachDeleteButton() {
const root = this.component();
const button = root.id('delete-info');
if (button.status()) button.attach('click', app => {
const root = app.component();
root.id("message").html('<!-- deleted -->');
});
}
setEvents() {
const root = this.component();
const que = this.question;
const main = this;
return new Promise((resolve, reject) => {
const get_select = function() {
const button = root.id('test_select');
button.attach('click', () => {
const name = 'question';
const type = main.question_type;
let correct = false;
if (type === 'radio') {
const elem = root.select(`input[name="${name}"]:checked`);
if (!elem.status()) {
resolve('no_select');
return;
}
const answer = Number(elem.value());
if (answer === que.correct) correct = true;
} else {
const elements = root.all('input[type="checkbox"]:checked');
if (elements.length === 0) {
resolve('no_select');
return;
}
const answer = elements.map(elem => Number(elem.property('id').slice(7)));
let correct_count = 0;
for (let i = 0; i < que.correct.length; i ++) {
if (
answer[i] === undefined ||
answer[i] === null
) break;
if (answer[i] === que.correct[i]) {
correct_count ++;
}
}
if (correct_count === que.correct.length) {
correct = true;
}
}
if (correct) {
main.correctCount ++;
resolve('correct');
} else {
resolve('incorrect');
}
});
};
try {
get_select();
} catch (err) {
reject(err);
}
});
}
setTitle() {
const isEnd = (this.questions.length === this.number);
if (!isEnd) {
this.title(`Quiz вопрос ${String(this.number + 1)}/${this.questions.length} - Find.js демо`);
} else {
this.title('Результаты!');
}
}
setForms(isDone) {
if (isDone) {
this.viewResults();
return;
}
const que = this.question;
let input_id = 0;
const root = this.component();
const content = root.id("content");
const title = root.id("title");
title.text(que.question);
if (Array.isArray(que.correct)) {
this.question_type = 'checkbox';
} else {
this.question_type = 'radio';
}
let image = '<!-- no image -->';
if (typeof que.image !== "undefined") {
image = Find.content(
`<figure
class="fit-image"
style="margin-bottom: 20px;">
<img
src="${que.image}"
style="border-radius: 20px;"
alt="Изображение к вопросу">
</img>
</figure>`
);
content.add(image);
}
for (let val in (que.variants)) {
if (Array.isArray(que.correct)) {
this.question_type = 'checkbox';
content.add(
Find.content(
`<label class="checkbox">
<input
type="checkbox"
id="variant${input_id}"
value="${input_id}"
name="question">
</input>
<span
class="has-text-weight-medium"
id="text${input_id}">
</span>
</label>
<br />`
)
);
} else {
content.add(
Find.content(
`<input
type="radio"
id="variant${input_id}"
value="${input_id}"
name="question">
<label class="radio" for="variant${input_id}">
<span class="has-text-weight-medium" id="text${input_id}"></span>
</label>
</input>
<br />`
)
);
}
content.id('text' + input_id).text(que.variants[val]);
input_id ++;
}
}
viewResults() {
const root = this.component();
const button = root.id("test_select");
const content = root.id("content");
const title = root.id("title");
let text = 'Попробовать снова';
let out = ` - ${this.correctCount / (this.questions.length / 100)}%`;
const user =
this.correctCount !== this.questions.length ?
`${this.correctCount} вопросов из ${this.questions.length}.` :
'все вопросы!';
if (this.correctCount > (this.questions.length / 2)) {
text = 'На главную';
}
title.text(`Ваш результат ${out}`);
button.text(text);
content.html(
Find.content(
`<span class="has-text-weight-bold">
Вы правильно ответили на ${user}
</span>`
)
);
button.attach('click', () => location.reload());
}
}
const quiz = new Quiz(questions);
quiz.init();