0

I have a page of database results as list items, each result having between none and several possible css classes dynamically assigned (but not known), for filtering purposes.

Using jQuery how do I programatically find what classes are assigned to each li, AND count the frequency of each class appearance on the page?

I need to be able to access them by the name of the css class, to update html on the page.

Ex html

    <ul class="results">
      <li class="a b c d>...</li>
      <li class="a c>...</li>
      <li class="b c f>...</li>
      <!— many more li —>
    </ul>

The target output is: option a 2 option b 2 option c 3 option d 1 option e 0 option f 1 ...

Where 'option a' is a filter already on the page, and the count would appear beside it. I have the filter ready to accept the html update:

echo ' <span class="' . $row_rsCategories['category'] . '"></span>';

Where the category is the name of the filter.

8
  • Use element.className.split(' ') to get an array of classes for an element, and loop through them counting each class. Commented Nov 14, 2013 at 18:35
  • Okay, and with that HTML what output do you expect? Commented Nov 14, 2013 at 18:36
  • @Barmer I'm trying to understand how this works - I can do it for each if hard coded, but the looping to get the count at the same time is escaping me. Can you please post a more comprehensive example? Commented Nov 14, 2013 at 18:37
  • Show the output that you want, and then we can explain how to get that (assuming it's possible, and it almost certainly is). If you wanted hypothetical speculation, then I will vote to close as off-topic. Commented Nov 14, 2013 at 18:38
  • Edited to show desired output Commented Nov 14, 2013 at 18:42

4 Answers 4

1

Try this:

var li = [];
var cnt = [];
$(".results").find("li").each(function () {
    var cls = $(this).attr("class").split(" ");

    var len = cls.length;
    for (var i = 0; i < len; i++) {
        if (li.indexOf(cls[i]) < 0) {
            li.push(cls[i]);
            cnt.push(1);
        } else {
            cnt[li.indexOf(cls[i])] = cnt[li.indexOf(cls[i])] + 1;
        }
    }
});

Fiddle here.

Sign up to request clarification or add additional context in comments.

5 Comments

this looks to be right along what I was trying to ask about, thank you. I see how you append the body, and tried modifying that to append the waiting html already on the page, but no success. Any suggestions? jsfiddle.net/gchelak/GNZ3z
Tried adding $("span.[i]").html(li[i] + cnt[i]); to append the spans above.
Check console. It throws error. It should be $("span."+li[i]).html(li[i] + cnt[i]);. Fiddle
Wow, very cool @Hiral. I really appreciate your help, as well as that of everyone else
For those trying to put this to use, I found that replacing $(this).attr("class") with var cls = this.className resolved TypeError undefined
1

This will create an object, classes, that contains a count of all classes applied to each list item.

var classes = {}; //{a: 2, b: 2, c: 3, d: 1, : 1, f: 1} 
$(".results li").each(function() {
   $.each(this.className.split(" "), function(i, cls) {
       classes[cls] = classes[cls] + 1 || 1;
   });
});

JSFiddle example

1 Comment

Couldn't make it work. My fault I'm sure. Plugged it into a demo: jsfiddle.net/gchelak/GNZ3z
0

Something like:

var classObject = {}
$("ul.results li").each(function() {
    var classes = this.className.split(" ");
    for (var i = 0; i < classes.length; i++) {
        if (classObject.hasOwnProperty(classes[i]))
            classObject[classes[i]]++;
        else
            classObject[classes[i]] = 1;
    }
});

Demo: http://jsfiddle.net/3FN7U/

3 Comments

I see how the output is logged to the console. How do I assign it to the appropriate html element waiting for it?
How do you want to output it?
Edited my question above to show an example, sorry I didn't include that in the original. Still trying to figure out how best to ask questions here.
0

A simple approach:

function classCount(el, prefix){
    // define the prefix, with a default in case a prefix is not supplied:
    prefix = prefix || '';

    /* use the passed-in selector to find the relevant element(s) (with a class)
       to search within:
    */
    var els = $(el).find('[class]'),
        // initialise variables to avoid declaring them within a loop:
        results = {},
        classes = [];

    // iterate over the elements found earlier
    els.each(function(){
        // find the classes of the element:
        classes = this.className.split(/\s+/);

        iterate over those classes:
        for (var i = 0, len = classes.length; i < len; i++){
            /* if there isn't a current property in the results object
               for the current class-name, create and initialise it:
            */
            if (!results[classes[i]]) {
                results[prefix + classes[i]] = 1;
            }
            // if it already exists, increment it:
            else {
                results[prefix + classes[i]]++;
            }
        }
    });

    // return the resulting object to the calling context:
    return results;
}

console.log(classCount('.results', 'option '));

JS Fiddle demo.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.