Skip to content
Browse files

0.1.3: major performance improvements

  • Loading branch information...
1 parent 648add5 commit 79feafafdf99cd08a2cd772b1b7f82718f2b3a1c @pyrsmk committed Oct 24, 2011
View
12 README.markdown
@@ -1,7 +1,10 @@
-Nut 0.1.2
+Nut 0.1.3
=========
-Nut is a concise query selector engine that just allows you to do extremely simple queries. These queries only accept ids, classes and tags with optional hierarchy.
+Nut is a concise query selector engine that just allows you to do extremely simple queries.
+
+Syntax
+------
Here's it can handle:
@@ -30,4 +33,7 @@ Of course, queries can have a context:
// Get nodes from the #foo context
nut('.bar p',nut('#foo'));
-And that's all you need to know ;)
+Performance
+-----------
+
+Nut, is faster than `querySelectorAll` (take a look at the benchmark) and then faster than all selector engines. But, nut doesn't implement request caching to avoid unnecessary code additions and performance loss: the user can easily keep a request and pass it as a context to another request.
View
23 benchmark/index.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+ <head>
+ <title>nut unit testing</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+ </head>
+ <body>
+ <div id="tests"></div>
+ <script src="../lib/consolelog.min.js" type="text/javascript"></script>
+ <script src="../lib/ready-20110918.min.js" type="text/javascript"></script>
+ <script src="../lib/benchmark-20111013.js" type="text/javascript"></script>
+ <script src="../src/nut.js" type="text/javascript"></script>
+ <script src="runner.js" type="text/javascript"></script>
+ <div id="foo">
+ <p></p>
+ <p class="bar">
+ <span></span>
+ <span></span>
+ </p>
+ <p></p>
+ </div>
+ </body>
+</html>
View
59 benchmark/runner.js
@@ -0,0 +1,59 @@
+domReady(function(){
+
+ var suite=new Benchmark.Suite;
+
+ // p
+ suite.add('[querySelectorAll] p',function(){
+ document.querySelectorAll('p');
+ })
+ .add('[nut] p',function(){
+ nut('p');
+ })
+
+ // #foo
+ .add('[querySelectorAll] #foo',function(){
+ document.querySelectorAll('#foo');
+ })
+ .add('[nut] #foo',function(){
+ nut('#foo');
+ })
+
+ // .bar from #foo context
+ .add('[querySelectorAll] .bar from #foo context',function(){
+ var foo=document.querySelectorAll('#foo'),
+ nodes=[],
+ bar,i,
+ j=foo.length,
+ k,l;
+ for(i=0;i<j;++i){
+ bar=foo[i].querySelectorAll('.bar');
+ l=bar.length;
+ for(k=0;k<l;++k){
+ nodes.push(bar[k]);
+ }
+ }
+ })
+ .add('[nut] .bar from #foo context',function(){
+ nut('.bar',nut('#foo'));
+ })
+
+ // #foo .bar span
+ .add('[querySelectorAll] #foo .bar span',function(){
+ document.querySelectorAll('#foo .bar span');
+ })
+ .add('[nut] #foo .bar span',function(){
+ nut('#foo .bar span');
+ })
+
+ // Display results
+ .on('complete',function(){
+ var j=this.length;
+ for(var i=0;i<j;++i){
+ log(this[i].toString());
+ }
+ })
+
+ // Run benchmarks
+ .run();
+
+});
View
2 build/Makefile
@@ -1,5 +1,5 @@
# npm install smoosh -g
smoosh:
smoosh run project.json
- smoosh run unit.json
+ smoosh run quality.json
uglifyjs -nc ../src/nut.js > ../nut.min.js
View
3 build/unit.json → build/quality.json
@@ -1,6 +1,7 @@
{
"JAVASCRIPT":{
- "unit":["../unit/runner.js"]
+ "unit":["../unit/runner.js"],
+ "benchmark":["../benchmark/runner.js"]
},
"JSHINT_OPTS":{
"boss" : true,
View
2,710 lib/benchmark-20111013.js
2,710 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
View
0 lib/ready-110918.min.js → lib/ready-20110918.min.js
File renamed without changes.
View
0 lib/sink-110925.js → lib/sink-20110925.js
File renamed without changes.
View
164 src/nut.js
@@ -1,36 +1,112 @@
/*
nut, the concise CSS selector engine
- Version : 0.1.2
+ Version : 0.1.3
Author : Aurélien Delogu (dev@dreamysource.fr)
URL : https://github.com/pyrsmk/nut
License : MIT
TODO
- [ ] cache
- [ ] benchmark against qwery
[/] lint
+ [ ] #foo,div syntax
*/
-this.nut=function(selectors,context){
- // No selectors or contains forbidden chars
- if(selectors.match(/^(\s*[#.]?\w+\s*)+$/)===null){
- return [];
- }
- // Init
- if(!context){
- context=[this.document];
- }
- if(context.length===undefined){
- context=[context];
- }
- var nodes;
- // Define a replacement getElementsByClassName function for IE<9
- var getNodesByClassName=function(name,context){
+
+(function(window,document){
+
+ /*
+ Select DOM nodes
+
+ Parameters
+ string selectors : CSS selectors
+ array, object contexts : context nodes
+
+ Return
+ array : found nodes
+ */
+ window.nut=function(selectors,contexts){
+ // No selectors or contains forbidden chars
+ if(!selectors.match(/^[#.\w\s]+$/)){
+ return [];
+ }
+ // Format
+ if(!contexts){
+ contexts=[this.document];
+ }
+ if(contexts.length===undefined){
+ contexts=[contexts];
+ }
+ // Init vars
+ var nodes=[],
+ elements,
+ nodelist,
+ node,
+ re_selectors=/\s+/,
+ re_tokens=/^([#.])?(.+)/,
+ tokens,
+ i=0,
+ j,k,l;
+ // Browse contexts
+ while(context=contexts[i++]){
+ // Set context
+ nodes.push(context);
+ // Browse selectors
+ selectors=selectors.split(re_selectors);
+ j=0;
+ while(selector=selectors[j++]){
+ // Split selector
+ tokens=selector.match(re_tokens);
+ // No tokens? Goodbye!
+ if(!tokens){
+ return [];
+ }
+ // Apply current selector to all current nodes
+ elements=[];
+ k=0;
+ while(node=nodes[k++]){
+ switch(tokens[1]){
+ // Get elements by class
+ case '.':
+ nodelist=node.getElementsByClassName?
+ node.getElementsByClassName(tokens[2]):
+ getNodesByClassName(tokens[2],node);
+ break;
+ // Get elements by id
+ case '#':
+ nodelist=[document.getElementById(tokens[2])];
+ break;
+ // Get elements by tag
+ default:
+ nodelist=node.getElementsByTagName(tokens[2]);
+ }
+ // Push new elements
+ l=0;
+ while(node=nodelist[l++]){
+ elements.push(node);
+ }
+ }
+ // Update nodes
+ nodes=elements;
+ }
+ }
+ return nodes;
+ };
+
+ /*
+ Define a getElementsByClassName replacement function for IE<9
+
+ Parameters
+ string name : class name
+ object context : context node
+
+ Return
+ array : found nodes
+ */
+ function getNodesByClassName(name,context){
// Init vars
var nodes=[],
j=context.childNodes.length,
classname;
- // Browe children
+ // Browse children
for(var i=0;i<j;++i){
if(classname=context.childNodes[i].className){
// Match the class
@@ -43,51 +119,5 @@ this.nut=function(selectors,context){
}
return nodes;
};
- // Browse context
- for(var i in context){
- // Try querySelectorAll method
- /*if(context[i].querySelectorAll){
- return context[i].querySelectorAll(selectors);
- }*/
- // Set context
- nodes=[context[i]];
- // Browse selectors
- selectors=selectors.split(/\s+/);
- for(var j in selectors){
- // Split selector
- var elements=[],
- nodelist,
- tokens=selectors[j].match(/^([#.])?(.+)/);
- // No tokens? Goodbye!
- if(!tokens){
- return [];
- }
- // Apply current selector to all current nodes
- for(var k in nodes){
- switch(tokens[1]){
- // Get elements by class
- case '.':
- nodelist=nodes[k].getElementsByClassName?
- nodes[k].getElementsByClassName(tokens[2]):
- getNodesByClassName(tokens[2],nodes[k]);
- break;
- // Get elements by id
- case '#':
- nodelist=[this.document.getElementById(tokens[2])];
- break;
- // Get elements by tag
- default:
- nodelist=nodes[k].getElementsByTagName(tokens[2]);
- }
- // Append new elements
- var m=nodelist.length;
- for(var l=0;l<m;++l){
- elements.push(nodelist[l]);
- }
- }
- // Update nodes
- nodes=elements;
- }
- }
- return nodes;
-};
+
+})(this,this.document);
View
6 unit/index.html
@@ -1,14 +1,14 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
-<html class="a b c">
+<html>
<head>
<title>nut unit testing</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<div id="tests"></div>
<script src="../lib/consolelog.min.js" type="text/javascript"></script>
- <script src="../lib/ready-110918.min.js" type="text/javascript"></script>
- <script src="../lib/sink-110925.js" type="text/javascript"></script>
+ <script src="../lib/ready-20110918.min.js" type="text/javascript"></script>
+ <script src="../lib/sink-20110925.js" type="text/javascript"></script>
<script src="../src/nut.js" type="text/javascript"></script>
<script src="runner.js" type="text/javascript"></script>
<div id="foo">
View
4 unit/runner.js
@@ -9,10 +9,10 @@ domReady(function(){
// #foo
nodes=nut('#foo');
ok(nodes.length==1 && (typeof nodes[0]=='object'),'#foo');
- // #foo .bar
+ // .bar from #foo context
nodes=nut('.bar',nut('#foo'));
ok(nodes.length==1 && (typeof nodes[0]=='object'),'.bar from #foo context');
- // #foo .bar
+ // .bar from #foo context
nodes=nut('.bar',nut('#foo')[0]);
ok(nodes.length==1 && (typeof nodes[0]=='object'),'.bar from #foo context');
// #foo .bar span

0 comments on commit 79feafa

Please sign in to comment.
Something went wrong with that request. Please try again.