Anthony Accioly
Anthony Accioly

Reputation: 22481

Return all elements for which any attribute starts with something

I'm aware of [name^="value"] selector but is there a analogous selector (or technique) that queries all attributes starting with the given value?

I'm looking for something like $("[*^='http://www.something.com']")(that does not exist).

It would match all elements which contains at least one attribute with a value that begins with http://www.something.com.

Say:

<img src="http://www.something.com/image.jpg" />
<a href="http://www.something.com">Something</a>
<link rel="stylesheet" href="http://www.something.com/css/style.css" type="text/css">

Attribute name could be anything, not just src and href, even non standard attributes.

Is there a known way to do it?

Upvotes: 4

Views: 209

Answers (3)

Anthony Accioly
Anthony Accioly

Reputation: 22481

I've put together some of the ideas from other answers and wrote a custom selector.

Selector

$.expr[':'].hasAttrStartingWithValue = function (obj, index, meta) {

    var startsWithAttrValue = false;
    var value = meta[3];

    for (var i = 0; i < obj.attributes.length; i++) {
        var attr = obj.attributes[i];
        // attr.value starts with value
        if (attr.specified && attr.value.lastIndexOf(value, 0) === 0) {
            startsWithAttrValue = true;
            break;
        }
    }

    return startsWithAttrValue;
};

It has not been properly tested for cross-browsing and correctness, and I'm sure that it can be further optimized, but it seems to be working well with IE 11, FF 24 and Chrome 32.

Usage

// Logs every occurrence of a value in any attribute of the page
$(":hasAttrStartingWithValue('http://www.something.com')").each(function (i, e) {
    console.log(i + " - " + e.outerHTML);
});

// Matches only children of test
$("#test :hasAttrStartingWithValue('http://www.something.com')")
   .css('background-color', 'red'); 

Working Fiddle.

Upvotes: 3

rjreed
rjreed

Reputation: 236

If you want to do it for img, a, and link tags, then you could do it like this:

var ref = '"http://www.something.com"';
var elems = [].slice.call(document.querySelectorAll('img[src='+ref+'], a[href='+ref+'], link[href='+ref+']'));
//do something with the elems array

If you want to go the other route...

JS Fiddle of Working Abomination in Vanilla JS

Code that makes me sad (query everything in sight, loops in loops, regex in loops, etc.):

var rx = /(^http:\/\/www.something.com)/;
var loopAgain = function () {
    for (var j = 0, leng = attrs.length; j < leng; j++) {
        if (rx.test(attrs[j].value)) {
            return true;
        }
        return false;
    }
};
var allTheThings = [].slice.call(document.querySelectorAll('*'));
for (var i = 0, len = allTheThings.length; i < len; i++) {
    var attrs = allTheThings[i].attributes;
    if (loopAgain()) {
        console.log(allTheThings[i]);
    }
}

Upvotes: 1

Mahmoud.Eskandari
Mahmoud.Eskandari

Reputation: 1478

function strstr (haystack, needle, bool) {
  var pos = 0;

  haystack += '';
  pos = haystack.indexOf(needle);
  if (pos == -1) {
    return false;
  } else {
    if (bool) {
      return haystack.substr(0, pos);
    } else {
      return haystack.slice(pos);
    }
  }
}
    $( document ).ready(function(){
    $('*').each(function() {
      $.each(this.attributes, function() {
        // this.attributes is not a plain object, but an array
        // of attribute nodes, which contain both the name and value
        if(this.specified) {
          if( strstr(this.value,'http://') )
            alert(this.name+'+'+this.value);
        }
      });
    });

    });

Alert All attributes And values...
Custom this code...
jsfiddle

Upvotes: 1

Related Questions