Permalink
Browse files

Adding the pseudo-class selectors. The built file doesnt contain all …

…the pseudo-classes but checkout the readme file to build it with them. More specs and better docs.
  • Loading branch information...
fabiomcosta committed Feb 20, 2011
1 parent 8582e26 commit 947a4ffdc6689e01096aae81cc53863f90856c60
Showing with 169 additions and 56 deletions.
  1. +14 −10 Makefile
  2. +23 −0 README.md
  3. +4 −3 dist/uSelector.js
  4. +24 −24 src/uSelector.js
  5. +49 −0 src/uSelectorPseudoClasses.js
  6. +2 −1 tests/index.html
  7. +53 −18 tests/specs.js
View
@@ -1,22 +1,30 @@
-
MODULE_NAME = uSelector
UNCOMPRESSED = dist/${MODULE_NAME}.uncompressed.js
-MODULES = src/uSelector.js
+CORE = src/uSelector.js
+ALL_MODULES = \
+ $(CORE) \
+ src/uSelectorPseudoClasses.js
build: compress
@echo "Removing unnecessary files..."
@cd dist;\
- rm $$(ls -Sr | egrep -v $$(ls -Sr | head -1));\
+ rm $$(ls | egrep -v $$(ls -S | tail -1));\
mv * ${MODULE_NAME}.js;\
- echo "Resulting file has`ls -lh *.js | tail -1 | cut -d " " -f 7,9`.";\
+ echo "Resulting file has `ls -lh *.js | tail -1 | awk '{ print $$5 }'`.";\
gzip -c ${MODULE_NAME}.js > ${MODULE_NAME}.js.gzip;\
- echo "Resulting file gzipped has`ls -lh *.gzip | tail -1 | cut -d " " -f 7,9`.";\
+ echo "Resulting file gzipped has `ls -lh *.gzip | tail -1 | awk '{ print $$5 }'`.";\
rm -rf *.gzip
compress:
@rm -rf dist
@mkdir -p dist
- @cat ${MODULES} > ${UNCOMPRESSED}
+ @\
+ if [ "$(all)" ]; then\
+ MODULES="$(ALL_MODULES)";\
+ else\
+ MODULES="$(CORE)";\
+ fi;\
+ cat $$MODULES > ${UNCOMPRESSED}
@echo "Compressing with google compiler..."
@java -jar assets/compiler.jar --jscomp_warning undefinedVars --charset utf8 --compilation_level ADVANCED_OPTIMIZATIONS --js ${UNCOMPRESSED} --js_output_file dist/${MODULE_NAME}.cc.js
@echo "Compressing with yui compressor..."
@@ -27,7 +35,3 @@ compress:
test:
@open tests/index.html
-push: build
- @git commit -a
- @git push
-
View
@@ -17,11 +17,34 @@ It's based on [Slick](https://github.com/mootools/slick), the selector used on t
* multiple expressions (expressions with comma, ex: "div, span")
* attribute (ex: "a[title='title']")
+### Suported with the uSelectorPseudoClasses module
+* :empty
+* :first-child
+* :last-child
+* :only-child
+* :first-of-type
+* :last-of-type
+* :only-of-type
+* :disabled
+* :checked
+* :selected
+
+note: To build with these pseudo-selectors included do `make build all=true`
+
How to use
----------
$u('your-selector') -> returns an array of nodes that match the selector
+Create your own pseudo-class
+--------------------------------
+
+$u.pseudo['your-custom-pseudo'] = function(node){
+ return boolean;
+};
+
+It should return true if the passed node fits the behavior of your pseudo. see the [[ "src/uSelectorPseudoClasses.js" ]]
+
Examples
--------
View

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
View
@@ -7,7 +7,7 @@
*/
(function(global, document){
-
+
var elements,
parsed,
parsedClasses,
@@ -16,9 +16,9 @@
context,
currentDocument,
reTrim = /^\s+|\s+$/g;
-
+
var supports_querySelectorAll = !!document.querySelectorAll;
-
+
var $u = function(selector, _context, append){
elements = append || [];
context = _context || $u.context;
@@ -32,10 +32,10 @@
currentDocument = context.ownerDocument || context;
parse(selector.replace(reTrim, ''));
find();
-
+
return elements;
};
-
+
var matchSelector = function(node){
if (parsed.tag){
var nodeName = node.nodeName.toUpperCase();
@@ -45,55 +45,55 @@
if (nodeName != parsed.tag) return false;
}
}
-
+
if (parsed.id && node.getAttribute('id') != parsed.id){
return false;
}
-
+
if ((parsedClasses = parsed.classes)){
var className = (' ' + node.className + ' ');
for (var i = parsedClasses.length; i--;){
if (className.indexOf(' ' + parsedClasses[i] + ' ') < 0) return false;
}
}
-
+
if ((parsedPseudos = parsed.pseudos)){
for (var i = parsedPseudos.length; i--;){
var pseudoClass = pseudos[parsedPseudos[i]];
- if (!(pseudoClass && pseudoClass(node))) return false;
+ if (!(pseudoClass && pseudoClass.call($u, node))) return false;
}
}
-
+
return true;
};
-
+
var find = function(){
-
+
var parsedId = parsed.id,
merge = ((parsedId && parsed.tag || parsed.classes || parsed.pseudos)
|| (!parsedId && (parsed.classes || parsed.pseudos))) ?
arrayFilterAndMerge : arrayMerge;
-
+
if (parsedId){
-
+
var el = currentDocument.getElementById(parsedId);
if (el && (currentDocument === context || contains(el))){
merge([el]);
}
-
+
} else {
-
+
merge(context.getElementsByTagName(parsed.tag || '*'));
-
+
}
-
+
};
-
+
var parse = function(selector){
parsed = {};
while ((selector = selector.replace(/([#.:])?([^#.:]*)/, parser))){};
};
-
+
var parser = function(all, simbol, name){
if (!simbol){
parsed.tag = name.toUpperCase();
@@ -114,7 +114,7 @@
}
return '';
};
-
+
var slice = Array.prototype.slice;
var arrayFrom = function(collection){
elements = slice.call(collection, 0);
@@ -129,20 +129,20 @@
} catch(e) {
arrayFrom = arrayMerge;
}
-
+
var arrayFilterAndMerge = function(found){
for (var i = 0, node; node = found[i++];){
if (matchSelector(node)) elements.push(node);
}
};
-
+
var contains = function(node){
do {
if (node === context) return true;
} while ((node = node.parentNode));
return false;
};
-
+
$u['pseudos'] = pseudos;
$u['context'] = document;
global['uSelector'] = $u;
@@ -0,0 +1,49 @@
+(function(){
+
+ var pseudos = {
+ empty: function(node){
+ var child = node.firstChild;
+ return !(child && child.nodeType == 1) && !(node.innerText || node.textContent || '').length;
+ },
+ 'first-child': function(node){
+ while ((node = node.previousSibling)) if (node.nodeType == 1) return false;
+ return true;
+ },
+ 'last-child': function(node){
+ while ((node = node.nextSibling)) if (node.nodeType == 1) return false;
+ return true;
+ },
+ 'only-child': function(node){
+ return this.pseudos['first-child'](node) && this.pseudos['last-child'](node);
+ },
+ 'first-of-type': function(node){
+ var nodeName = node.nodeName;
+ while ((node = node.previousSibling)) if (node.nodeName == nodeName) return false;
+ return true;
+ },
+ 'last-of-type': function(node){
+ var nodeName = node.nodeName;
+ while ((node = node.nextSibling)) if (node.nodeName == nodeName) return false;
+ return true;
+ },
+ 'only-of-type': function(node){
+ return this.pseudos['first-of-type'](node) && this.pseudos['last-of-type'](node);
+ },
+ disabled: function(node){
+ return node.disabled;
+ },
+ checked: function(node){
+ return node.checked || node.selected;
+ },
+ selected: function(node){
+ return node.selected;
+ }
+ };
+
+ for (var pseudo in pseudos){
+ $u.pseudos[pseudo] = pseudos[pseudo];
+ }
+
+})();
+
+
View
@@ -7,7 +7,8 @@
<script type="text/javascript" src="../assets/jasmine-1.0.1/jasmine-html.js"></script>
<!-- include source files here... -->
- <script type="text/javascript" src="../src/uselector.js"></script>
+ <script type="text/javascript" src="../src/uSelector.js"></script>
+ <script type="text/javascript" src="../src/uSelectorPseudoClasses.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="specs.js"></script>
View
@@ -5,55 +5,90 @@ describe('Micro Selector', function() {
var $u = uSelector;
$u.context = context.document;
+ beforeEach(function(){
+ this.addMatchers({
+ toFind: function(n){
+ var found = $u(this.actual).length;
+ this.message = function() {
+ return [
+ "Expected " + this.actual + " to find " + n + " but found " + found,
+ "Expected " + this.actual + " not to find " + n
+ ];
+ };
+ return found == n;
+ }
+ });
+ });
+
it('should select elements by id', function(){
- expect($u('#title').length).toEqual(1);
- expect($u('#other').length).toEqual(0);
- expect($u('#divid').length).toEqual(1);
- expect($u('#divid2').length).toEqual(1);
+ expect('#title').toFind(1);
+ expect('#other').toFind(0);
+ expect('#divid').toFind(1);
+ expect('#divid2').toFind(1);
expect($u('#divid', $u('#divid2')[0]).length).toEqual(0);
});
it('should select elements by tagName', function(){
var h2Collection = $u('h2');
expect(h2Collection instanceof Array).toEqual(true);
expect(h2Collection.length).toEqual(19);
- expect($u('ul').length).toEqual(22);
+ expect('ul').toFind(22);
expect($u('div', $u('#divid')[0]).length).toEqual(4);
});
it('should select elements by className', function(){
var classVcardCollection = $u('.vcard');
expect(classVcardCollection instanceof Array).toEqual(true);
expect(classVcardCollection.length).toEqual(5);
- expect($u('.pattern').length).toEqual(40);
- expect($u('.example').length).toEqual(43);
+ expect('.pattern').toFind(40);
+ expect('.example').toFind(43);
expect($u('.inner', $u('.wrapper')[0]).length).toEqual(1);
});
it('should select elements by tagName and id', function(){
- expect($u('h1#title').length).toEqual(1);
- expect($u('div#title').length).toEqual(0);
+ expect('h1#title').toFind(1);
+ expect('div#title').toFind(0);
});
it('should select elements by tagName and className', function(){
- expect($u('div.wrapper').length).toEqual(4);
- expect($u('b.wrapper').length).toEqual(1);
+ expect('div.wrapper').toFind(4);
+ expect('b.wrapper').toFind(1);
});
it('should select elements with untrimed selectors', function(){
- expect($u(' #title ').length).toEqual(1);
- expect($u(' ul ').length).toEqual(22);
- expect($u(' .example ').length).toEqual(43);
- expect($u(' h1#title ').length).toEqual(1);
- expect($u(' abbr.some#abbr-id.classes.here').length).toEqual(1);
+ expect(' #title ').toFind(1);
+ expect(' ul ').toFind(22);
+ expect(' .example ').toFind(43);
+ expect(' h1#title ').toFind(1);
+ expect(' abbr.some#abbr-id.classes.here').toFind(1);
});
it('should select elements with the added pseudo classes', function(){
$u.pseudos['contains-cheese'] = function(node){
return node.innerHTML.indexOf('cheese') > -1;
};
- expect($u('div:contains-cheese').length).toEqual(1);
- expect($u('div:non-existent-pseudo').length).toEqual(0);
+ expect('div:contains-cheese').toFind(1);
+ expect('div:non-existent-pseudo').toFind(0);
+ });
+
+ describe('Extra pseudo classes contained on the uSelectorPseudoClasses', function(){
+
+ it('should find elements by the defined pseudo-classes', function(){
+ expect('a:empty').toFind(30);
+
+ expect('p:first-child').toFind(54);
+ expect('p:last-child').toFind(19);
+ expect('p:only-child').toFind(3);
+
+ expect('p:first-of-type').toFind(57);
+ expect('p:last-of-type').toFind(57);
+ expect('p:only-of-type').toFind(15);
+
+ expect(':disabled').toFind(0);
+ expect(':checked').toFind(0);
+ expect(':selected').toFind(0);
+ });
+
});
});

0 comments on commit 947a4ff

Please sign in to comment.