JavaScript: parsing dei selettori CSS

Alcune librerie (come jQuery) utilizzano le espressioni regolari per il parsing dei selettori CSS. Quella che segue è un'implementazione di una semplice funzione che trasforma in un array un'espressione CSS contenente i selettori. L'espressione regolare usata è stata presa in prestito da jQuery e da alcuni contributi di John Resig.

La funzione è la seguente:


function parseCSSSelector(expression) {
	var chunker = /((?:\([^\)]+\)|\[[^\]]+\]|[^ ,\(\[]+)+)(\s*,\s*)?/g;
	var parts = [];
	chunker.lastIndex = 0;
	while ( (m = chunker.exec(expression)) !== null ) {
  		parts.push( m[1] );
  
  		if ( m[2] ) {
    		break; // stop quando si incontra una virgola
  		}
	}
	return parts;	
}

Esempi d'uso:


console.log(parseCSSSelector('#test div.foo'));
console.log(parseCSSSelector('div.class > span:not(:first-child) a[href]'));

/* 
	["#test", "div.foo"]
	["div.class", ">", "span:not(:first-child)", "a[href]"]
	
 */

Il segreto del parsing in questo caso sta nell'espressione regolare usata. Come si può notare, tale espressione tiene anche conto degli spazi e dei token letterali che nei CSS hanno la funzione di selettori (come il segno di maggiore).

Risulta chiaro come una volta ottenuti i vari selettori si possano quindi estrarne gli elementi per lavorare sul DOM:


var id = null;
var element = parts[0]; // '#test'

if(typeof document.querySelector === 'function') {

	id = document.querySelector(element);

} else {

	var _id = element.replace('#', '');
	
	id = document.getElementById(_id);

}