Javascript code to get several random elements from array not working - javascript

I've just started with JS, and I'm trying to get random elements from an array. The amount is decided by a user's input, and that part works, I think. The functions are called by onClick of buttons.
Scouring the internet has given me the solution below as the best one, but I can't make the part of fetching elements work even in console.log.
What I actually see in console is an empty array [] with length:0
What's the matter with my code? This is the way to do it I keep seeing on forums and people say it works for them and it's basically the same code with changed words.
userArray = [];
function addElement(){
let element = document.getElementById("add-input").value;
userArray.push(element);
document.getElementById("add-input").value = "";
}
function getElements(){
let amount = document.getElementById("amount-input").value;
newList = [];
for(i=0; i<amount.value; i++){
randomElement = userArray[Math.floor(Math.random() * userArray.length)];
newList.push(randomElement);
}
console.log(newList);
}
<div class="phase-add">
<p class="label-p">Input an element</p>
<div class="input-box">
<input class="add-input" type="text" name="add-input" id="add-input">
<button class="add-btn" onclick="addElement()">Add</button>
</div>
</div>
<div class="phase-get">
<div class="input-box">
<p class="label-p">Choose the amount</p>
<input type="text" name="amount-input" id="amount-input">
</div>
<button onclick="getElements()">Get elements</button>
</div>

The Variable amount is already a string/number. You need not get the value of it again in the for loop. Changing to for(i=0; i<amount; i++){ in for loop will fix the issue.
userArray = [];
function addElement(){
let element = document.getElementById("add-input").value;
userArray.push(element);
document.getElementById("add-input").value = "";
}
function getElements(){
let amount = document.getElementById("amount-input").value;
console.log(amount)
newList = [];
for(i=0; i<amount; i++){
randomElement = userArray[Math.floor(Math.random() * userArray.length)];
newList.push(randomElement);
}
console.log(newList);
}
<input id = "add-input" type = "text" ></input>
<button onclick = "addElement()">Add Element</button>
<input id = "amount-input" type = "number"></input>
<button onclick = "getElements()">Get Elements</button>

Related

How to clone or create a nested DOM node and change all its containing id values according to a current id?

I need to display some numbers, strings from a class named Student, but i can't figure it out how i can change the id from children element. I have to use JavaScript.
what i tried to do:
class Student{
static count = 0;
constructor(nume, prenume, data_nasterii, foaie_matricola){
this.IdClasa = ++Student.count;
//definirea atributelor
this.nume = nume;
this.prenume = prenume;
this.data_nasterii = data_nasterii;
this.foaie_matricola = foaie_matricola;
}
afiseazaVarsta(){
}
afiseazaNotele(){
}
calculeazaMedia(){
}
adaugaNota(nota_noua){
}
}
var Stud = [new Student("Name", "Name1", "2000.01.01", "0123123"),
new Student("Green", "Blue", "2022/12.12", "321321")];
function afisareStudenti(){
let i = 0; let bol = false;
for(let x=1; x<=Student.count; x++) {
console.log(document.getElementById("AfisareStudenti"+x)==null);
if(document.getElementById("AfisareStudenti"+x)==null)
{
i = x;
bol = true;
break;
} else {
bol = false;
}
}
if((i<=Student.count)&&(bol==true)){
for(i; i<=Student.count; i++) {
console.log("i="+i);
var div = document.querySelector('#AfisareStudenti1');
var divClone = div.cloneNode(true);
console.log(divClone);
divClone.id = 'AfisareStudenti'+(i);
div.after(divClone);
var NumeStud = document.getElementById("NumeStudent"+(i-1));
var PrenumeStud = document.getElementById("PrenumeStudent"+(i-1));
var dataNastStud = document.getElementById("intData"+(i-1));
var FoaiaMatStud = document.getElementById("FoaiaMatStud"+(i-1));
NumeStud.id = "NumeStudent"+(i);
PrenumeStud.id = "PrenumeStud"+(i);
dataNastStud.id = "intData"+(i);
FoaiaMatStud.id = "FoaiaMatStud"+(i);
}
}
}
and this is the html file(the div that i want to clone):
<!--AFISARE-->
<div id="AfisareStudenti1">
<h2> Afisare Student 1</h2>
<label>Ce student doriti sa modificati? </label>
<form>
<label>Nume:</label><br>
<input type="text" id="NumeStudent1"><br>
<label>Prenume:</label><br>
<input type="text" id="PrenumeStudent1"><br>
<label>Data Nasterii:</label><br>
<input type="date" id="intData1"><br>
<label>Foaie matricola:</label><br>
<input type="text" id="FoaiaMatStud1"><br><br>
<input class="butoane" type="submit" value="Afisare"
onclick="afisareMeniuAfisStudenti()">
</form>
</div>
the class is saved in a dynamic array (could be n object of the class) so i have to make somehow to display the information dynamic. My version changes the id from all elements with the same id (every incrementation of i, the idnumber from id is incremented also). I tried to create that div with document.createElement but is impossible(at least for me) xD . I started coding in javascript 2 days ago, so please take it slow on me :(
I think i found the problem, but it doesn't solve it. (i need to put (i-1) when calling for getting the ids). (Newbie mistake)
Having commented ...
"I have the feeling that if provided with the broader picture the audience could be of much more help since the OP could be provided back with leaner/cleaner and better maintainable approaches."
... I nevertheless hereby lately provide a template-based approach which, besides supporting the OP's id based querying of student-items, is also easier to read and to maintain.
The code provided within the example-code's main function does not just implement the usage of the template-based node-creation via template literals and DOMParser.parseFromString but also prevents the default behavior of each student-form's submit-button by making use of event-delegation.
function createStudentElement(studentId) {
const markup =
`<div class="student-item" id="AfisareStudenti${ studentId }">
<h2> Afisare Student ${ studentId }</h2>
<label>Ce student doriti sa modificati? </label>
<form>
<label>Nume:</label><br>
<input type="text" id="NumeStudent${ studentId }"><br>
<label>Prenume:</label><br>
<input type="text" id="PrenumeStudent${ studentId }"><br>
<label>Data Nasterii:</label><br>
<input type="date" id="intData${ studentId }"><br>
<label>Foaie matricola:</label><br>
<input type="text" id="FoaiaMatStud${ studentId }"><br><br>
<input
class="butoane" type="submit" value="Afisare"
onclick="afisareMeniuAfisStudenti(${ studentId })"
>
</form>
</div>`;
const doc = (new DOMParser).parseFromString(markup, 'text/html');
return doc.body.removeChild(doc.body.firstElementChild);
}
// the button click handler.
function afisareMeniuAfisStudenti(studentId) {
console.log({ studentId })
}
function main() {
const itemsRoot = document.querySelector('.student-items');
// - prevent any form-submit by making use of event-delegation.
itemsRoot.addEventListener('submit', evt => evt.preventDefault());
// - just for demonstration purpose ...
// ... create student-items from a list of student IDs.
[1, 2, 3, 4, 5].forEach(studentId =>
itemsRoot.appendChild(
createStudentElement(studentId)
)
);
}
main();
.as-console-wrapper { left: auto!important; width: 50%; min-height: 100%; }
<div class="student-items"></div>
Tom's answer above is what you want for the element id problem that you asked about.
For your code in particular, you are going to have a couple other problems:
Because the final input is type="submit", its going to reload the page by default when it is clicked. The name of the "onclick" function also needs to match the function you defined (afisareStudenti).
You have:
<input class="butoane" type="submit" value="Afisare" onclick="afisareMeniuAfisStudenti()">
Change this to:
<input class="butoane" type="submit" value="Afisare" onclick="afisareStudenti(event)">
Now, when you click that button, it will call the afisareStudenti function and pass in the "event". So if you change:
function afisareStudenti(){
let i = 0; let bol = false;
to:
function afisareStudenti(event){
event.preventDefault()
let i = 0; let bol = false;
This will correctly call your function, and prevent the "default" action of that submit button from reloading the page.
To change the id attribute of children elements, you could use Element.querySelector() on divClone.
Because if you use Document.querySelector() or Document.getElementById() you will get the first element that matches your selector (i.e.children of div#AfisareStudenti1).
let i = 2;
var div = document.querySelector('#AfisareStudenti1');
var divClone = div.cloneNode(true);
divClone.id = 'AfisareStudenti'+(i);
divClone.querySelector("h2").innerText = "Afisare Student " + i;
var NumeStud = divClone.querySelector("#NumeStudent1");
var PrenumeStud = divClone.querySelector("#PrenumeStudent1");
var dataNastStud = divClone.querySelector("#intData1");
var FoaiaMatStud = divClone.querySelector("#FoaiaMatStud1");
NumeStud.id = "NumeStudent"+(i);
PrenumeStud.id = "PrenumeStud"+(i);
dataNastStud.id = "intData"+(i);
FoaiaMatStud.id = "FoaiaMatStud"+(i);
div.after(divClone);
<div id="AfisareStudenti1">
<h2> Afisare Student 1</h2>
<label>Ce student doriti sa modificati? </label>
<form>
<label>Nume:</label><br>
<input type="text" id="NumeStudent1" /><br>
<label>Prenume:</label><br>
<input type="text" id="PrenumeStudent1" /><br>
<label>Data Nasterii:</label><br>
<input type="date" id="intData1" /><br>
<label>Foaie matricola:</label><br>
<input type="text" id="FoaiaMatStud1" /><br><br>
<input class="butoane" type="submit" value="Afisare" onclick="afisareMeniuAfisStudenti()" />
</form>
</div>

calculating from an input

I'm starting studying the DOM in javascript and I'd like to create a program which makes the sum of two numbers given on input and show it.
I'd like to know what functions should I use, and what functions it is better I didn't.
This is my (very simple) html code:
let warp = document.getElementById('warp');
let first = document.getElementById('first').value;
let one = parseInt(first);
let second = document.getElementById('second').value;
let two = parseInt(second);
let res = document.getElementById('res');
//res.addEventListener('click', calcul);
//res.onclick(calcul);
let nouveau = document.createElement('div');
nouveau.id = 'nouveau';
nouveau.textContent = "nouveau";
warp.appendChild(nouveau);
function calcul(first, second) {
console.log(one + two);
event.preventDefault();
}
<!DOCTYPE html>
</head>
<body>
<div id="warp">
<form>
<input id="first" type="number">first number</input>
<input id="second" type="number">second number</input>
<input id="res" type="submit" value="Envoyer" onclick="calcul()" />
</form>
<div>
</body>
let answerElemenet = document.createElement("h1");
// You can create a h1 element to display your answer after calculating it
document.body.appendChild(answerElemenet);
// Inside the calculate Function you get the values of input one and two
// and then you store the sum value in a variable and just change your
// answerElement to have the innerHTML value of the finalSum Variable
function calculate(){
let valueOne = parseFloat(document.getElementById('first').value);
let valueTwo = parseFloat(document.getElementById('second').value);
let finalSum = valueOne + valueTwo;
answerElemenet.innerHTML = finalSum;
}
Welcome to Stackoverflow!
I copied your answer and made some small changes. Here comes a brief description and explanation of what you could do better:
If you don't plan to change these references use const instead of let. Also try to keep input elements separated from their values. The reference to the input probably won't change but their value most certainly will.
const warp = document.getElementById('warp');
const first = document.getElementById('first');
const second = document.getElementById('second');
const res = document.getElementById('res');
When calculating input values, you usually want them as fresh as possible so instead of saving input values right at the beginning of the script, you get them when you need them, in the calcul() function.
You will also need some kind of validation. Here we try to convert the input to a number and set to zero if not possible:
function calcul() {
event.preventDefault();
const one = parseFloat(first.value) || 0;
const two = parseFloat(second.value) || 0;
console.log(one + two);
}
The preferred way of adding event handlers to DOM elements is using the event API. So to call the calcul()function you use the line you had commented:
res.addEventListener('click', calcul);
This also means you should remove the onClick attribute from the DOM. Also, input cannot have children:
<input id="first" type="number" />
<input id="second" type="number" />
<input id="res" type="submit" value="Envoyer"/>
All together looks like this:
const warp = document.getElementById('warp');
const first = document.getElementById('first');
const second = document.getElementById('second');
const res = document.getElementById('res');
function calcul() {
event.preventDefault();
const one = parseFloat(first.value) || 0;
const two = parseFloat(second.value) || 0;
console.log(one + two);
}
res.addEventListener('click', calcul);
let nouveau = document.createElement('div');
nouveau.id = 'nouveau';
nouveau.textContent = "nouveau";
warp.appendChild(nouveau);
<!DOCTYPE html>
</head>
<body>
<div id="warp">
<form>
<input id="first" type="number" />
<input id="second" type="number" />
<input id="res" type="submit" value="Envoyer"/>
</form>
<div>
</body>
Keep up the good job and never stop asking questions!
This will work. You just need to call the values based on their id in the calcul() function itself.
let warp = document.getElementById('warp');
let res = document.getElementById('res');
let nouveau = document.createElement('div');
nouveau.id = 'nouveau';
nouveau.textContent = "nouveau";
warp.appendChild(nouveau);
function calcul() {
let first = document.getElementById('first').value;
let one = parseInt(first);
let second = document.getElementById('second').value;
let two = parseInt(second);
if(isNaN(one) || isNaN(two)){
event.preventDefault();
return
}
console.log(one + two);
event.preventDefault();
}
<!DOCTYPE html>
</head>
<body>
<div id="warp">
<form>
<input id="first" type="number">first number</input>
<input id="second" type="number">second number</input>
<input id="res" type="submit" value="Envoyer" onclick="calcul()" />
</form>
<div>
</body>

Why does getting a data-attribute within a loop work, but still throws an error?

I have some input elements and I want to create a reset button, so that I can programatically revert their values to their original state.
Here is my code:
let people = document.getElementsByClassName('person')
function reset() {
for (var key in people) {
let string = people[key].dataset.name
people[key].value = string
}
}
let app = document.getElementById('app')
let button = document.createElement('button')
button.innerHTML = "reset"
button.addEventListener('click', reset)
app.append(button)
<div id="app">
<input class="person" data-name="John" value="John">
<input class="person" data-name="Steve" value="Steve">
<input class="person" data-name="Peter" value="Peter">
</div>
This actually works as intended, but I get an error saying that the value of 'data-name' cannot be read, but this cannot be true as the function works as intended.
Does anyone know what is happening here and how I can fix this?
in iterates over all enumerable properties in not only the object itself, but also in all objects in the internal prototype chain. Log the key, and you'll see:
let people = document.getElementsByClassName('person')
function reset() {
for (var key in people) {
console.log(key);
}
}
reset();
<div id="app">
<input class="person" data-name="John" value="John">
<input class="person" data-name="Steve" value="Steve">
<input class="person" data-name="Peter" value="Peter">
</div>
The HTMLCollection has more enumerable properties than just 0, 1, and 2, so trying to access the .dataset on those other properties fails.
Use for..of instead, to invoke the collection's iterator (which will only iterate over the elements in the collection, as desired).
let people = document.getElementsByClassName('person')
function reset() {
for (const input of people) {
input.value = input.dataset.name;
}
}
let app = document.getElementById('app')
let button = document.createElement('button')
button.innerHTML = "reset"
button.addEventListener('click', reset)
app.append(button)
<div id="app">
<input class="person" data-name="John" value="John">
<input class="person" data-name="Steve" value="Steve">
<input class="person" data-name="Peter" value="Peter">
</div>
In general, I'd suggest avoiding in loops usually - often, for..of or Object.keys or Object.entries work better.
This line of code here
for (var key in people)
should be
for (let i = 0; i < people.length; i++)
as the for...in... loop will also get the length property of the people HTMLCollection. You would then be accessing the value property of people.length, which does not exist.
Completed Code:
let people = document.getElementsByClassName('person')
function reset() {
for (let i = 0; i < people.length; i++) {
let string = people[i].dataset.name
people[i].value = string
}
}
let app = document.getElementById('app')
let button = document.createElement('button')
button.innerHTML = "reset"
button.addEventListener('click',reset)
app.append(button)
<div id="app">
<input class="person" data-name="John" value="John">
<input class="person" data-name="Steve" value="Steve">
<input class="person" data-name="Peter" value="Peter">
</div>

Why can't get input value checkbox in array?

In the code described below, the value of the input should be taken from everyone in the array and a new div with the input value in innerHtml should be created. I don't know why get an error that length.value not defined?
<input type="checkbox" class="checkboxnewdivs" id="checkboxnewdivs" name="checkboxnewdivs" value="divsone">
<input type="checkbox" class="checkboxnewdivs" id="checkboxnewdivs" name="checkboxnewdivs" value="divstwo">
<input type="checkbox" class="checkboxnewdivs" id="checkboxnewdivs" name="checkboxnewdivs" value="divsthree">
<button onclick="myFunction()">Click me</button>
<div id="container"></div>
function myFunction() {
let array = [];
var checkboxnewdivs = document.querySelectorAll('input[name="checkboxnewdivs"]:checked');
for (var i = 0; i < checkboxnewdivs.length; i++) {
var iddivs = array.push(checkboxnewdivs[i].value);
var div_new = document.createElement("DIV");
div_new.innerHTML = "ID div:"+iddivs ;
document.getElementById("container").appendChild(div_new);
}
}
var checkboxnewdivs = document.querySelectorAll('input[name="checkboxnewdivs"]:checked').value;
Should be
var checkboxnewdivs = document.querySelectorAll('input[name="checkboxnewdivs"]:checked');
The first one is trying to get a value property from a node collection, which will obviously be undefined.
You also had some typos (double 's') and don't define array anywhere. Define that where you defined checkboxnewdivs.
Working demo: https://jsfiddle.net/mitya33/m9L2dvz5/1/

How do you make javascript(including function with array and return) write in div on button click without going to another page

I have had a lot of problems with this problem. When I console.log(sum); I get the answer I am looking for, but when I try to output the answer from a button click and an input field it does not work. I changed felt3.innerHTML=addnumber(ttt); to document.write(addnumber(ttt)); which made it work, but it is sending it to another page, which is something I do not want. How I can make this work:
<form id="form3">
Tall:<input type="number" id="number"><br>
<input type="button" id="button3" value="plusse"><br>
</form>
<div id="felt3"></div>
and:
var number = document.getElementById("number");
var felt3 = document.getElementById("tall3");
var form3 = document.getElementById("form3");
var button3 = document.getElementById("button3");
var sum=0;
function addnumber(x){
var array = [];
array.push(x);
for (var i = 0; i < array.length; i++) {
sum=sum+array[i];
}
return sum;
}
button3.onclick=function(){
var ttt=Number(number.value);
felt3.innerHTML=addnumber(ttt);
}
If I understand your question correctly, then the solution here is to update the argument that you are passing to getElementById("tall3"), rewriting it to document.getElementById("felt3");.
Doing this will cause your script to aquire the reference to the div element with id felt3. When your onclick event handler is executed, the result of addnumber() will be assigned to the innerHTML of the valid felt3 DOM reference as required:
var number = document.getElementById("number");
// Update this line to use "felt3"
var felt3 = document.getElementById("felt3");
var form3 = document.getElementById("form3");
var button3 = document.getElementById("button3");
var sum=0;
function addnumber(x){
var array = [];
array.push(x);
for (var i = 0; i < array.length; i++) {
sum=sum+array[i];
}
return sum;
}
button3.onclick=function(){
var ttt=Number(number.value);
// Seeing that felt3 is now a valid reference to
// a DOM node, the innerHTML of div with id felt3
// will update when this click event is executed
felt3.innerHTML=addnumber(ttt);
}
<form id="form3">
Tall:<input type="number" id="number"><br>
<input type="button" id="button3" value="plusse"><br>
</form>
<div id="felt3"></div>

Categories