Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

adds support for |= attribute selector

fixes $= selector
adds tests for all attribute selectors
also a few random little nits
  • Loading branch information...
commit 6dd841d3ca8c240713641d822db4c9535426b0b8 1 parent d415375
@fat fat authored
View
22 qwery.js
@@ -17,7 +17,7 @@
html = doc.documentElement,
tokenizr = /\s(?![\s\w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^'"]*\])/,
simple = /^([a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/,
- attr = /\[([\w\-]+)(?:([\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/,
+ attr = /\[([\w\-]+)(?:([\|\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/,
chunker = new RegExp(simple.source + '(' + attr.source + ')?');
function array(ar) {
@@ -28,7 +28,6 @@
return r;
}
-
var cache = function () {
this.c = {};
};
@@ -37,8 +36,7 @@
return this.c[k] || undefined;
},
s: function (k, v) {
- this.c[k] = v;
- return v;
+ return this.c[k] = v;
}
};
@@ -82,8 +80,8 @@
}
function loopAll(tokens) {
- var r = [], token = tokens.pop(), intr = q(token), tag = intr[1] || '*', i, l, els;
- var root = tokens.length && (m = tokens[0].match(idOnly)) ? doc.getElementById(m[1]) : doc;
+ var r = [], token = tokens.pop(), intr = q(token), tag = intr[1] || '*', i, l, els,
+ root = tokens.length && (m = tokens[0].match(idOnly)) ? doc.getElementById(m[1]) : doc;
if (!root) {
return r;
}
@@ -98,7 +96,7 @@
}
function clean(s) {
- return cleanCache.g(s) || cleanCache.s(s, s.replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'));
+ return cleanCache.g(s) || cleanCache.s(s, s.replace(/([\.\*\+\?\^\$\{\}\(\)\|\[\]\/\\])/g, '\\$1'));
}
function checkAttr(qualify, actual, val) {
@@ -108,11 +106,13 @@
case '^=':
return actual.match(attrCache.g('^=' + val) || attrCache.s('^=' + val, new RegExp('^' + clean(val))));
case '$=':
- return actual.match(attrCache.g('$=' + val) || attrCache.s('$=' + val, new RegExp('$' + clean(val))));
+ return actual.match(attrCache.g('$=' + val) || attrCache.s('$=' + val, new RegExp(clean(val) + '$')));
case '*=':
return actual.match(attrCache.g(val) || attrCache.s(val, new RegExp(clean(val))));
case '~=':
return actual.match(attrCache.g('~=' + val) || attrCache.s('~=' + val, new RegExp('(?:^|\\s+)' + clean(val) + '(?:\\s+|$)')));
+ case '|=':
+ return actual.match(attrCache.g('|=' + val) || attrCache.s('|=' + val, new RegExp('^' + clean(val) + '(-|$)')));
}
return false;
}
@@ -154,7 +154,7 @@
return container !== element && container.contains(element);
} :
function (element, container) {
- while ((element = element.parentNode)) {
+ while (element = element.parentNode) {
if (element === container) {
return 1;
}
@@ -222,8 +222,8 @@
}
return result;
}
- for (items = selector.split(','), i = items.length; item = items[--i];) {
- collections[i] = _qwery(item);
+ for (items = selector.split(','), i = items.length; i--;) {
+ collections[i] = _qwery(items[i]);
}
for (i = collections.length; collection = collections[--i];) {
var ret = collection;
View
2  qwery.min.js
@@ -5,4 +5,4 @@
* MIT License
*/
-!function(a,b){function V(a){var b=[],c,d;label:for(c=0;c<a.length;c++){for(d=0;d<b.length;d++)if(b[d]==a[c])continue label;b[b.length]=a[c]}return b}function U(a,c){c=typeof c=="string"?U(c)[0]:c||b;if(!c)return[];if(h=T(a,c))return h;if(b.getElementsByClassName&&(h=a.match(y)))return G(c.getElementsByClassName(h[1]));return G(c.querySelectorAll(a))}function T(a,c){if(h=a.match(x))return(m=b.getElementById(h[1]))?[m]:[];if(h=a.match(z))return G(c.getElementsByTagName(h[1]));return!1}function R(a){var b=[],c=[],d,g=L.g(a)||L.s(a,a.split(C));g=g.slice(0);if(!g.length)return b;b=O(g);if(!g.length)return b;for(e=b.length,f=0;e--;){n=b[e],j=n;for(d=g.length;d--;)parents:while(j!==B&&(j=j.parentNode))if(p=N.apply(j,M(g[d])))break parents;p&&(c[f++]=n)}return c}function Q(a,b,c){switch(a){case"=":return b==c;case"^=":return b.match(K.g("^="+c)||K.s("^="+c,new RegExp("^"+P(c))));case"$=":return b.match(K.g("$="+c)||K.s("$="+c,new RegExp("$"+P(c))));case"*=":return b.match(K.g(c)||K.s(c,new RegExp(P(c))));case"~=":return b.match(K.g("~="+c)||K.s("~="+c,new RegExp("(?:^|\\s+)"+P(c)+"(?:\\s+|$)")))}return!1}function P(a){return J.g(a)||J.s(a,a.replace(/([\.\*\+\?\^\$\{\}\(\)\|\[\]\/\\])/g,"\\$1"))}function O(a){var c=[],d=a.pop(),e=M(d),f=e[1]||"*",g,i,j,k=a.length&&(h=a[0].match(x))?b.getElementById(h[1]):b;if(!k)return c;j=k.getElementsByTagName(f);for(g=0,i=j.length;g<i;g++)m=j[g],(r=N.apply(m,e))&&c.push(r);return c}function N(a,b,c,e,f,g,h){var j,k,l;if(b&&this.tagName.toLowerCase()!==b)return!1;if(c&&(j=c.match(v))&&j[1]!==this.id)return!1;if(c&&(q=c.match(w)))for(d=q.length;d--;){k=q[d].slice(1);if(!(I.g(k)||I.s(k,new RegExp("(^|\\s+)"+k+"(\\s+|$)"))).test(this.className))return!1}if(e&&!h){i=this.attributes;for(l in i)if(Object.prototype.hasOwnProperty.call(i,l)&&(i[l].name||l)==f)return this}if(e&&!Q(g,this.getAttribute(f)||"",h))return!1;return this}function M(a){return a.match(F)}function G(a){k=[];for(d=0,o=a.length;d<o;d++)k[d]=a[d];return k}var c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v=/#([\w\-]+)/,w=/\.[\w\-]+/g,x=/^#([\w\-]+$)/,y=/^\.([\w\-]+)$/,z=/^([\w\-]+)$/,A=/^([\w]+)?\.([\w\-])+$/,B=b.documentElement,C=/\s(?![\s\w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^'"]*\])/,D=/^([a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/,E=/\[([\w\-]+)(?:([\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/,F=new RegExp(D.source+"("+E.source+")?"),H=function(){this.c={}};H.prototype={g:function(a){return this.c[a]||undefined},s:function(a,b){this.c[a]=b;return b}};var I=new H,J=new H,K=new H,L=new H,S="compareDocumentPosition"in B?function(a,b){return(b.compareDocumentPosition(a)&16)==16}:"contains"in B?function(a,b){return b!==a&&b.contains(a)}:function(a,b){while(a=a.parentNode)if(a===b)return 1;return 0},W=function(){if(b.querySelector&&b.querySelectorAll)return U;return function(a,c){c=typeof c=="string"?W(c)[0]:c||b;if(!c)return[];var d,f=[],g=[],i;if(h=T(a,c))return h;if(h=a.match(A)){s=c.getElementsByTagName(h[1]||"*"),k=I.g(h[2])||I.s(h[2],new RegExp("(^|\\s+)"+h[2]+"(\\s+|$)"));for(d=s.length,e=0;d--;)k.test(s[d].className)&&(f[e++]=s[d]);return f}for(s=a.split(","),d=s.length;r=s[--d];)g[d]=R(r);for(d=g.length;u=g[--d];){var j=u;if(c!==b){j=[];for(e=u.length;i=u[--e];)S(i,c)&&j.push(i)}f=f.concat(j)}return V(f)}}(),X=a.qwery;W.noConflict=function(){a.qwery=X;return this},a.qwery=W}(this,document)
+!function(a,b){function V(a){var b=[],c,d;label:for(c=0;c<a.length;c++){for(d=0;d<b.length;d++)if(b[d]==a[c])continue label;b[b.length]=a[c]}return b}function U(a,c){c=typeof c=="string"?U(c)[0]:c||b;if(!c)return[];if(h=T(a,c))return h;if(b.getElementsByClassName&&(h=a.match(y)))return G(c.getElementsByClassName(h[1]));return G(c.querySelectorAll(a))}function T(a,c){if(h=a.match(x))return(m=b.getElementById(h[1]))?[m]:[];if(h=a.match(z))return G(c.getElementsByTagName(h[1]));return!1}function R(a){var b=[],c=[],d,g=L.g(a)||L.s(a,a.split(C));g=g.slice(0);if(!g.length)return b;b=O(g);if(!g.length)return b;for(e=b.length,f=0;e--;){n=b[e],j=n;for(d=g.length;d--;)parents:while(j!==B&&(j=j.parentNode))if(p=N.apply(j,M(g[d])))break parents;p&&(c[f++]=n)}return c}function Q(a,b,c){switch(a){case"=":return b==c;case"^=":return b.match(K.g("^="+c)||K.s("^="+c,new RegExp("^"+P(c))));case"$=":return b.match(K.g("$="+c)||K.s("$="+c,new RegExp(P(c)+"$")));case"*=":return b.match(K.g(c)||K.s(c,new RegExp(P(c))));case"~=":return b.match(K.g("~="+c)||K.s("~="+c,new RegExp("(?:^|\\s+)"+P(c)+"(?:\\s+|$)")));case"|=":return b.match(K.g("|="+c)||K.s("|="+c,new RegExp("^"+P(c)+"(-|$)")))}return!1}function P(a){return J.g(a)||J.s(a,a.replace(/([\.\*\+\?\^\$\{\}\(\)\|\[\]\/\\])/g,"\\$1"))}function O(a){var c=[],d=a.pop(),e=M(d),f=e[1]||"*",g,i,j,k=a.length&&(h=a[0].match(x))?b.getElementById(h[1]):b;if(!k)return c;j=k.getElementsByTagName(f);for(g=0,i=j.length;g<i;g++)m=j[g],(r=N.apply(m,e))&&c.push(r);return c}function N(a,b,c,e,f,g,h){var j,k,l;if(b&&this.tagName.toLowerCase()!==b)return!1;if(c&&(j=c.match(v))&&j[1]!==this.id)return!1;if(c&&(q=c.match(w)))for(d=q.length;d--;){k=q[d].slice(1);if(!(I.g(k)||I.s(k,new RegExp("(^|\\s+)"+k+"(\\s+|$)"))).test(this.className))return!1}if(e&&!h){i=this.attributes;for(l in i)if(Object.prototype.hasOwnProperty.call(i,l)&&(i[l].name||l)==f)return this}if(e&&!Q(g,this.getAttribute(f)||"",h))return!1;return this}function M(a){return a.match(F)}function G(a){k=[];for(d=0,o=a.length;d<o;d++)k[d]=a[d];return k}var c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v=/#([\w\-]+)/,w=/\.[\w\-]+/g,x=/^#([\w\-]+$)/,y=/^\.([\w\-]+)$/,z=/^([\w\-]+)$/,A=/^([\w]+)?\.([\w\-])+$/,B=b.documentElement,C=/\s(?![\s\w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^'"]*\])/,D=/^([a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/,E=/\[([\w\-]+)(?:([\|\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/,F=new RegExp(D.source+"("+E.source+")?"),H=function(){this.c={}};H.prototype={g:function(a){return this.c[a]||undefined},s:function(a,b){return this.c[a]=b}};var I=new H,J=new H,K=new H,L=new H,S="compareDocumentPosition"in B?function(a,b){return(b.compareDocumentPosition(a)&16)==16}:"contains"in B?function(a,b){return b!==a&&b.contains(a)}:function(a,b){while(a=a.parentNode)if(a===b)return 1;return 0},W=function(){if(b.querySelector&&b.querySelectorAll)return U;return function(a,c){c=typeof c=="string"?W(c)[0]:c||b;if(!c)return[];var d,f=[],g=[],i;if(h=T(a,c))return h;if(h=a.match(A)){s=c.getElementsByTagName(h[1]||"*"),k=I.g(h[2])||I.s(h[2],new RegExp("(^|\\s+)"+h[2]+"(\\s+|$)"));for(d=s.length,e=0;d--;)k.test(s[d].className)&&(f[e++]=s[d]);return f}for(s=a.split(","),d=s.length;d--;)g[d]=R(s[d]);for(d=g.length;u=g[--d];){var j=u;if(c!==b){j=[];for(e=u.length;i=u[--e];)S(i,c)&&j.push(i)}f=f.concat(j)}return V(f)}}(),X=a.qwery;W.noConflict=function(){a.qwery=X;return this},a.qwery=W}(this,document)
View
20 src/qwery.js
@@ -11,7 +11,7 @@
html = doc.documentElement,
tokenizr = /\s(?![\s\w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^'"]*\])/,
simple = /^([a-z0-9]+)?(?:([\.\#]+[\w\-\.#]+)?)/,
- attr = /\[([\w\-]+)(?:([\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/,
+ attr = /\[([\w\-]+)(?:([\|\^\$\*\~]?\=)['"]?([ \w\-\/\?\&\=\:\.\(\)\!,@#%<>\{\}\$\*\^]+)["']?)?\]/,
chunker = new RegExp(simple.source + '(' + attr.source + ')?');
function array(ar) {
@@ -22,7 +22,6 @@
return r;
}
-
var cache = function () {
this.c = {};
};
@@ -31,8 +30,7 @@
return this.c[k] || undefined;
},
s: function (k, v) {
- this.c[k] = v;
- return v;
+ return this.c[k] = v;
}
};
@@ -76,8 +74,8 @@
}
function loopAll(tokens) {
- var r = [], token = tokens.pop(), intr = q(token), tag = intr[1] || '*', i, l, els;
- var root = tokens.length && (m = tokens[0].match(idOnly)) ? doc.getElementById(m[1]) : doc;
+ var r = [], token = tokens.pop(), intr = q(token), tag = intr[1] || '*', i, l, els,
+ root = tokens.length && (m = tokens[0].match(idOnly)) ? doc.getElementById(m[1]) : doc;
if (!root) {
return r;
}
@@ -102,11 +100,13 @@
case '^=':
return actual.match(attrCache.g('^=' + val) || attrCache.s('^=' + val, new RegExp('^' + clean(val))));
case '$=':
- return actual.match(attrCache.g('$=' + val) || attrCache.s('$=' + val, new RegExp('$' + clean(val))));
+ return actual.match(attrCache.g('$=' + val) || attrCache.s('$=' + val, new RegExp(clean(val) + '$')));
case '*=':
return actual.match(attrCache.g(val) || attrCache.s(val, new RegExp(clean(val))));
case '~=':
return actual.match(attrCache.g('~=' + val) || attrCache.s('~=' + val, new RegExp('(?:^|\\s+)' + clean(val) + '(?:\\s+|$)')));
+ case '|=':
+ return actual.match(attrCache.g('|=' + val) || attrCache.s('|=' + val, new RegExp('^' + clean(val) + '(-|$)')));
}
return false;
}
@@ -148,7 +148,7 @@
return container !== element && container.contains(element);
} :
function (element, container) {
- while ((element = element.parentNode)) {
+ while (element = element.parentNode) {
if (element === container) {
return 1;
}
@@ -216,8 +216,8 @@
}
return result;
}
- for (items = selector.split(','), i = items.length; item = items[--i];) {
- collections[i] = _qwery(item);
+ for (items = selector.split(','), i = items.length; i--;) {
+ collections[i] = _qwery(items[i]);
}
for (i = collections.length; collection = collections[--i];) {
var ret = collection;
View
5 tests/index.html
@@ -30,6 +30,11 @@
<div id="attr-test1" -data-attr></div>
<div id="attr-test2" -data-attr></div>
<div id="attr-test3" class="found you" -data-attr title="whatup duders"></div>
+ <div id="attributes">
+ <div test="one" unique-test="baz" id="attr-test-1"></div>
+ <div test="two-foo" id="attr-test-2"></div>
+ <div test=" three " id="attr-test-3"></div>
+ </div>
<div>
<div class="tokens" title="one" id="token-one"></div>
<div class="tokens" title="one two" id="token-two"></div>
View
47 tests/tests.js
@@ -64,6 +64,53 @@ sink('CSS 2', function (test, ok) {
});
+sink('attribute selectors', function (test, ok) {
+
+ /* CSS 2 SPEC */
+
+ test('[attr]', 1, function () {
+ var expected = document.getElementById('attr-test-1');
+ ok(Q('#attributes div[unique-test]')[0] == expected, 'found attribute with [attr]');
+ });
+
+ test('[attr=val]', 3, function () {
+ var expected = document.getElementById('attr-test-2');
+ ok(Q('#attributes div[test="two-foo"]')[0] == expected, 'found attribute with =');
+ ok(Q("#attributes div[test='two-foo']")[0] == expected, 'found attribute with =');
+ ok(Q('#attributes div[test=two-foo]')[0] == expected, 'found attribute with =');
+ });
+
+ test('[attr~=val]', 1, function () {
+ var expected = document.getElementById('attr-test-3');
+ ok(Q('#attributes div[test~=three]')[0] == expected, 'found attribute with ~=');
+ });
+
+ test('[attr|=val]', 2, function () {
+ var expected = document.getElementById('attr-test-2');
+ ok(Q('#attributes div[test|="two-foo"]')[0] == expected, 'found attribute with |=');
+ ok(Q('#attributes div[test|=two]')[0] == expected, 'found attribute with |=');
+ });
+
+ /* CSS 3 SPEC */
+
+ test('[attr^=val]', 1, function () {
+ var expected = document.getElementById('attr-test-2');
+ ok(Q('#attributes div[test^=two]')[0] == expected, 'found attribute with ^=');
+ });
+
+ test('[attr$=val]', 1, function () {
+ var expected = document.getElementById('attr-test-2');
+ ok(Q('#attributes div[test$=foo]')[0] == expected, 'found attribute with $=');
+ });
+
+ test('[attr*=val]', 1, function () {
+ var expected = document.getElementById('attr-test-3');
+ ok(Q('#attributes div[test*=hree]')[0] == expected, 'found attribute with *=');
+ });
+
+});
+
+
sink('tokenizer', function (test, ok) {
test('should not get weird tokens', 5, function () {
Please sign in to comment.
Something went wrong with that request. Please try again.