1

Assuming example elements:

<a href="..." rel="...">...
<a href="..." rel="..." target="...">...

How can I match only the first element? I would like to tell jQuery to match only the <a> element which has an href and a rel attribute, but no other attributes. :not() requires me to mention specific attributes to exclude, but what about unknown ones?

aalaap
  • 3,888
  • 5
  • 48
  • 56
  • https://stackoverflow.com/q/12340737/8252164 Multiple attribute selectors – samuellawrentz Jul 12 '18 at 12:07
  • @CBroe good point. It seems performing an exclusive selector with `:not()` is your only choice, other than applying specific classes (which would be better in the long run) – Rory McCrossan Jul 12 '18 at 12:08
  • 2
    This feels a bit [XY problem-y](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) … can you explain _why_ you would need to select an element based specifically on those criteria? Maybe there’s other ways. Or maybe at least the amount of non-allowed attributes can be limited to a certain set? – CBroe Jul 12 '18 at 12:12
  • Agree with @CBroe . Seems like an unusual requirement – charlietfl Jul 12 '18 at 12:23
  • I agree, it is an unusual requirement and that's what brings me here! – aalaap Jul 13 '18 at 10:02

4 Answers4

4

Use filter() and check the attributes length. Note that adding anything like class or data attributes would mean you would need to modify this

$('a[href][rel]').filter(function(){
   return this.attributes.length === 2;  
}).css('color','red')
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#" rel="foo" target="_blank"> Has target</a>
<a href="#" rel="foo" > No target</a>
<a href="#"  > No rel </a>
charlietfl
  • 169,044
  • 13
  • 113
  • 146
  • I had frowned upon other `filter` uses, because it simply felt like a shortcut for a `forEach` loop, but this bit is brilliant! – aalaap Jul 13 '18 at 10:04
1

You can use the not() and first() function for this, to select the first element in a collection & filter out the unwanted elements.

Example:

$("a[href][rel]").not("[target]").first();

In order to exclude items that contain other unknown attributes, you should use filter as the other answers advise.

This wouldn't be a good solution however, it would be much better to add a class to the elements you need to select, or have them in another div.

totallyNotLizards
  • 8,209
  • 9
  • 48
  • 84
0

Use .filter() with test condition to check element has only attributes length

$('a[href][rel]').filter(function() {
  return this.attributes.length == 2
}).addClass('a');
.a {
  background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="..." rel="...">...</a>
<a href="..." rel="..." target="...">...</a>
Satpal
  • 129,808
  • 12
  • 152
  • 166
0

You can use this.hasAttribute and further check this.attributes.length === 2 to confirm that <a> element has only two attributes:

$('a').each(function(){
   if(this.attributes.length == 2 && this.hasAttribute("href") && this.hasAttribute("rel")){
     $(this).addClass('selected');
   }
});
.selected{
  color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="..." rel="...">1111</a>
<a href="..." rel="..." target="...">222</a>
<a href="..." rel="...">333</a>
<a href="..." rel="..." target="...">444</a>
Ankit Agarwal
  • 29,658
  • 5
  • 35
  • 59