0

I'm looping through all classnames in my html body. I'd like to store the classname with textSize value. Each time there is a duplicate value for a given classname, I want to increment its textSize.

$("*").each(function() {
    classname = $(this).get(0).className;
    myarray.push({"className" : classname, "textSize" : 5});

Here, I attempt to sort the classnames, then get a count for each duplicate:

myarray.sort();
var current = null;
var dupCount = 0;

for (var i = 0; i < myarray.length-1; i++) {
    if (myarray[i]["className"] !== "") {
        if (myarray.indexOf(myarray[i]["className"]) == -1) {
            log(myarray[i]["className"]);
        }
        else {
            log("DUP");
            myarray[i]["textSize"] = myarray[i]["textSize"] += 5;
            dupCount++;
        }
    }
}

log(myarray[i]["className"]);, shown in the image below, clearly shows duplicates:

enter image description here

Yet, log("DUP"); is never called once. Why is that?

Moreover, why doesn't myarray.sort(); sort them alphabetically? If it did that, I could just do if (myarray[i]["className"] === myarray[i++]["className"]) { to check if the value equals the next value in the array. But sort doesn't work.


Edit:

So when looping through, I should be able to alter the css per classname, right?

for(var classname in classes) {
    console.log(classes[classname].textSize);
    var $val = $(classes[classname]);                       
    $val.css({
        "color" : "blue",
        "fontSize": $val.textSize+"px"
    });
}

This doesn't work even though console.log(classes[classname].textSize); gives text sizes per element

4 Answers 4

1

Try using an object instead of an array, using class names as the keys:

var classes = {};

$("*").each(function() {
    var classname = $(this).get(0).className;
    var c = classes[classname] || 
        (classes[classname] = { className: classname, textSize: 0 });
    c.textSize += 5;
});

for(var classname in classes) {
    console.log(classes[classname]);
}

Remember that any element can have multiple classes. If you want to account for that, you'll have to split up the class names:

$("*").each(function() {
    var classnames = $(this).get(0).className.split(' ');
    for(var i=0; i<classnames.length; i++) {
        var classname = classnames[i];
        var c = classes[classname] || 
            (classes[classname] = { className: classname, textSize: 0 });
        c.textSize += 5;
    }
});

See this demonstration: http://jsfiddle.net/FSBhv/

UPDATE: the OP clarified that he wants to set the text size on the elements based on the number of elements that have that class. Doing that will take a slightly different approach (we'll actually have to store the elements):

var eltsByClass = {};

$("*").each(function() {
    var $this = $(this);
    $this.get(0).className.split(' ').forEach(function(cname) {
        var c = eltsByClass[cname] || 
            (eltsByClass[cname] = []);
        c.push($this.get(0));
    });
});

for(var cname in eltsByClass) {
    var elts = eltsByClass[cname];
    $(elts).css('font-size', (elts.length + 1) * 5 + 'px');
}
Sign up to request clarification or add additional context in comments.

4 Comments

Ethan, can you help me understand what is going on here? var c = classes[classname] || (classes[classname] = { className: classname, textSize: 0 });
Sure. classes is an object that contains a record (another object) for each class name found. Either the record already exists (classes[classname] is truthy, and c gets set to that), or it hasn't been created yet, in which case we create and assign it in the same step: classes[classname] = { className: classname, textSize: 0 }.
Okay thanks! I've updated above. I'm trying to set css on the class names. The more frequently they occur, the more the textsize gets incremented for that classname. For some reason, the css isn't being set
Oh, sorry, that part wasn't clear to me. That's a slightly harder problem: you have to count them all first and THEN set their size. I'll update my answer.
0

Store your data in an object, not an Array. And it can be simplified as:

var classes = {};

$("*").each(function() {
    var classname = $(this).get(0).className;
    classes[classname] = (classes[classname] || 0) + 5;
});

for(var classname in classes) {
    console.log(classname + " textSize:" + classes[classname]);
}

1 Comment

$(this).get(0).className vs this.className?
0

myarray.indexOf(myarray[i]["className"]) is a problem.

You know that myarray contains only objects, but you're asking for the position of a string within that list. That's never going to return anything but -1.

Consider using a second array to store the frequency count, instead of trying to do both with myarray.

var frequency = {};

myarray.forEach(function (i) {
  frequency[i.className] = frequency[i.className] || 0 
  frequency[i.className]++;
}

1 Comment

And what happens when I have <div class="constructor">...</div>? :)
0

This will hely you to sort array alphabetically based on classname

    var myarray=[];
$("*").each(function() 
{
    classname = $(this).get(0).className;
    myarray.push({"className" : classname, "textSize" : 5});
});


function compare(a,b) 
{
  if (a.className < b.className)
     return -1;
  if (a.className > b.className)
    return 1;
  return 0;
}       

myarray.sort(compare);

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.