0

I'm trying to find the total amount group by data attribute name from a list using jQuery. Similar to grouping categories and find the sum.

For example, I would like to create something like this:

group1 = 3
group2 = 5
group3 = 3

from this list:

<span class="data-center" data-category="group1" data-amount="1"></span>
<span class="data-center" data-category="group2" data-amount="1"></span>
<span class="data-center" data-category="group2" data-amount="2"></span>
<span class="data-center" data-category="group1" data-amount="2"></span>
<span class="data-center" data-category="group2" data-amount="2"></span>
<span class="data-center" data-category="group3" data-amount="3"></span>

I wonder if there is some jQuery function help to achieve it, something like groupByName()?

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
Joe209
  • 65
  • 5
  • Please make an effort and show what you've tried. – isherwood Jan 18 '15 at 19:14
  • About your question: nope, there is not. About "how it can be done": you still use object as Hashtable to make calculations. – Regent Jan 18 '15 at 19:14
  • @isherwood: I have tried to create an array and store the category name and each value. Then every time, I have to loop back to check if there is an existing group, if there is, I will update the value. Well it work, but I think there would be a better solution. – Joe209 Jan 18 '15 at 19:21
  • @Regent; interesting, I have never known that jquery support hashtable. Thank for the info. – Joe209 Jan 18 '15 at 19:22
  • @Joe209 1. not jQuery but pure JavaScript. 2. Not hashtables but objects, which can be used as hashtable simulation. You're welcome. – Regent Jan 18 '15 at 19:31

2 Answers2

3

Using pure JavaScript:

Example Here

function getCategoryTotal(cat) {
    var total = 0,
        elements = document.querySelectorAll('[data-category="' + cat + '"]');

    Array.prototype.forEach.call(elements, function (el, i) {
        total += parseInt(el.dataset.amount, 10);
    });

    return total;
}

console.log(getCategoryTotal('group1')); // 3
console.log(getCategoryTotal('group2')); // 5
console.log(getCategoryTotal('group3')); // 3
Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
  • Well, `document.querySelectorAll()` is not _pure JavaScript_, but whatever. What I actually want to say is: what about more flexible solution, which works with any number of groups? Something like [this question](http://stackoverflow.com/questions/9318427/how-to-select-elements-with-the-same-attribute-value-in-jquery) or [this one](http://stackoverflow.com/questions/15314872/group-and-count-html-elements-by-data-attribute-in-jquery). – Regent Jan 18 '15 at 19:19
  • @Regent How is `document.querySelectorAll()` not pure JS? I was under the impression that it was. What would you classify it as? It's not using jQuery as the OP requested.. – Josh Crozier Jan 18 '15 at 19:21
  • It's not obvious difference between pure JS and HTML DOM interface (which can be accessed from different programming languages), I agree, but it is still here: – Regent Jan 18 '15 at 19:30
0

I guess you asked about a jQuery way of doing so, which I did:

$.fn.amountByData = function(dataAttr, amountDataAttr) {
    if (typeof amountDataAttr == "undefined")
        amountDataAttr = "amount";

    var dataAmountArr = new Array();

    $(this).each(function() {
        var dataAttrVal = $(this).data(dataAttr);

        if (typeof dataAmountArr[dataAttrVal] == "undefined")
            dataAmountArr[dataAttrVal] = parseInt($(this).data(amountDataAttr));
        else 
            dataAmountArr[dataAttrVal] += parseInt($(this).data(amountDataAttr));
    });

    return dataAmountArr;
};

Here's how I would achieve it jQuery way ! This gives a LOT of flexibility, because you can choose by which data attribute you want to calculate the amount based on, and you can also choose to precise a different amount data attribute if it is not named amount.

PS: I know an answer has already been chosen, but contrary to @Josh Crozier, I understood you wanted a jQuery method to achieve your goal.

Cheers,

cram2208
  • 416
  • 6
  • 14