-1

My question is simple let's say you have multiple <span> elements like this

 <span class="hi">10,000</span>
 <span class="hi">20,000</span>
 <span class="hi">40,000</span>
 <span class="hi">500,000</span>

How do you get each number content inside the span tag, strip the commas away and add the numbers get the answer and add commas, cause I can't seem to figure out a way to do this.

This is what I want to achieve

//data would be gotten from Span tag with class HI

<script> 
var addthevalue = 10000+20000+40000+500000;
$(#theans).html(addthevalue);
</script>

 <div id=theans></div>
Yevhen Horbunkov
  • 14,965
  • 3
  • 20
  • 42
Shasha
  • 439
  • 8
  • 26
  • If jQuery solution is what you're looking for, there's a [neat one](https://stackoverflow.com/a/60459005/11299053) you may consider. – Yevhen Horbunkov Feb 28 '20 at 20:46

6 Answers6

4

You can use spread syntax on querySelectorAll to get an array and then you can use reduce method to calculate sum.

const sum = [...document.querySelectorAll('span')].reduce((r, e) => {
  return r + parseInt(e.textContent.replace(',', ''))
}, 0)

console.log(sum)
<span class="hi">10,000</span>
<span class="hi">20,000</span>
<span class="hi">40,000</span>
<span class="hi">500,000</span>
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176
  • Just want to note that IE does not support spread syntax. In case if the OP needs to care about IE compatibility. – Yunhai Feb 28 '20 at 20:47
  • @Yunhai : since we're talking *uglifying* one's code for the sake of *walking dead* IE compatibility, it will also stumble over arrow function notation. – Yevhen Horbunkov Feb 28 '20 at 21:33
  • @YevgenGorbunkov - If OP has a requirement to ensure code functions in IE then using a transpiler such as Babel would probably be the solution here. Although I do agree IE is garbage, it still might be important that the code works as expected in that browser (for any cavemen is using it). – Tom O. Feb 28 '20 at 21:50
  • @NenadVracar really like your answer. But in case of multiple commas there will be an problem. Maybe you want to change `replace(',', '')` with `.replace(/,/g, '')` to be sure all commas are deleted. – KingKabyle Feb 29 '20 at 15:19
2

Try this:

 const sum = Array.from(document.getElementsByClassName('hi'))
      .map(el => parseFloat(el.textContent.replace(/[^0-9\.]/g, '')))
      .reduce((total, current) => total + current);

document.getElementById('sum').innerHTML = `sum: ${sum.toLocaleString()}`;
<span class="hi">10,000</span>
<span class="hi">20,000</span>
<span class="hi">40,000</span>
<span class="hi">500,000.01</span>
<div id="sum"></div>

edit: forgot to remove the commas, credit to Jeremy Harris. And credit to Yevgen Gorbunkov for performance/function enhancements.

stjns
  • 1,420
  • 13
  • 16
  • That's a fair point. I wasn't super focused on performance, but I will edit to reflect this suggestion. – stjns Feb 28 '20 at 21:53
  • Whoops, you're totally right. I just forgot to add that in. – stjns Feb 28 '20 at 22:12
  • You're still using `innerHTML` to modify text content of `
    ` :) You might want to check out [this one](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent#Differences_from_innerHTML), to get your patterns adjusted ;) Happy coding.
    – Yevhen Horbunkov Feb 28 '20 at 22:34
2

While not the most concise way to do it, this is one way to do it:

You can get the elements and use a regular expression to parse anything that is not a number, and then add it to a variable tracking the total.

const elements = document.querySelectorAll('.hi');
let total = 0;
elements.forEach((el, i) => {
    const val = el.innerHTML.replace(/[^0-9]/, '');
    total += parseInt(val);
});

console.log("Total:", total);
 <span class="hi">10,000</span>
 <span class="hi">20,000</span>
 <span class="hi">40,000</span>
 <span class="hi">500,000</span>
Jeremy Harris
  • 24,318
  • 13
  • 79
  • 133
  • If OP cares about performance, above code could work much faster with `getElementsByClassName()`+`textContent` rather than `querySelectorAll()`+`innerHTML`. Besides, your `replace()` will mess up floating numbers should they occur. Another point is that since we're outside of typescript world, `total += +val` is much shorter (though one may find it sneaky). – Yevhen Horbunkov Feb 28 '20 at 21:23
2

You can do this easily by stripping out the commas using a regex. Once you've done that you basically just need to sum up the values - Array.prototype.reduce is an easy way to achieve this. Finally, once you have the correct sum, use another regex function to convert to a string properly formatted commas. See the code comments for details:

// Util functions
const stripCommas = s => s.replace(/,/g, ''); // Util function to remove commas from string
const numberToFormattedString = n => n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");

// Get the sum as a number
const sum = Array.from(document.querySelectorAll('.hi')) // Gather an array of DOM elements
  .map(el => Number(stripCommas(el.innerText))) // Strip the commas and turn to Numbers
  .reduce((sum, n) => sum + n, 0); // Sum the numbers using reduce

// Convert the number to a formatted string
const sumWithCommas = numberToFormattedString(sum);

console.dir(sumWithCommas)
<span class="hi">10,000</span>
<span class="hi">20,000</span>
<span class="hi">40,000</span>
<span class="hi">500,000</span>

Note: I got the code for numberToFormattedString directly from the accepted answer of this SO question.

Tom O.
  • 5,730
  • 2
  • 21
  • 35
2

The core of the solution is (just like in most of other answers) Array.prototype.reduce(), but, since everyone else, has ignored tag, I'll go for my attempt:

const total = [...$('.hi')].reduce((sum,span) => sum +=+ $(span).text().replace(/\,/g,''), 0)

$('#sum').text(total)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="hi">10,000</span>
 <span class="hi">20,000</span>
 <span class="hi">40,000</span>
 <span class="hi">500,000</span>
<div style="font-weight:bold;">The total is: <span id="sum"></span></div>
Yevhen Horbunkov
  • 14,965
  • 3
  • 20
  • 42
2
var total = 0;
$(".hi").each(function() {
    total += parseInt($(this).html().replace(",", ""));
});
$("#theans").html(total);
Cat
  • 64
  • 5
  • I will not downvote, but this one will fail to deal with numbers, like `100,000,000` (e.g. having more than a single comme), I don't even say `10,000.50` – Yevhen Horbunkov Feb 28 '20 at 21:15
  • @yevgengorbunkov Thanks, I have edited his answer to clean off anything not a number with total += parseInt($(this).html().replace(/\D/g, '')); instead of total += parseInt($(this).html().replace(',', '')); – Shasha Mar 01 '20 at 04:26
  • @Shasha : well, I must say, you have chosen the worst among suggested solutions (unnecessarily verbose, compared to `reduce()`-based; using `html()` whereas `text()` is needed; replacing only single comma; without a single word of explanation or live-snippet) and gone a little bit further into getting it even worse, so your code now will not be able to handle floating numbers. If clean and flexible jQuery solution is what you were after, you should have chosen [this one](https://stackoverflow.com/a/60459005/11299053). – Yevhen Horbunkov Mar 01 '20 at 07:03