What would be the most efficient way of parsing a css selector input string, that features any combination of:
[key=value] : attributes, 0 to * instances #id : ids, 0 to 1 instances .class : classes, 0 to * instances tagName : tag names, 0 to 1 instances (found at start of string only)(note: '*', or other applicable combinator could be used in lieu of tag?)
Such as:
div.someClass#id[key=value][key2=value2].anotherClass
Into the following output:
['div','.someClass','#id','[key=value]','[key2=value2]','.anotherClass']
Or for bonus points, into this form efficiently (read: a way not just based on using str[0] === '#' for example):
{
tags : ['div'],
classes : ['someClass','anotherClass'],
ids : ['id'],
attrs :
{
key : value,
key2 : value2
}
}
(note removal of # . [ = ])
I imagine some combination of regex and .match(..) is the way to go, but my regex knowledge is nowhere near advanced enough for this situation.
Many thanks for your help.
You might do the splitting using
var tokens = subselector.split(/(?=\.)|(?=#)|(?=\[)/)
which changes
div.someClass#id[key=value][key2=value2].anotherClass
to
["div", ".someClass", "#id", "[key=value]", "[key2=value2]", ".anotherClass"]
and after that you simply have to look how starts each token (and, in case of tokens starting with [, checking if they contain a =).
Here's the whole working code building exactly the object you describe :
function parse(subselector) {
var obj = {tags:[], classes:[], ids:[], attrs:[]};
subselector.split(/(?=\.)|(?=#)|(?=\[)/).forEach(function(token){
switch (token[0]) {
case '#':
obj.ids.push(token.slice(1));
break;
case '.':
obj.classes.push(token.slice(1));
break;
case '[':
obj.attrs.push(token.slice(1,-1).split('='));
break;
default :
obj.tags.push(token);
break;
}
});
return obj;
}
demonstration
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With