Print Incremental List items Javascript - javascript

This is a pure JavaScript question no jQuery please.
Trying to make a JavaScript Dartboard score keeper. Running into an issue of printing an incremental list. When you click a part of the dartboard would like to calculate throws 1, 2, and 3. The problem is I would like to print off those throws in incremental list format.
HTML:
<button class="score-section" data-value="20" data-multiplier="1">20</button>
<ul id="dartTotals">
<li>Throw 1: {total}</li>
<li>Throw 2: {total}</li>
<li>Throw 3: {total}</li>
</ul>
JavaScript
document.body.onclick = function(e){
e = e.target;
if (e.className && e.className.indexOf('score-section') != -1) {
var i = 0;
(function increment(){
document.getElementById('dartTotals').innerHTML += "<li> Throw " + ++i + ": " + " total </li>";
}());
}
}
The only thing I've been able to do is add 1 to i and just keep printing that off with out incrementing i. Or run a for loop and print off the list but it does it 3 at a time. Could someone assist in helping to show how I can go about making this incremental list with each click? Thanks in advance.
JSFIDDLE
Update:
Updated Fiddle
On body click the function was getting reset. Moved var i, now called dartThrow out of the function scope and is working as expected.
var dartThrow = 0;
document.body.onclick = function(e) {
e = e.target;
if (e.className && e.className.indexOf('score-section') != -1) {
(function increment() {
document.getElementById('dartTotals').innerHTML += "<li> Throw " + ++dartThrow + ": " + " total </li>";
}());
}
}

You're setting $i to 0 on every click and then increment that value. Just do a variable outside your functions scope and then it should increment properly everytime with the code you already do have. You'll just need a reset when $i reaches your total throw count that you want.

Related

Javascript For Loop keeps doubling up my divs

I have written a script that creates a number of fields based on a number the user inputs (k).
I originally wrote a script that would create the correct number of fields. However I wanted to arrange them like vectors on the screen, so I adapted my script.
I wanted the following script to create the correct number of fields and place them in DIVS, so I could lay them out as I wish on the page.
Since doing this, the script now produces duplicate DIVS as iff it runs through the loop twice, but I can't for life of me work out why...
function createFields(k)
{
k=k+1
for (var n=1; n<k; n++) {
var makeBox=document.createElement("div");
makeBox.id = "box" + n;
document.getElementById("top").appendChild(makeBox);
document.getElementById("box" + n).setAttribute('class',"box");
var addOpen=document.createElement("div");
addOpen.id = "open"+n;
document.getElementById("box" + n ).appendChild(addOpen);
document.getElementById("open" + n).setAttribute('class',"open");
var vectorBox=document.createElement("div");
vectorBox.id = "vector" + n;
document.getElementById("box" + n).appendChild(vectorBox);
document.getElementById("vector" + n).setAttribute('class',"vect");
var xVector=document.createElement("div");
xVector.id = "top" + n;
document.getElementById("vector" + n).appendChild(xVector);
document.getElementById("top" + n).setAttribute('class',"xVect");
var newx=document.createElement("input");
newx.id = "x" + n;
document.getElementById("top" + n).appendChild(newx);
document.getElementById("x" + n).setAttribute('name',"x" + n);
document.getElementById("x" + n).setAttribute('type',"text");
document.getElementById("x" + n).setAttribute('size',"4");
document.getElementById("x" + n).setAttribute('maxlength',"4");
var yVector=document.createElement("div");
yVector.id = "bottom" + n;
yVector.class = "yVect";
document.getElementById("vector" + n).appendChild(yVector);
document.getElementById("bottom" + n).setAttribute('class',"yVect");
var newy=document.createElement("input");
newy.id = "y" + n;
document.getElementById("bottom" + n).appendChild(newy);
document.getElementById("y" + n).setAttribute('name',"y" + n);
document.getElementById("y" + n).setAttribute('type',"text");
document.getElementById("y" + n).setAttribute('size',"4");
document.getElementById("y" + n).setAttribute('maxlength',"4");
var addClose=document.createElement("div");
addClose.id = "close"+n;
document.getElementById("box" + n ).appendChild(addClose);
document.getElementById("close" + n).setAttribute('class',"close");
}
}
Any clues?
UPDATED:
The Code is called via another function:
function getVectors()
{
v = document.getElementById("vectorN").value;
v=parseInt(v); //turn the text into an integer
document.getElementById("q1").innerHTML="Enter your Vectors below!";
createFields(v);
document.getElementById("enter").innerHTML="<input type=\"button\" id=\"button\" value=\"Submit Numbers\" onclick=\"canvas()\"/>";
}
Which is called by onchange in the html:
<p id="q1">How many Vectors will you need?
<input id="vectorN" name="vectorN" type="text" onChange="getVectors()" size="4" maxlength="4">
</p>
Further UPDATE
After checking the console.log,
the only place that calls createFields() is the getVectors() function. It does appear to be calling createFields twice (despite only doing so once in the script).
The ONLY place that calls getVectors() is the onChange event in the input field.
Is it possible that when I change the innerHTML and remove the input field that this is being registered as an onChange event and calling the function again?
Your function looks fine. aren't you just calling the function twice? Do a console.log right after function createFields(k) { to check if that's the case. Maybe 2 event listeners on the field where the user inputs k (onkeyup, change)?
If you're not sure where you call createFields from. Do a find in all files and look for createFields. Add a console.log('Calling createFields from here'); just before you call createFields.
This SO Question sheds some light on the problem. I'd been tabbing out of the text box, which only triggers the onChange event once. Pressing enter fires it twice, which is the problem you were getting.
There are a couple of ways to get around this. I've chosen to keep track of the number of fields entered. If this changes, generate the fields. If not do nothing.
var fields = 0;
function createFields(k) {
if (k != fields) {
fields = k;
console.log("Fields: " + k);
//Rest of the code the same;
}
}
Demo: http://jsfiddle.net/Ej8Ly/5/
You could also do something similar in the getVectors() function instead.
Rather than "creating" all the elements with the DOM why not build a "string" and then set a container objects .innerHTML = the_string value? This way it won't matter if the function gets called twice because it will simply overwrite itself the second time and produce the same output.

Stopping FOR loop on certain number in JavaScript

I have the following JSFiddle: http://jsfiddle.net/uX8ZQ/
Basically I am trying to achieve a continuing for loop until a variable gets to a certain number, loading 5 at a time. This is what I have so far:
HTML:
<button onclick="go()">Load</button>
<p id="demo"></p>
JavaScript:
var max=16;
var y=5;
function go(){
var x="";
for (var i=1;i<=y;i++){
if(i>max){
return;
}
x=x + "The count is " + i + "<br>";
}
document.getElementById("demo").innerHTML=x;
y=y+5;
}
The result I get is the loop stops at 15 and won't load 16
I am new to JavaScript and trying to learn my way through loops but this one I cannot seem to get.
By the way, in the JSFiddle I have used window.go = function(){ as JSFiddle will not work by simply defining the function. I am using the above code in my document.
Use break instead of return as return will exit the function before it gets to update the HTML.
function go(){
var x="";
for (var i=1;i<=y;i++){
if(i>max){
break;
}
x=x + "The count is " + i + "<br>";
}
document.getElementById("demo").innerHTML=x;
y=y+5;
}

Javascript code and methods do not work

I recently started learning javascrpt, but I have some experience with C#. My school gave me an old text book called Complete Concepts and Techniques(second Edition). this book was written by Shelly Cashman and Dorin Quasney... My problem is that I cant get any of the methods or functions to work. Here are 2 of my most current issues:
var scrollMsg = "Mortage rates are at their lowest!"
var msgSpace = "--- ---"
var beginPos = 0
function scrollingMsg() {
document.msgForm.scrollingMsg.value =
scrollMsg.substring(beginPos,scrollMsg.length)+msgSpace+scrollMsg.substring(0,begi
nPos)
beginPos = beginPos + 1
If (beginPos > scrollMsg.length) {
beginPos = 0
}
window.setTimeout("scrollingMsg()",200)
}
function doMort() {
document.MortCalc.Amount.value=" "
document.MortCalc.Rate.value=" "
document.MortCalc.Years.value=" "
document.MortCalc.Payment.value" "
document.MortCalc.Amount.focus()
}
The scrollingMsg() function does not work. It does not place anything in the scrollingMsg text box. So there is no message in it. My second issue is with the doMort() function. The function does clear any of the boxes nor does it set a focus. Can you please tell me what's wrong. P.S. These are not my own code. These were project codes from the txt book, but they do not work.
Try adding semicolons after each statement, and you have a typo ('If' needs to be lowercase).
I fixed the code to comply with JSLint, use this site to verify your javascript
http://www.javascriptlint.com/online_lint.php
var scrollMsg = "Mortage rates are at their lowest!";
var msgSpace = "--- ---";
var beginPos = 0;
function scrollingMsg() {
document.msgForm.scrollingMsg.value = scrollMsg.substring(beginPos,scrollMsg.length) + msgSpace + scrollMsg.substring(0,beginPos);
beginPos = beginPos + 1;
if (beginPos > scrollMsg.length) {
beginPos = 0;
}
window.setTimeout("scrollingMsg()",200);
}
function doMort() {
document.MortCalc.Amount.value=" ";
document.MortCalc.Rate.value=" ";
document.MortCalc.Years.value=" ";
document.MortCalc.Payment.value=" ";
document.MortCalc.Amount.focus();
}

How do I make keep these values from rewriting into the HTML?

I have a small piece of code that is writing some values into a textarea inside a form. The write whenever I click a button. However if I click the button more than once they will write over and over. I need to be able to click the button multiple times (for example if the user changes a value) and have the values that I am writing simply refresh rather than repeat. Here is what I have...
var endwallPanelLengths = [totalHeightInches];
var i = 0;
while (endwallPanelLengths[i] > eaveInches)
{
endwallPanelLengths.push(endwallPanelLengths[i] - peakHeightDecrease);
document.getElementById("test83").value += "4 - " + endwallPanelLengths[i] + "\n";
i++;
}
When I click the button the first time the values are correct however they write again after everytome i click it?
In this line:
document.getElementById("test83").value += "4 - " + endwallPanelLengths[i] + "\n";
you're appending a value to test83. Presumably (since I can't see your html!!!) you just need to remove the + from the +=.
EDIT: in case you want to append all of the values in your loop, and nothing else, simply clear the value before you enter your loop and leave the +=
document.getElementById("test83").value = "";
var endwallPanelLengths = [totalHeightInches];
......
I think you want to do the whole iteration when the user change a value. Then you just need to reset the value of the textarea to empty before the loop. Something like this:
var endwallPanelLengths = [totalHeightInches];
var i = 0;
document.getElementById("test83").value = ''; //Reset the value
while (endwallPanelLengths[i] > eaveInches) {
endwallPanelLengths.push(endwallPanelLengths[i] - peakHeightDecrease);
document.getElementById("test83").value += "4 - " + endwallPanelLengths[i] + "\n";
i++;
}
I have worked out a demo page. Hope that is what you are after.
Try this:
var endwallPanelLengths = [totalHeightInches];
var i = 0;
document.getElementById("test83").value = '';
while (endwallPanelLengths[i] > eaveInches)
{
endwallPanelLengths.push(endwallPanelLengths[i] - peakHeightDecrease);
document.getElementById("test83").value += "4 - " + endwallPanelLengths[i] + "\n";
i++;
}
I'm assuming that all the code is executed eacht time you click the button, am I right ?
you need to implement a clickEventhandler that checks whether or not your texts exists.....

How do I make a loop advance using onclick?

I've been trying to figure this out for a while, and I'm totally stumped.
I'm writing a program that is supposed to display a basic series of multiple-choice questions. You see a question, you click one of the answers, and you move on to the next question.
The problem is, I can't figure out how to display one question, then display the next question when the user clicks one of the buttons. Nothing happens when I click a button. What's going wrong?
// progress meter
var progress = new Array();
for (var i = 0; i < questions.length; i++) progress.push("0");
var i = 0;
display(0);
// display questions
function display(i) {
var prg_string;
for (var j = 0; j < progress.length; j++) prg_string += progress[j];
document.write(
"<div id = 'background'>"
+ "<div id = 'progress'>" + progress + "</div>"
+ "<div id = 'title'>-JogNog Test v1-<br></br>" + tower + "</div>"
+ "<div id = 'question'>" + questions[i].text + "</div>"
+ "<div id = 'stats'>Level " + level + "/" + total_levels + " Question " + (i + 1) + "/" + questions.length + "</div>"
+ "</div>"
);
document.write("<button id = 'answer1' onclick = 'next(questions[i].answers[0].correct)'>" + questions[i].answers[0].text + "</button>");
if (questions[i].answers.length > 0)
document.write("<button id = 'answer2' onclick = 'next(questions[i].answers[1].correct)'>" + questions[i].answers[1].text + "</button>");
if (questions[i].answers.length > 1)
document.write("<button id = 'answer3' onclick = 'next(questions[i].answers[2].correct)'>" + questions[i].answers[2].text + "</button>");
if (questions[i].answers.length > 2)
document.write("<button id = 'answer4' onclick = 'next(questions[i].answers[3].correct)'>" + questions[i].answers[3].text + "</button>");
}
// go to next question, marking whether answer was right or wrong
function next(correct) {
if(correct) progress[i] = "T";
else progress[i] = "F";
i += 1;
display(i);
}
I haven't read through your code, (you might want to work on posting SSCCEs by focusing just on the part that handles the loop) but I get the feeling a loop is not what you want here. Loops are great if you need to automatically iterate through something. But really, you want to display only a single question at a time.
The easiest way to do this, assuming you have a means of handling each question independently, is just to keep track of which question the user is up to. Display that question. When the user submits an answer, call whatever function renders a question using the counter, plus one. Make sure to check that you haven't hit the end of the quiz so that you don't reference a question that doesn't exist.
Here's some pseudocode:
var questionNumber, questions; //assume these already have values
function printQuestion(questionNumber){ ... }
function nextQuestion(){
if(questionNumber < questions){
questionNumber++;
printQuestion(questionNumber);
}
else{
showResults();
}
}
I agree with #ngmiceli that a loop isn't what you want here. You want to display one question, and then create click event handlers that will move on to the next question when the user selects an answer to the previous question.
I went ahead and created a different setup to demonstrate. You can see a demo here:
-- jsFiddle DEMO --
But I'll walk through the process. First, I set up a basic HTML document:
<body>
<h1>-Test v1-</h1>
<h2>Simple Math</h2>
<div id="container">
<div><span id="numRight">0</span> of <span id="numQuestions">0</span></div>
<div id="question"></div>
<div id="answers"></div>
</div>
</body>
Then, I created a questions array, each element in the array being an object. Each question object contains the question itself, an array of possible answers, and an "answerIdx" property that indicates the array index of the correct answer.
questions = [
{
question: 'What is 0 / 6 ?',
options: ['0','1','2'],
answerIdx: 0
},
{
question: 'What is 2 + 2 ?',
options: ['72','4','3.5'],
answerIdx: 1
}
]
I also created some other variables that point to the HTML elements I am going to want to manipulate:
numRight = 0,
numQuestions = 0,
answerDiv = document.getElementById('answers'),
questionDiv = document.getElementById('question'),
numRightSpan = document.getElementById('numRight'),
numQuestionsSpan = document.getElementById('numQuestions');
Next, I created a 'displayQuestion' function which takes a single question object as a parameter:
function displayQuestion(q) {
// insert the question text into the appropriate HTML element
questionDiv.innerHTML = q.question;
// remove any pre-existing answer buttons
answerDiv.innerHTML = '';
// for each option in the 'options' array, create a button
// attach an 'onclick' event handler that will update
// the question counts and display the next question in the array
for(i = 0; i < q.options.length; i++) {
btn = document.createElement('button');
btn.innerHTML = q.options[i];
btn.setAttribute('id',i);
// event handler for each answer button
btn.onclick = function() {
var id = parseInt(this.getAttribute('id'),10);
numQuestionsSpan.innerHTML = ++numQuestions;
// if this is the right answer, increment numRight
if(id === q.answerIdx) {
numRightSpan.innerHTML = ++numRight;
}
// if there is another question to be asked, run the function again
// otherwise, complete the test however you see fit
if(questions.length) {
displayQuestion(questions.shift());
} else {
alert('Done! You got '+numRight+' of '+numQuestions+' right!');
}
}
answerDiv.appendChild(btn);
}
}
Finally, I displayed the first question:
displayQuestion(questions.shift());

Categories

Resources