1

How can I find all elements have any attribute other than some specified attributes? for example: any other attributes excepts (href + title + id).

Erik
  • 103
  • 1
  • 9

2 Answers2

2
var attrs = ["href", "title", "id"],
    els = document.getElementsByTagName("*"),
    result = Array.prototype.slice.call(els).filter(function(el) {
        if (el.attributes.length === 0)
            return false;

        for (var i = 0, l = attrs.length; i < l; i++) {
            if (el.hasAttribute(attrs[i]))
                return false;
        }
        return true;
    });

console.log(result);
VisioN
  • 143,310
  • 32
  • 282
  • 281
  • 1
    This will also return elements that have no attributes. – Niet the Dark Absol Jan 08 '13 at 23:42
  • Redundantly checks `.length` every time it goes through the loop ;) You should check the number of attributes first, then loop if the number is nonzero. – Niet the Dark Absol Jan 08 '13 at 23:49
  • @Kolink It's 2 a.m. here. What do you want from me? :D – VisioN Jan 08 '13 at 23:51
  • Just curious; why the revert? Going from computing `attrs.length` once to (still) thousands of times. (Although it is better than in the `for` conditional.) – Brock Adams Jan 09 '13 at 00:33
  • @BrockAdams I think it's quite minor, since picking up property is almost the same as getting the value of a variable. This variant is shorter and looks more cute. – VisioN Jan 09 '13 at 00:36
  • Squeeee!   I luuurve cute! Alas, I can only upvote once. :-( ... ... But, if you add a picture of a unicorn, I'll serial-upvote you. ;-) – Brock Adams Jan 09 '13 at 00:40
1

The only way to do this is to loop through ALL elements in the page and filter out the ones you don't want.

In this implementation, you pass an array of the attributes that you want to ignore (and optionally a tag type) and it returns an array of elements that have some attribute other than one of those you passed in:

function getElemsWithOtherAttribute(attArray, tags) {
    tags = tags || "*";
    // put all passed in attributes in an object for fast lookup
    // add leading underscore to avoid any built-in property conflicts
    var attLookup = {}, i, j, len, results = [], atts;
    for (i = 0, len = attArray.length; i < len; i++) {
        attLookup["_" + attArray[i].toLowerCase()] = true;
    }
    // get all elements and loop through them all
    var elems = document.getElementsByTagName(tags);
    for (i = 0, len = elems.length; i < len; i++) {
        // get all attributes on this element and loop through them all
        // until we find one that isn't in our attLookup object
        atts = elems[i].attributes;
        for (j = 0; j < atts.length; j++) {
            // if we have an attribute name that is not in our passed in list, then
            // add this element to the results array
            if (attLookup["_" + atts[j].name.toLowerCase()] !== true) {
                results.push(elems[i]);
                break;
            }
        }
    }
    return(results);
}

// example usage
var regAttributes = ["href", "title", "id"];
var items = getElemsWithOtherAttribute(regAttributes, "img");

This uses the .attributes collection to get a list of all attributes specified in the HTML for a given element and then looks at the .name property on the attribute node to see what the name of that given attribute is.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • I notice that you've just edit your reply, though your previous post already solved my problem. you are really responsible! thanks a lot. VisioN's answer looks prettier, though doesn't give the exactly result, but I can understand his ideal. I wonder which way may lead to a heavier work for CPU? – Erik Jan 09 '13 at 04:49
  • @Erik - I just added a feature so you could decide what kind of tags you were interested in (since it seems likely you would want that) and added a sample function call. I put the attributes into an object so presumably looking for them would be more efficient than VisonN's looping through the array each time - that difference would be even more apparent the more attributes you had in the array. But, as with all javascript performance comparisons, if you really want to know you'd have to set up a benchmark and test each algorithm with some meaningful sample data. – jfriend00 Jan 09 '13 at 05:10
  • 1
    @Erik - FYI, if performance is paramount, then there are probably better ways to solve your problem than looking at every element in the DOM - but we'd have to know more about the actual problem you're trying to solve in order to come up with better ideas. – jfriend00 Jan 09 '13 at 05:12