Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Создать тест с вариантами ответов (https://javascript.ru/forum/misc/23808-sozdat-test-s-variantami-otvetov.html)

Anya 07.12.2011 12:20

Создать тест с вариантами ответов
 
Сделать тест в формате html. Тест должен состоять из 3-5 вопросов. Каждый вопрос состоять из 2-4 вариантов ответа. Должны быть вопросы, как с одним правильным вариантом ответа (radio), так и с несколькими (checkbox).Снизу должна находиться кнопка проверки, при нажатии на которую вызывается функция checkTest(), которая проверяет заполненность теста (выводится сообщение "Вы ответили не на все вопросы") или результат (выводится сообщение "Тест пройден" или "Тест не пройден").

devote 07.12.2011 12:38

в раздел работа

ksa 07.12.2011 13:49

Anya, у меня уже есть такой - цена туве тусясы уплей... (с) тренер ГазМяса :D

GuardCat 07.12.2011 16:00

Вложений: 1
У меня есть похожий пример, но он:
а) выдаёт вопросы по одному,
б) если не дан ответ на вопрос, засчитывает это за неверный ответ,
в) писался на скорую руку и не оптимизировался.

Зато можно писать разные любые тесты с любым количеством вопросов, как с одним, так и с несколькими возможными ответами.

Если сможете изменить так, как вам нужно или (что ещё сложнее) сдать работу в таком виде — честь вам и хвала.

P.S. Буду рад критическим отзывам Гуру, буде возникнет у них профицит времени и желания ковыряться в рулонах посредственного кода.

Код псевдокласса
/* 
		Синглтон GCTester принимает в качестве аргумента один массив
	правильных ответов. В массиве должны быть номера правильных ответов,
	считая от нуля, расположенные в порядке задавания вопросов. Для 
	вопросов, где используется checkbox обязательно передаётся массив ответов,
	независимо от их (правильных ответов) количества.
		Для работы класса необходима форма с id = "GCTest", внутри которой
	Находится текст теста, причём каждый вопрос начинается с символа «~»,
	а каждый ответ начинается с символа «^». Вопрос, в котором может
	быть (теоретически) несколько вариантов ответа должен начинаться
	с сочетания символов «~*».
		В вопросах и ответах можно использовать: символ «*» в любом месте. 
	Использовать html-теги не получится, текст вопроса заключается в тег <pre>.
		В вопросах и ответах нельзя использовать служебные символы
	(«~», «^»), кроме как в соответствующих местах, предусмотренных этой
	инструкцией.
*/
function GCTester(rightArray) {
	if (!this.constructor.notFirstStart) { /* Только один экземпляр! */
		this.constructor.notFirstStart = this;
	} else {
		return this.constructor.notFirstStart;
	}
	var testSource = document.getElementById("GCTest");
	var questions = testSource.innerHTML.split("~");
	var x, y, div, quest, answer, button, label, questionNumber;
	var multiple = false, thisRight = false, now = -1, questsElements = [];
	var answersTemp, rightAnswersMultipleCount, rightAnswersCount = 0;
	var testCaption = document.createElement("p"), txtResult, pre;
	testCaption.className = "GCTestCaption";
	testCaption.innerHTML = questions[0];
 	testSource.innerHTML = "";
	testSource.appendChild(testCaption);
	/* Вспомогательная функция, проверяет наличие значения в массиве (нестрогое соответствие) */
	function checkInArray(array, txt) {
		for (var x = 0; x < array.length; x++) {
			if (array[x] == txt) return true;
		}
		return false;
	}
	for(x = 1; x < questions.length; x++) {
		questions[x] = questions[x].split("^"); /* Разбираем варианты ответа */
		div = document.createElement("div");
		div.className = "GCTestBlock";
 		questionNumber = document.createElement("p");
		questionNumber.className 	= "GCTestQNumber";
		questionNumber.innerHTML = "Вопрос " + x + " из " + (questions.length - 1);
		div.appendChild(questionNumber);
		quest = document.createElement("p");
		quest.className = "GCTestQuestion";
		if(questions[x][0].substr(0,1) === "*") {
			multiple = true;
			questions[x][0] = questions[x][0].substr(1);
		} else {
			multiple = false;
		}
		pre = document.createElement("pre")
		pre.className = "GCTestQuestion";
		pre.innerHTML = questions[x][0]
		quest.appendChild(pre);
		div.appendChild(quest);
		for(y = 1; y < questions[x].length; y++) {
			answer = document.createElement("input");
			label = document.createElement("p");
 			answer.type = multiple ? "checkbox" : "radio";
			answer.name = "q" + x;
			label.className = "GCTestAnswer";
 			label.appendChild(answer); 
			label.innerHTML += y + ". " + questions[x][y];
			div.appendChild(label);
		}
		questsElements.push(div);
	}
	this.constructor.prototype.analyzer = function () {
		rightAnswersMultipleCount = 0;
		if (now === -1) {
			testSource.insertBefore(questsElements[0], button);
			now++;
		} else if (now <= questsElements.length) {
			if (rightArray[now] instanceof Array) {
				answersTemp = testSource.querySelectorAll("input[type=checkbox]");
				multiple = true;
			} else {
				answersTemp = testSource.querySelectorAll("input[type=radio]");
				multiple = false;
			}
			if (answersTemp.length === 0) {
				alert("Допущена ошибка при формировании теста. Обратитесь к автору текста теста. Ответы, скорее всего, будут подсчитаны неверно, потому тест прерван.");
				thisRight = false;
			} else {
				if (multiple) {
					for (x = 0; x < answersTemp.length; x++) {
						if (answersTemp[x].checked) {
							if (!checkInArray(rightArray[now],x)){
								thisRight = false;
								break;
							} else {
								rightAnswersMultipleCount++;
							}
						}
					}
					if (rightAnswersMultipleCount !== rightArray[now].length) {
						thisRight = false;
					} else {
						thisRight = true;
					}
				} else {
					if (answersTemp[rightArray[now]].checked) {
						thisRight = true;
					} else {
						thisRight = false;
					}
				}
				if (thisRight) {
					rightAnswersCount++;
				}
				if (now >= questsElements.length - 1) {
					testSource.removeChild(questsElements[now]);
					testSource.removeChild(button);
					txtResult = "<p class = 'GCTestResult'>Тест завершён<p>";
					txtResult += "<p class = 'GCTestResult'>Вы дали верных ответов: " + rightAnswersCount + ".<p>";
					txtResult += "<p class = 'GCTestResult'>Вы набрали процентов: " + (rightAnswersCount / questsElements.length * 100).toFixed(1) + "%" + ".<p>";
					testSource.innerHTML += txtResult;
					return;
				}
				testSource.removeChild(questsElements[now]);
				testSource.insertBefore(questsElements[++now], button);
			}
		}
	}
	button = document.createElement("input");
	button.value = "Далее";
	button.type = "button";
	button.onclick = this.analyzer;
	button.className = "GCTestButton";
	testSource.appendChild(button);
	button.onclick();
}

Пример использования, вместе с тестом, разметкой и таблицей стилей см. во вложении.

Anya 07.12.2011 21:07

GuardCat спасибо! Это мне пригодится;)

ksa 07.12.2011 21:08

Anya, мой вариант более удобочитабельный... ;)

Anya 07.12.2011 21:10

ksa,
прости, ты в пролете, сегодня не твой день:victory:

ksa 07.12.2011 21:13

Anya, не хотел тебя расстраивать... Но пока в пролёте - ты. :haha:

devote 07.12.2011 21:14

Anya,
ksa,
подеритесь еще :D

Anya 16.12.2011 14:06

Еще чего!?=) Пожалуй маникюр поберегу =)


Часовой пояс GMT +3, время: 17:16.