So I have this blueprint object:
function User (theName, theEmail) {
this.name = theName;
this.email = theEmail;
this.quizScores = [];
this.currentScore = 0;
}
I create a new user like this var user1 = new User (theName.value, theEmail.value); which is inside a function for event listener when user types in his name and email. Now there are questions and a button for next question. Everytime user clicks next question button, I want to increment currentScore by one. Problem is that it stays 0 all the time. I do it like this:
scoretag = document.createElement("p");
scoretag.innerHTML = user1.currentScore;
body.appendChild(scoretag);
Event listener and main loop:
for (var i = 0; i < theChoices[question1.theChoices].length; i++) {
var arrayQ = document.createElement("p");
arrayQ.innerHTML = theChoices[question1.theChoices][i];
list.appendChild(arrayQ);
var radio = document.createElement("input");
radio.type = "radio";
listOptions.appendChild(radio);
dbtn.addEventListener("click", function() {
//list.removeChild(arrayQ);
//listOptions.removeChild
list.removeChild(list.firstChild);
list.removeChild(list.lastChild);
user1.currentScore = user1.currentScore+1;
scoretag = document.createElement("p");
scoretag.innerHTML = user1.currentScore;
body.appendChild(scoretag);
})
}
UPDATE: I putted the code for appending a child to a body element inside the loop after incrementation of score, but this results in many numbers printed on the page one after another.
But like I said, when I try t increment by one on button click, it still keeps showing 0 on the screen. Any help?
Every time you increment the score, you need to update the HTML element. This is an idea:
function User (theName, theEmail) {
this.name = theName;
this.email = theEmail;
this.quizScores = [];
this.currentScore = 0;
}
var user1 = new User ("aa","bb");
function updateScore(){
user1.currentScore++;
document.getElementById('score').innerText = user1.currentScore;
}
<button id="btn" onclick="updateScore()">next</button>
<p id="score">0</p>
Related
Working on a JavaScript program, and the first thing that happens when run is asking the user whether they want to enter something using prompt()s, or using a textarea. The textarea option comes with a clickable button element to press once the user has entered everything they want into the textarea.
If this option is chosen, I want the rest of my program to not run until this button is clicked, and the user is confirming that they are finished with their input. Currently I have the button code within the selection part (where the user has chosen to use a textarea), as below:
if (trimmedResponse == 'manual') {
... (irrelevant code)
} else { //if paste is chosen
var createArray = function(howMany){
var pasteInput = document.createElement("TEXTAREA");
var makingArray = [];
document.body.appendChild(pasteInput);
pasteInput.rows = howMany;
let done = document.createElement("button");
done.innerHTML = 'Enter terms';
done.onclick = function(){
for (var j = 0; j < howMany; j++){
makingArray[j] = String((pasteInput.value).replace(/ /g,'').split('-')).split('\n');
}
pasteInput.style.display = 'none';
done.style.display = 'none';
}
document.body.appendChild(done);
return makingArray;
}
termArray = window.createArray(numOfTerms); //getting a variable holding the array from the prior function, to access later
}
The rest of the script.js file is made up of the regular subroutines - preload, setup, draw, and some initialisation and other small methods in the open scope before preload(), as below in a greatly reduced format:
let BG;
let translateEdit = document.createElement("button");
translateEdit.innerHTML = "Edit a translation";
translateEdit.style.position = 'absolute';
translateEdit.style.left = '50px';
translateEdit.style.top = '130px';
let list = "";
translateEdit.onclick = function () {
this.blur();
do {
replaceChoice = prompt("Which translation do you want to edit? (1-"+numOfTerms+") \n"+list+" \nOr enter any letter to leave this screen.");
} while (replaceChoice < 1 || replaceChoice > termArray.length)
termArray[replaceChoice-1][1] = prompt("What is the new translation for the term "+termArray[replaceChoice-1][0]+"?");
list = "";
for (let i = 0; i < numOfTerms ; i++){
list += ((i+1)+". ["+termArray[i][0] + "] - [" + termArray[i][1] + "]\n") //adds each term and translation in a user-friendly / clear display to the list variable for later display
}
alert("The term list currently looks as follows: \n"+list);
};
document.body.appendChild(translateEdit);
let temp1;
let temp2;
let temp3;
var performanceDisplay = "";
function preload() { //function loading image from file into variable
Helvetica = loadFont('Helvetica-Bold.ttf');
BG = loadImage('images/background.png');
}
function setup() { //function to create display/background using image file and dimensions and instantiate objects (character,terms,counters) as well as slider and icon to be displayed for it
alert("Below are the terms you have entered: \n" + list + "If any of the above are incorrect, use the edit buttons on the next screen to adjust terms or translations.");
speakericon = loadImage('images/speaker.png');
createCanvas(width, height);
... (further code in setup())
}
function draw() { //make background + objects visible on screen, allow them to act as they must, creating new terms when necessary, calling functions in class files such as player movement (calls all functions in classes throughout function) - all run every tick
image(BG, 0, 0, width, height); //set the display to the background image from BG variable in preload()
... (further code in draw())
}
In essence, I need to stop everything else from running until the button 'done' is clicked, and would appreciate any help with anything to achieve this.
the counter number is not updating even after clicking the button.
var counterNumber = 0;
var counterText = document.querySelector("strong");
var reduceButton = document.querySelectorAll("button")[0];
var increaseButton = document.querySelectorAll("button")[1];
increaseButton.addEventListener("click", function() {
counterNumber++;
})
reduceButton.addEventListener("click", function() {
counterNumber--;
})
counterText.textContent = counterNumber;
Your eventListener acts on the button clicks and counterNumber are increased as it should (you can add a console.log to see this) But you never assign the new value to your text counterText. That row is run once and not everytime you click a button.
Move this row:
counterText.textContent = counterNumber;
to be within your eventListener functions
So currently i have a card which has some radio buttons with the name="radio-0" i want when i clone the card that all the radio buttons to change to name="radio-1" for exapmle
I have made a function that get the last child from the element being but it isn't working and only works one time.
My fiddle https://jsfiddle.net/abdotamer3/s57jauxw/22/
My function:
function nameRadioButtons(clone, radioButtons) {
var allQuestions = clone.querySelector(".radioItemToggle:last-child");
var radioID = allQuestions.getAttribute("name").split("-")[1];
console.log(radioID)
radioButtons.forEach((element, index) => {
radioID =+ 1
element.setAttribute("name", "radio-" + radioID.toString());
});
}
My cloning function:
function cloneQuestion() {
var question = document.querySelector(".questions");
var clone = $(question).clone(true, true).get(0);
var numItems = $(".questions").closest(".radioListItemPrimaryContent").length;
var radioButtons = question.querySelectorAll(".radioItemToggle");
console.log(numItems);
nameRadioButtons(clone, radioButtons);
clone.querySelector(".questionMainTextArea").value = "Untitled Question";
var addBtn = document.querySelector(".addQuestionBtnRow");
var tbody = addBtn.parentNode;
tbody.insertBefore(clone, addBtn);
}
Create a global variable to store the currently maximum question index, and add 1 to it every time before setting the new name.
let radioGroupIndex = 0
function nameRadioButtons(clone) {
radioGroupIndex++
clone.querySelectorAll('input[type=radio]').forEach(_radio => {
_radio.setAttribute('name', `radio-${radioGroupIndex}`)
})
}
https://jsfiddle.net/suvfg1o9
I'm trying to create a browser extension popup (in JS) that creates a number of buttons with links that open up different webpages. The function takes a number of parameters, the main one being b_link which is an array of URL's to the website. For some reason, only the last URL in array is applied to all of the buttons that are created.
I'm not entirely sure what the problem is, I could speculate but I don't think that would be productive. One thing I did notice and had to compensate for was using b_link in the lambda function. Just using b_link[i], the lambda function only saw undefined so no webpage opened, but using var tmpLink = b_link[i]; at least gets the link into the function and allows a webpage to open.
How should I make these buttons so that they all have their own links, rather than only the last one in the array?
The function in question:
function createSiteButton(numBtns, b_id, b_class, b_text, b_link, b_bg)
{
// check if the input text is an array
if (Array.isArray(b_text))
{
// create the new set of buttons
for (i= 0; i < numBtns; i++)
{
var newButton = document.createElement('button');
var tmpLink = b_link[i];
newButton.id = b_id;
newButton.class = b_class;
newButton.innerHTML = b_text[i];
newButton.style.background = b_bg;
newButton.addEventListener("click", function()
{
if (tmpLink)
{
window.open(tmpLink, "_blank");
}
});
button_array[i] = newButton;
}
// add the new buttons the screen
for (i= 0; i < numBtns; i++)
{
divID.appendChild(button_array[i]);
}
}
}
I found a way to do this via creating an a element, setting href via a.href = tmpLink and appending the button to the a element as a child. The final function is:
function createSiteButton(numBtns, b_id, b_class, b_text, b_link, b_bg)
{
var outputElem = document.getElementById('output');
// check if the input text is an array
if (Array.isArray(b_text))
{
//var tmpLink = null;
// create the new set of buttons
for (i= 0; i < numBtns; i++)
{
var a = document.createElement('a');
var newButton = document.createElement('button');
var tmpLink = b_link[i];
newButton.id = b_id;
newButton.class = b_class;
newButton.innerHTML = b_text[i];
newButton.style.background = b_bg;
a.href = tmpLink;
a.appendChild(newButton);
divID.appendChild(a);
button_array[i] = newButton;
}
}
}
The code below gets info from xml file.
I succesfully presents the id and name of each planet with a button.
I want to add an onclick event on the button.
Problem now is: it does add the onclick event but only on the last button created in the loop.
What am i doing wrong? Why doesnt it create a onclick event for each button, but only for the last one in loop?
function updatePlaneten() {
var valDiv, planets, valButton, textNode;
// Get xml files
planets = this.responseXML.getElementsByTagName("planeet");
// loop through the <planet> tags
for (var i = 0; i < planets.length; i++) {
valDiv = ''; // clear valDiv each time loop starts
// Get the id and the name from the xml info in current <planet> tag
valDiv += planets[i].getElementsByTagName("id")[0].childNodes[0].nodeValue + "<br>";
valDiv += planets[i].getElementsByTagName("name")[0].childNodes[0].nodeValue + "<br>";
document.getElementById("planetenID").innerHTML += valDiv + "<br>";
// Create button with a value and pass in this object for later reference use (valButton.object=this)
valButton = document.createElement("input");
// valButton.setAttribute("planeetID", planets[i].getElementsByTagName("id")[0].childNodes[0].nodeValue);
valButton.setAttribute("value", 'Meer info');
valButton.setAttribute("type", 'button');
valButton.id = (i + 1);
valButton.object = this;
//
// Here is the problem i cant get fixed
//
//valButton.onclick = function(){ showinfo(); }
valButton.addEventListener('click', showinfo);
// Place the button on screen
document.getElementById("planetenID").appendChild(valButton);
}
}
// simple function to check if it works
function showinfo() {
console.log(this.object);
console.log(this.id);
}
The trouble is this line:
document.getElementById("planetenID").innerHTML += valDiv + "<br>";
When you set innerHTML the content currently in there gets destroyed and replaced with the new html, meaning all your old buttons are now destroyed and new ones are created. The previously attached event listeners do not get attached to the new buttons.
Instead simply create a div/span or whatever container would best help, add your planet text or whatever to it and then use appendChild
valDiv = document.createElement("div");
var id = planets[i].getElementsByTagName("id")[0].childNodes[0].nodeValue;
var name = planets[i].getElementsByTagName("name")[0].childNodes[0].nodeValue;
valDiv.innerHTML = id+"<br>"+name+"<br>";
document.getElementById("planetenID").appendChild(valDiv);
You could also use insertAdjacentHTML
var id = planets[i].getElementsByTagName("id")[0].childNodes[0].nodeValue;
var name = planets[i].getElementsByTagName("name")[0].childNodes[0].nodeValue;
valDiv = id+"<br>"+name+"<br>";
document.getElementById("planetenID").insertAdjacentHTML("beforeend",valDiv);
function updatePlaneten() {
var valDiv, planets, valButton, textNode;
// Get xml files
planets = this.responseXML.getElementsByTagName("planeet");
// loop through the <planet> tags
for (var i = 0; i < planets.length; i++) {
(function(num){
valDiv = document.createElement("div");
// Get the id and the name from the xml info in current <planet> tag
var id = planets[num].getElementsByTagName("id")[0].childNodes[0].nodeValue + "<br>";
var name = planets[num].getElementsByTagName("name")[0].childNodes[0].nodeValue + "<br>";
valDiv.innerHTML = id+"<br>"+name+"<br>";
document.getElementById("planetenID").appendChild(valDiv);
// Create button with a value and pass in this object for later reference use (valButton.object=this)
valButton = document.createElement("input");
// valButton.setAttribute("planeetID", planets[i].getElementsByTagName("id")[0].childNodes[0].nodeValue);
valButton.setAttribute("value", 'Meer info');
valButton.setAttribute("type", 'button');
valButton.id = (num + 1);
valButton.object = this;
// FIX: PASS showinfo TO AN ANONYMOUS FUNCTION CONTAINING THE OBJECT
valButton.addEventListener('click', function(){
showinfo(valButton);
});
// Place the button on screen
document.getElementById("planetenID").appendChild(valButton);
}(i));
}
}
// simple function to check if it works
function showinfo(valButton) {
console.log(valButton.object);
console.log(valButton.id);
}