Skip to content

Commit

Permalink
- updated Slick.
Browse files Browse the repository at this point in the history
  • Loading branch information
kamicane committed May 6, 2010
1 parent 02f557b commit 61a42a6
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 98 deletions.
139 changes: 78 additions & 61 deletions Source/Slick/Slick.Finder.js
Expand Up @@ -8,6 +8,8 @@ requires: Slick.Parser
*/

(function(){

var exports = this;

var local = {};

Expand Down Expand Up @@ -176,10 +178,8 @@ local.search = function(context, expression, append, first){

// setup

var parsed, i, l;
var parsed, i;

this.positions = {};
this.positionsReverse = {};
var uniques = this.uniques = {};

if (this.document !== (context.ownerDocument || context)) this.setDocument(context);
Expand Down Expand Up @@ -212,19 +212,25 @@ local.search = function(context, expression, append, first){
} else { // other junk
return found;
}


// cache elements for the nth selectors

this.posNTH = {};
this.posNTHLast = {};
this.posNTHType = {};
this.posNTHTypeLast = {};

// should sort if there are nodes in append and if you pass multiple expressions.
// should remove duplicates if append already has items
var shouldUniques = !!(append && append.length);

// if append is null and there is only a single selector with one expression use pushArray, else use pushUID
this.push = this.pushUID;
if (!shouldUniques && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) this.push = this.pushArray;
this.push = (!shouldUniques && (first || (parsed.length == 1 && parsed.expressions[0].length == 1))) ? this.pushArray : this.pushUID;

if (found == null) found = [];

// avoid duplicating items already in the append array
if (shouldUniques) for (i = 0, l = found.length; i < l; i++) this.uniques[this.getUID(found[i])] = true;
if (shouldUniques) for (i = found.length; i--;) this.uniques[this.getUID(found[i])] = true;

// default engine

Expand Down Expand Up @@ -321,35 +327,38 @@ local.parseNTHArgument = function(argument){
return (this.cacheNTH[argument] = parsed);
};

local.nthPseudo = function(child, sibling, positions, node, argument, nodeName){
var uid = this.getUID(node);
if (!this[positions][uid]){
var parent = node.parentNode;
if (!parent) return false;
var el = parent[child], count = 1;
if (nodeName){
do {
if (el.nodeName !== nodeName) continue;
this[positions][this.getUID(el)] = count++;
} while (el !== node && (el = el[sibling]));
local.createNTHPseudo = function(child, sibling, positions, ofType){
return function(node, argument){
var uid = this.getUID(node);
if (!this[positions][uid]){
var parent = node.parentNode;
if (!parent) return false;
var el = parent[child], count = 1;
if (ofType){
var nodeName = node.nodeName;
do {
if (el.nodeName !== nodeName) continue;
this[positions][this.getUID(el)] = count++;
} while ((el = el[sibling]));
} else {
do {
if (el.nodeType !== 1) continue;
this[positions][this.getUID(el)] = count++;
} while ((el = el[sibling]));
}
}
argument = argument || 'n';
var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument);
if (!parsed) return false;
var a = parsed.a, b = parsed.b, pos = this[positions][uid];
if (a == 0) return b == pos;
if (a > 0){
if (pos < b) return false;
} else {
do {
if (el.nodeType !== 1) continue;
this[positions][this.getUID(el)] = count++;
} while (el !== node && (el = el[sibling]));
if (b < pos) return false;
}
}
argument = argument || 'n';
var parsed = this.cacheNTH[argument] || this.parseNTHArgument(argument);
if (!parsed) return false;
var a = parsed.a, b = parsed.b, pos = this[positions][uid];
if (a == 0) return b == pos;
if (a > 0){
if (pos < b) return false;
} else {
if (b < pos) return false;
}
return ((pos - b) % a) == 0;
return ((pos - b) % a) == 0;
};
};

local.pushArray = function(node, tag, id, selector, classes, attributes, pseudos){
Expand Down Expand Up @@ -389,12 +398,16 @@ local.matchPseudo = function(node, name, argument){
};

local.matchSelector = function(node, tag, id, parts, classes, attributes, pseudos){
if (tag && tag == '*' && (node.nodeType != 1 || node.nodeName.charCodeAt(0) == 47)) return false; // Fix for comment nodes and closed nodes
if (tag && tag != '*' && (!node.nodeName || node.nodeName != tag)) return false;
if (tag){
if (tag == '*'){
if (node.nodeName < '@') return false; // Fix for comment nodes and closed nodes
} else {
if (node.nodeName != tag) return false;
}
}
if (id && node.getAttribute('id') != id) return false;
if (parts) for (var i = 0, l = parts.length, part, cls; i < l; i++){
part = parts[i];
if (!part) continue;
if (part.type == 'class' && classes !== false){
cls = ('className' in node) ? node.className : node.getAttribute('class');
if (!(cls && part.regexp.test(cls))) return false;
Expand Down Expand Up @@ -541,8 +554,7 @@ var pseudos = {
},

'contains': function(node, text){
var inner = node.innerText || node.textContent || '';
return (inner) ? inner.indexOf(text) > -1 : false;
return (node.innerText || node.textContent || '').indexOf(text) > -1;
},

'first-child': function(node){
Expand All @@ -563,28 +575,32 @@ var pseudos = {
return true;
},

'nth-child': function(node, argument){
return this.nthPseudo('firstChild', 'nextSibling', 'positions', node, argument);
},
'nth-child': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTH'),

'nth-last-child': function(node, argument){
return this.nthPseudo('lastChild', 'previousSibling', 'positionsReverse', node, argument);
},
'nth-last-child': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHLast'),

'nth-of-type': function(node, argument){
return this.nthPseudo('firstChild', 'nextSibling', 'positions', node, argument, node.nodeName);
},
'nth-of-type': local.createNTHPseudo('firstChild', 'nextSibling', 'posNTHType', true),

'nth-last-of-type': local.createNTHPseudo('lastChild', 'previousSibling', 'posNTHTypeLast', true),

'nth-last-of-type': function(node, argument){
return this.nthPseudo('lastChild', 'previousSibling', 'positionsReverse', node, argument, node.nodeName);
'first-of-type': function(node){
var nodeName = node.nodeName;
while ((node = node.previousSibling)) if (node.nodeName === nodeName) return false;
return true;
},

'first-of-type': function(node, argument){
return this['pseudo:nth-of-type'](node, '1');
'last-of-type': function(node){
var nodeName = node.nodeName;
while ((node = node.nextSibling)) if (node.nodeName === nodeName) return false;
return true;
},

'last-of-type': function(node, argument){
return this['pseudo:nth-last-of-type'](node, '1');
'only-of-type': function(node){
var prev = node, nodeName = node.nodeName;
while ((prev = prev.previousSibling)) if (prev.nodeName === nodeName) return false;
var next = node;
while ((next = next.nextSibling)) if (next.nodeName === nodeName) return false;
return true;
},

// custom pseudos
Expand Down Expand Up @@ -674,7 +690,7 @@ local.override(/./, function(expression, found, first){ //querySelectorAll overr
var i, hasOthers = !!(found.length);

if (local.starSelectsClosedQSA) for (i = 0; node = nodes[i++];){
if (node.nodeName.charCodeAt(0) != 47 && (!hasOthers || !local.uniques[local.getUIDHTML(node)])) found.push(node);
if (node.nodeName > '@' && (!hasOthers || !local.uniques[local.getUIDHTML(node)])) found.push(node);
} else for (i = 0; node = nodes[i++];){
if (!hasOthers || !local.uniques[local.getUIDHTML(node)]) found.push(node);
}
Expand Down Expand Up @@ -704,7 +720,7 @@ local.override(/^[\w-]+$|^\*$/, function(expression, found, first){ // tag overr
});

local.override(/^\.[\w-]+$/, function(expression, found, first){ // class override
if (local.isXMLDocument) return false;
if (local.isXMLDocument || (!this.getElementsByClassName && this.querySelectorAll)) return false;

var nodes, node, i, hasOthers = !!(found && found.length), className = expression.substring(1);
if (this.getElementsByClassName && !local.brokenGEBCN){
Expand All @@ -717,7 +733,8 @@ local.override(/^\.[\w-]+$/, function(expression, found, first){ // class overri
var matchClass = new RegExp('(^|\\s)'+ Slick.escapeRegExp(className) +'(\\s|$)');
nodes = this.getElementsByTagName('*');
for (i = 0; node = nodes[i++];){
if (!node.className || !matchClass.test(node.className)) continue;
className = node.className;
if (!className || !matchClass.test(className)) continue;
if (first) return node;
if (!hasOthers || !local.uniques[local.getUIDHTML(node)]) found.push(node);
}
Expand All @@ -733,7 +750,7 @@ local.override(/^#[\w-]+$/, function(expression, found, first){ // ID override
if (!el) return found;
if (local.idGetsName && el.getAttributeNode('id').nodeValue != id) return false;
if (first) return el || null;
var hasOthers = !!(found.length) ;
var hasOthers = !!(found.length);
if (!hasOthers || !local.uniques[local.getUIDHTML(el)]) found.push(el);
if (hasOthers) local.sort(found);
return true;
Expand All @@ -743,7 +760,7 @@ if (typeof document != 'undefined') local.setDocument(document);

// Slick

var Slick = local.Slick = this.Slick || {};
var Slick = local.Slick = exports.Slick || {};

Slick.version = '0.9dev';

Expand Down Expand Up @@ -836,6 +853,6 @@ Slick.isXML = local.isXML;

// export Slick

if (!this.Slick) this.Slick = Slick;
if (!exports.Slick) exports.Slick = Slick;

})();
}).apply((typeof exports != 'undefined') ? exports : this);
68 changes: 31 additions & 37 deletions Source/Slick/Slick.Parser.js
Expand Up @@ -16,7 +16,8 @@ var parsed,
partIndex,
reversed,
cache = {},
reverseCache = {};
reverseCache = {},
reUnescape = /\\/g;

var parse = function(expression, isReversed){
expression = ('' + expression).replace(/^\s+|\s+$/g, '');
Expand Down Expand Up @@ -129,65 +130,61 @@ function parser(
if (reversed && currentSeparator[combinatorIndex])
currentSeparator[combinatorIndex].reverseCombinator = reverseCombinator(combinator);
currentSeparator[++combinatorIndex] = {combinator: combinator, tag: '*', parts: []};
partIndex = 0;
partIndex = -1;
}

var currentParsed = parsed.expressions[separatorIndex][combinatorIndex];

if (tagName){
currentParsed.tag = tagName.replace(/\\/g,'');
return '';
currentParsed.tag = tagName.replace(reUnescape, '');

} else if (id){
currentParsed.id = id.replace(/\\/g,'');
return '';
currentParsed.id = id.replace(reUnescape, '');

} else if (className){
className = className.replace(/\\/g,'');
className = className.replace(reUnescape, '');

if (!currentParsed.classes) currentParsed.classes = [className];
else currentParsed.classes.push(className);

currentParsed.parts[partIndex] = {
currentParsed.parts[++partIndex] = {
type: 'class',
value: className,
regexp: new RegExp('(^|\\s)' + escapeRegExp(className) + '(\\s|$)')
};
partIndex++;

} else if (pseudoClass){
if (!currentParsed.pseudos) currentParsed.pseudos = [];

var value = pseudoClassValue || null;
if (value) value = value.replace(/\\/g,'');

currentParsed.pseudos.push(currentParsed.parts[partIndex] = {
pseudoClassValue = pseudoClassValue ? pseudoClassValue.replace(reUnescape, '') : null;

currentParsed.pseudos.push(currentParsed.parts[++partIndex] = {
type: 'pseudo',
key: pseudoClass.replace(/\\/g,''),
value: value
key: pseudoClass.replace(reUnescape, ''),
value: pseudoClassValue
});
partIndex++;

} else if (attributeKey){
if (!currentParsed.attributes) currentParsed.attributes = [];

var key = attributeKey.replace(/\\/g,'');
var operator = attributeOperator;
var attribute = (attributeValue || '').replace(/\\/g,'');
attributeKey = attributeKey.replace(reUnescape, '');
attributeValue = (attributeValue || '').replace(reUnescape, '');

var test, regexp;

switch (operator){
case '^=' : regexp = new RegExp( '^'+ escapeRegExp(attribute) ); break;
case '$=' : regexp = new RegExp( escapeRegExp(attribute) +'$' ); break;
case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attribute) +'(\\s|$)' ); break;
case '|=' : regexp = new RegExp( '^'+ escapeRegExp(attribute) +'(-|$)' ); break;
switch (attributeOperator){
case '^=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) ); break;
case '$=' : regexp = new RegExp( escapeRegExp(attributeValue) +'$' ); break;
case '~=' : regexp = new RegExp( '(^|\\s)'+ escapeRegExp(attributeValue) +'(\\s|$)' ); break;
case '|=' : regexp = new RegExp( '^'+ escapeRegExp(attributeValue) +'(-|$)' ); break;
case '=' : test = function(value){
return attribute == value;
return attributeValue == value;
}; break;
case '*=' : test = function(value){
return value && value.indexOf(attribute) > -1;
return value && value.indexOf(attributeValue) > -1;
}; break;
case '!=' : test = function(value){
return attribute != value;
return attributeValue != value;
}; break;
default : test = function(value){
return !!value;
Expand All @@ -198,14 +195,13 @@ function parser(
return value && regexp.test(value);
};

currentParsed.attributes.push(currentParsed.parts[partIndex] = {
currentParsed.attributes.push(currentParsed.parts[++partIndex] = {
type: 'attribute',
key: key,
operator: operator,
value: attribute,
key: attributeKey,
operator: attributeOperator,
value: attributeValue,
test: test
});
partIndex++;

}

Expand All @@ -214,16 +210,14 @@ function parser(

// Slick NS

var Slick = this.Slick || {};
var Slick = exports.Slick || {};

Slick.parse = function(expression){
return parse(expression);
};

Slick.escapeRegExp = escapeRegExp;

// export Slick

if (!this.Slick) this.Slick = Slick;
if (!exports.Slick) exports.Slick = Slick;

})();
}).apply((typeof exports != 'undefined') ? exports : this);

0 comments on commit 61a42a6

Please sign in to comment.