// JavaScript Document
/**
 * @author kelicb
 * SunDun.HAS 项目Javascript基本命名空间
 */
   //命名空间注册   
   var has;
   if (typeof has == "undefined" || !has) {   
       has = {};
   }    
   has.namespace = function() {
       var a=arguments, o=null, i, j, d;
       for (i=0; i<a.length; i=i+1) {
           d=a[i].split(".");
           o=has;
   
           for (j=(d[0] == "has") ? 1 : 0; j<d.length; j=j+1) {
               o[d[j]]=o[d[j]] || {};
               o=o[d[j]];
           }
       }   
       return o;
   };   
/* 命名空间注册和调用办法：  
   注册方式：
   注册1：has.namespace("fn"); 注册一个一级的对象函数
   注册2：has.namespace("fn","fn2"); 注册多个一级的对象函数
   注册3：has.namespace("fn.nfn"); 注册一个二级的对象函数
   函数编写：has.fn = function(arg,arg){ code };  参数arg可选
            也可直接增加一级对象：
            has.fn.geturl = function(arg,arg){ code };  参数arg可选      
   调用：has.fn();   has.fn.geturl();
*/
var urlpath = window.document.location.pathname;
var i = urlpath.indexOf("/");
if(i==0)
{
	urlpath=urlpath.substr(1);
}
i = urlpath.indexOf("/");
urlpath = "/" + urlpath.substr(0,i + 1);
//注册命名空间
has.namespace("common");
has.common.getDb = function(cateId){
	var returnVal;
	var url = urlpath + "common.do?method=getMetaDbByCateId&cateId=" + cateId;
	$.ajax({
	  url: url,
	  async: false,
	  dataType: "json",
	  success: function(data){
		returnVal = data.data[0];
	 }
	})
	return returnVal;
}

has.common.getCate = function(tableId){
	var returnVal;
	var url = urlpath + "common.do?method=getMetaCategoryByTableId&tableId=" + tableId;
	$.ajax({
	  url: url,
	  async: false,
	  dataType: "json",
	  success: function(data){
		returnVal = data.data[0];
	 }
	})
	return returnVal;
}

$.parent = function(){
	if(!!$.getQueryString("isIframeDlg")){
		return window.parent.window.dialogArguments.window;
	}
	else if(window.opener != null){
		return window.opener;
	}
	else if(window.dialogArguments != null){
		return window.dialogArguments.window;
	}
	else if(window.parent != null){
		return window.parent;
	}
}

$.open = function(url, params, pWidth, pHeight, pOpenMode){
	if(pOpenMode == null || pOpenMode == 'undefined'){
		pOpenMode = 2;
	}
	
	//对话模方式打开
	if(pOpenMode == '1' || pOpenMode == 'modal'){
		var returnVal = $.openModalDlg(url, params, pWidth, pHeight);
		return returnVal;
	}
	
	//普通窗口方式打开
	else if(pOpenMode == '2' || pOpenMode == 'window'){
		$.openWindow(url, pWidth, pHeight);
	}
	
	//win窗口方式打开
	else if(pOpenMode == '3' || pOpenMode == 'dialog'){
		$().dialog({
			 width : pWidth,
			 height : pHeight,
			 data : "iframe:" + url,
			 callBack : function(handle){},
			 autoHeight:false
		});
	}
	//win窗口方式打开
	else if(pOpenMode == '4' || pOpenMode == 'iframeDialog'){
		var returnVal = $.openModalIframeDlg(url, params, pWidth, pHeight);
		return returnVal;
	}
	
	//默认对话模方式打开
	else{
		$.openWindow(url, pWidth, pHeight);
	}
}

/*
*添加树节点
*
*/
$.addNode = function(obj, nodes){
	var parentNodeId = "";
	if($.isEmpty(nodes.length)){
		nodes = [nodes];
	}
	
	for(i = 0; i < nodes.length; i++){	
		$(obj).tree('addNode', [nodes[i]], nodes[i].pgid);
	}
}

/*
*编辑树节点
*/
$.editNode = function(obj, nodes){
	var parentNodeId = "";
	if($.isEmpty(nodes.length)){
		nodes = [nodes];
	}	
	for(i = 0; i < nodes.length; i++){	
		$(obj).tree('editNode', [nodes[i]]);
	}
	

}

$(document).ready(function(){
//对话模无法进行form窗口，对话模形式进行关闭
	$(".form-btn-cancel").click(function(){
		try{
			has.form.closeWindow();
		}
		catch(e){
		
		}
	})
	
	//如果是对话模iframe
	if(!!$.getQueryString("isIframeDlg")){
		//改变原有的关闭窗口事件
		window.close = function(){
			$.parent().returnValue = window.returnValue;
			$.parent().close();
		}
	}
})

$.openModalIframeDlg = function(sPath, oArgs, iX, iY){
	window.iframeSrc = sPath;
	$.openModalDlg(urlpath + "ModalDlg.jsp", oArgs, iX, iY);
}


has.common.sourceHref = window.location.href;
$.reload = function(){
	if(window.dialogArguments != null){
		window.location.href = has.common.sourceHref;
	}
	else{
		window.location.reload();
	}
}

has.common.showRequest = function(formData, jqForm, options) {
	/*var queryString = $.param(formData);
	alert('提交内容: \n\n' + queryString); */
	$("#u_content").tip('middle','数据提交中，请稍候...',0)
	return true; 
} ; 
 
has.common.showResponse = function(responseText, statusText, successFun, errorFun){
	//屏蔽原来的js调用function showResponse(responseText, statusText, xhr, $form) 
	if(!(typeof successFun == "function" || typeof errorFun == "function")){
		has.common.showResponse(responseText, statusText, function(){}, function(){})
		return;
	}
	//{success:'true或false',id:'1',msg:''}
	if(statusText == "success"){
		$(document).tip("close");
		
		//如果返回对象不是json对象,使它变成json对象
		if(responseText.success == "undefined" || responseText.success == null){
			responseText = stringToJSON(responseText);
		}
		if(responseText.success){
			
			$('.success-text').html(responseText.msg);
			
			setTimeout(function(){			
				$("tfoot").hide();
				
				$(".form-content").fadeOut(200);	
				
				$(".form-step .step1").addClass("step1-disable");
				$(".form-step .step2").removeClass("disable");
				setTimeout(function(){
					$("table.success").fadeIn(300);
				},200);
				
			},600);
			
			if(!$.isEmpty(successFun)){
				successFun(responseText);
			}
			
		}else{
			$.msgbox.errorInfo(responseText.msg);
			if(!$.isEmpty(errorFun)){
				errorFun(responseText);
			}
		}
	}
	else{
		$.msgbox.errorInfo("网络没有连通");
	}
}

jsonToString = function(obj){   
        var THIS = this;    
        switch(typeof(obj)){   
            case 'string':   
                return '"' + obj.replace(/(["\\])/g, '\\$1') + '"';   
            case 'array':   
                return '[' + obj.map(THIS.jsonToString).join(',') + ']';   
            case 'object':   
                 if(obj instanceof Array){   
                    var strArr = [];   
                    var len = obj.length;   
                    for(var i=0; i<len; i++){   
                        strArr.push(THIS.jsonToString(obj[i]));   
                    }   
                    return '[' + strArr.join(',') + ']';   
                }else if(obj==null){   
                    return 'null';   
  
                }else{   
                    var string = [];   
                    for (var property in obj) string.push(THIS.jsonToString(property) + ':' + THIS.jsonToString(obj[property]));   
                    return '{' + string.join(',') + '}';   
                }   
            case 'number':   
                return obj;   
            case false:   
                return obj;   
        }   
    }
    
stringToJSON = function(obj){   
        return eval('(' + obj + ')');   
} 

$.formArrayToQueryString = function(arr){
	var queryString = "";
	for(var i = 0; i < arr.length; i++){
		var json = arr[i];
		if(json.name != 'password'){
		
			if(queryString != ""){
				queryString += "&";
			}
			
			queryString += json.name + "=" + escape(json.value);
						
			/*if(i < arr.length - 1){
				queryString += "&";
			}*/
		}
	}
	return queryString;
}

//注册命名空间
has.namespace("form");
//关闭表单窗口
has.form.closeWindow = function(){
	//以对话模方式打开的窗口
	if(window.dialogArguments != null){
		window.close();
	}
	
	//以普通窗口方式打开的窗口
	else if(window.opener != null){
		window.close();
	}
	
	//以win方式打开的窗口
	else{
		if(parent.parent.$("body").layout==null || parent.parent.$("body").layout=="undefined"){
			top.sundun.dialog('close');
		}
		else{
			parent.sundun.dialog('close');
		}
		
	}
}

//刷新表单父窗口
has.form.refreshParentWindow = function(){
	try{
		
		//以对话模方式打开的窗口
		if(window.dialogArguments != null){
			dialogArguments.location.reload();
		}
		
		//以普通窗口方式打开的窗口
		else if(window.opener != null){
			opener.location.reload();
		}	
		
		//以win方式打开的窗口
		else{
			//$('#sundun_grid').xgrid('reload');
		}
	}
	catch(err){
	
	}
}

/**
 * 判断是否是数字
 * param s 输入参数
 */
sundun.isInt = function(s)
	{
	    return new RegExp(/^(0|[1-9][0-9]*)$/).test(sundun.trim(s));
	}
	
/**
 * 判断是否是电子邮件地址
 * param s 输入参数
 */
sundun.isEmail = function(s)
	{
	    return new RegExp(/^(\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*)$/).test(this.trim(s));
	}
		
/**
 * 判断是否是身份证号码
 * param s 输入参数
 */
sundun.isSFZ = function(s)
	{
	    return new RegExp(/^\d{14}(\d{1}|\d{4}|(\d{3}[xy]))$/).test(sundun.trim(s));
	}

/**
 * 判断是否是合法IP地址
 * param ip 输入参数
 */
sundun.isIP = function (ip)   
  	{   
	    var re=/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/g; //匹配IP地址的正则表达式
	    
   	 	if(re.test(ip))
   		{
    		if( RegExp.$1 <256 && RegExp.$2<256 && RegExp.$3<256 && RegExp.$4<256) 
    			return true;
   		}
   		
	    return false;	   
  	}		
  	
/**
 * 判断是否为空
 * param s 输入参数
 */
sundun.isEmpty = function(obj){
	if(obj == null || obj == "undefinded" || obj == ""){
		return true;
	}
	else if(typeof obj == "string" && sundun.trim(obj).length == 0){
		return true;
	}
	else if(typeof obj == "number" && obj == 0){
		return true;
	}
	else if(typeof obj == "boolean" && obj == false){
		return true;
	}
	return false;
}

//注册命名空间
has.namespace("json");


has.json.jsonToQueryString = function(json){
	var queryString = "";
	var jsonToQueryString2 = function(json, queryString, index, jsonIndex2){
		for(var jsonIndex in json){
			if(!jsonIndex2){
				showJsonIndex = jsonIndex;
			}
			else{
				showJsonIndex = jsonIndex2 + "." + jsonIndex;
			}
			if(typeof json[jsonIndex] != "Array" && typeof json[jsonIndex] != "object"){
				if(index > 0){
					queryString += "&";
				}
				queryString += showJsonIndex + "=" + json[jsonIndex];
				index++;
			}
			else{
				queryString = jsonToQueryString2(json[jsonIndex], queryString, index, showJsonIndex)
			}
			
		}
		return queryString;
	}
	queryString = jsonToQueryString2(json, queryString, 0);
	return queryString;
}

has.json.queryStringToJson = function(){
	var returnValue = "";
	var URLString = new String(document.location);
	var serachLocation = -1;
	serachLocation = URLString.indexOf("?");
	var queryString = "";
	if (serachLocation != -1) {
		queryString = URLString.substr(serachLocation + 1);
	}
	var parmName = "";
	var parmValue = "";
	var json = {};
	var ampIndex = -1;//&amp;
	while(serachLocation != -1) {
		serachLocation = queryString.indexOf("=");
		if (serachLocation != -1) {
			parmName = queryString.substr(0, serachLocation);
			queryString = queryString.substr(serachLocation + 1);
			ampIndex = queryString.indexOf("&amp;");
			serachLocation = queryString.indexOf("&");
			//如果找到"&amp;"就继续找下一个
			for(var i = 0; serachLocation != -1 && ampIndex != -1 && serachLocation == ampIndex; i++){
				serachLocation = queryString.indexOf("&", serachLocation + 1);
				ampIndex = queryString.indexOf("&amp;", ampIndex + 1);
			}
			if (serachLocation != -1) {
				parmValue = queryString.substr(0, serachLocation);
				queryString = queryString.substr(serachLocation + 1);
			}
			else{
				//如果有值就赋值给VALUE
				if(queryString){
					parmValue = queryString;
				}
			}
			//如果已有值，就增加值到数组后面
			if(json[parmName]){
				if(typeof json[parmName] == "Array"){
					json[parmName].push(parmValue);
				}
				else{
					var parmValue2 = new Array();
					parmValue2.push(json[parmName]);
					parmValue2.push(parmValue);
					json[parmName] = parmValue2;
				}
			}
			else{
				json[parmName] = parmValue;
			}
			
		}

	}	
	return json;
}

has.json.getEvalArrayTag = function(json, attr, valueArray, valueIndex, evalStr){
	if(valueIndex == null){
		valueIndex = 0;
	}
	if(evalStr == null){
		evalStr = "";
	} 
	for(var jsonIndex in json){
		if(json[jsonIndex][attr] == valueArray[valueIndex]){
			valueIndex++;
			if(valueIndex < valueArray.length){
				json = json[jsonIndex]["children"];
				evalStr += "[" + jsonIndex + "][\"children\"]"
				return has.json.getEvalArrayTag(json, attr, valueArray, valueIndex, evalStr);
			}
			else{
				evalStr += "[" + jsonIndex + "]";
				break;
			}
		}
	}
	return evalStr;
}

has.json.add = function(json, node, indexArray, indexName){
	tag = has.json.getEvalArrayTag(json, indexName, indexArray);
	if(tag != ""){
		tag2 = tag + "[\"children\"]";
	}
	childlength = 0;
	eval("if(!json" + tag2 + "){json" + tag + ".children = []}")
	eval("childlength = json" + tag2 + ".length");
	eval("json" + tag + "[\"children\"][" + childlength + "]=node");
}

has.json.edit = function(json, node, indexArray, indexName){
	tag = has.json.getEvalArrayTag(json, indexName, indexArray);
	for(var i in node){
		eval("json" + tag + "[\"" + i + "\"]=node[\"" + i + "\"]");
	}
}

has.json.remove = function(json, indexArray, indexName){
	tag = has.json.getEvalArrayTag(json, indexName, indexArray);
	//alert(tag)
	startIndex = tag.lastIndexOf("[");
	lastIndex = tag.lastIndexOf("]");
	removeIndex = tag.substring(startIndex + 1, lastIndex);
	tag = tag.substring(0, startIndex);
	childIndex = 0;
	eval("json" + tag + ".splice(removeIndex,1)")
	eval("if(json" + tag + ".length == 0){json" + tag + "=undefined}")
}

has.json.concat = function(){

	var rtnJSON = {};
    if(arguments){
    	for(var i = 0; i < arguments.length; i++){
    		for( var j in arguments[i]){
		        rtnJSON[j] = arguments[i][j];
		    } 
    	}
    }
    return rtnJSON;
}

/****json2.js  start*************/
if (!this.JSON) {
    this.JSON = {};
}

(function () {

    function f(n) {
        // Format integers to have at least two digits.
        return n < 10 ? '0' + n : n;
    }
    if (typeof Date.prototype.toJSON !== 'function') {

        Date.prototype.toJSON = function (key) {
            return isFinite(this.valueOf()) ?
                   this.getUTCFullYear()   + '-' +
                 f(this.getUTCMonth() + 1) + '-' +
                 f(this.getUTCDate())      + 'T' +
                 f(this.getUTCHours())     + ':' +
                 f(this.getUTCMinutes())   + ':' +
                 f(this.getUTCSeconds())   + 'Z' : null;
        };
        String.prototype.toJSON =
        Number.prototype.toJSON =
        Boolean.prototype.toJSON = function (key) {
            return this.valueOf();
        };
    }
    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        gap,
        indent,
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        rep;
    function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
        escapable.lastIndex = 0;
        return escapable.test(string) ?
            '"' + string.replace(escapable, function (a) {
                var c = meta[a];
                return typeof c === 'string' ? c :
                    '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
            }) + '"' :
            '"' + string + '"';
    }

    function str(key, holder) {
// Produce a string from holder[key].
        var i,          // The loop counter.
            k,          // The member key.
            v,          // The member value.
            length,
            mind = gap,
            partial,
            value = holder[key];

// If the value has a toJSON method, call it to obtain a replacement value.
        if (value && typeof value === 'object' &&
                typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
        if (typeof rep === 'function') {
            value = rep.call(holder, key, value);
        }
// What happens next depends on the value's type.
        switch (typeof value) {
        case 'string':
            return quote(value);

        case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
            return isFinite(value) ? String(value) : 'null';

        case 'boolean':
        case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
            return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
        case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
            if (!value) {
                return 'null';
            }
// Make an array to hold the partial results of stringifying this object value.
            gap += indent;
            partial = [];

// Is the value an array?
            if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
                length = value.length;
                for (i = 0; i < length; i += 1) {
                    partial[i] = str(i, value) || 'null';
                }
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
                v = partial.length === 0 ? '[]' :
                    gap ? '[\n' + gap +
                            partial.join(',\n' + gap) + '\n' +
                                mind + ']' :
                          '[' + partial.join(',') + ']';
                gap = mind;
                return v;
            }
// If the replacer is an array, use it to select the members to be stringified.
            if (rep && typeof rep === 'object') {
                length = rep.length;
                for (i = 0; i < length; i += 1) {
                    k = rep[i];
                    if (typeof k === 'string') {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            } else {
// Otherwise, iterate through all of the keys in the object.
                for (k in value) {
                    if (Object.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            }
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
            v = partial.length === 0 ? '{}' :
                gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' +
                        mind + '}' : '{' + partial.join(',') + '}';
            gap = mind;
            return v;
        }
    }
// If the JSON object does not yet have a stringify method, give it one.
    if (typeof JSON.stringify !== 'function') {
        JSON.stringify = function (value, replacer, space) {

// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
            var i;
            gap = '';
            indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
            if (typeof space === 'number') {
                for (i = 0; i < space; i += 1) {
                    indent += ' ';
                }
// If the space parameter is a string, it will be used as the indent string.
            } else if (typeof space === 'string') {
                indent = space;
            }
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
            rep = replacer;
            if (replacer && typeof replacer !== 'function' &&
                    (typeof replacer !== 'object' ||
                     typeof replacer.length !== 'number')) {
                throw new Error('JSON.stringify');
            }
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.

            return str('', {'': value});
        };
    }
// If the JSON object does not yet have a parse method, give it one.

    if (typeof JSON.parse !== 'function') {
        JSON.parse = function (text, reviver) {

// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
            var j;
            function walk(holder, key) {

// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
                var k, v, value = holder[key];
                if (value && typeof value === 'object') {
                    for (k in value) {
                        if (Object.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
            text = String(text);
            cx.lastIndex = 0;
            if (cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return '\\u' +
                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.

// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

            if (/^[\],:{}\s]*$/.
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

                j = eval('(' + text + ')');

// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.

                return typeof reviver === 'function' ?
                    walk({'': j}, '') : j;
            }

// If the text is not JSON parseable, then a SyntaxError is thrown.

            throw new SyntaxError('JSON.parse');
        };
    }
}());
/****json2  end*************/
/**** JPath 1.0.4  start*************/
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 );
   }

};
/**** JPath 1.0.4 end*************/


