git-svn-id: file:///tmp/snv/trunk@9 12951d8a-c33d-4b7c-b961-822215c816e1master
parent
3d33406796
commit
0aa71851ef
@ -1,7 +1,7 @@ |
||||
move to JSON data format -- done |
||||
XBL -- done |
||||
format JS/refactor JS/Use FUEL -- done |
||||
put license |
||||
caching/db, threading, XUL templates |
||||
new UI |
||||
caching/db, threading |
||||
new UI, icons, thumbnails |
||||
JQuery |
||||
put license |
||||
|
@ -0,0 +1,355 @@ |
||||
/* |
||||
JPath 1.0.3 - json equivalent to xpath |
||||
Copyright (C) 2007 Bryan English <bryan at bluelinecity dot com> |
||||
|
||||
This program is free software; you can redistribute it and/or |
||||
modify it under the terms of the GNU General Public License |
||||
as published by the Free Software Foundation; either version 2 |
||||
of the License, or (at your option) any later version. |
||||
|
||||
This program is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
along with this program; if not, write to the Free Software |
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
|
||||
Usage:
|
||||
var jpath = new JPath( myjsonobj ); |
||||
|
||||
var somevalue = jpath.$('book/title').json; //results in title
|
||||
//or
|
||||
var somevalue = jpath.query('book/title'); //results in title
|
||||
|
||||
Supported XPath-like Syntax: |
||||
/tagname |
||||
//tagname
|
||||
tagname |
||||
* wildcard |
||||
[] predicates |
||||
operators ( >=, ==, <= ) |
||||
array selection |
||||
..
|
||||
* |
||||
and, or |
||||
nodename[0] |
||||
nodename[last()] |
||||
nodename[position()] |
||||
nodename[last()-1] |
||||
nodename[somenode > 3]/node |
||||
nodename[count() > 3]/node |
||||
|
||||
Tested With: |
||||
Firefox 2-3, IE 6-7 |
||||
|
||||
Update Log: |
||||
1.0.1 - Bugfix for zero-based element selection |
||||
1.0.2 - Bugfix for IE not handling eval() and returning a function |
||||
1.0.3 - Bugfix added support for underscore and dash in query() function |
||||
Bugfix improper use of Array.concat which was flattening arrays |
||||
Added support for single equal sign in query() function |
||||
Added support for count() xpath function |
||||
Added support for and, or boolean expression in predicate blocks |
||||
Added support for global selector $$ and //
|
||||
Added support for wildcard (*) selector support
|
||||
*/ |
||||
|
||||
function JPath( json, parent ) |
||||
{
|
||||
this.json = json;
|
||||
this._parent = parent;
|
||||
} |
||||
|
||||
JPath.prototype = { |
||||
|
||||
/* |
||||
Property: json |
||||
Copy of current json segment to operate on |
||||
*/ |
||||
json: null, |
||||
|
||||
/* |
||||
Property: parent |
||||
Parent json object, null if root. |
||||
*/ |
||||
parent: null, |
||||
|
||||
/* |
||||
Method: $ |
||||
Performs a find query on the current jpath object. |
||||
|
||||
Parameters: |
||||
str - mixed, find query to perform. Can consist of a nodename or nodename path or function object or integer. |
||||
|
||||
Return: |
||||
jpath - Returns the resulting jpath object after performing find query. |
||||
|
||||
*/ |
||||
'$': function ( str ) |
||||
{ |
||||
var result = null; |
||||
var working = this; |
||||
|
||||
if ( this.json && str !== null ) |
||||
{ |
||||
switch ( typeof(str) ) |
||||
{ |
||||
case 'function': |
||||
result = this.f(str).json; |
||||
break; |
||||
|
||||
case 'number': |
||||
result = this.json[str] || null; |
||||
break; |
||||
|
||||
case 'string': |
||||
var names = str.split('/');
|
||||
|
||||
//foreach slash delimited node name//
|
||||
for ( var i=0; i<names.length ; i++ ) |
||||
{ |
||||
var name = new RegExp('^' + names[i].replace(/\*/g,'.*') + '$');
|
||||
var isArray = (working.json instanceof Array); |
||||
var a = new Array(); |
||||
|
||||
//foreach working node property//
|
||||
for ( var p in working.json ) |
||||
{ |
||||
if ( typeof( working.json[p] ) != 'function' ) |
||||
{ |
||||
if ( isArray && (arguments.callee.caller != this.$$) ) |
||||
{ |
||||
a = a.concat( this.findAllByRegExp( name, working.json[p] ) ); |
||||
} |
||||
else if ( name.test(p) ) |
||||
{
|
||||
a.push( working.json[p] ); |
||||
} |
||||
}
|
||||
} |
||||
|
||||
working = new JPath( ( a.length==0 ? null : ( ( a.length == 1) ? a[0] : a ) ), working ); |
||||
} |
||||
|
||||
return working; |
||||
break; |
||||
}
|
||||
} |
||||
|
||||
return new JPath( result, this ); |
||||
}, |
||||
|
||||
/* |
||||
Method: $$ |
||||
Performs a global, recursive find query on the current jpath object. |
||||
|
||||
Parameters: |
||||
str - mixed, find query to perform. Can consist of a nodename or nodename path or function object or integer. |
||||
|
||||
Return: |
||||
jpath - Returns the resulting jpath object after performing find query. |
||||
|
||||
*/ |
||||
'$$': function( str ) |
||||
{
|
||||
var r = this.$(str,true).json; |
||||
var arr = new Array(); |
||||
|
||||
if ( r instanceof Array )
|
||||
arr = arr.concat(r);
|
||||
else if ( r !== null ) |
||||
arr.push(r); |
||||
|
||||
for ( var p in this.json ) |
||||
{ |
||||
if ( typeof( this.json[p] ) == 'object' ) |
||||
{ |
||||
arr = arr.concat( new JPath( this.json[p], this ).$$(str).json ); |
||||
} |
||||
} |
||||
|
||||
return new JPath( arr, this ); |
||||
}, |
||||
|
||||
/* |
||||
Method: findAllByRegExp |
||||
Looks through a list of an object properties using a regular expression |
||||
|
||||
Parameters: |
||||
re - regular expression, to use to search with |
||||
obj - object, the object to search through |
||||
|
||||
Returns: |
||||
array - resulting properties |
||||
*/ |
||||
findAllByRegExp: function( re, obj ) |
||||
{ |
||||
var a = new Array(); |
||||
|
||||
for ( var p in obj ) |
||||
{ |
||||
if ( obj instanceof Array ) |
||||
{ |
||||
a = a.concat( this.findAllByRegExp( re, obj[p] ) ); |
||||
} |
||||
else if ( typeof( obj[p] ) != 'function' && re.test(p) ) |
||||
{ |
||||
a.push( obj[p] ); |
||||
} |
||||
} |
||||
|
||||
return a; |
||||
}, |
||||
|
||||
/* |
||||
Method: query (beta) |
||||
Performs a find query on the current jpath object using a single string similar to xpath. This method |
||||
is currently expirimental. |
||||
|
||||
Parameters: |
||||
str - string, full xpath-like query to perform on the current object. |
||||
|
||||
Return: |
||||
mixed - Returns the resulting json value after performing find query. |
||||
|
||||
*/ |
||||
query: function( str ) |
||||
{ |
||||
var re = { |
||||
" and ":" && ", |
||||
" or ":" || ", |
||||
"([\\#\\*\\@a-z\\_][\\*a-z0-9_\\-]*)(?=(?:\\s|$|\\[|\\]|\\/))" : "\$('$1').", |
||||
"\\[([0-9])+\\]" : "\$($1).", |
||||
"\\.\\." : "parent().", |
||||
"\/\/" : "$", |
||||
"(^|\\[|\\s)\\/" : "$1root().", |
||||
"\\/" : '', |
||||
"([^\\=\\>\\<\\!])\\=([^\\=])" : '$1==$2', |
||||
"\\[" : "$(function(j){ with(j){return(", |
||||
"\\]" : ");}}).", |
||||
"\\(\\.":'(', |
||||
"(\\.|\\])(?!\\$|\\p)":"$1json", |
||||
"count\\(([^\\)]+)\\)":"count('$1')" |
||||
}; |
||||
|
||||
//save quoted strings//
|
||||
var quotes = /(\'|\")([^\1]*)\1/; |
||||
var saves = new Array(); |
||||
while ( quotes.test(str) ) |
||||
{ |
||||
saves.push( str.match(quotes)[2] );
|
||||
str = str.replace(quotes,'%'+ (saves.length-1) +'%'); |
||||
} |
||||
|
||||
for ( var e in re ) |
||||
{ |
||||
str = str.replace( new RegExp(e,'ig'), re[e] ); |
||||
} |
||||
//alert('this.' + str.replace(/\%(\d+)\%/g,'saves[$1]') + ";");
|
||||
|
||||
return eval('this.' + str.replace(/\%(\d+)\%/g,'saves[$1]') + ";"); |
||||
}, |
||||
|
||||
/* |
||||
Method: f |
||||
Performs the equivilant to an xpath predicate eval on the current nodeset. |
||||
|
||||
Parameters: |
||||
f - function, an iterator function that is executed for every json node and is expected to return a boolean |
||||
value which determines if that particular node is selected. Alternativly you can submit a string which will be |
||||
inserted into a prepared function. |
||||
|
||||
Return: |
||||
jpath - Returns the resulting jpath object after performing find query. |
||||
|
||||
*/ |
||||
f: function ( iterator ) |
||||
{ |
||||
var a = new Array(); |
||||
|
||||
if ( typeof(iterator) == 'string' ) |
||||
{ |
||||
eval('iterator = function(j){with(j){return('+ iterator +');}}'); |
||||
} |
||||
|
||||
for ( var p in this.json ) |
||||
{ |
||||
var j = new JPath(this.json[p], this); |
||||
j.index = p; |
||||
if ( iterator( j ) ) |
||||
{ |
||||
a.push( this.json[p] ); |
||||
} |
||||
} |
||||
|
||||
return new JPath( a, this ); |
||||
}, |
||||
|
||||
/* |
||||
Method: parent |
||||
Returns the parent jpath object or itself if its the root node |
||||
|
||||
Return: |
||||
jpath - Returns the parent jpath object or itself if its the root node |
||||
|
||||
*/ |
||||
parent: function() |
||||
{ |
||||
return ( (this._parent) ? this._parent : this ); |
||||
}, |
||||
|
||||
/* |
||||
Method: position |
||||
Returns the index position of the current node. Only valid within a function or predicate |
||||
|
||||
Return: |
||||
int - array index position of this json object. |
||||
*/ |
||||
position: function() |
||||
{ |
||||
return this.index; |
||||
}, |
||||
|
||||
/* |
||||
Method: last |
||||
Returns true if this is the last node in the nodeset. Only valid within a function or predicate |
||||
|
||||
Return: |
||||
booean - Returns true if this is the last node in the nodeset |
||||
*/ |
||||
last: function() |
||||
{ |
||||
return (this.index == (this._parent.json.length-1)); |
||||
}, |
||||
|
||||
/* |
||||
Method: count |
||||
Returns the count of child nodes in the current node |
||||
|
||||
Parameters: |
||||
string - optional node name to count, defaults to all |
||||
|
||||
Return: |
||||
booean - Returns number of child nodes found |
||||
*/ |
||||
count: function(n) |
||||
{ |
||||
var found = this.$( n || '*').json;
|
||||
return ( found ? ( found instanceof Array ? found.length : 1 ) : 0 ); |
||||
}, |
||||
|
||||
/* |
||||
Method: root |
||||
Returns the root jpath object. |
||||
|
||||
Return: |
||||
jpath - The top level, root jpath object. |
||||
*/ |
||||
root: function () |
||||
{ |
||||
return ( this._parent ? this._parent.root() : this ); |
||||
} |
||||
|
||||
}; |
Loading…
Reference in new issue