Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

proposing a configure() method #68

Merged
merged 10 commits into from

2 participants

@rvagg
Collaborator

As an alternative to directly setting nonStandardEngine, a configure() method that takes an options object that could be extended in the future (maybe..). NWMatcher uses a configure() so it seems like a good idea to standardise that; although it uses a USE_QSAPI key which I'm not so fond of so I've gone with NATIVE_QSA.

The select() method is set at configure time so there's no additional function layer to go through and read the boolean.

Updated the docs for this and remved reference to using the pseudos by disabling qSA support, as I said previously this shouldn't be necessary because of the try{}catch{} around qSA calls.

Also, I've adjusted the tests so that everything is run twice, once with qSA and again without qSA, should give really nice coverage of native and non-native in modern browsers. The native-qSA path needs testing cause there is still work done on the way there that can go wrong.

What think you?

@rvagg
Collaborator

I had a change of heart and went with camelCase useNativeQSA rather than the more Java-looking NATIVE_QSA (JavaScript is where I come to escape from Java).

@rvagg
Collaborator

Oh, and also, I'd like to put in a PR for adding matchesSelector in as default backend for is() where it's available, with a fall-back to non-native like we do with the try{}catch{} in selectCSS3() and selectCSS2qSA(). I have a small feature detect ready to go for it in Traversty: https://github.com/rvagg/traversty/blob/0a1ab78cae3a991f78631a3be60bfb03873b8c52/src/traversty.js#L14-18

This would mean it'd be logical to also have an additional config option: useNativeMatchesSelector / useNativeMatches / useNativeMS, whatever.

@rvagg
Collaborator

BTW, I'm thinking that we can pull out the all the IE8 specific CSS2 qSA stuff. Since we have the try/catch around qSA we could just loosen up the qSA detector (just check for existence, not CSS3 compliance) and let it fall through if native qSA doesn't support the query. Would remove a lot of cruft.

@ded
Owner

right on. agreed on that, 100%

@rvagg rvagg referenced this pull request
Closed

complex pseudos fix #69

@rvagg
Collaborator

oooooooo yea, feels good to be removing code from Qwery rather than adding it, I should do this more often!

Sliced at least 30% off the simple benchmark suite across the board for IE8, current Qwery is on par with Sizzle for those but the new one is on par or quicker than NW (in IE8!). Mainly due to taking away 1 regex test and 1 regex match, plus doing away with your nonStandardEngine branch & apply code (sorry)--this accounts for a ~5% improvement in most other browsers.

@rvagg
Collaborator

Hey, I hope you don't mind this but I've done a tiny bit of rearranging, let me know if you want me to roll back any of these changes.

Moved pseudos.js to a new pseudos/ directory and made a package.json for you to publish qwery-pseudos. I've also put the actual source for both pseudos and mobile into their own src/ subdirectories and modified the Smoosh config so they build into their respective directories so the NPM publishables have the copyright included.

Some minor changes to pseudos to get it to work as an Ender package and as a standalone, plus some minor fixes picked up by JSHint.

@ded
Owner
ded commented

hmmmm.... just reading the description, this is all fantastic news. Gotta be careful on the nonStandardEngine. Perhaps I should have labeled it as beta to begin with since I suppose the original intent was that it would change.

@ded
Owner
ded commented

but to be open so you're not in the dark, i'm terribly busy today and really want to look over this one carefully. possibly later this evening

@ded
Owner
ded commented

ok... here we gooooooooo

@ded ded referenced this pull request from a commit
@ded - style modifications
- bump version for new configure() method in #68
- update readme
96dedfc
@ded ded merged commit 452a183 into from
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 14, 2012
  1. @rvagg

    configure() method

    rvagg authored
  2. @rvagg

    clarify & keep jshint happy

    rvagg authored
  3. @rvagg
Commits on Jan 15, 2012
  1. @rvagg

    turn NATUVE_QSA on by default

    rvagg authored
Commits on Jan 16, 2012
  1. @rvagg

    change config keys to camelCase

    rvagg authored
  2. @rvagg

    update doc

    rvagg authored
Commits on Feb 5, 2012
  1. @rvagg

    Merge branch 'w3c' into config

    rvagg authored
  2. @rvagg
  3. @rvagg

    remove unnecessary tests

    rvagg authored
Commits on Feb 6, 2012
  1. @rvagg
This page is out of date. Refresh to see the latest.
View
12 README.md
@@ -68,11 +68,15 @@ qwery.pseudos.foo = function (el, val) {
}
```
-### Enabling the psuedos selector API
-Since qwery uses querySelectorAll by default (when supported) you need to enable non-standard pseudos by setting the `nonStandardEngine` flag on qwery.
+Configuring Qwery
+-----------------
+
+The `configure()` method takes an options object allowing you to adjust the way that Qwery works internally. Currenly only the `useNativeQSA` option is available to turn on and off the use of native `querySelectorAll()` where available.
``` js
-qwery.nonStandardEngine = true
+qwery.configure({
+ useNativeQSA: false
+})
```
Browser Support
@@ -160,4 +164,4 @@ Contributors
* [Dustin Diaz](https://github.com/ded/qwery/commits/master?author=ded)
* [Jacob Thornton](https://github.com/ded/qwery/commits/master?author=fat)
* [Rod Vagg](https://github.com/ded/qwery/commits/master?author=rvagg)
- * [Andrew McCollum](https://github.com/ded/qwery/commits/master?author=amccollum)
+ * [Andrew McCollum](https://github.com/ded/qwery/commits/master?author=amccollum)
View
8 config/smoosh.json
@@ -5,9 +5,13 @@
"./src/copyright.js"
, "./src/qwery.js"
]
- , "qwery-mobile": [
+ , "mobile/qwery-mobile": [
"./src/copyright.js"
- , "./mobile/qwery-mobile.js"
+ , "./mobile/src/mobile.js"
+ ]
+ , "pseudos/qwery-pseudos": [
+ "./src/copyright.js"
+ , "./pseudos/src/pseudos.js"
]
}
, "JSHINT_OPTS": {
View
7 mobile/qwery-mobile.js
@@ -1,3 +1,10 @@
+/*!
+ * Qwery - A Blazing Fast query selector engine
+ * https://github.com/ded/qwery
+ * copyright Dustin Diaz & Jacob Thornton 2011
+ * MIT License
+ */
+
!function (context, doc, win) {
var classOnly = /^\.([\w\-]+)$/,
View
0  qwery-mobile.min.js → mobile/qwery-mobile.min.js
File renamed without changes
View
7 qwery-mobile.js → mobile/src/mobile.js
@@ -1,10 +1,3 @@
-/*!
- * Qwery - A Blazing Fast query selector engine
- * https://github.com/ded/qwery
- * copyright Dustin Diaz & Jacob Thornton 2011
- * MIT License
- */
-
!function (context, doc, win) {
var classOnly = /^\.([\w\-]+)$/,
View
17 pseudos/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "qwery-pseudos",
+ "description": "Pseudo-selector extensions for Qwery",
+ "version": "1.0.0",
+ "homepage": "https://github.com/ded/qwery",
+ "authors": ["Dustin Diaz, @ded", "Jacob Thornton, @fat"],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/ded/qwery.git"
+ },
+ "dependencies": {
+ "qwery": "*"
+ },
+ "main": "./qwery-pseudos.js",
+ "keywords": ["ender", "query", "css", "pseudos", "pseudo", "selector engine"],
+ "ender": "noop"
+}
View
106 pseudos/qwery-pseudos.js
@@ -0,0 +1,106 @@
+/*!
+ * Qwery - A Blazing Fast query selector engine
+ * https://github.com/ded/qwery
+ * copyright Dustin Diaz & Jacob Thornton 2011
+ * MIT License
+ */
+
+!function () {
+ var q, pseudos, i, l, p, r, nodes, m, nthPattern = /\s*((?:\+|\-)?(\d*))n\s*((?:\+|\-)\s*\d+)?\s*/
+ if (typeof module != 'undefined' && typeof 'require' != 'undefined')
+ q = require('qwery')
+ else if (typeof qwery != 'undefined')
+ q = qwery
+ else
+ return
+
+ pseudos = q.pseudos
+
+ function children(node, ofType) {
+ var r = []
+ nodes = node.childNodes
+
+ for (i = 0, l = nodes.length; i < l; i++) {
+ if (nodes[i].nodeType == 1 && (!ofType || nodes[i].nodeName == ofType)) r.push(nodes[i])
+ }
+ return r
+ }
+
+ function checkNthExpr(el, nodes, a, b) {
+ if (!a) return (nodes[b-1] == el)
+ for (i = b, l = nodes.length; ((a > 0) ? (i <= l) : (i >= 1)); i += a) if (el == nodes[i-1]) return true
+ return false
+ }
+
+ function checkNth(el, nodes, val) {
+ if (isFinite(val)) return nodes[val - 1] == el
+ else if (val == 'odd') return checkNthExpr(el, nodes, 2, 1)
+ else if (val == 'even') return checkNthExpr(el, nodes, 2, 0)
+ else if (m = nthPattern.exec(val))
+ return checkNthExpr(el, nodes,
+ (m[2] ? parseInt(m[1], 10) : parseInt(m[1] + '1', 10)), // Check case where coefficient is omitted
+ (m[3] ? parseInt(m[3].replace(/\s*/, ''), 10) : 0)) // Check case where constant is omitted
+
+ return false
+ }
+
+ function text(el, s) {
+ if (el.nodeType === 3 || el.nodeType === 4) return el.nodeValue;
+ if (el.nodeType !== 1 && el.nodeType !== 9) return '';
+ for (s = '', el = el.firstChild; el; el = el.nextSibling) {
+ if (el.nodeType !== 8) s += el.textContent || el.innerText || text(el)
+ }
+ return s
+ }
+
+ // *was* going to be in CSS3, didn't quite make it
+ pseudos.contains = function(el, val) { return text(el).indexOf(val) != -1 }
+
+ pseudos.not = function(el, val) { return !q.is(el, val) }
+
+ pseudos['nth-child'] = function (el, val) {
+ if (!val || !(p = el.parentNode)) return false
+ return checkNth(el, children(p), val)
+ }
+
+ pseudos['nth-last-child'] = function (el, val) {
+ if (!val || !(p = el.parentNode)) return false
+ return checkNth(el, children(p).reverse(), val)
+ }
+
+ pseudos['nth-of-type'] = function (el, val) {
+ if (!val || !(p = el.parentNode)) return false
+ return checkNth(el, children(p, el.nodeName), val)
+ }
+
+ pseudos['nth-last-of-type'] = function (el, val) {
+ if (!val || !(p = el.parentNode)) return false
+ return checkNth(el, children(p, el.nodeName).reverse(), val)
+ }
+
+ pseudos['first-child'] = function (el) { return pseudos['nth-child'](el, 1) }
+ pseudos['last-child'] = function (el) { return pseudos['nth-last-child'](el, 1) }
+ pseudos['first-of-type'] = function (el) { return pseudos['nth-of-type'](el, 1) }
+ pseudos['last-of-type'] = function (el) { return pseudos['nth-last-of-type'](el, 1) }
+
+ pseudos['only-child'] = function (el) {
+ return (p = el.parentNode) && (nodes = children(p)) && (nodes.length == 1) && (el == nodes[0])
+ };
+
+ pseudos['only-of-type'] = function (el) {
+ return (p = el.parentNode) && (nodes = children(p, el.nodeName)) && (nodes.length == 1) && (el == nodes[0])
+ }
+
+ pseudos.target = function (el) {
+ return (el.getAttribute('id') == location.hash.substr(1))
+ }
+
+ pseudos.checked = function (el) { return el.checked }
+
+ pseudos.enabled = function (el) { return !el.disabled }
+
+ pseudos.disabled = function (el) { return el.disabled }
+
+ pseudos.empty = function (el) { return !el.childNodes.length }
+
+}();
View
7 pseudos/qwery-pseudos.min.js
@@ -0,0 +1,7 @@
+/*!
+ * Qwery - A Blazing Fast query selector engine
+ * https://github.com/ded/qwery
+ * copyright Dustin Diaz & Jacob Thornton 2011
+ * MIT License
+ */
+!function(){function j(a,b){var e=[];g=a.childNodes;for(c=0,d=g.length;c<d;c++)g[c].nodeType==1&&(!b||g[c].nodeName==b)&&e.push(g[c]);return e}function k(a,b,e,f){if(!e)return b[f-1]==a;for(c=f,d=b.length;e>0?c<=d:c>=1;c+=e)if(a==b[c-1])return!0;return!1}function l(a,b,c){return isFinite(c)?b[c-1]==a:c=="odd"?k(a,b,2,1):c=="even"?k(a,b,2,0):(h=i.exec(c))?k(a,b,h[2]?parseInt(h[1],10):parseInt(h[1]+"1",10),h[3]?parseInt(h[3].replace(/\s*/,""),10):0):!1}function m(a,b){if(a.nodeType===3||a.nodeType===4)return a.nodeValue;if(a.nodeType!==1&&a.nodeType!==9)return"";for(b="",a=a.firstChild;a;a=a.nextSibling)a.nodeType!==8&&(b+=a.textContent||a.innerText||m(a));return b}var a,b,c,d,e,f,g,h,i=/\s*((?:\+|\-)?(\d*))n\s*((?:\+|\-)\s*\d+)?\s*/;if(typeof module!="undefined"&&!0)a=require("qwery");else{if(typeof qwery=="undefined")return;a=qwery}b=a.pseudos,b.contains=function(a,b){return m(a).indexOf(b)!=-1},b.not=function(b,c){return!a.is(b,c)},b["nth-child"]=function(a,b){return!b||!(e=a.parentNode)?!1:l(a,j(e),b)},b["nth-last-child"]=function(a,b){return!b||!(e=a.parentNode)?!1:l(a,j(e).reverse(),b)},b["nth-of-type"]=function(a,b){return!b||!(e=a.parentNode)?!1:l(a,j(e,a.nodeName),b)},b["nth-last-of-type"]=function(a,b){return!b||!(e=a.parentNode)?!1:l(a,j(e,a.nodeName).reverse(),b)},b["first-child"]=function(a){return b["nth-child"](a,1)},b["last-child"]=function(a){return b["nth-last-child"](a,1)},b["first-of-type"]=function(a){return b["nth-of-type"](a,1)},b["last-of-type"]=function(a){return b["nth-last-of-type"](a,1)},b["only-child"]=function(a){return(e=a.parentNode)&&(g=j(e))&&g.length==1&&a==g[0]},b["only-of-type"]=function(a){return(e=a.parentNode)&&(g=j(e,a.nodeName))&&g.length==1&&a==g[0]},b.target=function(a){return a.getAttribute("id")==location.hash.substr(1)},b.checked=function(a){return a.checked},b.enabled=function(a){return!a.disabled},b.disabled=function(a){return a.disabled},b.empty=function(a){return!a.childNodes.length}}()
View
17 src/pseudos.js → pseudos/src/pseudos.js
@@ -1,8 +1,17 @@
!function () {
- var q = qwery, pseudos = q.pseudos, i, l, p, r, nodes, m, nthPattern = /\s*((?:\+|\-)?(\d*))n\s*((?:\+|\-)\s*\d+)?\s*/
+ var q, pseudos, i, l, p, r, nodes, m, nthPattern = /\s*((?:\+|\-)?(\d*))n\s*((?:\+|\-)\s*\d+)?\s*/
+ if (typeof module != 'undefined' && typeof 'require' != 'undefined')
+ q = require('qwery')
+ else if (typeof qwery != 'undefined')
+ q = qwery
+ else
+ return
+
+ pseudos = q.pseudos
function children(node, ofType) {
- nodes = node.childNodes, r = []
+ var r = []
+ nodes = node.childNodes
for (i = 0, l = nodes.length; i < l; i++) {
if (nodes[i].nodeType == 1 && (!ofType || nodes[i].nodeName == ofType)) r.push(nodes[i])
@@ -22,8 +31,8 @@
else if (val == 'even') return checkNthExpr(el, nodes, 2, 0)
else if (m = nthPattern.exec(val))
return checkNthExpr(el, nodes,
- (m[2] ? parseInt(m[1]) : parseInt(m[1] + '1')), // Check case where coefficient is omitted
- (m[3] ? parseInt(m[3].replace(/\s*/, '')) : 0)) // Check case where constant is omitted
+ (m[2] ? parseInt(m[1], 10) : parseInt(m[1] + '1', 10)), // Check case where coefficient is omitted
+ (m[3] ? parseInt(m[3].replace(/\s*/, ''), 10) : 0)) // Check case where constant is omitted
return false
}
View
54 qwery.js
@@ -30,11 +30,7 @@
, specialChars = /([.*+?\^=!:${}()|\[\]\/\\])/g
, simple = /^(\*|[a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/
, attr = /\[([\w\-]+)(?:([\|\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/
- , pseudo = /:([\w\-]+)(\(['"]?([\s\w\+\-]+)['"]?\))?/
- // check if we can pass a selector to a non-CSS3 compatible qSA.
- // *not* suitable for validating a selector, it's too lose; it's the users' responsibility to pass valid selectors
- // this regex must be kept in sync with the one in tests.js
- , css2 = /^(([\w\-]*[#\.]?[\w\-]+|\*)?(\[[\w\-]+([\~\|]?=['"][ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+["'])?\])?(\:(link|visited|active|hover))?([\s>+~\.,]|(?:$)))+$/
+ , pseudo = /:([\w\-]+)(\(['"]?([^()]+)['"]?\))?/
, easy = new RegExp(idOnly.source + '|' + tagOnly.source + '|' + classOnly.source)
, dividers = new RegExp('(' + splitters.source + ')' + splittersMore.source, 'g')
, tokenizr = new RegExp(splitters.source + splittersMore.source)
@@ -54,6 +50,8 @@
return (p1 = previous(node)) && (p2 = previous(contestant)) && p1 == p2 && p1
}
}
+ , useNativeQSA = 'useNativeQSA'
+ , select // main select() method, assign later
function cache() {
this.c = {}
@@ -266,7 +264,7 @@
if (m = selector.match(easy)) {
if (m[1]) return (el = byId(root, m[1])) ? [el] : []
if (m[2]) return arrayify(root[byTag](m[2]))
- if (supportsCSS3 && m[3]) return arrayify(root[byClass](m[3]))
+ if (hasByClass && m[3]) return arrayify(root[byClass](m[3]))
}
return select(selector, root)
@@ -313,19 +311,11 @@
} :
function(e, a) { return e.getAttribute(a) }
}()
- // does native qSA support CSS3 level selectors
- , supportsCSS3 = function () {
- if (doc[byClass] && doc.querySelector && doc[qSA]) {
- try {
- var p = doc.createElement('p')
- p.innerHTML = '<a/>'
- return p[qSA](':nth-of-type(1)').length
- } catch (e) { }
- }
- return false
- }()
- // native support for CSS3 selectors
- , selectCSS3 = function (selector, root) {
+ , hasByClass = !!doc[byClass]
+ // has native qSA support
+ , hasQSA = doc.querySelector && doc[qSA]
+ // use native qSA
+ , selectQSA = function (selector, root) {
var result = [], ss, e
try {
if (root.nodeType === 9 || !splittable.test(selector)) {
@@ -342,21 +332,6 @@
} catch(ex) { }
return selectNonNative(selector, root)
}
- // native support for CSS2 selectors only
- , selectCSS2qSA = function (selector, root) {
- var i, r, l, ss, result = []
- selector = selector.replace(normalizr, '$1')
- // safe to pass whole selector to qSA
- if (!splittable.test(selector) && css2.test(selector)) return arrayify(root[qSA](selector))
- each(ss = selector.split(','), collectSelector(root, function(ctx, s, rewrite) {
- // use native qSA if selector is compatile, otherwise use _qwery()
- r = css2.test(s) ? ctx[qSA](s) : _qwery(s, ctx)
- for (i = 0, l = r.length; i < l; i++) {
- if (ctx.nodeType === 9 || rewrite || isAncestor(r[i], root)) result[result.length] = r[i]
- }
- }))
- return ss.length > 1 && result.length > 1 ? uniq(result) : result
- }
// no native selector support
, selectNonNative = function (selector, root) {
var result = [], items, m, i, l, r, ss
@@ -378,15 +353,18 @@
}))
return ss.length > 1 && result.length > 1 ? uniq(result) : result
}
- , select = function () {
- var q = qwery.nonStandardEngine ? selectNonNative : supportsCSS3 ? selectCSS3 : doc[qSA] ? selectCSS2qSA : selectNonNative
- return q.apply(q, arguments)
+ , configure = function (options) {
+ // configNativeQSA: use fully-internal selector or native qSA where present
+ if (typeof options[useNativeQSA] !== 'undefined')
+ select = !options[useNativeQSA] ? selectNonNative : hasQSA ? selectQSA : selectNonNative
}
+ configure({ useNativeQSA: true })
+
+ qwery.configure = configure
qwery.uniq = uniq
qwery.is = is
qwery.pseudos = {}
- qwery.nonStandardEngine = false
return qwery
})
View
2  qwery.min.js
@@ -4,4 +4,4 @@
* copyright Dustin Diaz & Jacob Thornton 2011
* MIT License
*/
-!function(a,b){typeof module!="undefined"?module.exports=b():typeof define=="function"&&typeof define.amd=="object"?define(b):this[a]=b()}("qwery",function(){function z(){this.c={}}function E(a){return A.g(a)||A.s(a,"(^|\\s+)"+a+"(\\s+|$)",1)}function F(a,b){var c=0,d=a.length;for(;c<d;c++)b.call(null,a[c])}function G(a){for(var b=[],c=0,d=a.length;c<d;++c)S(a[c])?b=b.concat(a[c]):b[b.length]=a[c];return b}function H(a){var b=0,c=a.length,d=[];for(;b<c;b++)d[b]=a[b];return d}function I(a){while(a=a.previousSibling)if(a.nodeType==1)break;return a}function J(a){return a.match(x)}function K(a,b,c,d,e,h,i,j,k,l,m){var n,o,p,q,r;if(this.nodeType!==1)return!1;if(b&&b!=="*"&&this.tagName&&this.tagName.toLowerCase()!==b)return!1;if(c&&(o=c.match(f))&&o[1]!==this.id)return!1;if(c&&(r=c.match(g)))for(n=r.length;n--;)if(!E(r[n].slice(1)).test(this.className))return!1;if(k&&V.pseudos[k]&&!V.pseudos[k](this,m))return!1;if(d&&!i){q=this.attributes;for(p in q)if(Object.prototype.hasOwnProperty.call(q,p)&&(q[p].name||p)==e)return this}return d&&!M(h,Y(this,e)||"",i)?!1:this}function L(a){return B.g(a)||B.s(a,a.replace(p,"\\$1"))}function M(a,b,c){switch(a){case"=":return b==c;case"^=":return b.match(C.g("^="+c)||C.s("^="+c,"^"+L(c),1));case"$=":return b.match(C.g("$="+c)||C.s("$="+c,L(c)+"$",1));case"*=":return b.match(C.g(c)||C.s(c,L(c),1));case"~=":return b.match(C.g("~="+c)||C.s("~="+c,"(?:^|\\s+)"+L(c)+"(?:\\s+|$)",1));case"|=":return b.match(C.g("|="+c)||C.s("|="+c,"^"+L(c)+"(-|$)",1))}return 0}function N(a,b){var c=[],e=[],f,g,i,j,k,l,m,n,o=b,p=D.g(a)||D.s(a,a.split(w)),q=a.match(v);if(!p.length)return c;j=(p=p.slice(0)).pop(),p.length&&(i=p[p.length-1].match(h))&&(o=U(b,i[1]));if(!o)return c;m=J(j),l=o!==b&&o.nodeType!==9&&q&&/^[+~]$/.test(q[q.length-1])?function(a){while(o=o.nextSibling)o.nodeType==1&&(m[1]?m[1]==o.tagName.toLowerCase():1)&&(a[a.length]=o);return a}([]):o[d](m[1]||"*");for(f=0,g=l.length;f<g;f++)if(n=K.apply(l[f],m))c[c.length]=n;return p.length?(F(c,function(a){P(a,p,q)&&(e[e.length]=a)}),e):c}function O(a,b,c){if(Q(b))return a==b;if(S(b))return!!~G(b).indexOf(a);var d=b.split(","),e,f;while(b=d.pop()){e=D.g(b)||D.s(b,b.split(w)),f=b.match(v),e=e.slice(0);if(K.apply(a,J(e.pop()))&&(!e.length||P(a,e,f,c)))return!0}return!1}function P(a,b,c,d){function f(a,d,g){while(g=y[c[d]](g,a))if(Q(g)&&K.apply(g,J(b[d]))){if(!d)return g;if(e=f(g,d-1,g))return e}}var e;return(e=f(a,b.length-1,a))&&(!d||X(e,d))}function Q(a,b){return a&&typeof a=="object"&&(b=a.nodeType)&&(b==1||b==9)}function R(a){var b=[],c,d;a:for(c=0;c<a.length;++c){for(d=0;d<b.length;++d)if(b[d]==a[c])continue a;b[b.length]=a[c]}return b}function S(a){return typeof a=="object"&&isFinite(a.length)}function T(b){return b?typeof b=="string"?V(b)[0]:!b.nodeType&&S(b)?b[0]:b:a}function U(a,b,c){return a.nodeType===9?a.getElementById(b):a.ownerDocument&&((c=a.ownerDocument.getElementById(b))&&X(c,a)&&c||!X(a,a.ownerDocument)&&bb('[id="'+b+'"]',a)[0])}function V(a,b){var e,f,g=T(b);if(!g||!a)return[];if(a===window||Q(a))return!b||a!==window&&Q(g)&&X(a,g)?[a]:[];if(a&&S(a))return G(a);if(e=a.match(u)){if(e[1])return(f=U(g,e[1]))?[f]:[];if(e[2])return H(g[d](e[2]));if(Z&&e[3])return H(g[c](e[3]))}return bb(a,g)}function W(a,b){return function(c){var d,e;if(l.test(c)){a.nodeType!==9&&((e=d=a.getAttribute("id"))||a.setAttribute("id",e="__qwerymeupscotty"),c='[id="'+e+'"]'+c,b(a.parentNode||a,c,!0),d||a.removeAttribute("id"));return}c.length&&b(a,c,!1)}}var a=document,b=a.documentElement,c="getElementsByClassName",d="getElementsByTagName",e="querySelectorAll",f=/#([\w\-]+)/,g=/\.[\w\-]+/g,h=/^#([\w\-]+)$/,i=/^\.([\w\-]+)$/,j=/^([\w\-]+)$/,k=/^([\w]+)?\.([\w\-]+)$/,l=/(^|,)\s*[>~+]/,m=/^\s+|\s*([,\s\+\~>]|$)\s*/g,n=/[\s\>\+\~]/,o=/(?![\s\w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^'"]*\]|[\s\w\+\-]*\))/,p=/([.*+?\^=!:${}()|\[\]\/\\])/g,q=/^(\*|[a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/,r=/\[([\w\-]+)(?:([\|\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/,s=/:([\w\-]+)(\(['"]?([\s\w\+\-]+)['"]?\))?/,t=/^(([\w\-]*[#\.]?[\w\-]+|\*)?(\[[\w\-]+([\~\|]?=['"][ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+["'])?\])?(\:(link|visited|active|hover))?([\s>+~\.,]|(?:$)))+$/,u=new RegExp(h.source+"|"+j.source+"|"+i.source),v=new RegExp("("+n.source+")"+o.source,"g"),w=new RegExp(n.source+o.source),x=new RegExp(q.source+"("+r.source+")?"+"("+s.source+")?"),y={" ":function(a){return a&&a!==b&&a.parentNode},">":function(a,b){return a&&a.parentNode==b.parentNode&&a.parentNode},"~":function(a){return a&&a.previousSibling},"+":function(a,b,c,d){return a?(c=I(a))&&(d=I(b))&&c==d&&c:!1}};z.prototype={g:function(a){return this.c[a]||undefined},s:function(a,b,c){return b=c?new RegExp(b):b,this.c[a]=b}};var A=new z,B=new z,C=new z,D=new z,X="compareDocumentPosition"in b?function(a,b){return(b.compareDocumentPosition(a)&16)==16}:"contains"in b?function(a,c){return c=c.nodeType===9||c==window?b:c,c!==a&&c.contains(a)}:function(a,b){while(a=a.parentNode)if(a===b)return 1;return 0},Y=function(){var b=a.createElement("p");return(b.innerHTML='<a href="#x">x</a>')&&b.firstChild.getAttribute("href")!="#x"?function(a,b){return b==="class"?a.className:b==="href"||b==="src"?a.getAttribute(b,2):a.getAttribute(b)}:function(a,b){return a.getAttribute(b)}}(),Z=function(){if(a[c]&&a.querySelector&&a[e])try{var b=a.createElement("p");return b.innerHTML="<a/>",b[e](":nth-of-type(1)").length}catch(d){}return!1}(),$=function(a,b){var c=[],d,f;try{return b.nodeType===9||!l.test(a)?H(b[e](a)):(F(d=a.split(","),W(b,function(a,b){f=a[e](b),f.length==1?c[c.length]=f.item(0):f.length&&(c=c.concat(H(f)))})),d.length>1&&c.length>1?R(c):c)}catch(g){}return ba(a,b)},_=function(a,b){var c,d,f,g,h=[];return a=a.replace(m,"$1"),!l.test(a)&&t.test(a)?H(b[e](a)):(F(g=a.split(","),W(b,function(a,g,i){d=t.test(g)?a[e](g):N(g,a);for(c=0,f=d.length;c<f;c++)if(a.nodeType===9||i||X(d[c],b))h[h.length]=d[c]})),g.length>1&&h.length>1?R(h):h)},ba=function(a,b){var c=[],e,f,g,h,i,j;a=a.replace(m,"$1");if(f=a.match(k)){i=E(f[2]),e=b[d](f[1]||"*");for(g=0,h=e.length;g<h;g++)i.test(e[g].className)&&(c[c.length]=e[g]);return c}return F(j=a.split(","),W(b,function(a,d,e){i=N(d,a);for(g=0,h=i.length;g<h;g++)if(a.nodeType===9||e||X(i[g],b))c[c.length]=i[g]})),j.length>1&&c.length>1?R(c):c},bb=function(){var b=V.nonStandardEngine?ba:Z?$:a[e]?_:ba;return b.apply(b,arguments)};return V.uniq=R,V.is=O,V.pseudos={},V.nonStandardEngine=!1,V})
+!function(a,b){typeof module!="undefined"?module.exports=b():typeof define=="function"&&typeof define.amd=="object"?define(b):this[a]=b()}("qwery",function(){function A(){this.c={}}function F(a){return B.g(a)||B.s(a,"(^|\\s+)"+a+"(\\s+|$)",1)}function G(a,b){var c=0,d=a.length;for(;c<d;c++)b.call(null,a[c])}function H(a){for(var b=[],c=0,d=a.length;c<d;++c)T(a[c])?b=b.concat(a[c]):b[b.length]=a[c];return b}function I(a){var b=0,c=a.length,d=[];for(;b<c;b++)d[b]=a[b];return d}function J(a){while(a=a.previousSibling)if(a.nodeType==1)break;return a}function K(a){return a.match(w)}function L(a,b,c,d,e,h,i,j,k,l,m){var n,o,p,q,r;if(this.nodeType!==1)return!1;if(b&&b!=="*"&&this.tagName&&this.tagName.toLowerCase()!==b)return!1;if(c&&(o=c.match(f))&&o[1]!==this.id)return!1;if(c&&(r=c.match(g)))for(n=r.length;n--;)if(!F(r[n].slice(1)).test(this.className))return!1;if(k&&W.pseudos[k]&&!W.pseudos[k](this,m))return!1;if(d&&!i){q=this.attributes;for(p in q)if(Object.prototype.hasOwnProperty.call(q,p)&&(q[p].name||p)==e)return this}return d&&!N(h,Z(this,e)||"",i)?!1:this}function M(a){return C.g(a)||C.s(a,a.replace(p,"\\$1"))}function N(a,b,c){switch(a){case"=":return b==c;case"^=":return b.match(D.g("^="+c)||D.s("^="+c,"^"+M(c),1));case"$=":return b.match(D.g("$="+c)||D.s("$="+c,M(c)+"$",1));case"*=":return b.match(D.g(c)||D.s(c,M(c),1));case"~=":return b.match(D.g("~="+c)||D.s("~="+c,"(?:^|\\s+)"+M(c)+"(?:\\s+|$)",1));case"|=":return b.match(D.g("|="+c)||D.s("|="+c,"^"+M(c)+"(-|$)",1))}return 0}function O(a,b){var c=[],e=[],f,g,i,j,k,l,m,n,o=b,p=E.g(a)||E.s(a,a.split(v)),q=a.match(u);if(!p.length)return c;j=(p=p.slice(0)).pop(),p.length&&(i=p[p.length-1].match(h))&&(o=V(b,i[1]));if(!o)return c;m=K(j),l=o!==b&&o.nodeType!==9&&q&&/^[+~]$/.test(q[q.length-1])?function(a){while(o=o.nextSibling)o.nodeType==1&&(m[1]?m[1]==o.tagName.toLowerCase():1)&&(a[a.length]=o);return a}([]):o[d](m[1]||"*");for(f=0,g=l.length;f<g;f++)if(n=L.apply(l[f],m))c[c.length]=n;return p.length?(G(c,function(a){Q(a,p,q)&&(e[e.length]=a)}),e):c}function P(a,b,c){if(R(b))return a==b;if(T(b))return!!~H(b).indexOf(a);var d=b.split(","),e,f;while(b=d.pop()){e=E.g(b)||E.s(b,b.split(v)),f=b.match(u),e=e.slice(0);if(L.apply(a,K(e.pop()))&&(!e.length||Q(a,e,f,c)))return!0}return!1}function Q(a,b,c,d){function f(a,d,g){while(g=x[c[d]](g,a))if(R(g)&&L.apply(g,K(b[d]))){if(!d)return g;if(e=f(g,d-1,g))return e}}var e;return(e=f(a,b.length-1,a))&&(!d||Y(e,d))}function R(a,b){return a&&typeof a=="object"&&(b=a.nodeType)&&(b==1||b==9)}function S(a){var b=[],c,d;a:for(c=0;c<a.length;++c){for(d=0;d<b.length;++d)if(b[d]==a[c])continue a;b[b.length]=a[c]}return b}function T(a){return typeof a=="object"&&isFinite(a.length)}function U(b){return b?typeof b=="string"?W(b)[0]:!b.nodeType&&T(b)?b[0]:b:a}function V(a,b,c){return a.nodeType===9?a.getElementById(b):a.ownerDocument&&((c=a.ownerDocument.getElementById(b))&&Y(c,a)&&c||!Y(a,a.ownerDocument)&&z('[id="'+b+'"]',a)[0])}function W(a,b){var e,f,g=U(b);if(!g||!a)return[];if(a===window||R(a))return!b||a!==window&&R(g)&&Y(a,g)?[a]:[];if(a&&T(a))return H(a);if(e=a.match(t)){if(e[1])return(f=V(g,e[1]))?[f]:[];if(e[2])return I(g[d](e[2]));if($&&e[3])return I(g[c](e[3]))}return z(a,g)}function X(a,b){return function(c){var d,e;if(l.test(c)){a.nodeType!==9&&((e=d=a.getAttribute("id"))||a.setAttribute("id",e="__qwerymeupscotty"),c='[id="'+e+'"]'+c,b(a.parentNode||a,c,!0),d||a.removeAttribute("id"));return}c.length&&b(a,c,!1)}}var a=document,b=a.documentElement,c="getElementsByClassName",d="getElementsByTagName",e="querySelectorAll",f=/#([\w\-]+)/,g=/\.[\w\-]+/g,h=/^#([\w\-]+)$/,i=/^\.([\w\-]+)$/,j=/^([\w\-]+)$/,k=/^([\w]+)?\.([\w\-]+)$/,l=/(^|,)\s*[>~+]/,m=/^\s+|\s*([,\s\+\~>]|$)\s*/g,n=/[\s\>\+\~]/,o=/(?![\s\w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^'"]*\]|[\s\w\+\-]*\))/,p=/([.*+?\^=!:${}()|\[\]\/\\])/g,q=/^(\*|[a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/,r=/\[([\w\-]+)(?:([\|\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/,s=/:([\w\-]+)(\(['"]?([^()]+)['"]?\))?/,t=new RegExp(h.source+"|"+j.source+"|"+i.source),u=new RegExp("("+n.source+")"+o.source,"g"),v=new RegExp(n.source+o.source),w=new RegExp(q.source+"("+r.source+")?"+"("+s.source+")?"),x={" ":function(a){return a&&a!==b&&a.parentNode},">":function(a,b){return a&&a.parentNode==b.parentNode&&a.parentNode},"~":function(a){return a&&a.previousSibling},"+":function(a,b,c,d){return a?(c=J(a))&&(d=J(b))&&c==d&&c:!1}},y="useNativeQSA",z;A.prototype={g:function(a){return this.c[a]||undefined},s:function(a,b,c){return b=c?new RegExp(b):b,this.c[a]=b}};var B=new A,C=new A,D=new A,E=new A,Y="compareDocumentPosition"in b?function(a,b){return(b.compareDocumentPosition(a)&16)==16}:"contains"in b?function(a,c){return c=c.nodeType===9||c==window?b:c,c!==a&&c.contains(a)}:function(a,b){while(a=a.parentNode)if(a===b)return 1;return 0},Z=function(){var b=a.createElement("p");return(b.innerHTML='<a href="#x">x</a>')&&b.firstChild.getAttribute("href")!="#x"?function(a,b){return b==="class"?a.className:b==="href"||b==="src"?a.getAttribute(b,2):a.getAttribute(b)}:function(a,b){return a.getAttribute(b)}}(),$=!!a[c],_=a.querySelector&&a[e],ba=function(a,b){var c=[],d,f;try{return b.nodeType===9||!l.test(a)?I(b[e](a)):(G(d=a.split(","),X(b,function(a,b){f=a[e](b),f.length==1?c[c.length]=f.item(0):f.length&&(c=c.concat(I(f)))})),d.length>1&&c.length>1?S(c):c)}catch(g){}return bb(a,b)},bb=function(a,b){var c=[],e,f,g,h,i,j;a=a.replace(m,"$1");if(f=a.match(k)){i=F(f[2]),e=b[d](f[1]||"*");for(g=0,h=e.length;g<h;g++)i.test(e[g].className)&&(c[c.length]=e[g]);return c}return G(j=a.split(","),X(b,function(a,d,e){i=O(d,a);for(g=0,h=i.length;g<h;g++)if(a.nodeType===9||e||Y(i[g],b))c[c.length]=i[g]})),j.length>1&&c.length>1?S(c):c},bc=function(a){typeof a[y]!="undefined"&&(z=a[y]?_?ba:bb:bb)};return bc({useNativeQSA:!0}),W.configure=bc,W.uniq=S,W.is=P,W.pseudos={},W})
View
52 src/qwery.js
@@ -24,10 +24,6 @@
, simple = /^(\*|[a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/
, attr = /\[([\w\-]+)(?:([\|\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/
, pseudo = /:([\w\-]+)(\(['"]?([^()]+)['"]?\))?/
- // check if we can pass a selector to a non-CSS3 compatible qSA.
- // *not* suitable for validating a selector, it's too lose; it's the users' responsibility to pass valid selectors
- // this regex must be kept in sync with the one in tests.js
- , css2 = /^(([\w\-]*[#\.]?[\w\-]+|\*)?(\[[\w\-]+([\~\|]?=['"][ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+["'])?\])?(\:(link|visited|active|hover))?([\s>+~\.,]|(?:$)))+$/
, easy = new RegExp(idOnly.source + '|' + tagOnly.source + '|' + classOnly.source)
, dividers = new RegExp('(' + splitters.source + ')' + splittersMore.source, 'g')
, tokenizr = new RegExp(splitters.source + splittersMore.source)
@@ -47,6 +43,8 @@
return (p1 = previous(node)) && (p2 = previous(contestant)) && p1 == p2 && p1
}
}
+ , useNativeQSA = 'useNativeQSA'
+ , select // main select() method, assign later
function cache() {
this.c = {}
@@ -259,7 +257,7 @@
if (m = selector.match(easy)) {
if (m[1]) return (el = byId(root, m[1])) ? [el] : []
if (m[2]) return arrayify(root[byTag](m[2]))
- if (supportsCSS3 && m[3]) return arrayify(root[byClass](m[3]))
+ if (hasByClass && m[3]) return arrayify(root[byClass](m[3]))
}
return select(selector, root)
@@ -306,19 +304,11 @@
} :
function(e, a) { return e.getAttribute(a) }
}()
- // does native qSA support CSS3 level selectors
- , supportsCSS3 = function () {
- if (doc[byClass] && doc.querySelector && doc[qSA]) {
- try {
- var p = doc.createElement('p')
- p.innerHTML = '<a/>'
- return p[qSA](':nth-of-type(1)').length
- } catch (e) { }
- }
- return false
- }()
- // native support for CSS3 selectors
- , selectCSS3 = function (selector, root) {
+ , hasByClass = !!doc[byClass]
+ // has native qSA support
+ , hasQSA = doc.querySelector && doc[qSA]
+ // use native qSA
+ , selectQSA = function (selector, root) {
var result = [], ss, e
try {
if (root.nodeType === 9 || !splittable.test(selector)) {
@@ -335,21 +325,6 @@
} catch(ex) { }
return selectNonNative(selector, root)
}
- // native support for CSS2 selectors only
- , selectCSS2qSA = function (selector, root) {
- var i, r, l, ss, result = []
- selector = selector.replace(normalizr, '$1')
- // safe to pass whole selector to qSA
- if (!splittable.test(selector) && css2.test(selector)) return arrayify(root[qSA](selector))
- each(ss = selector.split(','), collectSelector(root, function(ctx, s, rewrite) {
- // use native qSA if selector is compatile, otherwise use _qwery()
- r = css2.test(s) ? ctx[qSA](s) : _qwery(s, ctx)
- for (i = 0, l = r.length; i < l; i++) {
- if (ctx.nodeType === 9 || rewrite || isAncestor(r[i], root)) result[result.length] = r[i]
- }
- }))
- return ss.length > 1 && result.length > 1 ? uniq(result) : result
- }
// no native selector support
, selectNonNative = function (selector, root) {
var result = [], items, m, i, l, r, ss
@@ -371,15 +346,18 @@
}))
return ss.length > 1 && result.length > 1 ? uniq(result) : result
}
- , select = function () {
- var q = qwery.nonStandardEngine ? selectNonNative : supportsCSS3 ? selectCSS3 : doc[qSA] ? selectCSS2qSA : selectNonNative
- return q.apply(q, arguments)
+ , configure = function (options) {
+ // configNativeQSA: use fully-internal selector or native qSA where present
+ if (typeof options[useNativeQSA] !== 'undefined')
+ select = !options[useNativeQSA] ? selectNonNative : hasQSA ? selectQSA : selectNonNative
}
+ configure({ useNativeQSA: true })
+
+ qwery.configure = configure
qwery.uniq = uniq
qwery.is = is
qwery.pseudos = {}
- qwery.nonStandardEngine = false
return qwery
})
View
10 tests/benchmarks.html
@@ -46,6 +46,13 @@
<script src="../vendor/nw.js"></script>
<script src="../vendor/sizzle.js"></script>
<script src="../src/qwery.js"></script>
+ <script type="text/javascript">
+ var qwerynew = qwery
+ </script>
+ <script src="../qwery.js"></script>
+ <script type="text/javascript">
+ var qweryold = qwery
+ </script>
</head>
<body>
<h1>Selector Benchmarks</h1>
@@ -118,7 +125,8 @@
var libs = [
{ fn: Sizzle, id: 'Sizzle' }
, { fn: NW.Dom.select, id: 'NW' }
- , { fn: qwery, id: 'Qwery' }
+ , { fn: qwerynew, id: 'Qwery (new)' }
+ , { fn: qweryold, id: 'Qwery (old)' }
]
var libidx = 0, testidx = 0, iterations
View
3  tests/index.html
@@ -12,10 +12,9 @@
<link rel="stylesheet" href="../node_modules/sink-test/src/sink.css" type="text/css">
<script src="../node_modules/sink-test/src/sink.js"></script>
<script src="../src/qwery.js"></script>
- <script src="../src/pseudos.js"></script>
+ <script src="../pseudos/qwery-pseudos.js"></script>
<script type="text/javascript">
var Q = qwery
- Q.nonStandardEngine = true
</script>
</head>
<body>
View
118 tests/tests.js
@@ -1,8 +1,18 @@
-
-// custom pseudo just for tests
+// silly custom pseudo just for tests
Q.pseudos.humanoid = function(e, v) { return Q.is(e, 'li:contains(human)') || Q.is(e, 'ol:contains(human)') }
+var hasQSA = !!document.querySelectorAll
+ , sinkSuite = function (label, suite) {
+ sink(label + (hasQSA ? ' [qSA]' : ''), function () {
+ hasQSA && Q.configure({ useNativeQSA: true })
+ suite.apply(null, arguments)
+ })
+ hasQSA && sink(label + ' [non-QSA]', function () {
+ Q.configure({ useNativeQSA: false })
+ suite.apply(null, arguments)
+ })
+ }
-sink('Contexts', function (test, ok) {
+sinkSuite('Contexts', function (test, ok) {
test('should be able to pass optional context', 2, function () {
ok(Q('.a').length === 3, 'no context found 3 elements (.a)');
@@ -38,9 +48,9 @@ sink('Contexts', function (test, ok) {
ok(!Q('#boosh', Q('#booshTest')).length, 'shouldn\'t find #boosh (ancestor) within #booshTest (descendent)')
ok(!Q('#boosh', Q('#lonelyBoosh')).length, 'shouldn\'t find #boosh within #lonelyBoosh (unrelated)')
})
-});
+})
-sink('CSS 1', function (test, ok) {
+sinkSuite('CSS 1', function (test, ok) {
test('get element by id', 2, function () {
var result = Q('#boosh');
ok(!!result[0], 'found element with id=boosh');
@@ -90,7 +100,7 @@ sink('CSS 1', function (test, ok) {
});
});
-sink('CSS 2', function (test, ok) {
+sinkSuite('CSS 2', function (test, ok) {
test('get elements by attribute', 4, function () {
var wanted = Q('#boosh div[test]')[0];
@@ -112,83 +122,7 @@ sink('CSS 2', function (test, ok) {
});
-sink('CSS 2 identification', function (test, ok) {
- // cases that we should be able to pass through to native non-CSS3 qSA where present (IE8)
- // we get to ignore grouping here since selectors are split up for this case anyway
- // we also get to work with normalized selectors
- // this regex must be kept in sync with the one in src/qwery.js for the test to make sense
- var css2 = /^(([\w\-]*[#\.]?[\w\-]+|\*)?(\[[\w\-]+([\~\|]?=['"][ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+["'])?\])?(\:(link|visited|active|hover))?([\s>+~\.,]|(?:$)))+$/
- , css2Selectors = [
- '*',
- , 'DIV',
- , 'e1 e2',
- , 'parent>child'
- , 'parent+child'
- , 'parent~child' // CSS3 but IE8 supports ~
- , '#id'
- , 'el#id'
- , 'el #id'
- , 'el>#id'
- , '#id>#id2'
- , '.class'
- , 'div.class'
- , '#id.class'
- , 'element.with.multiple.classes>bam'
- //, 'el:first-child' -> IE8 buggy, don't do native
- , 'a:link'
- , 'a#id:link'
- , '.class:visited'
- , '#boo:active'
- , 'div.class:hover'
- //, '*:focus' -> IE8 doesn't support, don't do native
- , 'hoo[foo]'
- , '#hah[boo="moo"]'
- , '.claz[attrib~=\'nooooooo!\']'
- , 'ele[prop|="huh?"]'
- , '.direct-descend>.direct-descend>.direct-descend'
- , '.direct-descend>.direct-descend>.direct-descend~.lvl2'
- ]
- , nonCSS2Selectors = [
- 'p:empty'
- , 'hoo:enabled'
- , 'haa:disabled'
- , '#bing:checked'
- , '*:first-of-type'
- , '*:last-of-type'
- , '.class:last-child'
- , 'yes:not'
- , 'p:nth-child(2n+1)'
- , 'p:nth-last-child(1n+2)'
- , 'p:nth-last-of-type(3n+3)'
- , 'p:nth-of-type(4n+2)'
- , '*:only-child'
- , '*:only-of-type'
- , 'p#id:root'
- , '#gak::selection'
- , 'body:target'
- // CSS2 buggy
- , 'el:first-child'
- , '*:focus'
- ]
-
- test('CSS2 selectors', css2Selectors.length, function() {
- for (var i = 0; i < css2Selectors.length; i++) {
- ok(css2.test(css2Selectors[i]), 'matched ' + css2Selectors[i])
- }
- })
-
- test('CSS2 selectors grouped', 1, function() {
- ok(css2.test(css2Selectors.join(',')), 'matched grouped CSS2 selectors')
- })
-
- test('non-CSS2 selectors', nonCSS2Selectors.length, function() {
- for (var i = 0; i < nonCSS2Selectors.length; i++) {
- ok(!css2.test(nonCSS2Selectors[i]), 'did not matche ' + nonCSS2Selectors[i])
- }
- })
-});
-
-sink('attribute selectors', function (test, ok, b, a, assert) {
+sinkSuite('attribute selectors', function (test, ok, b, a, assert) {
/* CSS 2 SPEC */
@@ -266,7 +200,7 @@ sink('attribute selectors', function (test, ok, b, a, assert) {
});
-sink('Uniq', function (test, ok) {
+sinkSuite('Uniq', function (test, ok) {
test('duplicates arent found in arrays', 2, function () {
ok(Q.uniq(['a', 'b', 'c', 'd', 'e', 'a', 'b', 'c', 'd', 'e']).length == 5, 'result should be a, b, c, d, e')
ok(Q.uniq(['a', 'b', 'c', 'c', 'c']).length == 3, 'result should be a, b, c')
@@ -274,7 +208,7 @@ sink('Uniq', function (test, ok) {
})
-sink('element-context queries', function(test, ok) {
+sinkSuite('element-context queries', function(test, ok) {
test('relationship-first queries', 5, function() {
var pass = false
try { pass = Q('> .direct-descend', Q('#direct-descend')).length == 2 } catch (e) { }
@@ -323,7 +257,7 @@ sink('element-context queries', function(test, ok) {
})
})
-sink('tokenizer', function (test, ok) {
+sinkSuite('tokenizer', function (test, ok) {
test('should not get weird tokens', 5, function () {
ok(Q('div .tokens[title="one"]')[0] == document.getElementById('token-one'), 'found div .tokens[title="one"]');
@@ -335,13 +269,13 @@ sink('tokenizer', function (test, ok) {
});
-sink('interesting syntaxes', function (test, ok) {
+sinkSuite('interesting syntaxes', function (test, ok) {
test('should parse bad selectors', 1, function () {
ok(Q('#spaced-tokens p em a').length, 'found element with funny tokens')
});
});
-sink('order matters', function (test, ok) {
+sinkSuite('order matters', function (test, ok) {
function tag(el) {
return el.tagName.toLowerCase();
@@ -364,7 +298,7 @@ sink('order matters', function (test, ok) {
});
-sink('pseudo-selectors', function (test, ok) {
+sinkSuite('pseudo-selectors', function (test, ok) {
test(':contains', 4, function() {
ok(Q('li:contains(humans)').length == 1, 'found by "element:contains(text)"')
ok(Q(':contains(humans)').length == 5, 'found by ":contains(text)", including all ancestors')
@@ -482,7 +416,7 @@ sink('pseudo-selectors', function (test, ok) {
});
-sink('argument types', function (test, ok) {
+sinkSuite('argument types', function (test, ok) {
test('should be able to pass in nodes as arguments', 5, function () {
var el = document.getElementById('boosh');
@@ -505,7 +439,7 @@ sink('argument types', function (test, ok) {
});
-sink('is()', function (test, ok) {
+sinkSuite('is()', function (test, ok) {
var el = document.getElementById('attr-child-boosh');
test('simple selectors', 9, function () {
ok(Q.is(el, 'li'), 'tag');
@@ -544,7 +478,7 @@ sink('is()', function (test, ok) {
});
});
-sink('selecting elements in other documents', function (test, ok) {
+sinkSuite('selecting elements in other documents', function (test, ok) {
var doc = document.getElementById('frame').contentWindow.document
doc.body.innerHTML =
'<div id="hsoob">' +
Something went wrong with that request. Please try again.