Skip to content

Commit

Permalink
This is an experimental matcher for Slick. It's working pretty well o…
Browse files Browse the repository at this point in the history
…n ff4b8 and webkit (all the other browsers will work the old way).

Only problem for now is on :nth-child(2n|even) selectors, they are returning wrong results on webkit (ff4b8 is fine).
  • Loading branch information
fabiomcosta committed Jan 18, 2011
1 parent 872f6c4 commit 7b6e897
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 12 deletions.
31 changes: 23 additions & 8 deletions Source/Slick.Finder.js
Expand Up @@ -47,6 +47,7 @@ local.setDocument = function(document){
= this.brokenCheckedQSA
= this.brokenEmptyAttributeQSA
= this.isHTMLDocument
= this.nativeMatchesSelector
= false;

var starSelectsClosed, starSelectsComments,
Expand All @@ -64,9 +65,9 @@ local.setDocument = function(document){
} catch(e){};

if (this.isHTMLDocument){

testNode.style.display = 'none';

// IE returns comment nodes for getElementsByTagName('*') for some documents
testNode.appendChild(document.createComment(''));
starSelectsComments = (testNode.getElementsByTagName('*').length > 0);
Expand Down Expand Up @@ -114,19 +115,27 @@ local.setDocument = function(document){
} catch(e){};

this.brokenGEBCN = cachedGetElementsByClassName || brokenSecondClassNameGEBCN;

// Webkit dont return selected options on querySelectorAll
try {
testNode.innerHTML = '<select><option selected="selected">a</option></select>';
this.brokenCheckedQSA = (testNode.querySelectorAll(':checked').length == 0);
} catch(e){};

// IE returns incorrect results for attr[*^$]="" selectors on querySelectorAll
try {
testNode.innerHTML = '<a class=""></a>';
this.brokenEmptyAttributeQSA = (testNode.querySelectorAll('[class*=""]').length != 0);
} catch(e){};


this.nativeMatchesSelector = root.matchesSelector || root.msMatchesSelector || root.mozMatchesSelector || root.webkitMatchesSelector;

try {
this.nativeMatchesSelector.call(root, ':slick');
// if matchesSelector trows errors on incorrect sintaxes we can use it
this.nativeMatchesSelector = null;
} catch(e){}

}

root.removeChild(testNode);
Expand Down Expand Up @@ -395,6 +404,12 @@ local.matchNode = function(node, selector){
var parsed = this.Slick.parse(selector);
if (!parsed) return true;

if (this.isHTMLDocument && this.nativeMatchesSelector){
try {
return this.nativeMatchesSelector.call(node, parsed.normalized);
} catch(matchError) {}
}

// simple (single) selectors
var expressions = parsed.expressions, reversedExpressions, simpleExpCounter = 0, i;
for (i = 0; (currentExpression = expressions[i]); i++){
Expand All @@ -404,7 +419,7 @@ local.matchNode = function(node, selector){
simpleExpCounter++;
}
}

if (simpleExpCounter == parsed.length) return false;

var nodes = this.search(this.document, parsed), item;
Expand Down Expand Up @@ -534,7 +549,7 @@ var combinators = {
this['combinator:!~'](node, tag, id, classes, attributes, pseudos);
},

'!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document
'!': function(node, tag, id, classes, attributes, pseudos){ // all parent nodes up to document
while ((node = node.parentNode)) if (node !== this.document) this.push(node, tag, id, classes, attributes, pseudos);
},

Expand Down Expand Up @@ -750,7 +765,7 @@ local.override(/./, function(expression, found, first){ //querySelectorAll overr
this.setAttribute('id', id);
expression = '#' + id + ' ' + expression;
}

try {
if (first) return this.querySelector(expression) || null;
else nodes = this.querySelectorAll(expression);
Expand Down
15 changes: 11 additions & 4 deletions Source/Slick.Parser.js
Expand Up @@ -14,7 +14,8 @@ var parsed,
reversed,
cache = {},
reverseCache = {},
reUnescape = /\\/g;
reUnescape = /\\/g,
reNormalizeExpression = /\[([^=]+=)\s*([^'"\]]+?)\s*\]/g;

var parse = function(expression, isReversed){
if (expression == null) return null;
Expand All @@ -23,9 +24,15 @@ var parse = function(expression, isReversed){
reversed = !!isReversed;
var currentCache = (reversed) ? reverseCache : cache;
if (currentCache[expression]) return currentCache[expression];
parsed = {Slick: true, expressions: [], raw: expression, reverse: function(){
return parse(this.raw, true);
}};
parsed = {
Slick: true,
expressions: [],
raw: expression,
normalized: expression.replace(reNormalizeExpression, '[$1"$2"]'),
reverse: function(){
return parse(this.raw, true);
}
};
separatorIndex = -1;
while (expression != (expression = expression.replace(regexp, parser)));
parsed.length = parsed.expressions.length;
Expand Down

0 comments on commit 7b6e897

Please sign in to comment.