// create the main name space
var JSLIB = window.JSLIB || {};

// this function is used to pre-populate namespace
JSLIB.namespace = function(name)  {
    var arrNames = name.split(".");
    if (arrNames[0] != "JSLIB") {
        return;
    }
    var obj = JSLIB;
    for (var i = 1; i < arrNames.length; i ++) {
        if (typeof obj[arrNames[i]] == "undefined") {
            obj[arrNames[i]] = {}
        }
        obj = obj[arrNames[i]]
    }
}


Object.prototype.Inherits = function( parent )
{
    if( arguments.length > 1 )
    {
        parent.apply( this, Array.prototype.slice.call( arguments, 1 ) );
    }
    else
    {
        parent.call( this );
    }
}

Function.prototype.Inherits = function( parent )
{
    this.prototype = new parent();
    this.prototype.constructor = this;
}

// browser sniffer
JSLIB.namespace("JSLIB.browser");

JSLIB.browser = {
	"browser":"",
	"version":"",
	"os":"",
	"gecko":false,
	"geckoVersion":0,
	"dom1":false
	}

var agt=navigator.userAgent.toLowerCase()

// following browser spoof other browsers.
// so detect them first.
if(agt.indexOf("opera")!=-1){
	JSLIB.browser.browser="opera"
	var reg=/opera( |\/)([0-9]+\.[0-9])/
	reg.exec(agt)
	JSLIB.browser.version=RegExp.$2
}
else if(agt.indexOf("konqueror")!=-1){
	JSLIB.browser.browser="konqueror"
	var reg=/konqueror( |\/)([0-9]+\.[0-9])/
	reg.exec(agt)
	JSLIB.browser.version=RegExp.$2
}
else if(agt.indexOf("safari")!=-1){
	JSLIB.browser.browser="safari"
	var reg=/safari( |\/)([0-9]+\.[0-9])/
	reg.exec(agt)
	JSLIB.browser.version=RegExp.$2
}

// resume detection
if(JSLIB.browser.browser.length==0){
	JSLIB.browser.gecko=agt.indexOf('gecko')!=-1
	JSLIB.browser.geckoVersion=agt.indexOf('gecko')
	if(JSLIB.browser.geckoVersion>0)JSLIB.browser.geckoVersion=parseInt(agt.substr(JSLIB.browser.geckoVersion+6,8))

	if(agt.indexOf("lynx")!=-1){
		JSLIB.browser.browser="lynx"
	}
    else if(agt.indexOf("links")!=-1){
		JSLIB.browser.browser="links"
	}
	else if(agt.indexOf("bot")!=-1||
		agt.indexOf("google")!=-1||
		agt.indexOf("scooter")!=-1||
		agt.indexOf("slurp")!=-1||
		agt.indexOf("spider")!=-1||
		agt.indexOf("spider")!=-1){
		JSLIB.browser.browser="bot"
	}
	else if(agt.indexOf("msie")!=-1){
		JSLIB.browser.browser="msie"
		var reg=/msie( |\/)([0-9]+\.[0-9])/
		reg.exec(agt)
		JSLIB.browser.version=RegExp.$2
	}
	else if(agt.indexOf("netscape")!=-1){
		JSLIB.browser.browser="netscape"
		var reg=/netscape( |\/)([0-9]+\.[0-9])/
		reg.exec(agt)
		JSLIB.browser.version=RegExp.$2
	}
	else if(agt.indexOf("firefox")!=-1){
		JSLIB.browser.browser="firefox"
		var reg=/firefox( |\/)([0-9]+\.[0-9])/
		reg.exec(agt)
		JSLIB.browser.version=RegExp.$2
	}
	else if(agt.indexOf("mozilla")!=-1){
		JSLIB.browser.browser="mozilla"
		var reg=/rv:([0-9]+\.[0-9])/
		reg.exec(agt)
		JSLIB.browser.version=RegExp.$1
	}
	else if(agt.indexOf("hotjava")!=-1){
		JSLIB.browser.browser="hotjava"
	}	
	else{
		JSLIB.browser.browser="other"
	}
}

if(agt.indexOf("win")>=0){
	if ((agt.indexOf("win16")!=-1) ||
	    (agt.indexOf("16bit")!=-1) || (agt.indexOf("windows 3.1")!=-1) ||
    	(agt.indexOf("windows 16-bit")!=-1)){
		JSLIB.browser.os="win16"
	}
	else{
		JSLIB.browser.os="win32"
	}
}
else if(agt.indexOf("linux")>=0){
	JSLIB.browser.os="linux"
}
else if(agt.indexOf("mac")>=0){
	JSLIB.browser.os="mac"
}
else if(agt.indexOf("sunos")>=0){
	JSLIB.browser.os="sunos"
}
else if(agt.indexOf("freebsd")>=0){
	JSLIB.browser.os="freebsd"
}
else if(agt.indexOf("irix")>=0){
	JSLIB.browser.os="irix"
}
else if(agt.indexOf("beos")>=0){
	JSLIB.browser.os="beos"
}
else if(agt.indexOf("os/2")>=0){
	JSLIB.browser.os="os/2"
}
else if(agt.indexOf("aix")>=0){
	JSLIB.browser.os="aix"
}
else {
	JSLIB.browser.os="other"
}

JSLIB.browser.dom1=((document.getElementById) ? true : false)

// JSLIB.object namespace
JSLIB.namespace("JSLIB.object");
JSLIB.object = {};
JSLIB.object.Inherits(Object);
JSLIB.object = function () {
    this.properties = {};
}
JSLIB.object.prototype.getProperty = function(name) {
    return this.properties[name];
}
JSLIB.object.prototype.setProperty = function(name, value) {
    this.properties[name] = value;
}

// create the util namespace
JSLIB.namespace("JSLIB.util");

JSLIB.util = {
    lTrim : function (str) {
        var str=new String(str); 
        return str.replace(/^\s*/,""); 
    },

    rTrim : function (str) {
        var str=new String(str); 
        return str.replace(/\s*$/,""); 
    },
    
    trim : function (str) {
        return this.lTrim(this.rTrim(str));
    },

    dirName : function (str) {
        var str=new String(str);
        var arr=str.match(/(.*)\/([^\/]*)$/);
        return (arr==null||typeof(arr)=="undefined"||typeof(arr[1])=="undefined")?".":arr[1];
    },

    baseName : function (str) {
        var str=new String(str);
        var arr = str.match(/(.*)\/([^\/]*)$/);
        return (arr==null||typeof(arr)=="undefined"||typeof(arr[2])=="undefined")?"":arr[2];
    },
    
    absUrl : function (str, win) {
        var str=new String(str);
        if (typeof(win) == "undefined" || !win || !win.location) {
            win = window;
        }
        var loc=win.location;
        
        // is it a abs url?
        var re=/^(http|https|ftp):\/\//i
        if(re.test(str)){
            return str;
        }
        else {
            // started with backslash?
            // use only protocol and hostname to construct abs url
            if (str.charAt(0) == "/") {
                return 
                    loc.protocol+"//"
                    +loc.hostname
                    +(loc.protocol!="http:"&&loc.port!=80?":"+loc.port:"")
                    +str;
            }
            // use existing location url and remove the file name,
            // then append file to its end
            else {
                return loc.href.substr(0,loc.href.lastIndexOf("/"))+"/"+str;
            }
        }    
    },
    
    // Description:
    //      encode characters used in HTML syntax to html entities
    // Arguments:
    //      str - string to be encoded
    //      flag - 
    //          undefined or 0 - escape double quote
    //          1 - do not escape double quote
    //          2 - quote single quote too
    // Return:
    //      encoded string
    htmlSpecialChars : function (str, flag) {
        var mystr = new String(str);
        if (typeof(flag) == "undefined") {
            flag = 0;
        }
        mystr=mystr.replace(/&/g,"&amp;");
        if (flag != 1) {
            mystr=mystr.replace(/\"/g,"&quot;");
        }
        if (flag == 2) {
            mystr=mystr.replace(/\'/g,"&#039;");
        }
        mystr=mystr.replace(/</g,"&lt;");
        mystr=mystr.replace(/>/g,"&gt;");
        // non-breakable space
        var re=new RegExp(String.fromCharCode(160), "g")
        mystr=mystr.replace(re,"&nbsp;");
        return mystr;
    },

    // Description:
    //      returns a string with backslashes before characters that need to be quoted 
    //      in javascript string
    // Arguments:
    //      str - string to be encoded
    // Return:
    //      string
    addSlashes : function (str) {
        var mystr = new String(str);
        mystr=mystr.replace(/\"/g,"\\\"");
        mystr=mystr.replace(/\'/g,"\\\'");
        mystr=mystr.replace(/\t/g,"\\t");
        mystr=mystr.replace(/\r/g,"\\r");
        mystr=mystr.replace(/\n/g,"\\n");
        return mystr;
    },
    
    // Description:
    //      determine whether input string looks like HTML code 
    // Arguments:
    //      str - string to be determined
    // Return:
    //      boolean
    //          - true: look like HTML
    //          - false: does not look like HTML
    isHtml : function (str) {
        var mystr = new String(str);
        var re=/<(p|h1|h2|h3|h4|h5|h6|table|td|tr|ul|ol|li|b|i|u|strong|em|strike|super|sup|big|small|body|html|br|hr|font|blockquote|pre|tt|script|object|embed)/i;
        if(re.test(mystr)) return true;
        re=/(&[a-zA-Z]{2,5};|&#[0-9]{1,5};)/i;
        if(re.test(mystr)) return true
        return false
    },
	
	isArray : function(a) {
		return this.isObject(a) && a.constructor == Array;
	},
	
	isBoolean : function(a) {
		return typeof a == 'boolean';
	},

	isEmpty : function(o) {
		var i, v;
		if (isObject(o)) {
			for (i in o) {
				v = o[i];
				if (isUndefined(v) && this.isFunction(v)) {
					return false;
				}
			}
		}
		return true;
	},
	
	isFunction : function(a) {
		return typeof a == 'function';
	},
	
	isNull : function(a) {
		return a === null;
	},
	
	isNumber : function(a) {
		return typeof a == 'number' && isFinite(a);
	},
	
	isObject : function(a) {
    	return (a && typeof a == 'object') || this.isFunction(a);
	},
	
	isString : function(a) {
		return typeof a == 'string';
	},
	
	isUndefined : function(a) {
    	return typeof a == 'undefined';
	},

    objToString : function (a) {
        if (JSLIB.util.isObject(a)) {
            var str = "";
            for (var key in a) {
                if (str.length > 0) {
                    str += ", ";
                }
                if (!JSLIB.util.isFunction(a[key])) {
                    str += key + ":" + a[key];
                }
                else {
                    str += key + ":FUNCTION";
                }
            }
            return "{" + str + "}";
        }
        else {
            return a;
        }
    }
};