Query selector attribute value starts with empty string fails

Viewed 934

Can anyone explain why the following returns an empty list:

var el = document.createElement('div');
el.dataset.mydata="hello";
document.body.appendChild(el);
document.querySelectorAll('div[data-mydata^=""]');

(If you're wondering why you'd ever do this, the actual code is using a variable as the attribute value in the querySelector. The function it is part of gets called recursively, on the first run the variable is empty.)

2 Answers

This happens because substring matching attribute selectors are dumb:

[att^=val]

Represents an element with the att attribute whose value begins with the prefix "val". If "val" is the empty string then the selector does not represent anything.

(Emphasis mine.)

All substring selectors are broken by design: When given the empty string, they return nothing (instead of matching all strings). I have no idea why, but it's what the selector specification says.

The best fix is probably to add a check to your code that says if var is empty, use 'div[data-mydata]' instead (i.e. only check for the presence of the attribute, not its value).

You should implement a condition that if the value is empty then to use = operator in selector and if value is not empty then use ^= operator.

Try running following snippet

var el = document.createElement('div');
var value = "";
el.dataset.mydata = value;
document.body.appendChild(el);
var elements = document.querySelectorAll(`div[data-mydata${value ? "^": ""}=""]`);
console.log(elements.length);

Related