Get text from each element with certain class and then add up - javascript

I'm trying to do some calculations using javascript. I'm basically getting the text of each element with a certain class, convert that to a number and then add those numbers up.
This is what I've got so far:
<p class="item-size">1000</p>
<p class="item-size">2000</p>
JS:
$(document).ready(function(){
var elements = document.getElementsByClassName("item-size");
var size = ''
for (var i=0; i<elements.length; i++) {
size += parseInt((elements[i].innerText).replace(/[^0-9.]/g, ""));
}
console.log(size);
});
This returns 10002000 in the console. However, I need to get each of those values and then add them up instead of displaying them as one number. So the result should be 3000.
I've tried this:
var myTotal = 0;
for(var i = 0, len = size.length; i < len; i++) {
myTotal += size[i][1];
console.log(myTotal);
}
However, this returns NaN. Any ideas how to do this?

You need a number as target variable.
$(document).ready(function(){
var elements = document.getElementsByClassName("item-size");
var size = 0; // <-- zero instead of an empty string
for (var i=0; i<elements.length; i++) {
size += parseInt((elements[i].innerText).replace(/[^0-9.]/g, ""), 10); // take base
}
console.log(size);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class="item-size">1000</p>
<p class="item-size">2000</p>

var size = 0, when you add string with integer it will return string and calculated as string. int + str = str
Here's ES5 version:
const elements = document.getElementsByClassName("item-size");
const size = Object.keys(elements)
.reduce((acc, curr) =>
acc + parseInt(elements[curr].innerText.replace(/[^0-9.]/g, "")), 0)
console.log(size);
https://jsfiddle.net/becg3vqu/3/

Loop through all the children of an element and for each one increment a number by the textcontent of the element with a unary operator.
function getSumOfClass(className, root) {
if (!(root instanceof HTMLElement)) root = document.body;
return [].reduce.call(root.querySelectorAll("." + className),
(result, dom) => result + (+dom.textContent || 0), 0);
}
console.log(getSumOfClass("item-size"));
<p class="item-not-size">500</p>
<p class="item-size">1000</p>
<p class="item-size">2000</p>
Adding a + or a - infront of a parameter or literal will convert it to a number. If it can't be converted to a number, the result will be NaN so you can just add an || operator to return a 0 in that case (so that the non arithmetic value will be ignored).

Using javascript vanilla
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p class="item-size">1000</p>
<p class="item-size">2000</p>
<script>
//getting the texts that contain numbers
let items = document.getElementsByClassName("item-size");
let sum = 0;
//Now for each element in the arrays
for (let i = 0; i < items.length; i++) {
sum = sum + parseInt(items[i].innerText);
}
console.log(sum);
</script>
</body>
</html>

Since size is initially an empty string the addition wont work as you expected. Initialize var size to 0.

Related

How do I collect and sum up these values by Class Name

I'm trying to add collect all the odds ,loop through the results and add them to array totalArr.
in the second step I tried to sum up the values in the totalArr but its not working. alert(sum)
is returning 03.32.51.82.2
<p class="slip-odds">3.3</p>
<p class="slip-odds">2.5</p>
<p class="slip-odds">1.8</p>
<p class="slip-odds">2.2</p>```
<script type="text/javascript">
let getSlipOdds = document.getElementsByClassName('slip-odds');
let totalArr = [];
for (let i = 0; i < getSlipOdds.length; i++) {
var slipOdd = getSlipOdds[i].innerHTML;
totalArr.push(slipOdd);
}
let sum = 0;
for (let i = 0; i < totalArr.length; i++) {
sum += totalArr[i];
}
alert(sum);
</script>
Convert to number before pushing to the array like this
totalArr.push(Number(slipOdd));
You should convert totalArr[i] to a number before adding.
it's because javascript thinks it's a string, not a number. you can easily multiply your array elements with 1 and it will convert it to a number
sum += totalArr[i] * 1;

JS: Reversing a string using nested loop does not work

I have written a function called reverseStr that takes in a string as a parameter and returns the string but with the characters in reverse.
For example: reverseStr('bootcamp'); => 'pmactoob'
Following is my program:
function reverseStr(str)
{
var splitStr = str.split("");
console.log(splitStr);
var reverseString = [];
for(var i = 0; i <= splitStr.length -1 ; i++)
{
for(var j = splitStr.length - 1; j >= 0; j--)
{
reverseString[i] = splitStr[j]
}
}
return reverseString.toString().replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
}
If I run the function reverseStr("bootcamp") it returns bbbbbbbb.
Does anyone see a problem with the code?
Note: I DONOT WANT TO USE REVERSE() BUILT-IN FUNCTION
However, I found success with the following code but still need an answer to my initial question
function reverseStr(str)
{
var splitStr = str.split("");
reverseStr = "";
for(var i = splitStr.length - 1; i >= 0 ; i = i - 1)
{
reverseStr += splitStr[i];
}
return reverseStr;
}
You don't need to double-iterate through the characters, i.e., do not need to nest for loops. Iterate once and grab the chars in reverse order, like this:
function reverseStr(str)
{
var splitStr = str.split("");
console.log(splitStr);
var reverseString = [];
for(var i = 0, j=splitStr.length-1; i <= splitStr.length -1 ; i++, j--)
{
reverseString[i] = splitStr[j]
}
return reverseString.toString().replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
}
You can see that here the loop goes on for as long as i <= splitStr.length -1,ie, length of the string. This is sufficient to get the mirroring character (i versus Array.length-i).
Here is a working snippet to demo:
var reverseStr = function(str) {
let result = String();
for(let i = str.length-1; i >= 0; i--) {
result += str.charAt(i);
}
return result.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, '');
}
$('button').click(function() {
$('.result').text(reverseStr($('#str').val()));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="str">
<button>Reverse it</button>
<div class="result"></div>
Perhaps a more elegant way to achieve the same (apart from Array.prototype.reverse()) would be to use String.prototype.chatAt(). This would avoid two conversions to and from an array, and also save you one variable. Granted, the code is much shorter and more obvious in what it is doing.
var reverseStr = function(str) {
let result = String(); // An empty string to store the result
for(let i = str.length-1; i >= 0; i--) { // Iterate backwards thru the chars and add to the result string
result += str.charAt(i);
}
return result.replace(/[&\/\\#,+()$~%.'":*?<>{}]/g, ''); // Original return method of the author
}
$('button').click(function() {
$('.result').text(reverseStr($('#str').val()));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="str">
<button>Reverse it</button>
<div class="result"></div>
The problem is that your nested for loop runs its whole course before it returns to the outer for loop. So, it just repeats one character the amount of times equal to the length. Instead of having another for loop, just add a simple counter for j like j++ inside your outer for loop and use that value with the i value.
To the original poster, consider this:
If you know the length of the original string, you therefore know the offset of that last position within the original string.
Iterate through the original string in reverse order, appending the current position's value to a new string. The new string would be the reverse of the original.
Aydin's example is essentially correct. Here's my very similar version, with comments:
function reverseString(inputString) {
// create a new empty string
var newString = "";
// iterate through the characters of the string in reverse order,
// appending to the new string
for (var i = inputString.length - 1; i >= 0; i--) {
newString += inputString[i];
}
return newString;
}
console.log(reverseString('bootcamp'));

How to format number to currency?

I currently doing formatting of number to currency but is not working on a collection of an array. I used javascript to use the Math.round function. I would like to know how properly use this function. I appreciate your suggestion. Thank you.
Array:
{
"data": [
[
"9812355000",
"23397000",
"13976000"
]
]
}
for (var x = 0; x < data.data.length; x++) {
for (var i0 = 0; i0 < data.data[x].length; i0++) {
dynamicColumn += `<td>${data.data[x][i0] === null || data.data[x][i0] === ""
? 0
: Math.round(data.data[x][i0])}</td>`;
}
}
Need to achieve:
9,812,355,000
23,397,000
13,976,000
To achieve the output you specified using your array, you can iterate though the digits backwards (meaning, starting from the last number and moving to the first number) and then inserting a comma after 3 digits. Some sample code could look like this:
for(let i = numberString.length - 1; i >= 0; i--) {
if (i % 3 === 0)
array.insert(i, ','); // this is not a real function. I leave it up to you to implement this. first param is index and second is what to insert
}
var thousandSeparationRegexp = /\B(?=(\d{3})+(?!\d))/g;
// iterate through numbers
var numberString = number.toString();
var formatted = numberString.replace(thousandSeparationRegexp, ',');
Or inline:
var formatted = number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
You can use an Intl.NumberFormat().format(x):
function myFunction() {
var x = document.getElementById("value_unformated").value
var a = Intl.NumberFormat().format(x)
var text = "Currency format: " + a + "<br>";
document.getElementById("value_formated").innerHTML = text;
}
<input type="number" id="value_unformated" value="13528468">
<button onclick="myFunction()">Format</button>
<p id="value_formated"></p>

JS: innerHTML inconsistency

I am using Google Chrome version 43.0.2357.130. I am trying to append output to an HTML element using innerHTML, which is being done inside of a loop. I get the expected result most of the time, but if I click on the "Generate" button over and over, eventually it will give me an unexpected result. For instance, one of the passwords will be chopped off at a random spot. I used the JS debugger in Chrome, but that didn't help much. Then I tried to debug it myself by using the alert() function alongside the innerHTML property so that I could compare the output. The output in the alert() popup was never truncated, unlike innerHTML.
I highlighted what I think is the problem code with '/* PROBLEM CODE */' in the JS file. The files should be placed in the same directory. Here is the HTML and JS:
<!DOCTYPE html>
<html>
<head>
<title>PassGen - Random Password Generator</title>
<!--link rel="stylesheet" src="//normalize-css.googlecode.com/svn/trunk/normalize.css"-->
<!--link href="css/main.css" rel="stylesheet" type="text/css"-->
<!--script src="../app/js/jquery-2.1.4.js"></script-->
</head>
<body>
<form>
<h2>Password amount</h2>
<input type="text" id="amount" name="amount" />
<h2>Letter amount</h2>
<input type="text" id="letters" name="letters" />
<h2>Number amount </h2>
<input type="text" id="numbers" />
<h2>Symbol amount</h2>
<input type="text" id="symbols" />
<input onclick="generatePassword(); return false;" type="submit" value="Generate" />
</form>
<p id="output"></p>
<script src="plain-app.js"></script>
</body>
</html>
// get the DOM element we will be using for the final output
var output = document.getElementById("output");
function generatePassword(amount) {
clearPasswords();
// get DOM form elements (user input)
var amount = document.getElementById("amount").value;
var letters = document.getElementById("letters").value;
var numbers = document.getElementById("numbers").value;
var symbols = document.getElementById("symbols").value;
// populate character sets
var letterSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
var numberSet = "0123456789";
var symbolSet = "~!##$%^&*()-_+=><";
var array = [];
// if there is no password amount specified, create one password
if(amount === undefined) {
amount = 1;
}
for(var j = 0; j < amount; j++) {
// random character sets to be concatenated later
var rl = "";
var rn = "";
var rs = "";
var tp = ""; // concatenated password before shuffling
// 3 random letters
for(var i = 0; i < letters; i++) {
var rnd = Math.floor((Math.random() * 52));
rl += letterSet[rnd];
}
// 3 random numbers
for(var i = 0; i < numbers; i++) {
var rnd = Math.floor((Math.random() * 10));
rn += numberSet[rnd];
}
// 3 random symbols
for(var i = 0; i < symbols; i++) {
var rnd = Math.floor((Math.random() * 17));
rs += symbolSet[rnd];
}
tp = rl + rn + rs; // string concatentation
tp = tp.split(''); // transform string into an array
// shuffling
for(var i = 0; i < tp.length; i++) {
var rnd = Math.floor(Math.random() * tp.length);
var temp = tp[i];
tp[i] = tp[rnd];
tp[rnd] = temp;
}
// transform the array into a string
tp = tp.join("");
array[j] = tp; // for logging and debugging purposes
// tp can be replaced with array[j], but still get the inconsistency
/* PROBLEM CODE */
output.innerHTML += (tp + "<br />");
/* PROBLEM CODE */
//alert(array[j]);
}
console.log(array);
return array; // not useful?
}
// clear all password output
function clearPasswords() {
while(output.hasChildNodes()) {
output.removeChild(output.firstChild);
}
}
Does innerHTML have side effects I don't know about or am I using it incorrectly? Should it not be used for appends? Should appendChild() be used instead?
The problem is that some characters have special meaning in HTML: <, >, &.
Therefore, you can
Remove those characters from the list
Escape them: <, >, &
output.innerHTML += tp.replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&') + "<br />";
Parse the text as text instead of as HTML, e.g.
Use textContent and white-space
output.textContent += tp + "\n";
#output { white-space: pre-line; }
Use createTextNode and appendChild
output.appendChild(document.createTextNode(tp));
output.appendChild(document.crateElement('br'));
The problem occurred in the symbolSet. It contained the characters < and >. When they were selected at random and added to the password, the browser tried to render them as elements when I was outputting the password to the screen. To fix this, I just removed the two characters from symbolSet, and changed the random symbol generation loop to reflect the shortened length of symbolSet.
I changed the two problematic sections of code to
var symbolSet = "~!##$%^&*()-_+=";
and
for(var i = 0; i < symbols; i++) {
var rnd = Math.floor((Math.random() * 15)); // this end of this line
rs += symbolSet[rnd];
}
In addition, I changed the useless if statement to (this can be applied to all of the fields)
if(!isNumber(amount) || amount === 0) {
amount = 1;
}
and added an isNumber function to check for valid input on all of the fields.
function isNumber(obj) {
return !isNaN(parseFloat(obj));
}

Treat the prev element in JavaScript array when creating object dynamically

I want to do something like:
var arr = []
for var(i=0;i<x;i++){
arr.push{ get num(){return this.previousArrayElement.num + randomNumber}}
}
how can I treat "previousArrayElement"?
I think you are just trying to create an array of size x containing numbers in order of size and separated by randomNumber intervals? Something like this would work:
var x = 100;
var arr = [0]
for (i=1; i<x; i++) {
arr.push( arr[i-1] + Math.random() );
}
Note that by starting the array out with an initial value (index 0) and beginning your iteration with the second value (index 1) you don't have to worry about accessing the 0-1 element at the first iteration.
I hope that helps!
Not 100% sure this is what you want. Expected output shown is not valid syntax and details provided are very open to interpretation
var arr = []
for (var i=0; i < x; i++){
var num = i > 0 ? arr[i-1].num : 0;
num= num + randomNumber; // is this an existing variable?
arr.push({ num: num}); // used object with property `num` based on example `previousArrayElement.num `
}

Categories