/*********************************************************************************

 * Module: string.js

 *		String handling utilities.

 *		This module includes extensions to the String prototype function as well as

 *		other utility functions related to Strings.

 *********************************************************************************/



// NOTE:  Tag regular expressions are no longer global.

// NS RegExp.exec() function has problems doing repeated matchings on a global regexp.

// Most string methods have a ..All function for global matching ( eg... .replace => .replaceAll )





/*********************************************************************************

 * Object: OBJECT

 *		Utility functions related to objects

 */



//document.write('<SCRIPT LANGUAGE="JavaScript" SRC="/scripts/version.js"><\/SCRIPT>');

/*

var pubPrStr = {

    pubProtocol:document.location.protocol,

    pubHost:document.location.host

}

*/

var pubPrStr = {};

	try{

		pubPrStr.pubProtocol = document.location.protocol;

		pubPrStr.pubHost     = document.location.host;

	}catch(e){

		pubPrStr.pubProtocol = "http:";

		pubPrStr.pubHost     = "localhost:8085";

	}



if (!window.appRoot) 

{

	var app = document.location.pathname;

	var indx = app.indexOf("\/",1);

	if(indx > -1){

		window.appRoot = app.substring(0,indx);

	}else{

		window.appRoot = app;

	}

	if(window.appRoot.charAt(0)!="\/")window.appRoot = "\/"+window.appRoot;

	/*

	if (location.pathname.substring(0, 8).indexOf('censoft') != -1)

	{	

		window.appRoot = '/censoft';

	}

	else

	{

		window.appRoot = '';

	}

	*/

}



function getLocationPath(){

	

	return pubPrStr.pubProtocol+'//'+pubPrStr.pubHost +window.appRoot;	

}

var OBJECT = {

	author:"CensoftZhongguancunSoftwareCoporationLimited",

	/*********************************************************************************

	 * Function: OBJECT.build(v,[fmt],[c])

	 *		Makes an exact copy of the object

	 * Inputs:

	 *		v:any type - The source variable

	 *		c:object - The variable constructor (String, Object, Array)

	 * Examples:

	 *		OBJECT.build([1,2,"abc"])

	 */

	build: function(v,fmt,c,prefix) {

		if (v == null) return "null";

		var r = "";

		if (!c) c = v.constructor;

		

		if (c == Object) {

			r = {};

			for (var p in v)

				r[p] = OBJECT.build(v[p]);

		} else if (c == Array) {

			r = [];

			for (var i=0; i<v.length; i++)

				r[i] = OBJECT.build(v[i]);

		} else {

			r = v;

		}



		return r;

	}

}



/*********************************************************************************

 * Object: STRING

 *		Utility functions related to strings

 */

 

var STRING = {

	

	/*********************************************************************************

	 * Function: STRING.build(v,[fmt],[c]) -> String

	 *		Convert a variable to a string representation of the variable

	 * Inputs:

	 *		v:any type - The source variable

	 *		fmt:integer - The format to use

	 *			Default: compact format

	 *			1: carriage returns and indentation for objects

	 *		c:object - The variable constructor (String, Object, Array)

	 * Outputs:

	 *		result:String - The string version of the contents variable

	 * Examples:

	 *		STRING.build([1,2,"abc"]) -> '[1,2,"abc"]'

	 */



	build: function(v,fmt,c,prefix) {

		if (v == null) return "null";

		var r = "";

		if (!c) c = v.constructor;

		if (c == String) {

			// This string conversion supports character codes from 1-255

			v = v.replace(/\\/g,"\\\\");	// Escape backslash characters

			v = v.replace(/\r/g,"\\r");		// Escape return

			v = v.replace(/\n/g,"\\n");		// Escape new line

			v = v.replace(/"/g,"\\\"");		// Escape quotes

			v = v.replace(/<\/script>/gi,"<\\/script>");		// Escape end script tags or web page will not parse correctly

			r = '"' + v + '"';

		} else if (c == Number) {

			r = "" + v;

		} else if (c == Boolean) {

			r = "" + v;

		} else if (c == Object || (typeof v == "object" && v.length == STRING.undef)) {

			if (fmt == 1) {

				if (!prefix) prefix = "\t";

				var cr = "\r\n";

			} else {

				cr = "";

				prefix = "";

			}

			var a = [];

			for (var p in v) a[a.length] = p;

			a.sort();		// Put the properties in sorted order

			for (var i=0; i<a.length; i++) {

				var p = a[i];

				if (r) r += "," + cr + prefix;

				r += p + ":" + STRING.build(v[p],fmt,null,prefix + "\t");

			}

			if (r) r = cr + prefix + r + cr;

			r = "{" + r + "}";

		} else if (c == Array || (typeof v == "object" && v.length != STRING.undef) ) {

			for (var i=0; i<v.length; i++) {

				if (r) r += ",";

				r += STRING.build(v[i]);

			}

			r = "[" + r + "]";

		} else {

			r = "unknown type";

		}

		return r;



	},

	

	noVulgar: function(s) {

		return s.replace(/\b(ass|bitch|blowjob|bondage|clit|cock|cornhole|cum|cunnilingus|cunt|defecation|dick|douche|erotic|fags|fellatio|feltch|fetish|fuck|genitalia|horny|kkk|lingerie|lust|masturbation|nazi|nigger|nudity|oral|panties|penis|piss|pussy|queer|sadomasochism|semen|sex|shit|slut|submissive|suck|tit|transsexual|transvestite|twat|urination|vagina)\b/gi, "***");

	},

	

	/*********************************************************************************

	 * Function: optional([prefix],s,[suffix]) -> String

	 *		Append the specified string with optional prefix and suffix

	 * Inputs:

	 *		prefix:S - Value to put before s if s is specified

	 *		s:S - String value to return

	 *		suffix:S - Value to put after s if s is specified

	 * Outputs:

	 *		result:S - Original string value with appended strings

	 */



	optional: function(prefix,s,suffix) {

		if (!s) return "";

		return (prefix ? prefix : "") + s + (suffix ? suffix : "");

	},



	// Format a value as a date string

	date: function(v) {

		if (!v) return "";

		if (typeof v == "string") v = parseInt(v);

		return new Date(v).toLocaleString()

	},

	convertTextToHTML:function(s) {

		s = s.replace(/\&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/\n/g, "<BR>");

		while (/\s\s/.test(s))

			s = s.replace(/\s\s/, "&nbsp; ");

		return s.replace(/\s/g, " ");

	}

	

}



/*********************************************************************************

 * Functions to return a QUOTED absolute URL from a relative path.

 * Inputs:

 *		this:	relative path

 *		bPL:	boolean, true if this is a relative path for a private label URL

 * Outputs:	

 *		result:String - an absolute URL

 * Examples:

 *		"/img/goodies.gif" -> "http://www.foo.com/img/goodies.gif"

 *********************************************************************************/



/*

  The following code line is commented out by Paul to be suitable for the case that lack of alias mapping when using WebSphere or WebLogic as Web Server,not Apache

  String.prototype.plDir = window.appRoot + '\/own\/' + document.location.hostname.replace(/[.:]/g,'_');

*/



String.prototype.plDir = window.appRoot + '\/own\/localhost';

String.prototype.absURL = function(bPL)

 {

	try

	{

	//	var p = location.protocol;

		var p = pubPrStr.pubProtocol;

		if (bPL) {

			if( ((this.lastIndexOf('.gif') == (this.length - 4)) || (this.lastIndexOf('.jpg') == (this.length - 4))) && (Version.bAkamai)) {

			//	return (p + '\/\/a1767.g.akamai.net\/7\/1767\/' + Version.akamaiAcc + '\/' + PL.plImgVersion + '\/' + document.location.host  + this.plDir + this );

				return (p + '\/\/a1767.g.akamai.net\/7\/1767\/' + Version.akamaiAcc + '\/' + PL.plImgVersion + '\/' + pubPrStr.pubHost  + this.plDir + this );

			}

			else {

			//	return (p + '\/\/' + document.location.host  + this.plDir + this );

			//	alert(this.plDir);

				return (p + '\/\/' + pubPrStr.pubHost  + this.plDir + this );

			}		

		} 

		else {

			if( (this.lastIndexOf('.gif') == (this.length - 4)) && (Version.bAkamai)) {

			//	return (p + '\/\/a1767.g.akamai.net\/7\/1767\/' + Version.akamaiAcc + '\/' + Version.censImgVersion + '\/' + document.location.host + this);

				return (p + '\/\/a1767.g.akamai.net\/7\/1767\/' + Version.akamaiAcc + '\/' + Version.censImgVersion + '\/' + pubPrStr.pubHost + this);

			}

			else {

			//	return (p + '\/\/' + document.location.host + window.appRoot + this);

				return (p + '\/\/' + pubPrStr.pubHost + window.appRoot + this);

			}

		}

	}

	catch(e)

	{

		//sometimes location unavailable so...

		return '..' + this;

	}

}

String.prototype.absURL2 = function()

 {

 	//alert("ss");

 	return (location.protocol + '\/\/' + location.host + window.appRoot + this);

 }

 String.prototype.templetAbsURL = function()

 {

 	//alert("ss");

 	var path = (location.protocol + '\/\/' + location.host + window.appRoot + this);

 	//	alert(path);

 	return path;

 }

/*********************************************************************************

 * Functions to test a string

 *********************************************************************************/

String.prototype.isNumRE = /[0-9]+(\.[0-9])*|\.[0-9]+/;

String.prototype.isNumber = function() {

	var m = this.match(this.isNumRE);

	return (m && this == m[0]);

	//return (this.isNumRE.test(this));

}



/*********************************************************************************

 * Function: String.containsInvalidChars() -> String or null

 *		Strip leading whitespace from a string

 * Inputs:

 *		none

 * Outputs:

 *		result:String of invalidChars

 * Examples:

 *		"abc{def[".containsInvalidChars() -> "{["

 *		"abcdef".containsInvalidChars() -> null

 */



String.prototype.invalidSearchChars = /[\?\(\)\/{}\[\]<>\\]/g;

String.prototype.containsInvalidSearchChars = function() {

	var res = this.match(this.invalidSearchChars);

	return (res ? res.join('') : null);

}



//String.prototype.invalidChars = /[{}\[\]<>"\\]/g;   //comment by mxz at 2003-2-23 for check invalid chars

String.prototype.invalidChars = /[*~!#$%^&{}\(\)\[\]<>"'\\]/g; 

String.prototype.containsInvalidChars = function() {

	var res = this.match(this.invalidChars);

	var c = null;



	if (USERBROWSER.ie) 

	{

		if (!res) res = [];

		for (var i=0; i < this.length; i++) 

		{

			c = this.charCodeAt(i);

			/*

			if (c > 127) {

				c = c.toString(16);

				for (var j=c.length;j<4; j++) {

					c = '0' + c;

				}

				eval('res[res.length] ="\\u' + c + '"');

			}

			*/

			if (c > 255) 

			{				

			   c = "&#" + c.toString(16) + ";" ;

			   // alert("c=" + c);

		           // convert char to &#nnnn;

			   res.join(c);

			}

		}

	}

	

	return (res ? res.join('') : null);

}



String.prototype.invalidDNChars = /[\\\n\r\",+=<>#;&\/]/g;

String.prototype.containsInvalidDNChars = function() {

	var res = this.match(this.invalidDNChars);

	var c = null;

	

	if (USERBROWSER.ie) 

	{

		if (!res) res = [];

		

		for (var i=0; i < this.length; i++) 

		{

			c = this.charCodeAt(i);

		/*	

			if (c > 127) 

			{

				c = c.toString(16);

				for (var j=c.length;j<4; j++) 

				{

					c = '0' + c;

				}

				eval('res[res.length] ="\\u' + c + '"');

			}

		*/

			if (c > 255) 

			{				

			   c = "&#" + c.toString(16) + ";" ;

			   // alert("c=" + c);

		           // convert char to &#nnnn;

			   res.join(c);

			}

																  

		}

        }

                

	return (res ? res.join('') : null);

}





/*********************************************************************************

 * Functions to trim whitespace from a string

 *********************************************************************************/





/*********************************************************************************

 * Function: String.ltrim() -> String

 *		Strip leading whitespace from a string

 * Inputs:

 *		none

 * Outputs:

 *		result:String - Source string with leading whitespace removed

 * Examples:

 *		"   test  ".ltrim() -> "test  "

 */

 String.prototype.great_summary = function(charNum) 

 {

 	detail_temp = new StringBuffer();

 	var detail = this;

     if(detail != null)

     {

         for(i = 0;i < detail.length;i++)

        {

        	detail_temp.a(detail.charAt(i));

            if(i == charNum)

            {

                detail_temp.a('…');

                break;

            }

        }

       return detail_temp.toString(); 

     }

     else

     {

       return "无";

     }

     

 }





String.prototype.ltrim = function() {

	return this.replace(/^\s+/,""); 

}





/*********************************************************************************

 * Function: String.rtrim() -> String

 *		Strip trailing whitespace from a string

 * Inputs:

 *		none

 * Outputs:

 *		result:String - Source string with trailing whitespace removed

 * Examples:

 *		"   test  ".rtrim() -> "   test"

 */



String.prototype.rtrim = function() {

	return this.replace(/\s+$/,"");

}





/*********************************************************************************

 * Function: String.trim() -> String

 *		Strip leading and trailing whitespace from a string

 * Inputs:

 *		none

 * Outputs:

 *		result:String - Source string with leading and trailing whitespace removed

 * Examples:

 *		"   test  ".trim() -> "test"

 */



String.prototype.trim = function() { 

	return this.replace(/^\s+|\s+$/g,"") 

}

String.prototype.trim2 = function() { 

	return this.replace(/\s+/g,"%20") 

}



/**

 * Function to take a string and convert it into a title.

 * 

 *	Converts first letter of each word to uppercase like the style used in book titles.   

 *	Keeps existing uppercase unchanged.

 *	Some words stay lowercase in the middle ("is", "a", "the", "an")

 * Examples:

 *		"john's test page" -> "John's Test View"

 *		"the IBM way" -> "The IBM Way"

 *		"this is a test" -> "This is a Test"

 *		"String Utility to Put UpperCase into Titles" -> "String Utility To Put UpperCase Into Titles"

 */





String.prototype.titleCase = function() {

	if (!this) return "";



	var p = /(^(\s*)([a-z]))|( \bis\b| \ban?\b| \bthe\b)|((\s)([a-z]))/g;

	var s = this.replace(p,"$2<$3>$4$6<$7>").replace(/<>/g,"").replace(/<[a-z]>/g,"*^*");

	for (var i=s.indexOf("*^*"); i>=0; i=s.indexOf("*^*"))

		s = s.substr(0,i) + this.charAt(i).toUpperCase() + s.substr(i+3);

	return s;

}



/*********************************************************************************

 * Functions to process "properties" form a property path

 *********************************************************************************/





/*********************************************************************************

 * Function: String.firstProp() -> String

 *		Return the first "property" name from a string in the format "company.profile.description"

 * Inputs:

 *		none

 * Outputs:

 *		result:String

 * Examples:

 *		"company.profile.description".firstProp() -> "company"

 *		"description".firstProp() -> "description"

 */



String.prototype.firstProp = function() {

	var r = this;

	if (r) {

		var p = r.indexOf(".");

		if (p > -1) {

			r = r.substring(0,p);

		} else {

			r = r.substring(0);

		}

	}

	return r;

}





/*********************************************************************************

 * Function: String.lastProp() -> String

 *		Return the last "property" name from a string in the format "company.profile.description"

 * Inputs:

 *		none

 * Outputs:

 *		result:String

 * Examples:

 *		"company.profile.description".lastProp() -> "description"

 *		"description".lastProp() -> "description"

 */



String.prototype.lastProp = function() {

	var r = this;

	if (r) {

		var p = r.lastIndexOf(".");

		if (p > -1) r = r.substring(p+1);

	}

	return r;

}





/*********************************************************************************

 * Function: String.lastProps() -> String

 *		Return the property path without the first property

 * Inputs:

 *		none

 * Outputs:

 *		result:String

 * Examples:

 *		"company.profile.description".lastProps() -> "profile.description"

 *		"description".lastProps() -> ""

 */



String.prototype.lastProps = function() {

	var r = this;

	if (r) {

		var p = r.indexOf(".");

		if (p > -1) {

			r = r.substring(p+1);

		} else {

			r = "_DefaultV";

		}

	}

	return r;

}





/*********************************************************************************

 * Functions to that check for the containment of other strings

 *********************************************************************************/





/*********************************************************************************

 * Function: String.IsStartWith(v) -> Boolean

 *		Returns true is the string starts with the specified string

 * Inputs:

 *		v:String - Value to check for at the start of the string

 * Outputs:

 *		result:Boolean - TRUE if starts with specified value

 * Examples:

 *		"this and that".IsStartWith("this") -> true

 *		"this and that".IsStartWith("that") -> false

 */



String.prototype.IsStartWith = function(v) {

	return (this.substring(0,v.length) == v)

}





/*********************************************************************************

 * Function: String.IsEndWith(v) -> Boolean

 *		Returns true is the string ends with the specified string

 * Inputs:

 *		v:String - Value to check for at the end of the string

 * Outputs:

 *		result:Boolean - TRUE if ends with specified value

 * Examples:

 *		"this and that".IsEndWith("this") -> false

 *		"this and that".IsEndWith("that") -> true

 */



String.prototype.IsEndWith = function(v) {

	return (this.substring(this.length-v.length) == v)

}





/*********************************************************************************

 * Function: String.IsContains(v) -> Boolean

 *		Test if the string IsContains the specified value

 * Inputs:

 *		v:String or RegExp - Value to check for within the string

 * Outputs:

 *		result:Boolean - TRUE if IsContains the specified value

 * Examples:

 *		"abc".IsContains("b") -> true

 *		"abc".IsContains(/a.c/) -> true

 */



String.prototype.IsContains = function(v) {

	if (!v) return true;

	if (v.constructor == String) {

		return (this.indexOf(v) != -1);

	} else {

		return v.test(this);

	}

}





/*********************************************************************************

 * Function: String.IsNotContain(v) -> Boolean

 *		Test if the string does not contain the specified value

 * Inputs:

 *		v:String or RegExp - Value to check for within the string

 * Outputs:

 *		result:Boolean - TRUE if does not contain the specified value

 * Examples:

 *		"abc".IsNotContain("d") -> true

 *		"abc".IsNotContain(/c/) -> false

 */



String.prototype.IsNotContain = function(v) {

	if (!v) return true;			// Return true if no value specified

	if (v.constructor == String) {

		return (this.indexOf(v) == -1);

	} else {

		return !v.test(this);

	}

}





/*********************************************************************************

 * Functions to perform type conversion

 *********************************************************************************/





/*********************************************************************************

 * Function: String.toObject() -> Object

 *		Converts a string representation of an object to a JavaScript object

 * Inputs:

 *		none

 * Outputs:

 *		result:Object - The Object that is represented as the string

 * Examples:

 *		"{a:1,b:2}" -> {a:1,b:2}

 *		"a:3,b:4" -> {a:3,b:4}

 */



String.prototype.toObject = function() {

	if (this) {

		var r = WEBBROWSER.eval(((this.charAt(0) == "{") ? this : "{" + this + "}"));

		if (r == null) r = {};		// Always return a valid object

	} else {

		r = {};

	}

	return r;

}





/*********************************************************************************

 * Function: String.toArray() -> Array

 *		Converts a string representation of an Array to a JavaScript Array

 * Inputs:

 *		none

 * Outputs:

 *		result:Array - The Array that is represented as the string

 * Examples:

 *		"[1,2,3]" -> [1,2,3]

 *		"1,2" -> [1,2]

 */



String.prototype.toArray = function() {

	if (this) {

		var r = WEBBROWSER.eval(this);

		if (r == null) r = [];		// Always return a valid object

	} else {

		r = [];

	}

	return r;

	//*** OMIT BRACKETS IF THEY ARE ALREADY IN THE STRING??? ***

}





/*********************************************************************************

 * Functions to extract portions of a string

 *********************************************************************************/





/*********************************************************************************

 * Function: String.range(value,start) -> Object {index,lastIndex}

 *		Test if the string IsContains the specified value

 * Inputs:

 *		value - String or RegExp

 *		start - index to start search, null = beginning

 * Outputs:

 *		result:Object





 *			lastIndex - ending position for the value (-1 if not found)

 * Examples:

 *		"abc".range("b") -> {index:1,lastIndex:1}

 *		"abc".range(/a.c/) -> {index:0,lastIndex:2}

 */



String.prototype.range = function(value, start) {

	var r = {};

	if (value) {

		if (typeof value == "string") {		// *** FASTER TO USE CONSTRUCTOR COMPARISON?? ***

			r.index = this.indexOf(value, start);

			r.lastIndex = (r.index > -1)  ? r.index + value.length : -1;

		} else {

			r2 = value.exec( start ? this.substring(start) : this );

			if (r2) {

				if ( !start ) start = 0;

				r2.lastIndex = r2.index + r2[0].length;

				r.index = r2.index + start;

				r.lastIndex = r2.lastIndex + start;

			} else {

				r.index = -1;

				r.lastIndex = -1;

			}

		}

	} else {

		r.index = 0;

		r.lastIndex = 0;

	}

	return r;

}





/*********************************************************************************

 * Function: String.Range([prefix],[suffix],[withPrefix],[withSuffix]) -> String

 *		Get the contents of a string between the specified values

 * Inputs:

 *		prefix - String or RegExp - Start of the range (start of string if not specified)

 *		suffix - String or RegExp - End of the range (end of String if not specified)

 *		withPrefix - Boolean - TRUE to include prefix in result

 *		withSuffix - Boolean - TRUE to include suffix in result

 * Outputs:

 *		result:String - Contents of the range

 * Examples:

 *		"this is a <b>test</b>".Range("<b>","</b>") -> "test"

 */



String.prototype.Range = function(prefix,suffix,withPrefix,withSuffix, count) {



	if (!this) return "";

	if(!count)

		count =1;



	// Locate the prefix value within the source string

	var pr = this.range(prefix);

	for(var i=1; i<count; i++)

	{

		if(pr.index <0 ) return '';

		pr = this.range(prefix, pr.lastIndex);

	}



	// Check if a value was found

	if (pr.index >= 0) {



		if (suffix) var sr = this.range(suffix,pr.lastIndex);



		if (sr && sr.index >= 0) {

			return this.substring( (withPrefix) ? pr.index : pr.lastIndex, (withSuffix) ? sr.lastIndex : sr.index );

		} else {

			return this.substring( (withPrefix) ? pr.index : pr.lastIndex );

		}



	} else {

		return "";

	}



}





/*********************************************************************************

 * Function: String.Before(match,[prefix],[suffix],[count]) -> String

 *		Get the range starting with the first instance of the prefix value

 *		BEFORE the match condition

 * Inputs:

 *		match:S or RegExp - Value to match

 *		prefix:S or Array - Start of the range (first instance prior to match)

 *			If an array is specified then match the first one prior to the value

 *		suffix:S - String or RegExp - End of the range (end of String if not specified)

 *		count:N - Which instance of the prefix to use (2=find twice)

 * Outputs:

 *		result:String - Contents of the range

 * Examples:

 *		"this is a <b>test</b>".Before("est","<b>","</b>") -> "test"

 */



String.prototype.Before = function(match,prefix,suffix,count) {



	if (!this) return "";

	if (!count) count = 1;



	// Locate the match value within the source string

	var mr = this.range(match);

	var r = "";

	

	// Check if a value was found

	if (mr.index >= 0) {

	

		var p = mr.index;

		var pa = (prefix.constructor == Array);	// Check if prefix is an array

		

		for (var i=0; i<count; i++) {

			if (pa) {

				var p1 = -1;							// Default to not found

				for (var j=0; j<prefix.length; j++) {	// Step through the array of prefix values

					var p2 = this.lastIndexOf(prefix[j],p-1);

					if (p2 > p1) p1 = p2;				// Remember the last instance found

				}

				p = p1;

			} else {

				p = this.lastIndexOf(prefix,p-1);

			}

		}

		

		if (p != -1) {

			r = this.substring(p);

			if (suffix) {

				mr = r.range(suffix, mr.index-p);

				r = r.substring(0,mr.lastIndex);

			}

		}

		

	}



	return r;

	

}



String.prototype.BT = function(match,TAG,count,n) {

	if (!this) return [];

	if (!count) count = 1;

	if (!n) n = 1;

	

	var prefix = [];

	prefix[0] = "<" + TAG.toUpperCase();

	prefix[1] = prefix[0].toLowerCase();

	

	// Locate the match value within the source string

	var r = "";

	var s = this;

		

	// Check if a value was found

	var mr = s.range(match);

	if (mr.index >= 0) {

	

		var p = mr.index;

		for (var i=0; i<count; i++) {

			var p1 = -1;							// Default to not found

			for (var j=0; j<prefix.length; j++) {	// Step through the array of prefix values

				var p2 = s.lastIndexOf(prefix[j],p-1);

				if (p2 > p1) p1 = p2;				// Remember the last instance found

			}

			p = p1;

		}

		

		if (p != -1) {									// Check if a match was found

			r = s

				.substring(p)							// Start the string at position p and then get the specified TAG

				.arrayByTag(TAG,null,null,null,null,n)			// Get the specified number of tags

				;

			if (n != 1) r = r.join("");	// Concatenate the tags

		}

		

	}



	return r;

}



// count - number of times to search backwards to get first instance of TAG

// n - number of instances of TAG to return (e.g. 2 tables)

String.prototype.BTA = function(match,TAG,count,n) {

	if (!this) return [];

	if (!count) count = 1;

	if (!n) n = 1;

	

	var prefix = [];

	prefix[0] = "<" + TAG.toUpperCase();

	prefix[1] = prefix[0].toLowerCase();

	

	// Locate the match value within the source string

	var r = [];

	var s = this;

		

	// Check if a value was found

	var mr = s.range(match);

	while (mr.index >= 0) {

	

		var p = mr.index;

		for (var i=0; i<count; i++) {

			var p1 = -1;							// Default to not found

			for (var j=0; j<prefix.length; j++) {	// Step through the array of prefix values

				var p2 = s.lastIndexOf(prefix[j],p-1);

				if (p2 > p1) p1 = p2;				// Remember the last instance found

			}

			p = p1;

		}

		

		if (p != -1) {									// Check if a match was found

			i = r.length;

			r[i] = s

				.substring(p)							// Start the string at position p and then get the specified TAG

				.arrayByTag(TAG,null,null,null,null,n)			// Get the specified number of tags

				;

			if (n != 1) r[i] = r[i].join("");			// Concatenate the tags

			s = s.substring(mr.lastIndex);				// Remainder of string

			mr = s.range(match);						// Check for the next match

		} else {

			mr.index = -1;								// Do not keep searching

		}

		

	}



	return r;

}





// String.RangeOuter - get OUTER range (includes prefix and suffix)



String.prototype.RangeOuter = function(prefix,suffix) {

	return this.Range(prefix,suffix,true,true);

}



// String.RangeLeft - get LEFT range (includes prefix)

String.prototype.RangeLeft = function(prefix,suffix) {

	return this.Range(prefix,suffix,true,false);

}



// String.RangeRight - get RIGHT range (includes suffix)

String.prototype.RangeRight = function(prefix,suffix) {

	return this.Range(prefix,suffix,false,true);

}





// String.arrayByRange([prefix,[suffix],[matchCriteria],[omitCriteria],[bInner]) -> Array

//		Return an array of ranges that match the prefix/suffix specification

// matchCriteria - String or RegExp - further restricts the resulting values

// omitCriteria - String or RegExp - causes values to be removed that meet the criteria

// bInner - Boolean - Indicates that the values between the prefix/suffix (vs including the prefix/suffix values) should be returned

// Examples:

//		"a<b>cd<e>fg".arrayByRange("<",">") -> ["b","e"]

//		"a<b>cd<e>fg".arrayByRange("<",">",/b/) -> ["b"]



String.prototype.arrayByRange = function(prefix,suffix,matchCriteria,omitCriteria,bInner,maxCount) {



	var result = [];



	if (!this) return result;



	var s = this;

	var more = true;

	var sPtr = 0;



	while (more) {



		var pr = s.range(prefix, sPtr);



		more = false;



		// Check if a value was found

		if (pr.index >= 0) {



			if (suffix) var sr = s.range(suffix, pr.lastIndex);

			if (sr && sr.index >= 0) {

				var match = s.substring(pr.index,sr.lastIndex);

				if (match && match.IsContains(matchCriteria) && match.IsNotContain(omitCriteria) ) {

					if (bInner) match = match.substring(pr.lastIndex-pr.index,sr.index-pr.index);

					result[result.length] = match;		// Add the value to the results array

				}

				sPtr = sr.lastIndex;

				more = true;



				if (maxCount && result.length >= maxCount) more = false;

			}

		}

	}

	return result;

}





// String.DeleteR(prefix,suffix,match) -> String

//		Strip ranges matching the criteria

// Prefix - String or RegExp - Start of ranges to be deleted

// Suffix - String or RegExp - End of ranges to be deleted

// match - String or RegExp - deleted String must match

// Examples:

//		"a<b>cd<e>fg".DeleteR("<",">") -> "acdfg"



String.prototype.DeleteR = function(prefix,suffix,match) {



	if (!this) return "";



	var s = this;

	var sPtr = 0;

	var more = true;

	var out = "";



	while (more) {



		// Locate the prefix value within the source string

		var pr = s.range(prefix, sPtr);



		more = false;



		// Check if a value was found

		if (pr.index >= 0) {



			if (suffix) var sr = s.range(suffix, pr.lastIndex);



			if (sr && sr.index >= 0) {

				var bDel=true;

				if(match )

				{

					var mr= s.range(match, pr.index);

					if(mr.index <0 || mr.index>sr.index)

						bDel= false;

				}

				if(bDel)

				{

					out += s.substring(sPtr,pr.index);

					sPtr = sr.lastIndex;

				}

				else

				{

					out += s.substring(sPtr,sr.lastIndex+1);

					sPtr = sr.lastIndex+1;

				}

				more = true;

			}

		}

	}

	out += s.substring( sPtr );



	return out;

}





// String.DeleteTag(tagName) -> String

//		Delete HTML elements from a string based on a specified TAG

// tagName - Name of HTML TAG to be deleted (e.g. "TABLE")

// Examples:

//		"this is <b>not</b> a test".DeleteTag("b") -> "this is  a test"



String.prototype.DeleteTag = function(tagName) {

	return this.DeleteR(Tag(tagName),EndTag(tagName));

}



// String.Match(matchExp,matchCount,matchIndex) -> String

//		Get the contents of a string matching the specified Regular Expression

// matchExp - RegExp - Expression to match

// matchCount - Integer (optional) - which item to return (first, second, etc.).  Defaults to 1.

// matchIndex - Integer (optional) - subexpression to return (defaults to 0).

// Examples:

//		"this is a test".Match(/t\wst/) -> "test"



String.prototype.Match = function(matchExp,matchCount,matchIndex) {



	if (!this) return "";

	

	if (! matchCount) matchCount = 1;	// Default to the first match found

	

	var r;

	

	if (matchCount <= 1) {

		r = matchExp.exec(this);

	} else {

		var sub = this;

		for (var i=0;i<matchCount;i++) {

			r = matchExp.exec(sub);

			if (r) {

				r.lastIndex = r.index + r[0].length;

				sub = sub.substring(r.lastIndex);

			} else {

				i = matchCount;	//exit the loop

			}

		}

	}

	

	if (r) {

		if (!matchIndex) matchIndex = 0;

		return r[matchIndex];

	} else {

		return "";

	}

	

}



// String.arrayByMatch(matchExp,filterExp) -> Array

//		Get an array of values matching the expression

// matchExp - RegExp - Expression to match

// filterExp - RegExp - Expression to evaluation which items to include



String.prototype.arrayByMatch = function(matchExp,filterExp) {



	if (!this || !matchExp) return [];



	matchExp = matchExp.source ? new RegExp( matchExp.source, "g" ) : matchExp;

	

	var r = this.match(matchExp);

	if (r) {

		if (filterExp) {

			for (var i=0; i<r.length; i++) r[i] = filterExp.getString(r[i]);

		}

		return r;

	} else {

		return [];

	}

	

}



// Return the count of the number of times the expression is found

// *** ADD SUPPORT FOR STRING ARGUMENT ***

String.prototype.count = function(exp) {

	var n = 0;						// Counter for number of occurances

	var h = this;

	while (h) {

		var p = h.range(exp);		// Find the next occurance

		if (p.lastIndex > -1) {

			h = h.substring(p.lastIndex);

			n++;						// Increment the counter

		} else {

			h = "";

		}

	}

	return n;

}



//--------------- Extract "TAG" contents from an HTML fragment ---------------



// String.Tag - Extract an HTML TAG from a String

// sTag - String - HTML TAG to match (e.g. "TABLE")

// matchCriteria - String or RegExp (optional) - Returned value must contain criteria

// omitCriteria - String or RegExp (optional) - Returned value must not contain criteria

// bInner - Boolean (optional) - Return innerHTML (without enclosing tags)

// bNoNest - Boolean (optional) - TRUE to not perform nested TAG checks



String.prototype.Tag = function(sTag,matchCriteria,omitCriteria,bInner,bNoNest) {

	return this.arrayByTag(sTag,matchCriteria,omitCriteria,bInner,bNoNest,1);

}



// Get the Nth instance of a TAG

String.prototype.TagByNum = function(sTag,n) {



	if (!this) return "";

	var t = Tag(sTag);

	var h = this;				// Result value

	

	// Skip initial values

	for (var i=0; i<n; i++) {

		var p = h.range(t);		// Find the next occurance

		if (p.lastIndex > -1) h = h.substring(p.lastIndex);

		if (!h) return "";

	}

	

	return h.arrayByTag(sTag,null,null,false,false,1);

}



// String.TagInner - Extract the innerHTML for an HTML TAG from a String

// sTag - String - HTML TAG to match (e.g. "TABLE")



String.prototype.TagInner = function(sTag) {

	return this.arrayByTag(sTag,null,null,true,false,1);

}



// String.arrayByTag - Extract an array of HTML tags from a String

// sTag - String - HTML TAG to match (e.g. "TABLE")

// matchCriteria - String or RegExp (optional) - Returned value must contain criteria

// omitCriteria - String or RegExp (optional) - Returned value must not contain criteria

// bInner - Boolean (optional) - Return innerHTML (without enclosing tags)

// bNoNest - Boolean (optional) - TRUE to not perform nested TAG checks

// maxCount - Integer (optional) - Maximum number of items in the array

// cs - boolean (optional) - Case sensitivity true if TAG is case sensitive



String.prototype.arrayByTag = function(sTag,matchCriteria,omitCriteria,bInner,bNoNest,maxCount,cs) {

	var s = this;



	if (!maxCount) maxCount = 0;

	if (maxCount == 1) {

		var result = "";

	} else {

		result = [];

	}

	

	if (!s) return result;

	

	var prefix; 

	var suffix;

						

	if ((cs != null) && cs)

	{

		prefix = XMLT(sTag);

		suffix = XMLTe(sTag);

	}

	else

	{

		prefix = Tag(sTag);

		suffix = EndTag(sTag);

	}

	var prefixStart, prefixEnd, suffixStart, suffixEnd, r, r1, r2;

	

	var more = true;



	while (more) {

			

		// Locate the prefix value within the source string

		r = prefix.exec(s);

						

		if (r) {

			r.lastIndex = r.index + r[0].length;

			

			prefixStart = r.index;

			prefixEnd = r.lastIndex;

		} else {

			prefixStart = -1;

		}

		more = false;

				

		// Check if a value was found

		if (prefixStart >= 0) {

			var prefixCount = 1;

			var nextPrefix;

			var nestEnd = 0;

			var s2 = s.substring(prefixEnd);

			

			if (bNoNest) {

				r1 = suffix.exec(s2);

				suffixStart = (r1) ? r1.index : -1;

			} else {

			

				// Handle nested tags

				

				while (prefixCount > 0) {

			

					r1 = suffix.exec(s2);

					suffixStart = (r1) ? r1.index : -1;

			

					r2 = prefix.exec(s2);

					nextPrefix = (r2) ? r2.index : suffixStart+1;

					

					if (suffixStart >= 0 && suffixStart > nextPrefix) {

						r2.lastIndex = r2.index + r2[0].length;

						s2 = s2.substring(r2.lastIndex);

						nestEnd += r2.lastIndex;

						prefixCount++;

					} else {

						if (r1 && prefixCount > 1) {

							r1.lastIndex = r1.index + r1[0].length;

							s2 = s2.substring(r1.lastIndex);

							nestEnd += r1.lastIndex;

						}

						prefixCount--;

					}

				}

			}

			

			if (suffixStart >= 0) {

				r1.lastIndex = r1.index + r1[0].length;

				suffixEnd = nestEnd + r1.lastIndex;

				var match = s.substring(prefixStart,prefixEnd+suffixEnd);

				if (match && match.IsContains(matchCriteria) && match.IsNotContain(omitCriteria) ) {

					if (bInner) match = s.substring(prefixEnd,prefixEnd+suffixStart+nestEnd)

					if (maxCount == 1) return match;

					result[result.length] = match;

				}



				if (bNoNest) {

					s = s.substring(prefixEnd+suffixEnd);

				} else {

					s = s.substring(prefixEnd);

				}

			}

			else  {

				var fPos;

				r1 = suffix.exec(s);

				if (r1) {

					(bInner) ? fPos = r1.index : fPos = r1.lastIndex;

					var match = s.substring(0, fPos);

					if (!bInner) {

						match = r[0] + match;

					}

					if (match && match.IsContains(matchCriteria) && match.IsNotContain(omitCriteria) ) {

						if (maxCount == 1) return match;

						result[result.length] = match;

						//s = s2;	

					}

					s = s.substring(r1.lastIndex);

				}

				else {

					return result;

				}

			}

			more = (maxCount == 0 || result.length < maxCount);



		}

		

	}



	return result;

}



// String.replaceAll( filter, text ) -> String

//		Replaces all filter matches with text

// Inputs:

//		filter - regular expression or string match

//		text - replacement text



String.prototype.replaceAll = function(filter,text) {

	if ( !filter ) return this;

	

	//filter = filter.source ? new RegExp( filter.source, filter.global ? "gi" : "g" ) : filter;

	if (filter.source)

	{

		var s = filter.toString();

		if ((s.charAt(s.length - 1) == 'i') || (s.charAt(s.length - 2) == 'i'))

		{

			filter = new RegExp(filter.source, "gi");

		}

		else

		{

			filter = new RegExp(filter.source, "g");

		}

	}

	else {

		var exp = /([\/\\\.\*\+\?\|\(\)\[\]\{\}'])/g;

		newcrit = filter.replace(exp, "\\$1");

		filter = new RegExp(newcrit, "g")

	}

	return this.replace( filter, text );

}



String.prototype.toElId = function(){

	var el_id = this;

	if(el_id.indexOf('.') != -1){

		el_id = el_id.replace(/\./g, '__');

	}

	if(el_id.indexOf('|') != -1){

		el_id = el_id.replace(/\|/g, '_$|').replace(/\|/g, '_');

	}

	

	return el_id;

}



// String.text() -> String

//		Convert an HTML string to the Text part of the string

// Inputs:

//		type - Type of conversion to perform

//			0: default

//			1: Differentiate P and BR

//			2: Replace "\n" with "<BR>"



String.prototype.text = function(type) { 



	var r;

	if (type == 1) {

		r = this.replace(/\n/g," ");

		r = r.replaceAll(Tag.BR,"\r");

		r = r.replaceAll(EndTag.TD,"\n");

		r = r.replaceAll(Tag.P,"\n");

	} else if (type == 2) {

		r = this.replaceAll(Tag("P|BR"),"\r");	// Convert to character that can be restored

	} else {

		r = this.replaceAll(Tag("P|BR"),"\n");	// Convert to CR

	}

	

	r = r.replace(TAG.all,"");			// Remove tags

	r = r.replace(/ +/g," ");			// Compress whitespace

	

	r = r.replace(/&nbsp;/g," ");		// Convert escaped characters

	r = r.replace(/&amp;/g,"&");

	r = r.trim();						// Trim whitespace

	

	if (type == 2) r = r.replace(/\r/g,"<BR>");	// Restore line breaks

	

	return r;

}



// String.filter(filterCriteria) -> String

// Function to restrict the string to the specified criteria.  Strips out all other text.

// filterCriteria - RegExp - Expression to match within the string

// Examples:

//		"abcabc".filter(/a/g) -> "aa"



String.prototype.filter = function(filterCriteria) {

	var result = "";

	var r = this.match(filterCriteria)

	if (r) for (var i=0;i<r.length;i++) result += r[i];

	return result;

};



// String.filterA(filterCriteria) -> Array

// Function to restrict the string to the specified criteria.  Strips out all other text.

// filterCriteria - RegExp - Expression to match within the string

// Examples:

//		"abcabc".filterA(/a/g) -> ["a","a"]



String.prototype.filterA = function(filterCriteria) {

	var r = this.match(filterCriteria)

	if (r) {

		return r;

	} else {

		return [];

	}

};



// String.strip(filterCriteria) -> String

// Function to strip text that meets filter criteria.  Multiple values can

// be passed to strip multiple types of text.

// filterCriteria - RegExp - Expression to match within the string

// Examples:

//		"abcabc".strip("b") -> "acac"

//		"abcabc".strip("a","c") -> "bb"



String.prototype.strip = function(filterCriteria) {

	if (arguments.length <= 1) {

		return this.replaceAll(filterCriteria,"");

	} else {

		var s = this.replaceAll(filterCriteria,"");

		for (var i=1;i<arguments.length;i++) s = s.replaceAll(arguments[i],"");

		return s;

	}

};



// String.flip() -> String

// Function to flip the order of a string in reverse order

// Examples:

//		"abcdef".flip() -> "fedcba"



String.prototype.flip = function() {

	var retVal = '';

	for( var i= this.length-1; i > -1; i-- ) {

		retVal += this.charAt(i);

	}

	return retVal;

};



String.prototype.hrefWP = function(wp) {

	var url = (wp.url2) ? wp.url2 : wp.url;



	var s = this;

	var h2 = HTML.href.split(url);			// Split the parts of the base URL

	var domain = h2.protocol + h2.host;	

	var dir = HTML.href.dir(url);



	// Update HTML attributes href, src, action	

	if (domain) {

		// Convert references within the domain

		s = s.replace( /(\s(href|src|action|background)\s*=\s*["']?)\//gi, "$1" + domain + "/");

	}



	if (url) {

		// Convert references within the domain

		s = s.replace( /(\s(href|src|action|background)\s*=\s*["']?)\#/gi, "$1" + url + "#");

	}



	if (dir) {			

		// Convert explicit references to include a tab character (so they are not changed)

		s = s.replace(/(\s(href|src|action|background)\s*=)\s*(["']?(https?:|\/\/|javascript:|mailto:))/gi, "$1" + "\t" + "$3");		// Use tab to avoid matching in next step



		// Convert references within the directory

		s = s.replace(/(\s(href|src|action|background)\s*= *["']?)([^\/\t'"])/gi, "$1" + dir + "$3");

	}

//	alert(s);

	return s;

}



// String.toRegExp() -> RegExp

// Convert a string value to a regular expression

// s - String - Source string

// exp - RegExp - Resulting expression

// Examples:

//		"/abc/i"  -->  /abc/i

//		"abc*"	--> /^abc.*$/



String.prototype.toRegExp = function() {

	var attributes = "";

	var s = this;

	if (s.charAt(0) == "/") {

		var p = s.lastIndexOf("/");

		attributes = s.substring(p+1);

		s = s.substring(1,p);	// Strip "/" delimiters

	} else {

		s = "^" + s.replace(/\*/g,".*") + "$";	// Interpret * as wildcard

	}

	s = s.replace(/\\/g,"\\\\");

	return new RegExp(s,attributes);

}





/*********************************************************************************

 * Function: String.apply(f) -> String

 *		Apply a function to a string

 * Inputs:

 *		f:Function - function to be applied to the string

 * Outputs:

 *		result:String - Source string after the function was applied

 */



String.prototype.apply = function(f) {

	return f(this); 

}





/*********************************************************************************

 * Regular Expression Utilities

 *********************************************************************************/





/*********************************************************************************

 * Function: RegExp.getString(str,[index]) -> String

 *		Get a string value result from a regular expression.

 *		Always returns a string value

 * Inputs:

 *		str:S - String value to apply regular expression to

 *		index:I - Index within regular expression if subexpressions are used

 * Outputs:

 *		result:S - Value that was found or "" if not found

 */



RegExp.prototype.getString = function(str, index) {

	if (! index) index = 0;			// Default to the first item in the result array

	var a = this.exec(str, index);	// Apply the expression to the string

	if (!a) return "";				// Return "" if no match found

	var r = a[index];

	if (!r) return "";				// Return "" if 	 index

	return r;						// Return the matched item

}





/*********************************************************************************

 * Tag Handling Utilities

 *********************************************************************************/



var TAG = {



	init: function() {	// Pre-calculate some common tags



		Tag("A");

		Tag("B");

		Tag("BR");

		Tag("IMG");

		Tag("P");

		Tag("TABLE");

		Tag("TD");

		Tag("TITLE");

		Tag("FONT");

		Tag("SCRIPT");

		Tag("DIV");



		EndTag("A");

		EndTag("B");

		EndTag("P");

		EndTag("TABLE");

		EndTag("TD");

		EndTag("TITLE");

		EndTag("FONT");

		EndTag("SCRIPT");

		EndTag("DIV");



		StartAndEndTag("A");

	},



//  Old not really NS barfs on syntax, will investigate futher

//

//	all: /<([^>'"]*|"[^"]*"|'[^']*')*>/g,	// Match all tags

//	all2: /<[^>]*>/g,	// Faster version for approximation of tags	

//	comment: /<!--([^>'"]*|"[^"]*"|'[^']*')*>/g,	// Match comment tags

	

	all: new RegExp( "<[^>]*>", "g" ),

	all2: new RegExp( "<[^>]*>", "g" ),	// Faster version for approximation of tags	

	comment: new RegExp( "<\!--[^>]*>", "g" ),	// Match comment tags



// NOTE:  Tag regular expressions are no longer global.

// NS RegExp.exec() function has problems doing repeated matchings on a global regexp.

// Most string methods have a ..All function for global matching ( eg... .replace => .replaceAll )

	

	startTag: function(tagName,bNoCache) {

		return TAG.exp(tagName,TAG.startTag,"<([T])(\\s+[^>'" + '"]*|"[^"]*"' + "|'[^']*')*>",bNoCache);

	},

	

	endTag: function(tagName,bNoCache) {

		return TAG.exp(tagName,TAG.endTag,"<\\/([T])>",bNoCache);

	},

	

	startOrEnd: function(tagName,bNoCache) {

		return TAG.exp(tagName,TAG.startOrEnd,"<\\/?([T])(\\s[^>'" + '"]*|"[^"]*"' + "|'[^']*')*>",bNoCache);

	},

	

	startEnd: function(tagName,bNoCache) {

		return TAG.exp(tagName,TAG.startEnd,"<([T])(\\s[^>'" + '"]*|"[^"]*"' + "|'[^']*')*>[^<]*<\\/([T])>",bNoCache);

		// *** EMBEDDED TAGS???  /<(a|A)(\s[^>'"]*|"[^"]*"|'[^']*')*>([^<'"]*|"[^"]*"|'[^']*')*<\/(a|A)>/g;



	},



	startXML: function(tagName,bNoCache) {

		return TAG.XMLexp(tagName,TAG.startTag,"<([T])(\\s[^>'" + '"]*|"[^"]*"' + "|'[^']*')*>",bNoCache);

	},

	

	endXML: function(tagName,bNoCache) {

		return TAG.XMLexp(tagName,TAG.endTag,"<\\/([T])>",bNoCache);

	},

	

	startOrEndXML: function(tagName,bNoCache) {

		return TAG.XMLexp(tagName,TAG.startOrEnd,"<\\/?([T])(\\s[^>'" + '"]*|"[^"]*"' + "|'[^']*')*>",bNoCache);

	},

	

	startEndXML: function(tagName,bNoCache) {

		return TAG.XMLexp(tagName,TAG.startEnd,"<([T])(\\s[^>'" + '"]*|"[^"]*"' + "|'[^']*')*>[^<]*<\\/([T])>",bNoCache);

		// *** EMBEDDED TAGS???  /<(a|A)(\s[^>'"]*|"[^"]*"|'[^']*')*>([^<'"]*|"[^"]*"|'[^']*')*<\/(a|A)>/g;



	},



	

	make: {		// Functions to build standard versions of HTML tags

		A: function(href,text,title) { 

			if (!href) return "";

			if (!text) text=href; 

			return "<a " + ( (title) ? "title='"+title+"' " : "" ) + "href='" + href + "'>" + text + "</a>" 

		},

		

		extA: function(href,text,params,w,h) {

			w = (w) ? w : 300;

			h = (h) ? h : 300;



			if (USERBROWSER.ie4) {

				h += 20;

				w += 20;

			}

			

			var idx = -1;

			if (params) {

				if (!window.params) window.params = [];

				idx = window.params.length;

				window.params[idx] = params;

			}

			return '<a href="javascript:DIALOG.exPopUp(\'' + href + '\','+ idx + ','+ w + ','+ h + ')">' + text + '</a>' 

		},

		

		IFRAME: function(src) { 

			if (!src) return "";

			return "<iframe application=yes width=100% src='" + src + "'></iframe>";

		},

		

		detailLink: function(text,dLink_Value) {

			return '<a href="javascript:VIEWLVL.updateDetail(\'' + dLink_Value + '\');" title="master detail link">' + text + '</a>';

		}

	},

	

	clean: {	// Returned "cleansed" versions of source tags

		A: function(sHTML,cleanType) {	// cleanType=0: href & text, 1:href only

			if (!cleanType) cleanType = 0;

			var href = HTML.attribute(sHTML,"href");



			// Clean up . and .. paths in href

			href = TAG.clean.href( href );

						

			var text = (cleanType == 1) ? null : sHTML.text();

			return TAG.make.A(href,text);

		},



		// Could not use Regular expressions

		// NS had a bitch of a time processing /\// like statements

		href: function( href ) {

			if (!href) href = "";

			

			if ( !href.IsContains( "/../" ) && !href.IsContains( "/./" ) )

				return href;

			

			var aParts = href.split( "/" );

			for( var i = 0; i < aParts.length; i++ )

			{

				if( aParts[i] == "." ) {

					aParts[i] = null;

				} else if ( aParts[i] == ".." && i > 2 ) {

					aParts[i] = null;

					aParts[i-1] = null;

				}				

			}

			href = "";

			for( var i = 0; i < aParts.length; i++ )

				href += ( aParts[i] != null ) ? aParts[i] + "/" : "";		



			return href.substr( 0, href.length-1 );

		}

	},

	

	match: /\[T\]/g,

	

	exp: function(tagName,cache,expString,bNoCache) {

		var v = cache[tagName];

		if (!v) {

			

			var t = tagName.toLowerCase() + "|" + tagName.toUpperCase();

			//v = new RegExp(expString.replace(TAG.match,t),"g");

			v = new RegExp(expString.replace(TAG.match,t));



			//var t = tagName.toLowerCase() + "|" + tagName.toUpperCase();

			//v = new RegExp(expString.replace(TAG.match,tagName),"gi");

			//v = new RegExp(expString.replace(TAG.match,tagName), "i");

			if (!bNoCache) cache[tagName] = v;		// Do not cache resulting expression is flag is set

		}

		return v;

	},



	XMLexp: function(tagName,cache,expString,bNoCache) {

		var v = cache[tagName];

		if (!v) {

			v = new RegExp(expString.replace(TAG.match,tagName));

			if (!bNoCache) cache[tagName] = v;		// Do not cache resulting expression is flag is set

		}

		return v;

	}



}





/*********************************************************************************

 * Shortcuts to functions

 * Used to avoid verbose functions for commonly used utility functions

 *********************************************************************************/



Tag = TAG.startTag;

EndTag = TAG.endTag;

StartOrEndTag = TAG.startOrEnd;

StartAndEndTag = TAG.startEnd;



XMLT = TAG.startXML;

XMLTe = TAG.endXML;

XMLTs_e = TAG.startOrEndXML;

XMLTse = TAG.startEndXML;



// Initialize the TAG object



TAG.init();



/*********************************************************************************

 * StringBuffer uses an array to efficiently build a string

 *********************************************************************************/

function StringBuffer() {

	this.buffer = [];

}

StringBuffer.prototype = new Object();

StringBuffer.prototype.a = function (x) {

	this.buffer[this.buffer.length] = x;

}



StringBuffer.prototype.toString = function () {

	return this.buffer.join("");

}



StringBuffer.prototype.length = function () {

	return this.buffer.length;

}



StringBuffer.prototype.init = function () {

	this.buffer.length = 0;

}

StringBuffer.prototype.deleteString = function (x) {

	for(var i = 0; i < this.buffer.length;i++){

		if(this.buffer[i] == x){

			delete this.buffer[i];

			break;

		}

	}

}



String.prototype.gUserURL = function(bRefresh) {

	var tStampCookie = '';

	var tIdx = document.cookie.indexOf("T=");

	var tEdx = document.cookie.indexOf(";", tIdx); //check for endpoint at ';'

	

	if( bRefresh || tIdx == -1 ) { //if the cookie is not there or when we force it to change the cookie

		if (!/censoft\.com/i.test(document.location.host)) {

			document.cookie = "T=" + (new Date()).getTime() + "; expires=Thursday, 15-Apr-2010 20:00:00 GMT;path=/";

		} else {

			document.cookie = "T=" + (new Date()).getTime() + "; expires=Thursday, 15-Apr-2010 20:00:00 GMT;path=/;domain=.censoft.com";

		}

	}



	if (tEdx == -1) {

		tStampCookie = document.cookie.Range('T=','');

	} else {

		tStampCookie = document.cookie.Range('T=',';');

	}

	

	return this + "?u=" + gUserCookie + tStampCookie;

}



/*********************************************************************************

 * Object: String prototype insert()

 * Purpose: Will insert a string at the specified offset location.

 * Examples: '<Object style="width:100%"></Object>'.insert(15,'margin:2px;') -->

 *			 '<Object style="margin:2px;width:100%"></Object>'

 */

String.prototype.insert = function(offset, s) {

	var fSet = this.substring(0,offset);

	var lSet = this.substring(offset,this.length);

	return  fSet + s + lSet;

}



/*********************************************************************************

 * Object: String prototype getActiveXWrapper()

 * Purpose: Wraps up string object TAG with a div and sets the margin on the object TAG

 *          to 2px.

 * Examples: '<Object style="width:100%;"></Object>' --> '<div><Object style="margin:2px;width:100%"></Object></div>

 *			 '<Object></Object>' --> '<div><Object style="margin:2px"></Object></div>

 */

String.prototype.activeXWrapper = function(objString) {

	var s = this;

	var ts = s.toLowerCase(); //only use this variable to compare with other string.

	

	if( !s.IsContains('margin:') ) {//if there is no margin on the object TAG

		var offset = ts.range('style=\'');

		

		if( offset.lastIndex == -1 ) {//if style is not using single quote then check for double quote

			offset = ts.range('style="');

		}

		

		if( offset.lastIndex == -1 ) {//Case for when there is no style TAG

			var offsetObj = ts.range('<object ');

			if( offsetObj.lastIndex != -1 ) {

				s = s.insert(offsetObj.lastIndex, 'style="margin:2px;" ');

			}

		} else {

			s = s.insert(offset.lastIndex, 'margin:2px;');

		}

	}

	

	return  '<div>' + s + '</div>';

}//end activeXWrapper





 /*********************************************************************************

   * Function: String.getEachNthTag(Tag, mainTag, [tagPosition], [startElement], [removeTags], [maxCount]) -> array of string

   *		Returns array containing each Nth HTML element of type "Tag" that is embedded with an HTML element

   *		of type "mainTag"

   *

   * Inputs:

   *		Tag - string - (tagname) the TAG being extracted

   *		mainTag - string - (tagname) the tags being extracted from

   *		tagPosition - Integer - the position of Tag within mainTag to get(default = 0)

   *		startElement - Integer - the element to start with (default=0)

   *		removeTag - Boolean - 	true = return only table data. 

   					false = return table tags and table data (<td>data</td>)

   *					(default=true)

   *		maxCount - Integer - the maximum number of tags to get(default = no maximum)

   *

   * Outputs:

   *		Array of strings match the criteria

   * Examples:

   *	   <div>

   *		<b>Company</b>

   *		<b>Ticker</b>

   *		<b>Price</b>

   *	   </div>

   *   

   *	   <div>

   *		<b>Intel</b>

   *		<b>INTC</b>

   *	   <b>30.00</b>

   *	   </div>

   *

   *	   <div>

   *	   <b>Cisco</b>

   *	   <b>CSCO</b>

   *	   <b>15.00</b>

   *	   </div>

   *

   *	   <div>

   *	   <b>Yahoo</b>

   *	   <b>YHOO</b>

   *	   <b>20.00</b>

   *	   </div>

   *

   *	   getEachNthTag("B","DIV",0,2) --> ["Cisco","Yahoo"]

   */

   

   String.prototype.getEachNth = function(TAG, mTag, pos, start, rem, max)

   {	

   	var results = [];

   

    	if ((TAG == null) || (mTag == null))

    	{

   		return null;

    	}

    	if (pos == null)

    	{

   		pos = 0;

    	}

    	if (start == null)

    	{

   		start = 0;

    	}

    	if (rem == null)

    	{

   		rem = true;

    	}

    	if ((max == null) || (max == -1))

    	{

   		max = 0;

   	}

   	

   	var mainElements = this.arrayByTag(mTag, null, null, true, true);

   	if (start >= mainElements.length)

   	{

   		return null;

   	}

   	var j = 0;

   	for (var i = start; i < mainElements.length; i++) 

   	{

   		var e = mainElements[i].TagByNum(TAG, pos);

   		if (rem == true)

   		{

   			e = e.Tag(TAG, null, null, true, true);

   		}

   		results[j++] = e;

 		if ((max != 0) && (j == max))

 			break;

   	}

   	return results;

   	

   }

 

 /*********************************************************************************

  * Function: String.GC([colPosition],[startElement],[removeTags],[maxCount]) -> Array of Strings

  *		Return an array of maxCount elements starting at startElement from the columnPosition column of 

  *		an HTML table, with the table tags kept or removed.

  * Inputs:

  *		pos - integer - Postion of the column to return

  *		start - integer - Position of element to start with

  *		rem - Boolean - TRUE if only data is to be returned (no tags).

  *		max - integer - Maximum number of elements to include (no max if -1)

  * Outputs:

  *		result:Array of elements from the specified column

  * Examples:

  *		var table = 	"<TABLE>

  *				<TR>	<TD>this</TD> 	   <TD>is</TD> 	       	<TD>a</TD>	</TR>

  *				<TR>	<TD>test</TD> 	   <TD>of</TD> 	       	<TD>the</TD>	</TR>

  * 				<TR>	<TD>emergency</TD> <TD>broadcast</TD>	<TD>system</TD>	</TR>

  *				</TABLE>"

  *			

  *		table.getColumn(2, 1, true) = {"the", "system"}

  *		table.getColumn(1, 2, false) = {"<TD>broadcast</TD>"}

  */

  

  String.prototype.GC = function(pos,start,rem,max)

  {

  	return this.getEachNth("td|th", "tr", pos, start, rem, max);

  }

  

 

 /*********************************************************************************

   * Function: String.getFromNth(innerTag, outerTag, [rowPosition],[startElement],[removeTags],[maxCount]) -> Array of Strings

   *		Return an array of maxCount elements of TAG type inner embedded in the HTML TAG outer

   *		at position pos within the page, starting with the inner TAG at position start. 

   * Inputs:

   *		inner - String - Inner HTML TAG to extract

   *		outer - String - Outer HTML TAG to extract from

   *		pos - integer - Postion of the row to return

   *		start - integer - Position of element to start with

   *		removeTags - Boolean - TRUE if only data is to be returned (no tags).

   *		maxCount - integer - Maximum number of elements to include (no max if -1)

   * Outputs:

   *		result:Array of elements from the specified row

   * Examples:

   *		var table = 	"<TABLE>

   *				<TR>	<TD>this</TD> 	   <TD>is</TD> 	       	<TD>a</TD>	</TR>

   *				<TR>	<TD>test</TD> 	   <TD>of</TD> 	       	<TD>the</TD>	</TR>

   * 				<TR>	<TD>emergency</TD> <TD>broadcast</TD>	<TD>system</TD>	</TR>

   *				</TABLE>"

   *			

   *		table.getFromNth(2, 1, true) = {"broadcast", "system"}

   *		table.getFromNth(1, 2, false) = {"<TD>the</TD>"}

   */

 

 String.prototype.getFromNth = function(inner, outer, pos, start,rem,max)

 {

    	if (pos == null)

  		pos = 0;

  	if (start == null)

  		start = 0;

  	if (rem == null)

  		rem = true;

  	if (max == null)

  		max = 0;

  		

	var outerList = this.TagByNum(outer, pos);

	var innerList = outerList.arrayByTag(inner, null, null, rem, false);

   	if (start >= innerList.length)

   	{

   		return null;

   	}

   	var r = [];

   	for (i = 0; i < innerList.length; i++) {

   		if (i < max) {

   			r[i] = innerList[start];

   		}

   		else {

   			break;

   		}

   		start++;

   	}

   	return r;

   	//return innerList.slice(start, innerList.length);



 }

 

    

 /*********************************************************************************

  * Function: String.GR([rowPosition],[startElement],[removeTags],[maxCount]) -> Array of Strings

  *		Return an array of maxCount elements starting at startElement from the rowPosition row of 

  *		an HTML table, with the table tags kept or removed.

  * Inputs:

  *		rowPosition - integer - Postion of the row to return

  *		startPosition - integer - Position of element to start with

  *		removeTags - Boolean - TRUE if only data is to be returned (no tags).

  *		maxCount - integer - Maximum number of elements to include (no max if -1)

  * Outputs:

  *		result:Array of elements from the specified row

  * Examples:

  *		var table = 	"<TABLE>

  *				<TR>	<TD>this</TD> 	   <TD>is</TD> 	       	<TD>a</TD>	</TR>

  *				<TR>	<TD>test</TD> 	   <TD>of</TD> 	       	<TD>the</TD>	</TR>

  * 				<TR>	<TD>emergency</TD> <TD>broadcast</TD>	<TD>system</TD>	</TR>

  *				</TABLE>"

  *			

  *		table.getRow(2, 1, true) = {"broadcast", "system"}

  *		table.getRow(1, 2, false) = {"<TD>the</TD>"}

  */

 

 String.prototype.GR = function(pos,start,rem,max)

 {

 	return this.getFromNth("td|th", "tr", pos, start, rem, max);

 }

 

 /*********************************************************************************

   * Function: String.cleanTag([tagName], [attributeList]) -> string

   *		Strips attributes from an HTML TAG			

   *

   * Inputs:

   *		tagName - string - the name of the TAG that is being affected (the rest of the string stays intact)

   *		attibuteList - array of strings - the attributes to keep. The other attributes are stripped.

   * Outputs:

   *		result:Attributes not in the TAG are removed from the string

   * Examples:

   *		var html = 'My dog: <img  class="blah" onclick="swap()" src="image.gif" alt="My dog"><br>My cat: <img  class="blah" onclick="swap()" src="image2.gif" alt="My cat">'

   *		html.cleanTag("IMG", ["SRC","ALT"]) --> 'My dog: <img src="image.gif" alt="My dog"><br>My cat: <img src="image2.gif" alt="My cat">'

   */



 

/*********************************************************************************/



String.prototype.cleanTag = function(tagName, attrList)

{

	// get the property list

	attrList = attrList.join("|");

	

	// define expression to find the elements

	var tagCrit = "/<" + tagName + "[^>]*>/i";

	eval('var tagExp = ' + tagCrit);



	// define expression for finding attributes

	var attrcrit = "/(\\s+(" + attrList + ")\\s*=\\s*(\\w+|[\"][^\"]*[\"]|['][^']*[']))+/i";

	eval('var attrexp = ' + attrcrit);

	

	var sr;

	var s = this;

	var result = new StringBuffer("");

	var base = 0;



	// iterate through the string, building a new string in the process

	while ((sr = tagExp.exec(s)) != null)

	{

		result.a(s.substring(base, sr.index));

		//var newTag = sr[0].replace(attrexp, '');

		var newTag;

		result.a('<');

		result.a(tagName);

		while ((newTag = attrexp.exec(sr[0])) != null) {

			//var newTag = attrexp.exec(sr[0]);

			result.a(newTag[0]);

			sr[0] = sr[0].substring(newTag.lastIndex);

		}

		s = s.substring(sr.lastIndex);

		result.a('>');

	}

	result.a(s);

	return result.toString();

}



/*

tagName -- String, tag name

col -- int, column to be deleted, must >=1

'<TABLE><TR><TD>1</TD><TD>2</TD></TR><TR><TD>3</TD><TD>4</TD></TR></TABLE>'.DeleteColumn('TD', 2)

	--> ‘<TABLE><TR><TD>1</TD></TR><TR><TD>3</TD></TR></TABLE>’
*/



String.prototype.DeleteColumn= function(tagName, col)

{

	var s= this;

	var r='';



	var pos =0;

	var posSearch=0;

	for(var i=0;true;i++)

	{

		var ps= s.range(Tag(tagName), posSearch);

	

		if(ps.index == -1)

			break;

		if( i%col == (col-1))

		{

			r += s.substring(pos, ps.index);

			pe= s.range(EndTag(tagName), ps.index);

			if(pe.lastIndex > -1)

				pos= pe.lastIndex ;

			else

				pos= ps.lastIndex ;

			posSearch= pos;

		}

		else

			posSearch= ps.lastIndex + 1;

	}

	r += s.substr(pos);



	return r;

}



// Format the web page

String.prototype.formatPage= function()

{

//	alert("format");

	var s= this;

	if(!s) return;

	var frms= s.arrayByMatch(Tag('FRAME'));

	if(frms && frms.length>0)

	{

		var r= '';

		for(var i=0; i<frms.length; i++)

		{

			var src= HTML.attribute(frms[i], 'src');

			r+= TAG.make.A(src, src);

			if( i != frms.length -1)

				r+= '<br>';

		}

		return r;

	}

	return this

		.replace("\00","")								// Eliminate null characters

	//	.DeleteTag("SCRIPT")									// Remove SCRIPT TAG contents

		.DeleteTag("HEAD")										// Remove HEAD TAG contents

		.DeleteTag("STYLE")									// Remove STYLE TAG contents

	//	.DeleteR("<!--","-->")								// Remove HTML comments

		.strip(Tag("FONT|HTML"),EndTag("FONT|HTML"))			// Remove some of the formatting

	//	.replace(/([\s'"])on\w+\s*=/gi,"$1onevent=")	// Disable inline JavaScript

		.replace(/\sid\w+\s*=/gi," id_=")				// Disable IDs so they don't conflict with namespace

		.replace(/<body/gi,"<DIV")						// Change BODY to a DIV

		.replace(/<\/body/gi,"</DIV")					// Change BODY to a DIV

		.replace(/<form /gi,"<form target='newwindow' onsubmit='EVENT.onsubmit(this)' ")	// Assign custom onsubmit handler

		.replace(/([\s'"])target\w+\s*=/gi,"$1onevent=")	// Disable inline JavaScript

		;

}



// Format the web page

String.prototype.formatPageForPortlet = function()

{

	var s= this;

	if(!s) return;

	var frms= s.arrayByMatch(Tag('FRAME'));

	if(frms && frms.length>0)

	{

		var r= '';

		for(var i=0; i<frms.length; i++)

		{

			var src= HTML.attribute(frms[i], 'src');

			r+= TAG.make.A(src, src);

			if( i != frms.length -1)

				r+= '<br>';

		}

		return r;

	}

	

	

	return this

		.replace("\00","")								// Eliminate null characters

	//	.DeleteTag("SCRIPT")									// Remove SCRIPT TAG contents

//		.DeleteTag("HEAD")										// Remove HEAD TAG contents

	//	.DeleteTag("STYLE")									// Remove STYLE TAG contents

	//	.DeleteR("<!--","-->")								// Remove HTML comments

		.strip(Tag("FONT|HTML"),EndTag("FONT|HTML"))			// Remove some of the formatting

		//.replace(/([\s'"])on\w+\s*=/gi,"$1onevent=")	// Disable inline JavaScript

		.replace(/\sid\w+\s*=/gi," id_=")				// Disable IDs so they don't conflict with namespace

		.replace(/<body/gi,"<DIV")						// Change BODY to a DIV

		.replace(/<\/body/gi,"</DIV")					// Change BODY to a DIV

		.replace(/<form /gi,"<form onsubmit='EVENT.onsubmit(this)' ")	// Assign custom onsubmit handler

		.replace(/([\s'"])target\w+\s*=/gi,"$1onevent=")	// Disable inline JavaScript

		;

}



/**

	保留javascript  add by  meng

	if the function is in the html body,then It will be picked out

	else the script file will be all included.//only can do this

	*/

	String.prototype.KeepStyle = function()

	{

		if(this == null) return "";

		arrscript=this.arrayByRange("<link",">");

	//	alert("arrscript.length="+arrscript.length);

	   	for(var i = 0 ; i < arrscript.length; i++)

	   	{

	   		

	   	}

	   	

	}

	String.prototype.keepIframeJs = function()

	{

			var re = /<script/gi;

		//	alert(content);

			 var old = this;

			if (this.search(re)!=-1)

		   {		     

			   old=this.replace(re, "<script defer");

			   re=/<\/script>/gi;

			   old=old.replace(re,"<\/script>");

			//   this = old

		   }

		  // alert(old);

			return old;

	//	   return content+content.KeepJs();

	},

	String.prototype.KeepJs = function() {

	   if (this==null) return "";

	   var retvalue="";//存放返回值
	   re = /<script/gi;

	   if (this.search(re)!=-1)

	   {		     

		   var old=this.replace(re, "<script defer");

		   re=/<\/script>/gi;

		   old=old.replace(re,"<\/script>");

		   

		   onload=old.Range("<body",">");

		   var posonload=onload.indexOf("onload=");

		   

		   if (posonload>-1)

		   {

			   endonload=onload.indexOf("\"",posonload+8);

			   onload=onload.substring(posonload+8,endonload);

		   }else

			   onload="";

		 

		   arrscript=old.arrayByRange("<script","</script>");

		   if (arguments.length<1){//保留全部script

			   for (var i=0;i<arrscript.length ;i++ )

			   {

				   reg=/document.write\(/gi;

				   arrscript[i]=arrscript[i].replace(reg,"1;\/\/document.write\(");

				   reg=/window.open\(/gi;

				   arrscript[i]=arrscript[i].replace(reg,"1;\/\/window.open\(");

				   /*if the page exists the two script method above,the IE maybe crush.

				   If you find any other method,You can append it like above.*/

				   retvalue=retvalue+arrscript[i];



				   /*think it over if it can improve the performance or not?.

				   if (arrscript[i].search(reg)==-1)

				   {

					   retvalue=retvalue+arrscript[i];	   

				   }*/		

			   }

		   }  else {			   

			   var oldVal=this;

			   for (var i=0;i<arrscript.length ;i++ )

			   {

				   var sigvalue="";

				   var pre=arrscript[i].RangeOuter("<script",">");//for example <script defer language="javascript">

				   have=false;

				   for (var j=0;j<arguments.length ;j++ )

				   {

					   var reg=" "+arguments[j].toLowerCase();

					   var regexp=new RegExp(reg,"gi");

					   var start=arrscript[i].search(regexp);

					   if (start>0)

					   {						   

						   have=true;

						   var num=0;

						   var child=arrscript[i].substring(start,arrscript[i].length);

                           var end=child.search(/{/);

						   if (start+end>start){

							   num=1; 						   

							   while (end<child.length)

							   {

								   end++;								   

								   if (child.charAt(end)=="{")

									 num++;

								   if (child.charAt(end)=="}")

									 num--;									   

								   

								   if (num==0) break;//结束循环

							   }

							   sigvalue += "function " + arrscript[i].substring(start, start + end + 1);	

						   }

					   }

				   }//end arg loop

				   if (have)

     				   retvalue += pre + sigvalue + "</scr" + "ipt>";

			   }			  

		   }

		   if (onload!="")

		   {

			   retvalue += "<script defer language=\"javascript\">" + onload + "</scr" + "ipt>";

		   }



	   }

	   return retvalue;	   //should add the onload script



    }











// find user cookie

//

/*

var gUserCookie = "";

var uIdx = document.cookie.indexOf("U=");

if (uIdx == -1) 

{

	gUserCookie = "anon";

} 

else 

{

	var uEdx = document.cookie.indexOf(";", uIdx);

	if (uEdx == -1) 

	{

		gUserCookie = document.cookie.substring(uIdx);

	} 

	else 

	{

		gUserCookie = document.cookie.substring(uIdx+2,uEdx);

	}//end if

	gUserCookie = gUserCookie.substring(2);

	

}//end if

*/



function updateTCookie() {

	if (!/censoft\.com/i.test(document.location.host)) {

		document.cookie = "T=" + (new Date()).getTime() + "; expires=Thursday, 15-Apr-2010 20:00:00 GMT;path=/";

	} else {

		document.cookie = "T=" + (new Date()).getTime() + "; expires=Thursday, 15-Apr-2010 20:00:00 GMT;path=/;domain=.censoft.com";

	}

}



function InitUserCookie() 

{

	var uIdx = document.cookie.indexOf("U=");

	

	var g_UserCookie = "";

		

	if (uIdx == -1) 

	{

		//g_UserCookie = "anon";

		return("anon");

	} 

	else 

	{

		var uEdx = document.cookie.indexOf(";", uIdx);

		if (uEdx == -1) 

		{

			g_UserCookie = document.cookie.substring(uIdx);

		} 

		else 

		{

			g_UserCookie = document.cookie.substring(uIdx+2,uEdx);

		}

		//g_UserCookie = g_UserCookie.substring(2);

		//TODO: why do we change uIdx in only one case, but always substring g_userCookie?

		// use a different local var from the equivalent global var.

		return(g_UserCookie = g_UserCookie.substring(2));

	}

	//return(g_UserCookie);

}

var Debug={

	_flagDebug: true,

	_file: 'c:\\censoft-grp-trace.txt',

	trace: function(s)

	{

		if(!Debug._flagDebug) return;



		var date= new Date();		

		var fso= new ActiveXObject("Scripting.FileSystemObject");

		var f= fso.OpenTextFile(Debug._file, 8/*for appending*/, true);

		var time= date.getYear() + "-" + (date.getMonth()+1)+ "-" + date.getDate() + " " + date.getHours() + ":" + date.getMinutes()+ ":" + date.getSeconds();

		var log= ""+time +" : " + s;

		f.WriteLine(log);

		f.Close();

	},

	traceObj: function(o, name, bRecurse)

	{

		if(!Debug._flagDebug) return;



		if(!o) return;



		var date= new Date();		

		var fso= new ActiveXObject("Scripting.FileSystemObject");

		var f= fso.OpenTextFile(Debug._file, 8/*for appending*/, true);

		var time= date.getYear() + "-" + (date.getMonth()+1)+ "-" + date.getDate() + " " + date.getHours() + ":" + date.getMinutes()+ ":" + date.getSeconds();

		var log= ""+time +" : " + (name?name:'object');

		f.WriteLine(log);

		

		if(o)

		{

			if(typeof(o) == 'string')

				f.WriteLine(name + " = " + o);

			else

			{

				var level=1;

				for(os in o)

				{

					Debug.printObj(eval("o."+os), os, f, level, bRecurse);

				}

			}

		}

		else

			f.WriteLine("\t null");



		f.Close();

	},

	//call debuger

	debug: function()

	{

		if(!Debug._flagDebug) return;



		eval('alert(123;');

	},

	//private function

	printObj: function(o, name , f, level, bRecurse)

	{

		

		if(o == null)

			return;



		var sTab=""; 

		for(var i=0; i<level; i++)

			sTab += "\t";



		if(bRecurse && o == '[object Object]' )

		{

			f.WriteLine(sTab + name + " : ");

			f.WriteLine(sTab +"\t"+ "{");

			for(os in o)

			{

				if(os == '[object Object]')

					Debug.printObj(eval("o."+os), os, f, level+1);

				else

				{

					var s= "" + os;

					s.replaceAll("\n", "\n"+sTab+"\t\t");

					f.WriteLine(sTab+"\t\t" + os + " : " + eval("o."+os));

				}

			}

			f.WriteLine(sTab +"\t"+ "}");

		}

		else

		{

			

			var s= "" + o;

			s.replaceAll("\n", "\n"+sTab+"\t");

			f.WriteLine(sTab + name + " : " + s);

		}

	}

}



function Hex2Dec(hexStr)

{

	var decNum = 0;

	var j   = 0;

	var factor = new Array(4096,256,16,1);



	var k = hexStr.length;

	for(j = 0; j < k; j++)

	{

		var num1 = 0;

		var num2 = factor[j];

		

		var ch = hexStr.charAt(j).toUpperCase();

		switch (ch)

		{

		case 'F':

			num1  = 15 * num2 ;

			break;

		case 'E':

			num1  = 14 * num2 ;

			break;

		case 'D':

			num1  = 13 * num2 ;

			break;

		case 'C':

			num1  = 12 * num2 ;

			break;

		case 'B':

			num1  = 11 * num2 ;

			break;

		case 'A':

			num1  = 10 * num2 ;

			break;

		default:

			num1  = parseInt(ch) * num2 ;

			break;

		}

		decNum += num1;

		// alert("ch = " + ch + ", num1 = " + num1 + ", num2 = " + num2 + ", decNum = " + decNum);

		

	}

	// alert("hexStr = " + hexStr + ", decNum = " + decNum );

	return decNum;

}

function getChineseHex(str) /* \uhhhh\uhhhh */

{

	var len    = str.length;

	var i      = 0;

	var pos    = -1;

	var newStr = str;

	var chWord = "";

	var uniValue = 0;

	

	for(i = 0;i<len;i++)

	{

		pos = str.indexOf("\\u",i);

		if(pos > -1)

		{

			pattern  = new RegExp("\\\\u" + str.substring(pos+2,pos+6) ,"i");

			uniValue = Hex2Dec(str.substring(pos+2,pos+6));

			chWord   = String.fromCharCode(uniValue);

			newStr   = newStr.replace(pattern,chWord);

			i = pos + 5;

		}

	}

	return newStr;

}

function getChinese2(unistr)

{

	var newStr = getChineseHex(unistr);

	return newStr;

}

function getUnicodeValue(str,bHex,prex)

{

   var i   = 0;

   var ch  = '';

   var len = 0;

   var ret = "";

   

   // alert("str=" + str);

   

   len = str.length;

   for(i=0;i<len;i++)

   {

      ch = str.charCodeAt(i);

      if (ch > 255) 

		{

			if(bHex)

			{		

		   	ch = prex + ch.toString(16);

		   }

		   else

			{		

		   	ch = prex + ch.toString();

		   }

			if(prex == "&#") 

			{

				ch += ";" ;		

			}

		}

		else

		{

			ch = str.charAt(i);

		}

		

	   ret += ch;

	   

   }

   

   // alert("ch=" + ch);

   return ret;

}



function getCookieVal(offset)

{ 

　　var endstr=document.cookie.indexOf(";",offset);

　　if (endstr==-1) 

　　endstr=document.cookie.length; 

　　return unescape(document.cookie.substring(offset,endstr));

} 

function getcookie(name)

{ 

	var arg=name+"=";

    var alen=arg.length;

    var clen=document.cookie.length;

    var i=0;

    while(i<clen)

	{ 

	 var j=i+alen; 

　　  if(document.cookie.substring(i,j)==arg)

　　  return getCookieVal(j); 

　　  i=document.cookie.indexOf(" ",i)+1; 

　　  if(i==0) break;

    } 

　　return null;

} 





function deletecookie(name)

{ 

　　var exp=new Date(); 

　　exp.setTime(exp.getTime()-1); 

　　var cval=getcookie(name); 

　　document.cookie=name+"=NO;path=/;expires="+exp.toGMTString();

} 



var gUserCookie = InitUserCookie();



////////////by dj in 20030405 for recordpulse/////

function writeRecordScript(){



	document.write('<SCRIPT id="recordPulse" LANGUAGE="JavaScript" SRC=""><\/SCRIPT>');



}

function setRecordPulse_public(param)

{

	if(document.all.recordPulse){

	//	document.all.recordPulse.setAttribute("src", '/doOnlineuser'.servletURL() + '?a=RECORDPULSE&doingWhat='+param);

	}

}

function setRecordPulseForManager(param)

{

	if(document.all.recordPulse){

	//	document.all.recordPulse.setAttribute("src", '/CensManager'.servletURL() + '?a=RECORDPULSE&doingWhat='+param);

	}

}

function setRecordPulse_delete(param)

{

	if(document.all.recordPulse){

	//	document.all.recordPulse.setAttribute("src", '/doOnlineuser'.servletURL() + '?a=DELETEONLINEUSER');

	}

}

function setWindowUnloadEvnt(){

	window.onbeforeunload = function() {

	//	alert("index");

		setRecordPulse_delete();

	}	

}

//////////////////////////////////



/**

 * Provides a method to encode any string into a URL-safe

 * form.

 * Non-ASCII characters are first encoded as sequences of

 * two or three bytes, using the UTF-8 algorithm, before being

 * encoded as %HH escapes.

 * zhou 2003-5-7

 */

var URLUTF8Encoder=

{



	hex:[

		"%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07",

		"%08", "%09", "%0a", "%0b", "%0c", "%0d", "%0e", "%0f",

		"%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17",

		"%18", "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f",

		"%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27",

		"%28", "%29", "%2a", "%2b", "%2c", "%2d", "%2e", "%2f",

		"%30", "%31", "%32", "%33", "%34", "%35", "%36", "%37",

		"%38", "%39", "%3a", "%3b", "%3c", "%3d", "%3e", "%3f",

		"%40", "%41", "%42", "%43", "%44", "%45", "%46", "%47",

		"%48", "%49", "%4a", "%4b", "%4c", "%4d", "%4e", "%4f",

		"%50", "%51", "%52", "%53", "%54", "%55", "%56", "%57",

		"%58", "%59", "%5a", "%5b", "%5c", "%5d", "%5e", "%5f",

		"%60", "%61", "%62", "%63", "%64", "%65", "%66", "%67",

		"%68", "%69", "%6a", "%6b", "%6c", "%6d", "%6e", "%6f",

		"%70", "%71", "%72", "%73", "%74", "%75", "%76", "%77",

		"%78", "%79", "%7a", "%7b", "%7c", "%7d", "%7e", "%7f",

		"%80", "%81", "%82", "%83", "%84", "%85", "%86", "%87",

		"%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f",

		"%90", "%91", "%92", "%93", "%94", "%95", "%96", "%97",

		"%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f",

		"%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7",

		"%a8", "%a9", "%aa", "%ab", "%ac", "%ad", "%ae", "%af",

		"%b0", "%b1", "%b2", "%b3", "%b4", "%b5", "%b6", "%b7",

		"%b8", "%b9", "%ba", "%bb", "%bc", "%bd", "%be", "%bf",

		"%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7",

		"%c8", "%c9", "%ca", "%cb", "%cc", "%cd", "%ce", "%cf",

		"%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7",

		"%d8", "%d9", "%da", "%db", "%dc", "%dd", "%de", "%df",

		"%e0", "%e1", "%e2", "%e3", "%e4", "%e5", "%e6", "%e7",

		"%e8", "%e9", "%ea", "%eb", "%ec", "%ed", "%ee", "%ef",

		"%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",

		"%f8", "%f9", "%fa", "%fb", "%fc", "%fd", "%fe", "%ff"

	],



	/**

	 * Encode a string to the "x-www-form-urlencoded" form, enhanced

	 * with the UTF-8-in-URL proposal. This is what happens:

	 *

	 * <ul>

	 * <li><p>The ASCII characters 'a' through 'z', 'A' through 'Z',

	 *        and '0' through '9' remain the same.

	 *

	 * <li><p>The unreserved characters - _ . ! ~ * ' ( ) remain the same.

	 *

	 * <li><p>The space character ' ' is converted into a plus sign '+'.

	 *

	 * <li><p>All other ASCII characters are converted into the

	 *        3-character string "%xy", where xy is

	 *        the two-digit this.hexadecimal representation of the character

	 *        code

	 *

	 * <li><p>All non-ASCII characters are encoded in two steps: first

	 *        to a sequence of 2 or 3 bytes, using the UTF-8 algorithm;

	 *        secondly each of these bytes is encoded as "%xx".

	 * </ul>

	 *

	 * @param s The string to be encoded

	 * @return The encoded string

	 */

	encode:function(s)

	{

		var sbuf = new StringBuffer();

		var len = s.length;

		for(var i = 0; i < len; i++)

		{

			var ch = s.charAt(i);

			if('A' <= ch && ch <= 'Z')

			{ // 'A'..'Z'

				sbuf.a(ch);

			}

			else if('a' <= ch && ch <= 'z')

			{ // 'a'..'z'

				sbuf.a(ch);

			}

			else if('0' <= ch && ch <= '9')

			{ // '0'..'9'

				sbuf.a(ch);

			}

			else if(ch == ' ')

			{ // space

				sbuf.a('+');

			}

			else if(ch == '-' || ch == '_' // unreserved

					|| ch == '.' || ch == '!'

					|| ch == '~' || ch == '*'

					|| ch == '\'' || ch == '('

					|| ch == ')')

			{

				sbuf.a(ch);

			}

			else

			{

				ch = s.charCodeAt(i);

				if(ch <= 0x007f)

				{ // other ASCII

					sbuf.a(this.hex[ch]);

				}

				else if(ch <= 0x07FF)

				{ // non-ASCII <= 0x7FF

					sbuf.a(this.hex[0xc0 | (ch >> 6)]);

					sbuf.a(this.hex[0x80 | (ch & 0x3F)]);

				}

				else

				{ // 0x7FF < ch <= 0xFFFF

					sbuf.a(this.hex[0xe0 | (ch >> 12)]);

					sbuf.a(this.hex[0x80 | ((ch >> 6) & 0x3F)]);

					sbuf.a(this.hex[0x80 | (ch & 0x3F)]);

				}

			}

		}

		return sbuf.toString();

	}

}





function pubSearchArg(n,search) {

		var re = new RegExp("[&\\?]" + n + "=([^&]*)(&|$)" );

		var a = re.exec(search);

		return (a) ? unescape(a[1]) : null;

	//	return (a) ? a[1] : "";

}

var forFrameSet = {

	$frameset: function() {

		var h = getEntire()

			.DeleteTag("SCRIPT")							// Remove SCRIPT TAG contents

			.DeleteTag("STYLE")								// Remove STYLE TAG contents

			.DeleteR("<!--","-->")							// Remove HTML comments

			.Tag("FRAMESET");

		if (!h) return "";

		var u = getEntire("$url2");			// In case the actual URL loaded was different from the original request

		// Convert to explicit URL references so that the src attributes will be absolute references

		return HTML.expandRefs(h,u);

	},

	

	// Individual frames from the frameset

	$f0: {_Copye: "Web_Frame",$n: 0},

	$f1: {_Copye: "Web_Frame",$n: 1},

	$f2: {_Copye: "Web_Frame",$n: 2},

	$f3: {_Copye: "Web_Frame",$n: 3},

	$f4: {_Copye: "Web_Frame",$n: 4},

	$f5: {_Copye: "Web_Frame",$n: 5},

	$f6: {_Copye: "Web_Frame",$n: 6},

	$f7: {_Copye: "Web_Frame",$n: 7},

	$f8: {_Copye: "Web_Frame",$n: 8},

	$f9: {_Copye: "Web_Frame",$n: 9}

}


