I'm finding DOM manipulation tricky. I have written a function that uses the filter method on an array with numbers that are divisible by two.
The function evenNums works. I want to use the push() method to push numbers from the input text field to the array and display the result from the function evenNums on the page.
HTML
<!DOCTYPE html>
<html>
<head> </head>
<body>
<label for="text">Enter Text</label>
<input id="myText" type="text" />
<input type="radio" />
<label for="function">Function 1</label>
<input type="radio" />
<label for="function">Function 2</label>
<button id="btn">Click Me</button>
<div id="result"></div>
<script src="array.js"></script>
</body>
</html>
ignore the radio buttons. This is my Javascript
const inputBtn = document.getElementById("btn")
const myText = document.getElementById("myText")
const result = document.getElementById("result")
//function 1 filter method on array.
const nums = [1,2,3];
const answer = nums.filter(evenNums);
function evenNums(nums) {
if (nums%2 == 0) {
return nums
}
}
result.innerHTML = answer;
console.log(nums) // original array
console.log(answer) // array using filter method
//How do I push a value from the user to the array?
inputBtn.addEventListener ("click", function() {
nums.push(myText.value);
myText.value ='';
evenNums(nums);
});
This is how far I've got. How do I push a value from the user to the array and display it on the page? Am I close?
Thanks for all your help!
What you are doing is almost correct, just make sure you call the filter and set the textcontent when clicking the button. Also the value is a string, you will have to parseInt() it to do the even / odd calculation. It is also safer to use textcontent instead of innerHTML.
const inputBtn = document.getElementById("btn")
const myText = document.getElementById("myText")
const result = document.getElementById("result")
const nums = [1, 2, 3];
inputBtn.addEventListener("click", function() {
nums.push(parseInt(myText.value));
myText.value = '';
const answer = nums.filter(evenNums);
function evenNums(nums) {
if (nums % 2 == 0) {
return nums
}
}
result.textContent = answer;
});
<label for="text">Enter Text</label>
<input id="myText" type="text" />
<button id="btn">Click Me</button>
<div id="result"></div>
Just a sidenote: filter() expects a boolean as return value, the reason your filter works is because you return nums which is seen as truthy.
This should be better.
const nums = [1, 2, 3];
const answer = nums.filter(evenNums);
function evenNums(nums) {
if (nums % 2 == 0) {
return true;
}
}
console.log(answer);
You could simplify your filter to.
const nums = [1,2,3];
const answer = nums.filter(n => n % 2 === 0);
console.log(answer);
Because (x === y) returns a boolean.
The short answer would be.
const inputBtn = document.getElementById("btn")
const myText = document.getElementById("myText")
const result = document.getElementById("result")
const nums = [1, 2, 3];
inputBtn.addEventListener("click", function() {
nums.push(parseInt(myText.value));
myText.value = '';
result.textContent = nums.filter(n => n % 2 === 0);
});
<label for="text">Enter Text</label>
<input id="myText" type="text" />
<button id="btn">Click Me</button>
<div id="result"></div>
Seems like you are on the right track. After you push the user's input to the array, you can display the result of filtered array on the page by setting the innerHTML attribute.
Just calling the function on its own is not going to do anything for you.
document.getElementById("result").innerHTML = nums.filter(evenNums);
Related
I want to only show the text from the arrays that are selected with the checkboxes (so, if i only want txt and ran, it only shows options from those arrays)
function myFunc() {
let txt = ["txt1", "txt2", "txt3"];
let test = ["test1", "test2", "test3"];
let ran = ["ran1", "ran2", "ran3"];
let tst = txt[Math.floor(Math.random() * txt.length)] + "<br><br><br>" + test[Math.floor(Math.random() * test.length)] + "<br><br><br>" + ran[Math.floor(Math.random() * ran.length)];
document.getElementById("tst").innerHTML = tst;
}
<input type="checkbox"> txt<br>
<input type="checkbox"> test<br>
<input type="checkbox"> ran
<br>
<br>
<button onclick="myFunc()">One Character</button>
<p id="tst">
sum text lol
</p>
Code: https://jsfiddle.net/RoseLovesGreene/ps17u8yd/6/
I'd also like to be able to show it in a random order so that each array doesn't have it's own line.
To get the values of your checkboxes, you need to give them actual values - and to reference the arrays without a bunch of IF statements, they need to be referencable in something like an object.
This will get random values from each array as it loops the forEach, but the final output needs to be shuffled (per your spec). There are many ways of doing this - I grabbed one of the more concise versions, but there are many to choose from here: How to randomize (shuffle) a JavaScript array?
function shuffle(a, b, c, d) { //array,placeholder,placeholder,placeholder
c = a.length;
while (c) b = Math.random() * (--c + 1) | 0, d = a[c], a[c] = a[b], a[b] = d;
return a
}
function myFunc() {
let vars = {
txt: ["txt1", "txt2", "txt3"],
test: ["test1", "test2", "test3"],
ran: ["ran1", "ran2", "ran3"]
}
// get the checked values into an array
let flatArr = [];
document.querySelectorAll('[type=checkbox]:checked').forEach(el => {
flatArr = [...flatArr, vars[el.value][Math.floor(Math.random() * vars[el.value].length)]]
});
document.getElementById("tst").innerHTML = shuffle(flatArr).join(" ");
}
<input type="checkbox" value='txt'> txt<br>
<input type="checkbox" value='test'> test<br>
<input type="checkbox" value='ran'> ran
<br>
<br>
<button onclick="myFunc()">One Character</button>
<p id="tst">
sum text lol
</p>
You could use an if clause to determine whether or not the checkbox is checked. Then if it is checked, use the random number as a key to the array, which you can then append to the result.
function myFunc() {
let txt = ["txt1", "txt2", "txt3"];
let test = ["test1", "test2", "test3"];
let ran = ["ran1", "ran2", "ran3"];
let target = document.getElementById('tst');
let result = "";
let txtKey = [Math.floor(Math.random() * txt.length)]
let testKey = [Math.floor(Math.random() * test.length)]
let ranKey = [Math.floor(Math.random() * ran.length)]
if (document.getElementById('txt').checked) {
result = result+txt[txtKey];
}
if (document.getElementById('test').checked) {
result = result+test[testKey];
}
if (document.getElementById('ran').checked) {
result = result+ran[ranKey];
}
target.innerHTML = result;
}
<input id="txt" type="checkbox"> <label for="txt">txt</label><br>
<input id="test" type="checkbox"> <label for="test">test</label><br>
<input id="ran" type="checkbox"> <label for="ran">ran</label>
<br>
<br>
<button onclick="myFunc()">One Character</button>
<p id="tst">
sum text lol
</p>
There are a few things that you could do to make this more elegant, but I think the idea works.
//Object of arrays
let options = {
txt : ["txt1", "txt2", "txt3"],
test : ["test1", "test2", "test3"],
ran : ["ran1", "ran2", "ran3"]
};
function myFunc() {
//Get all checkboxes
let checkedBoxes = document.querySelectorAll('input[type=checkbox]:checked');
//array for texts from arrays
let texts = [];
//loop through selected checkboxes
checkedBoxes.forEach(function(ele) {
// select respective array from object based on checkbox value
let cOpt = options[ele.value];
// random index for texts array - to randomize array text line
let index = Math.floor(Math.random() * checkedBoxes.length);
// to make sure we didn't set a text to that index already
while( texts[index] !== undefined ) {
index = Math.floor(Math.random() * checkedBoxes.length);
}
// set selected array text to a random index in texts array
texts[index] = cOpt[Math.floor(Math.random() * cOpt.length)];
});
// text.join() to covert texts array into string
document.getElementById("tst").innerHTML = texts.join('<br><br>');
}
<input type="checkbox" value="txt"> txt<br>
<input type="checkbox" value="test"> test<br>
<input type="checkbox" value="ran"> ran<br>
<button onclick="myFunc()">One Character</button>
<p id="tst">
sum text lol
</p>
You need to make some adjustments in your approach. i.e set values to checkboxes, create a js obj with all arrays being its property.
Make sure checkboxes values and properties keys are the same.
I have added comments in the code so you can easily understand the purpose of each line.
I'm looking for a method where I can make a variable containing the document.getElementById and include the correct value for the ID as a variable value. What I have now is this:
let lenght = parseInt(document.getElementById("lenght").value);
let start = parseInt(document.getElementById("start").value);
let end = parseInt(document.getElementById("end").value);
But what I would like to have is something like this:
let documentById = parseInt(document.getElementById($elementName).value)
let lenght = documentById("lenght");
let start = documentById("start");
let end = documentById("end");
Am I thinking in the correct way or is this a method that does not make sense? Any tips/suggestions are welcome as I try to learn.
You could accomplish this with a simple function that takes in the ID of the element as a parameter and returns the value as intended
function documentById(id) {
const el = document.getElementById(id);
if (!el) return undefined; // element doesn't exist
const value = parseInt(el.value, 10); // parsing string to a number (default radix is 10)
return isNaN(value) ? { number: false, value: value } : { number: true, value: value };
}
const { number, value } = documentById('end'); // if value isnt a number return false (to prevent errors);
if (number) console.log(value); // if value is a number log its value
else console.log('not a valid number')
Sure, you can make a function that returns just that.
const getValueById = (id) => parseInt(document.getElementById(id).value, 10);
const length = getValueById("length");
const start = getValueById("start");
const end = getValueById("end");
console.log({ length, start, end });
<input id="length" value="5" />
<input id="start" value="2" />
<input id="end" value="6" />
I was able to figure out how to convert user input into an array of strings to an array of integers, but is map the only way or could I have used parseInt in some other way?
const myArray = [];
const addData = function() {
let inputData = document.getElementById('user_input');
myArray.push(inputData.value);
console.log(myArray.map(Number));
}
document.getElementById('myBtn').addEventListener('click', addData);
<input type="number" id="user_input">
<button type="button" id="myBtn">Click to store</button>
I used: myArray.map(Number);
The usual way is to call parseInt() on the input value before using it. This way you don't have to keep parsing everything in the array.
const myArray = [];
const addData = function() {
let inputData = document.getElementById('user_input');
myArray.push(parseInt(inputData.value));
console.log(myArray);
}
document.getElementById('myBtn').addEventListener('click', addData);
<input type="number" id="user_input">
<button type="button" id="myBtn">Click to store</button>
I've been on this all day.
HTML Code
<label>Input values</label>
<input type="text" id="arrays" placeholder="Enter Array" >
<button id="objectify" type= "button">Click</button>
<div id="results"></div>
JavaScript
var input= document.getElementById('arrays').value; //["book", 3, "pin", 4];//
var btn = document.getElementById('objectify');
var output = document.getElementById('results');
function objectifyArr(x) {
var myObject = {
String: [],
Number: []
};
for (var i = 0; i < x.length; i++) {
if (typeof x[i] === 'string' || x[i] instanceof String){
myObject.String.push(x[i]);
} else if (typeof x[i] === 'number' || x[i] instanceof Number){
myObject.Number.push(x[i]);
}
}
return myObject;
}
btn.onclick = function () {
output.textContent = JSON.stringify(objectifyArr(inputValue));
}
The code seems to work when I assign 'inputValue' a range of array values but doesn't when I get the array via getElementbyId.value. Is there an input type for arrays specifically or did I assign the wrong value to my variable?
Regardless of what the mistake is, I'll be glad if someone pointed it out for me.
How about just using JSON.parse() and waiting to get the value of the input until you actually click the button?
Also (FYI), label requires that you either nest the element that it is a label for within it or that you add the for attribute and give it the value of the id of the element that it is a label "for".
var input= document.getElementById('arrays'); //["book", 3, "pin", 4];//
var btn = document.getElementById('objectify');
var output = document.getElementById('results');
btn.addEventListener("click", function () {
let myArray = JSON.parse(input.value);
output.textContent = myArray;
console.log(myArray);
});
<label for="arrays">Input values</label>
<input id="arrays" placeholder="Enter Array" value='["book", 3, "pin", 4]'>
<button id="objectify" type= "button">Click</button>
<div id="results"></div>
Your first problem is that you declare this in the top of your JS file:
var input= document.getElementById('arrays').value
This is literally saying "assign the current value of the element to my input variable". Obviously, the input element at the start of the script is empty, therefore the value is ''.
After that, the other problem is that as your input only accepts text, all the characters inside will be String type, so looping and checking for the typeof of each character will always yield it as a String.
A workaround for that would be using a RegExp.
Here's a working JSFiddle
How would one go about stacking values to each other? So if you were to click on a button, it would add the numbers to each other and keep stacking on. I'm trying to add the values to a P tag's innerHTML that calculates the total but I just figured out how to display its true value without the addition of additional values.
const input = document.querySelector('input')
const button = document.querySelector('button')
const p = document.querySelector('p')
function addCal() {
const inputVal = input.value
p.innerHTML = inputVal
}
button.addEventListener('click', addCal)
<input type="text"/>
<button>Add Calories</button>
<p>0</p>
You just need to keep track of the last value somewhere and add that to the newest number.
Keep in mind that all values gotten from HTML are strings, so they must be converted (implicitly or explicitly) to numbers before math can be done. Also, .innerHTML is for when you are getting/ setting strings that contain HTML. When you aren't doing that, use .textContent.
Also note that you should always verify user input is what you think it is before you operate on it. What if the user doesn't enter anything, but clicks the button anyway? What if they enter non-numeric data?
const input = document.querySelector('input');
const button = document.querySelector('button');
const p = document.querySelector('p');
var total = null; // The running total will be kept here
function addCal() {
const inputVal = input.value;
// .parseInt() and .parseFloat() are two ways of
// explicitly converting strings that contain number
// characters to numbers. With .parseInt() the secon
// argument is the radix, which specifies what numeral
// system to use (base 10 here).
total = total + parseInt(inputVal, 10);
p.textContent = total;
}
button.addEventListener('click', addCal)
<input type="text"/>
<button>Add Calories</button>
<p>0</p>
One of the easiest ways is to use reduce to sum all the input values.
1) Pick up all the inputs with querySelectorAll.
2) Then iterate over the input elements with reduce adding each input's value to the total sum. We use +input.value to coerce the string type of the value to a number.
const inputs = document.querySelectorAll('input');
const button = document.querySelector('button');
const para = document.querySelector('p');
function addCal() {
para.textContent = [...inputs].reduce((sum, input) => {
return sum += +input.value;
}, 0);
}
button.addEventListener('click', addCal, false);
<input type="text" />
<input type="text" />
<input type="text" />
<input type="text" />
<button>Add Calories</button>
<p>0</p>
Just do convert p tag value to int and then added up. like
function addCal() {
const inputVal = input.value
p.innerHTML = ( parseInt(p.innerHTML) + parseInt(inputVal) )
}