我是业余程序员并在javascriptissexy's blog
上作为初学者课程的一部分构建动态测验我有一堆问题存储在这样的数组中:
var allQuestions = [
{question: "Which of the following is true about a cat's whiskers?", choices: ["Unlike fur, they don't shed at all", "Defend against predators", "They work as sensors", "They serve no purpose at all"], correctAnswer: 2},
{question: "How are cats different from dogs?", choices: ["Cats have the ability to move in the air", "Cats are highly social animals", "Dogs are independent but cats are the opposite", "Dogs love children but cats dont"], correctAnswer: 0},
{question: "What is a sure way of getting a cat's attention if you don't have treats?", choices: ["Call its name", "Stimulate the cat's curiousity", "Cats never pay attention to humans", "Serve some vegetarian food"], correctAnswer: 1},
];
选项设置为无线电输入。问题和选择一次显示一个。当用户单击下一步时,该页面将显示数组中的下一组问题和选项。如果用户单击下一步而未进行选择,则页面不会更新 - 会弹出一条警告,通知用户选择一个选项。在最后一个问题中,下一个按钮更改为“提交”,当用户点击提交时,将显示总分数。
我的问题是我正在尝试添加“上一个”按钮,因此点击后,用户可以查看上一个问题(直到第一个问题)以及他们所做的选择,也可以更改他们的答案。我很难定义处理程序功能并跟踪上一个问题的答案。我是否需要使用封闭机会?
到目前为止,这是我的代码的链接:fiddle
答案 0 :(得分:1)
让我们创建一个设计为
的对象var tempStorage = {};
让其键为allQuestions
的索引(即 pos
),值为相应的单选按钮的值。
在以下方法中,插入值为pos
的值作为键
function calcScore() {
var userAns = document.querySelector('input[name="choice"]:checked').value;
var correctAns = allQuestions[pos].correctAnswer;
tempStorage[pos] = userAns; // LIKE THIS
if(userAns == correctAns) {
this.totalScore++;
}
}
然后在上一个按钮点击中,将值设置为(在 updatePrevious()
中)
// Iterate through each radio element and based on value
// change the checked attribute
var radioButtons = document.getElementsByName("choice");
for (var x = 0; x < radioButtons.length; x++) {
if (radioButtons[x].value === tempStorage[pos]) {
radioButtons[x].checked = true;
}
}
签入此JSFIddle1
如果你对jQuery感兴趣那么
// LIKE THIS, here I used jQuery
$('input[name="choice"][value="'+tempStorage[pos]+'"]"').attr('checked', true)
签入此JSFIddle2
答案 1 :(得分:1)
有许多方法可以在这里工作,但这是一种方法。首先,跟踪用户提交的答案:
function collectUserAnswer() {
allQuestions[pos].userAnswer =
document.querySelector('input[name="choice"]:checked').value;
}
然后,当你倒退时,你需要确保填写用户的答案,如果他们选择了一个:
function createChoices() {
for(var i = 0; i < 4; i++) {
var choice = document.getElementsByTagName("p")[i];
var option = "<input id='ans_" + i
+ "' type='radio' name='choice' value='"
+ i + "'";
if ( i == allQuestions[pos].userAnswer ) {
option += " checked='checked'";
}
option += ">" + allQuestions[pos].choices[i]
+ "</input>";
choice.innerHTML = option;
}
}
计算分数时,不必跟踪运行总计就更容易了。使用总计,您有一组逻辑需要在用户向前导航时发生,而另一组逻辑在用户向后导航时发生。相反,我们可以使用一组逻辑,每次只计算整个分数:
function calcScore() {
var score = 0;
for ( var i = 0; i < allQuestions.length; i++ ) {
if ( allQuestions[i].userAnswer == allQuestions[i].correctAnswer ) {
score++;
}
}
this.totalScore = score;
}
接下来,您必须根据当前选择的问题复制创建正确按钮的逻辑,并将其放入updatePrevious()
函数中。但每当我看到代码重复时,我认为这是将重复代码拆分为自己的函数的绝佳机会,因此我可以重复使用它而不重复它。这样,如果您在该代码中发现了一个错误,则不必找到您将错误复制到的所有位置并在所有这些位置修复它。所以,我会像这样打破它:
function updateNavigationButtons() {
if(pos < len) {
createQuestion();
createChoices();
submitButton.innerHTML = '<input id="next" type="button" name="nextbutton" value="Next Question" onclick="updateNext();"><input id="back" type="button" name="backbutton" value="Previous Question" onclick="updatePrevious();">';
}
if(pos == len-1) {
submitButton.innerHTML = '<input id="submit" type="button" name="submitbutton" value="Submit Quiz" onclick="updateNext();"><input id="back" type="button" name="backbutton" value="Previous Question" onclick="updatePrevious();">';
}
if(pos == len) {
while(firstDiv.hasChildNodes()) {
firstDiv.removeChild(firstDiv.lastChild);
}
submitButton.innerHTML = "Your total score: " + this.totalScore;
}
}
最后,您需要确保上一个和下一个按钮处理程序调用新的updateNavigationButtons()
函数:
//update when user clicks next question
function updateNext() {
displayAlert();
collectUserAnswer();
calcScore();
pos++;
updateNavigationButtons();
};
//update when user clicks previous question
function updatePrevious() {
displayAlert();
collectUserAnswer();
calcScore();
pos--;
updateNavigationButtons();
}
我仍然有很多方法可以改进这段代码。 updateNext()
和updatePrevious()
看起来几乎完全相同,除了他们对pos
变量所做的事情;所以你可能想尝试找到一种方法来消除代码重复。在我开始之前,我注意到仍然存在向后导航的错误 - 如果没有选择答案,则会发生错误。
但希望这会让你更近一点。可以找到我的更改的小提琴here。