Fast, lightweight, extensible css selector engine.
npm install zest__zest__ is a fast, lightweight, and extensible CSS selector engine.
Zest was designed to be very concise while still supporting CSS3/CSS4
selectors and remaining fast.
`` js`
zest('section! > div[title="hello" i] > :local-link /href/ h1');
Each selector run 1000 times on Google Chrome 13 beta (ms):
benchmarking: header > h1 1000 times.body > header > h1
zest: 13
sizzle: 24
native: 13
benchmarking: 1000 times.html a
zest: 16
sizzle: 26
native: 13
benchmarking: 1000 times.:first-child
zest: 45
sizzle: 55
native: 12
benchmarking: 1000 times.:only-child
zest: 44
sizzle: 68
native: 11
benchmarking: 1000 times.:not(a)
zest: 49
sizzle: 66
native: 12
benchmarking: 1000 times.h1 + time:last-child
zest: 51
sizzle: 125
native: 12
benchmarking: 1000 times.h1 + time[datetime]:last-child
zest: 15
sizzle: 32
native: 13
benchmarking: 1000 times.header > h1, :not(a)
zest: 21
sizzle: 45
native: 14
benchmarking: 1000 times.a[rel~="section"]
zest: 72
sizzle: 212
native: 17
benchmarking: 1000 times.a, h1
zest: 41
sizzle: 54
native: 11
benchmarking: 1000 times.:nth-child(2n+1)
zest: 25
sizzle: 55
native: 11
benchmarking: 1000 times.
zest: 82
sizzle: 97
native: 13
__NOTE:__ If you want to run these benchmarks yourself make sure to turn off
Sizzle's (and Zest's) document.querySelectorAll delegation mechanism,document.querySelectorAll
otherwise you will be benchmarking against .
Zest will cache compiled selectors if it can't delegate to
document.querySelectorAll, document.getElementById, ordocument.getElementsByClassName (depending). __The benchmark tests you seedocument.querySelectorAll
above were performed with the caching mechanism disabled. If caching were
enabled, Zest would be faster than the native .__
` bash`
$ npm install zest
Zest currently includes support for ender.js, Prototype, and jQuery.
__Unsupported Selectors:__ :hover, :active, :link, :visited, all pseudo
elements, and namespaces.
:link, :visited, and pseudo elements are unsupported for obvious reasons:hover
(they don't work). and :active aren't supported because they examine:focus
a dynamic state, you should be binding to events for this ( is
supported, but there is no fallback for legacy browsers).
Zest doesn't support (m)any non-standard selectors, but it is possible to add
your own.
Adding simple selectors is fairly straight forward. Only the addition of pseudo
classes and attribute operators is possible. (Adding your own "style" of
selector would require changes to the core logic.)
Here is an example of a custom :name selector which will match for anname
element's attribute: e.g. h1:name(foo). Effectively an aliash1[name=foo]
for .
` jsparam
// if there was a parameter,
// it gets closured as `
zest.selectors[':name'] = function(param) {
return function(el) {
if (el.name === param) return true;
};
};
__NOTE__: if you're pseudo-class does not take a parameter, there will be no
closure.
` jsattr
// is the attributeval
// is the value to match`
zest.operators['!='] = function(attr, val) {
return attr !== val;
};
Adding a combinator is a bit trickier. It may seem confusing at first because
the logic is upside-down. Zest interprets selectors from right to left.
Here is an example how a parent combinator could be implemented:
` jsel
zest.combinators['<'] = function(test) {
return function(el) { // is the current element`
el = el.firstChild;
while (el) {
// return the relevant element
// if it passed the test
if (el.nodeType === 1 && test(el)) {
return el;
}
el = el.nextSibling;
}
};
};
The test function tests whatever simple selectors it needs to look for, but
it isn't important what it does. The most important part is that you return
the relevant element once it's found.
If you contribute code to this project, you are implicitly allowing your code
to be distributed under the MIT license. You are also implicitly verifying that
all code is your original work. `
(c) Copyright 2011-2012, Christopher Jeffrey (MIT Licensed).
See LICENSE for more info.