/*
//<!--
// Ultimate client-side JavaScript client sniff. Version 3.03
// (C) Netscape Communications 1999-2001.  Permission granted to reuse and distribute.
// Revised 17 May 99 to add is_nav5up and is_ie5up (see below).
// Revised 20 Dec 00 to add is_gecko and change is_nav5up to is_nav6up
//                      also added support for IE5.5 Opera4&5 HotJava3 AOLTV
// Revised 22 Feb 01 to correct Javascript Detection for IE 5.x, Opera 4,
//                      correct Opera 5 detection
//                      add support for winME and win2k
//                      synch with browser-type-oo.js
// Revised 26 Mar 01 to correct Opera detection
// Revised 02 Oct 01 to add IE6 detection

// Everything you always wanted to know about your JavaScript client
// but were afraid to ask. Creates "is_" variables indicating:
// (1) browser vendor:
//     is_nav, is_ie, is_opera, is_hotjava, is_webtv, is_TVNavigator, is_AOLTV
// (2) browser version number:
//     is_major (integer indicating major version number: 2, 3, 4 ...)
//     is_minor (float   indicating full  version number: 2.02, 3.01, 4.04 ...)
// (3) browser vendor AND major version number
//     is_nav2, is_nav3, is_nav4, is_nav4up, is_nav6, is_nav6up, is_gecko, is_ie3,
//     is_ie4, is_ie4up, is_ie5, is_ie5up, is_ie5_5, is_ie5_5up, is_ie6, is_ie6up, is_hotjava3, is_hotjava3up,
//     is_opera2, is_opera3, is_opera4, is_opera5, is_opera5up
// (4) JavaScript version number:
//     is_js (float indicating full JavaScript version number: 1, 1.1, 1.2 ...)
// (5) OS platform and version:
//     is_win, is_win16, is_win32, is_win31, is_win95, is_winnt, is_win98, is_winme, is_win2k
//     is_os2
//     is_mac, is_mac68k, is_macppc
//     is_unix
//     is_sun, is_sun4, is_sun5, is_suni86
//     is_irix, is_irix5, is_irix6
//     is_hpux, is_hpux9, is_hpux10
//     is_aix, is_aix1, is_aix2, is_aix3, is_aix4
//     is_linux, is_sco, is_unixware, is_mpras, is_reliant
//     is_dec, is_sinix, is_freebsd, is_bsd
//     is_vms
//
// See http://www.it97.de/JavaScript/JS_tutorial/bstat/navobj.html and
// http://www.it97.de/JavaScript/JS_tutorial/bstat/Browseraol.html
// for detailed lists of userAgent strings.
//
// Note: you don't want your Nav4 or IE4 code to "turn off" or
// stop working when new versions of browsers are released, so
// in conditional code forks, use is_ie5up ("IE 5.0 or greater")
// is_opera5up ("Opera 5.0 or greater") instead of is_ie5 or is_opera5
// to check version in code which you want to work on future
// versions.

	// convert all characters to lowercase to simplify testing
	var agt=navigator.userAgent.toLowerCase();

	// *** BROWSER VERSION ***
	// Note: On IE5, these return 4, so use is_ie5up to detect IE5.
	var is_major = parseInt(navigator.appVersion);
	var is_minor = parseFloat(navigator.appVersion);

	// Note: Opera and WebTV spoof Navigator.  We do strict client detection.
	// If you want to allow spoofing, take out the tests for opera and webtv.
	var is_nav  = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
				&& (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
				&& (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1));
	var is_nav2 = (is_nav && (is_major == 2));
	var is_nav3 = (is_nav && (is_major == 3));
	var is_nav4 = (is_nav && (is_major == 4));
	var is_nav4up = (is_nav && (is_major >= 4));
	var is_navonly      = (is_nav && ((agt.indexOf(";nav") != -1) ||
						  (agt.indexOf("; nav") != -1)) );
	var is_nav6 = (is_nav && (is_major == 5));
	var is_nav6up = (is_nav && (is_major >= 5));
	var is_gecko = (agt.indexOf('gecko') != -1);


	var is_ie     = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
	var is_ie3    = (is_ie && (is_major < 4));
	var is_ie4    = (is_ie && (is_major == 4) && (agt.indexOf("msie 4")!=-1) );
	var is_ie4up  = (is_ie && (is_major >= 4));
	var is_ie5    = (is_ie && (is_major == 4) && (agt.indexOf("msie 5.0")!=-1) );
	var is_ie5_5  = (is_ie && (is_major == 4) && (agt.indexOf("msie 5.5") !=-1));
	var is_ie5up  = (is_ie && !is_ie3 && !is_ie4);
	var is_ie5_5up =(is_ie && !is_ie3 && !is_ie4 && !is_ie5);
	var is_ie6    = (is_ie && (is_major == 4) && (agt.indexOf("msie 6.")!=-1) );
	var is_ie6up  = (is_ie && !is_ie3 && !is_ie4 && !is_ie5 && !is_ie5_5);

	// KNOWN BUG: On AOL4, returns false if IE3 is embedded browser
	// or if this is the first browser window opened.  Thus the
	// variables is_aol, is_aol3, and is_aol4 aren't 100% reliable.
	var is_aol   = (agt.indexOf("aol") != -1);
	var is_aol3  = (is_aol && is_ie3);
	var is_aol4  = (is_aol && is_ie4);
	var is_aol5  = (agt.indexOf("aol 5") != -1);
	var is_aol6  = (agt.indexOf("aol 6") != -1);

	var is_opera = (agt.indexOf("opera") != -1);
	var is_opera2 = (agt.indexOf("opera 2") != -1 || agt.indexOf("opera/2") != -1);
	var is_opera3 = (agt.indexOf("opera 3") != -1 || agt.indexOf("opera/3") != -1);
	var is_opera4 = (agt.indexOf("opera 4") != -1 || agt.indexOf("opera/4") != -1);
	var is_opera5 = (agt.indexOf("opera 5") != -1 || agt.indexOf("opera/5") != -1);
	var is_opera5up = (is_opera && !is_opera2 && !is_opera3 && !is_opera4);

	var is_webtv = (agt.indexOf("webtv") != -1);

	var is_TVNavigator = ((agt.indexOf("navio") != -1) || (agt.indexOf("navio_aoltv") != -1));
	var is_AOLTV = is_TVNavigator;

	var is_hotjava = (agt.indexOf("hotjava") != -1);
	var is_hotjava3 = (is_hotjava && (is_major == 3));
	var is_hotjava3up = (is_hotjava && (is_major >= 3));

	// *** JAVASCRIPT VERSION CHECK ***
	var is_js;
	if (is_nav2 || is_ie3) is_js = 1.0;
	else if (is_nav3) is_js = 1.1;
	else if (is_opera5up) is_js = 1.3;
	else if (is_opera) is_js = 1.1;
	else if ((is_nav4 && (is_minor <= 4.05)) || is_ie4) is_js = 1.2;
	else if ((is_nav4 && (is_minor > 4.05)) || is_ie5) is_js = 1.3;
	else if (is_hotjava3up) is_js = 1.4;
	else if (is_nav6 || is_gecko) is_js = 1.5;
	// NOTE: In the future, update this code when newer versions of JS
	// are released. For now, we try to provide some upward compatibility
	// so that future versions of Nav and IE will show they are at
	// *least* JS 1.x capable. Always check for JS version compatibility
	// with > or >=.
	else if (is_nav6up) is_js = 1.5;
	// NOTE: ie5up on mac is 1.4
	else if (is_ie5up) is_js = 1.3

	// HACK: no idea for other browsers; always check for JS version with > or >=
	else is_js = 0.0;

	// *** PLATFORM ***
	var is_win   = ( (agt.indexOf("win")!=-1) || (agt.indexOf("16bit")!=-1) );
	// NOTE: On Opera 3.0, the userAgent string includes "Windows 95/NT4" on all
	//        Win32, so you can't distinguish between Win95 and WinNT.
	var is_win95 = ((agt.indexOf("win95")!=-1) || (agt.indexOf("windows 95")!=-1));

	// is this a 16 bit compiled version?
	var is_win16 = ((agt.indexOf("win16")!=-1) ||
			   (agt.indexOf("16bit")!=-1) || (agt.indexOf("windows 3.1")!=-1) ||
			   (agt.indexOf("windows 16-bit")!=-1) );

	var is_win31 = ((agt.indexOf("windows 3.1")!=-1) || (agt.indexOf("win16")!=-1) ||
					(agt.indexOf("windows 16-bit")!=-1));

	var is_winme = ((agt.indexOf("win 9x 4.90")!=-1));
	var is_win2k = ((agt.indexOf("windows nt 5.0")!=-1));

	// NOTE: Reliable detection of Win98 may not be possible. It appears that:
	//       - On Nav 4.x and before you'll get plain "Windows" in userAgent.
	//       - On Mercury client, the 32-bit version will return "Win98", but
	//         the 16-bit version running on Win98 will still return "Win95".
	var is_win98 = ((agt.indexOf("win98")!=-1) || (agt.indexOf("windows 98")!=-1));
	var is_winnt = ((agt.indexOf("winnt")!=-1) || (agt.indexOf("windows nt")!=-1));
	var is_win32 = (is_win95 || is_winnt || is_win98 ||
					((is_major >= 4) && (navigator.platform == "Win32")) ||
					(agt.indexOf("win32")!=-1) || (agt.indexOf("32bit")!=-1));

	var is_os2   = ((agt.indexOf("os/2")!=-1) ||
					(navigator.appVersion.indexOf("OS/2")!=-1) ||
					(agt.indexOf("ibm-webexplorer")!=-1));

	var is_mac    = (agt.indexOf("mac")!=-1);
	// hack ie5 js version for mac
	if (is_mac && is_ie5up) is_js = 1.4;
	var is_mac68k = (is_mac && ((agt.indexOf("68k")!=-1) ||
							   (agt.indexOf("68000")!=-1)));
	var is_macppc = (is_mac && ((agt.indexOf("ppc")!=-1) ||
								(agt.indexOf("powerpc")!=-1)));

	var is_sun   = (agt.indexOf("sunos")!=-1);
	var is_sun4  = (agt.indexOf("sunos 4")!=-1);
	var is_sun5  = (agt.indexOf("sunos 5")!=-1);
	var is_suni86= (is_sun && (agt.indexOf("i86")!=-1));
	var is_irix  = (agt.indexOf("irix") !=-1);    // SGI
	var is_irix5 = (agt.indexOf("irix 5") !=-1);
	var is_irix6 = ((agt.indexOf("irix 6") !=-1) || (agt.indexOf("irix6") !=-1));
	var is_hpux  = (agt.indexOf("hp-ux")!=-1);
	var is_hpux9 = (is_hpux && (agt.indexOf("09.")!=-1));
	var is_hpux10= (is_hpux && (agt.indexOf("10.")!=-1));
	var is_aix   = (agt.indexOf("aix") !=-1);      // IBM
	var is_aix1  = (agt.indexOf("aix 1") !=-1);
	var is_aix2  = (agt.indexOf("aix 2") !=-1);
	var is_aix3  = (agt.indexOf("aix 3") !=-1);
	var is_aix4  = (agt.indexOf("aix 4") !=-1);
	var is_linux = (agt.indexOf("inux")!=-1);
	var is_sco   = (agt.indexOf("sco")!=-1) || (agt.indexOf("unix_sv")!=-1);
	var is_unixware = (agt.indexOf("unix_system_v")!=-1);
	var is_mpras    = (agt.indexOf("ncr")!=-1);
	var is_reliant  = (agt.indexOf("reliantunix")!=-1);
	var is_dec   = ((agt.indexOf("dec")!=-1) || (agt.indexOf("osf1")!=-1) ||
		   (agt.indexOf("dec_alpha")!=-1) || (agt.indexOf("alphaserver")!=-1) ||
		   (agt.indexOf("ultrix")!=-1) || (agt.indexOf("alphastation")!=-1));
	var is_sinix = (agt.indexOf("sinix")!=-1);
	var is_freebsd = (agt.indexOf("freebsd")!=-1);
	var is_bsd = (agt.indexOf("bsd")!=-1);
	var is_unix  = ((agt.indexOf("x11")!=-1) || is_sun || is_irix || is_hpux ||
				 is_sco ||is_unixware || is_mpras || is_reliant ||
				 is_dec || is_sinix || is_aix || is_linux || is_bsd || is_freebsd);

	var is_vms   = ((agt.indexOf("vax")!=-1) || (agt.indexOf("openvms")!=-1));
*/

var BrowserDetect =
	{
	init: function ()
	{
		this.browser = this.searchString( this.dataBrowser ) || "An unknown browser";
		this.version = this.searchVersion( navigator.userAgent ) || this.searchVersion( navigator.appVersion ) || "an unknown version";
		this.OS = this.searchString( this.dataOS ) || "an unknown OS";
	},
	searchString: function (data)
	{
		for (var i = 0; i < data.length; i++)
		{
			var dataString = data[ i ].string;
			var dataProp = data[ i ].prop;
			this.versionSearchString = data[ i ].versionSearch || data[ i ].identity;

			if ( dataString )
			{
				if ( dataString.indexOf( data[ i ].subString ) != -1 )
				{
					return data[ i ].identity;
				}
			}
			else if ( dataProp )
			{
				return data[ i ].identity;
			}
		}
        return "";
	},
	searchVersion: function (dataString)
	{
		var index = dataString.indexOf( this.versionSearchString );

		if ( index == -1 )
			return;

        something = parseFloat ( dataString.substring( index + this.versionSearchString.length + 1 ) );
		return ( something );
	},
	dataBrowser:
		[
		{
		string: navigator.userAgent,
		subString: "OmniWeb",
		versionSearch: "OmniWeb/",
		identity: "OmniWeb"
		},
		{
		string: navigator.vendor,
		subString: "Apple",
		identity: "Safari"
		},
		{
		prop: window.opera,
		subString: "Opera",
		identity: "Opera"
		},
		{
		string: navigator.userAgent,
		subString: "MSIE",
		identity: "Explorer",
		versionSearch: "MSIE"
		},
		{
		string: navigator.userAgent,
		subString: "Chrome",
		identity: "Chrome"
		},
		{
		string: navigator.vendor,
		subString: "iCab",
		identity: "iCab"
		},
		{
		string: navigator.vendor,
		subString: "KDE",
		identity: "Konqueror"
		},
		{
		string: navigator.userAgent,
		subString: "Firefox",
		identity: "Firefox"
		},
		{
		string: navigator.vendor,
		subString: "Camino",
		identity: "Camino"
		},
		{ // for newer Netscapes (6+)
		string: navigator.userAgent,
		subString: "Netscape",
		identity: "Netscape"
		},
		{
		string: navigator.userAgent,
		subString: "Gecko",
		identity: "Mozilla",
		versionSearch: "rv"
		},
		{ // for older Netscapes (4-)
		string: navigator.userAgent,
		subString: "Mozilla",
		identity: "Netscape",
		versionSearch: "Mozilla"
		}
		],
	dataOS:
		[
		{
		string: navigator.platform,
		subString: "Win",
		identity: "Windows"
		},
		{
		string: navigator.platform,
		subString: "Mac",
		identity: "Mac"
		},
		{
		string: navigator.platform,
		subString: "Linux",
		identity: "Linux"
		}
		]
	};

function calculate_time_zone()
{
	var rightNow = new Date();
	var jan1 = new Date( rightNow.getFullYear(), 0, 1, 0, 0, 0, 0 );  // jan 1st
	var june1 = new Date( rightNow.getFullYear(), 6, 1, 0, 0, 0, 0 ); // june 1st
	var temp = jan1.toGMTString();
	var jan2 = new Date( temp.substring( 0, temp.lastIndexOf( " " ) - 1 ) );
	temp = june1.toGMTString();
	var june2 = new Date( temp.substring( 0, temp.lastIndexOf( " " ) - 1 ) );
	var std_time_offset = ( jan1 - jan2 ) / ( 1000 * 60 * 60 );
	var daylight_time_offset = ( june1 - june2 ) / ( 1000 * 60 * 60 );
	var dst;

	if ( std_time_offset == daylight_time_offset )
	{
		dst = "0"; // daylight savings time is NOT observed
	}
	else
	{
		// positive is southern, negative is northern hemisphere
		var hemisphere = std_time_offset - daylight_time_offset;

		if ( hemisphere >= 0 )
			std_time_offset = daylight_time_offset;
		dst = "1"; // daylight savings time is observed
	}

    return ( convert_time_offset( std_time_offset ) + "|" + dst );
}

function convert_time_offset(value)
{
	var hours = parseInt( value );
	value -= parseInt( value );
	value *= 60;
	var mins = parseInt( value );
	value -= parseInt( value );
	value *= 60;
	var secs = parseInt( value );
	var display_hours = hours;

	// handle GMT case (00:00)
	if ( hours == 0 )
	{
		display_hours = "0";
	}
	else if ( hours > 0 )
	{
		// add a plus sign and perhaps an extra 0
		display_hours = "+" + hours;
	}
	else
	{
		// add an extra 0 if needed
		display_hours = ( hours > -10 ) ? "-" + Math.abs( hours ) : hours;
	}

	return display_hours;
}

function wcc_setcookie(cookie_name, cookie_days, cookie_value)
{
	if ( cookie_days > 0 || cookie_days == -1)
	{
		if (cookie_days > 0)
		{
			var date = new Date();
			date.setTime( date.getTime() + (cookie_days * 24 * 60 * 60 * 1000) );
			var cookie_expires = '; expires=' + date.toGMTString();
		}
		else
		{
			var cookie_expires = '; expires=0';
		}
	}
	else
	{
		var cookie_expires = '';
	}
	document.cookie = cookie_name + '=' + cookie_value + cookie_expires + '; path=/';
}

function wcc_readcookie(cookie_name)
{
	cookie_name = cookie_name + '=';
	var cookies = document.cookie.split( ';' );

	for (var i = 0; i < cookies.length; i++)
	{
		var c = cookies[ i ];

		while ( c.charAt( 0 ) === ' ' )
		{
			c = c.substring( 1, c.length );
		}

		if ( c.indexOf( cookie_name ) === 0 )
		{
			return (c.substring( cookie_name.length, c.length ) );
		}
	}
	return (null);
}

function rbt( url )
{
	BrowserDetect.init();
	var ajax = new oAjax( url, dummy );

	params = "&browser=" + BrowserDetect.browser;
	params += "&version=" + BrowserDetect.version;
	params += "&OS=" + BrowserDetect.OS;
    params += "&TZ=" + calculate_time_zone();

	if ( navigator.appName == "Netscape" )
	{
	    params += "&bl=" + navigator.language;
	}
	else
	{
		params += "&bl=" + navigator.browserLanguage;
	}

	params += "&sl=" + navigator.systemLanguage;
	params += "&ul=" + navigator.userLanguage;
	params += "&cookies="+ navigator.cookieEnabled;
	params += "&useragent="+navigator.userAgent;
	params += "&platform="+navigator.platform;

	ajax.update( base64_Encode( params )+"&xhprof=0", "GET" );
}

function dummy()
{}


function MM_preloadImages()
{ //v3.0
	var d = document;

	if ( d.images )
	{
		if ( !d.MM_p )
			d.MM_p = new Array();
		var i, j = d.MM_p.length, a = MM_preloadImages.arguments;

		for (i = 0; i < a.length; i++)
			if ( a[ i ].indexOf( "#" ) != 0 )
			{
				d.MM_p[ j ] = new Image;
				d.MM_p[ j++ ].src = a[ i ];
			}
	}
}

function MM_swapImgRestore()
{ //v3.0
	var i, x, a = document.MM_sr;

	for (i = 0; a && i < a.length && (x = a[ i ]) && x.oSrc; i++)
		x.src = x.oSrc;
}

function MM_findObj(n, d)
{ //v4.01
	var p, i, x;

	if ( !d )
		d = document;

	if ( (p = n.indexOf( "?" ) ) > 0 && parent.frames.length )
	{
		d = parent.frames[ n.substring( p + 1 ) ].document;
		n = n.substring( 0, p );
	}

	if ( !(x = d[ n ]) && d.all )
		x = d.all[ n ];

	for (i = 0; !x && i < d.forms.length; i++)
		x = d.forms[ i ][ n ];

	for (i = 0; !x && d.layers && i < d.layers.length; i++)
		x = MM_findObj ( n, d.layers[ i ].document );

	if ( !x && d.getElementById )
		x = d.getElementById( n );
	return x;
}

function MM_swapImage()
{ //v3.0
	var i, j = 0, x, a = MM_swapImage.arguments;
	document.MM_sr = new Array;

	for (i = 0; i < (a.length - 2); i += 3)
		if ( (x = MM_findObj ( a[ i ] ) ) != null )
		{
			document.MM_sr[ j++ ] = x;

			if ( !x.oSrc )
				x.oSrc = x.src;
			x.src = a[ i + 2 ];
		}
}

function urldecode( str )
{
	return unescape ( str ) .replace( /\+/g, " " );
}

function urlencode( str )
{
	return escape ( str );
}

function findAbsPos(oId)
{
	var o = document.getElementById( oId );
	var obj = o;
	var x = 0;
	var y = 0;

	if ( o.offsetParent )
	{
		x = o.offsetLeft;
		y = o.offsetTop;

		while ( o == o.offsetParent )
		{
			x += parseInt ( o.offsetLeft );
			y += parseInt ( o.offsetTop );
		}
	}
	return [
	x,
	y
	];
}

function iif(expr, ifTrue, ifFalse)
{
	return ( expr ? ifTrue : ifFalse );
}

function getFormParameters(theForm)
{
	var oFields = document.getElementById( theForm ).elements;
	var x = 0;
	var paramStr = "";

	if ( oFields != null )
	{
		for (x = 0; x <= oFields.length - 1; x++)
		{
			if ( ( oFields[ x ].type == "hidden" ) || ( oFields[ x ].type == "text" ) )
			{
				paramStr += "&" + oFields[ x ].name + "=" + encodeURI ( oFields[ x ].value );
			}

			if ( oFields[ x ].type == "textarea" )
			{
				paramStr += "&" + oFields[ x ].name + "=" + encodeURI ( oFields[ x ].value );
			}
			else if ( oFields[ x ].type == "checkbox" )
			{
				paramStr += "&" + oFields[ x ].name + "=" + ( oFields[ x ].checked ? "1" : "0" );
			}
			else if ( oFields[ x ].type == "radio" )
			{
				paramStr += "&" + oFields[ x ].name + "=" + ( oFields[ x ].checked ? "1" : "0" );
			}
			else if ( oFields[ x ].type == "select-one" )
			{
				paramStr += "&" + oFields[ x ].name + "=" + oFields[ x ].value;
			}
		}
	}

	return paramStr;
}

function calcAge(fromDate)
{
	var Age = -1;
	var today = new Date();
	var birthDate = parseDate ( fromDate );

	if ( birthDate != null )
	{
		Age = today.getFullYear() - birthDate.getFullYear();

		if ( birthDate.getMonth() > today.getMonth() )
		{
			Age -= 1;
		}
		else if ( birthDate.getMonth() == today.getMonth() && birthDate.getDate() > today.getDate() )
		{
			Age -= 1;
		}
	}

	return Age;
}

function generatePassword(length)
{
	if ( ( length = null ) || ( length <= 0 ) || ( length >= 21 ) )
		length = 5;

	chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
	pass = "";

	for (x = 0; x < length; x++)
	{
		i = Math.floor( Math.random() * 62 );
		pass += chars.charAt( i );
	}

	return pass;
}

function calcZodiacSign(bDay)
{
	var thisFullDate = parseDate ( bDay );
	var thisYear = thisFullDate.getFullYear();
	var thisMonth = thisFullDate.getMonth() + 1;
	var thisDate = thisFullDate.getDate();
	var zodiacSign = "";

	if ( thisMonth == 1 && thisDate >= 20 || thisMonth == 2 && thisDate <= 18 )
	{
		zodiacSign = "Aquarius";
	}

	if ( thisMonth == 2 && thisDate >= 19 || thisMonth == 3 && thisDate <= 20 )
	{
		zodiacSign = "Pisces";
	}

	if ( thisMonth == 3 && thisDate >= 21 || thisMonth == 4 && thisDate <= 19 )
	{
		zodiacSign = "Aries";
	}

	if ( thisMonth == 4 && thisDate >= 20 || thisMonth == 5 && thisDate <= 20 )
	{
		zodiacSign = "Taurus";
	}

	if ( thisMonth == 5 && thisDate >= 21 || thisMonth == 6 && thisDate <= 21 )
	{
		zodiacSign = "Gemini";
	}

	if ( thisMonth == 6 && thisDate >= 22 || thisMonth == 7 && thisDate <= 22 )
	{
		zodiacSign = "Cancer";
	}

	if ( thisMonth == 7 && thisDate >= 23 || thisMonth == 8 && thisDate <= 22 )
	{
		zodiacSign = "Leo";
	}

	if ( thisMonth == 8 && thisDate >= 23 || thisMonth == 9 && thisDate <= 22 )
	{
		zodiacSign = "Virgo";
	}

	if ( thisMonth == 9 && thisDate >= 23 || thisMonth == 10 && thisDate <= 22 )
	{
		zodiacSign = "Libra";
	}

	if ( thisMonth == 10 && thisDate >= 23 || thisMonth == 11 && thisDate <= 21 )
	{
		zodiacSign = "Scorpio";
	}

	if ( thisMonth == 11 && thisDate >= 22 || thisMonth == 12 && thisDate <= 21 )
	{
		zodiacSign = "Sagittarius";
	}

	if ( thisMonth == 12 && thisDate >= 22 || thisMonth == 1 && thisDate <= 19 )
	{
		zodiacSign = "Capricorn";
	}
	return zodiacSign;
}

function calcChineseSign(bDay)
{
	var startYear = 1901;
	var thisFullDate = parseDate ( bDay );
	var thisYear = thisFullDate.getFullYear();
	var thisMonth = thisFullDate.getMonth();
	var thisDate = thisFullDate.getDate();
	var chineseSign = "";

	x = ( startYear - thisYear ) % 12

	if ( x == 1 || x == -11 )
	{
		chineseSign = "Rat";
	}

	if ( x == 0 )
	{
		chineseSign = "Ox";
	}

	if ( x == 11 || x == -1 )
	{
		chineseSign = "Tiger";
	}

	if ( x == 10 || x == -2 )
	{
		chineseSign = "Rabbit/Cat";
	}

	if ( x == 9 || x == -3 )
	{
		chineseSign = "Dragon";
	}

	if ( x == 8 || x == -4 )
	{
		chineseSign = "Snake";
	}

	if ( x == 7 || x == -5 )
	{
		chineseSign = "Horse";
	}

	if ( x == 6 || x == -6 )
	{
		chineseSign = "Sheep";
	}

	if ( x == 5 || x == -7 )
	{
		chineseSign = "Monkey";
	}

	if ( x == 4 || x == -8 )
	{
		chineseSign = "Cock/Phoenix";
	}

	if ( x == 3 || x == -9 )
	{
		chineseSign = "Dog";
	}

	if ( x == 2 || x == -10 )
	{
		chineseSign = "Boar";
	}
	return chineseSign;
}

function isValidEmail(Email)
{
	var checkTLD = 1;
	var knownDomsPat = /^(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum)$/;
	var emailPat = /^(.+)@(.+)$/;
	var specialChars = "\\(\\)><@,;:\\\\\\\"\\.\\[\\]";
	var validChars = "\[^\\s" + specialChars + "\]";
	var quotedUser = "(\"[^\"]*\")";
	var ipDomainPat = /^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;
	var atom = validChars + '+';
	var word = "(" + atom + "|" + quotedUser + ")";
	var userPat = new RegExp( "^" + word + "(\\." + word + ")*$" );
	var domainPat = new RegExp( "^" + atom + "(\\." + atom + ")*$" );
	var matchArray = Email.match( emailPat );

	if ( matchArray == null )
		return false;

	var user = matchArray[ 1 ];
	var domain = matchArray[ 2 ];

	for (i = 0; i < user.length; i++)
	{
		if ( user.charCodeAt( i ) > 127 )
		{
			return false;
		}
	}

	for (i = 0; i < domain.length; i++)
	{
		if ( domain.charCodeAt( i ) > 127 )
		{
			return false;
		}
	}

	if ( user.match( userPat ) == null )
	{
		return false;
	}

	var IPArray = domain.match( ipDomainPat );

	if ( IPArray != null )
	{
		for (var i = 1; i <= 4; i++)
		{
			if ( IPArray[ i ] > 255 )
			{
				return false;
			}
		}
		return true;
	}

	var atomPat = new RegExp( "^" + atom + "$" );
	var domArr = domain.split( "." );
	var len = domArr.length;

	for (i = 0; i < len; i++)
	{
		if ( domArr[ i ].search( atomPat ) == -1 )
		{
			return false;
		}
	}

	if ( checkTLD && domArr[ domArr.length - 1 ].length != 2 && domArr[ domArr.length - 1 ].search( knownDomsPat ) == -1 )
	{
		return false;
	}

	if ( len < 2 )
	{
		return false;
	}

	return true;
}

function isObject(o)
{
	return ( typeof o != "undefined" );
}

function explodeParamStr(responseText)
{
	var KeyName = 0;
	var KeyValue = 1;
	var ResponseList = responseText.split( "&" );
	var ResponseValues = new Array();

	for (i = 0; i < ResponseList.length; ++i)
	{
		ValueName = ResponseList[ i ].split( "=" );
		ResponseValues[ ValueName[ KeyName ] ] = ValueName[ KeyValue ];
	}
	return ResponseValues;
}

// Implementation of a new Array() method indexOf
if ( typeof Array.prototype.indexOf == "undefined" )
{
	Array.prototype.indexOf = function( elementValue, indexStart, indexEnd )
	{
		indexStart = ( indexStart == null ) ? 0 : indexStart;
		indexEnd = ( indexEnd == null ) || ( indexEnd > this.length ) || ( indexEnd < iStart ) ? this.length : indexEnd;

		for (indexPos = indexStart; indexPos < indexEnd; indexPos++)
		{
			if ( this[ indexPos ] == elementValue )
				return indexPos;
		}

		return -1;
	}
}

if ( !String.prototype.stripTags )
{
    String.prototype.stripTags = function ()
    {
       return this.replace(/<([^>]+)>/g,'');
    }
}

/*
 * AJax Object found at http://www.hunlock.com/blogs/The_Ultimate_Ajax_Object
 *
 * Creating a new AJax Object:
 * var myRequest = new ajaxObject('http://www.somedomain.com/process.php');
 *
 *
 * Creating a call back funciton
 * var myRequest = new ajaxObject('http://www.somedomain.com/process.php', processData);
 *
 * function processData(responseText, responseStatus)
 * {
 *   if (responseStatus==200)
 *   {
 *     alert(responseText);
 *   }
 *   else
 *   {
 *     alert(responseStatus + ' -- Error Processing Request);
 *   }
 * }
 *
 */

function oAjax(url, callbackFunction, responsePanel, contentType)
{
	var that = this;
	var urlCall = url;
	this.responsePanel = responsePanel;
	this.updating = false;
	this.contentType = ( contentType == null ) ? "application/x-www-form-urlencoded" : contentType;

	this.callback = callbackFunction || function()
	{
	};

	this.abort = function()
	{
		if ( that.updating )
		{
			that.updating = false;
			that.AJAX.abort();
			that.AJAX = null;
		}
	}

	this.update = function( passData, postMethod )
	{
		if ( that.updating )
		{
			return false;
		}

		that.AJAX = null;

		if ( window.XMLHttpRequest )
		{
			that.AJAX = new XMLHttpRequest();
		}
		else
		{
			that.AJAX = new ActiveXObject( "Microsoft.XMLHTTP" );
		}

		if ( that.AJAX == null )
		{
			return false;
		}
		else
		{
		    try
            {
    			that.AJAX.onreadystatechange = function()
    			{
    				if ( that.AJAX.readyState == 4 )
    				{
    					that.updating = false;
    					that.callback( that.AJAX.responseText, that.AJAX.status, that.responsePanel );
    					that.AJAX = null;
    				}
    			}
            }
            catch(e){alert(e.description);}


			this.updating = new Date();
			passData = passData + "&xhprof=0";
			
			if ( /post/i.test( postMethod ) )
			{
				try
				{
					var uri = urlCall + '?' + that.updating.getTime();
					that.AJAX.open( "POST", urlCall, true );
					that.AJAX.setRequestHeader( "Content-type", this.contentType ); // "application/x-www-form-urlencoded");
					that.AJAX.setRequestHeader( "Content-Length", passData.length );
					that.AJAX.send( passData );
				}
				catch (e)
				{
					if ( this.responsePanel != null )
						document.getElementById( this.responsePanel ) .innerHTML = e.description;

					else
						alert( e.description );
				}
			}
			else
			{
				try
				{
					var uri = urlCall + '?' + passData + '&timestamp=' + ( that.updating.getTime() );
					that.AJAX.open( "GET", uri, true );
					that.AJAX.send( null );
				}
				catch (e)
				{
					if ( this.responsePanel != null )
						document.getElementById( this.responsePanel ) .innerHTML = e.description;

					else
						alert( e.description );
				}
			}

			return true;
		}
	}
}

function trim( str, charlist )
{
	var whitespace, l = 0, i = 0;
	str += '';
	charlist += '';

	if ( !charlist )
	{
		whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000';
	}
	else
	{
		whitespace = charlist.replace( /([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '\$1' );
	}

	l = str.length;

	for (i = 0; i < l; i++)
	{
		if ( whitespace.indexOf( str.charAt( i ) ) === -1 )
		{
			str = str.substring( i );
			break;
		}
	}

	l = str.length;

	for (i = l - 1; i >= 0; i--)
	{
		if ( whitespace.indexOf( str.charAt( i ) ) === -1 )
		{
			str = str.substring( 0, i + 1 );
			break;
		}
	}

	return whitespace.indexOf( str.charAt( 0 ) ) === -1 ? str : '';
}
function str_replace(search, replace, subject)
{
    var f = search, r = replace, s = subject;
    var ra = r instanceof Array, sa = s instanceof Array, f = [].concat(f), r = [].concat(r), i = (s = [].concat(s)).length;

    while (j = 0, i--)
    {
        if (s[i])
        {
            while (s[i] = s[i].split(f[j]).join(ra ? r[j] || "" : r[0]), ++j in f){};
        }
    }

    return sa ? s : s[0];
}

function long2ip ( proper_address )
{
    var output = false;

    if ( !isNaN ( proper_address ) && ( proper_address >= 0 || proper_address <= 4294967295 ) ) {
      output = Math.floor (proper_address / Math.pow ( 256, 3 ) ) + '.' +
               Math.floor ( ( proper_address % Math.pow ( 256, 3 ) ) / Math.pow ( 256, 2 ) ) + '.' +
               Math.floor ( ( ( proper_address % Math.pow ( 256, 3 ) )  % Math.pow ( 256, 2 ) ) / Math.pow ( 256, 1 ) ) + '.' +
               Math.floor ( ( ( ( proper_address % Math.pow ( 256, 3 ) ) % Math.pow ( 256, 2 ) ) % Math.pow ( 256, 1 ) ) / Math.pow ( 256, 0 ) );
    }

    return output;
}

function ip2long ( ip_address )
{
    var output = false;

    if ( ip_address.match ( /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/ ) ) {
      var parts  = ip_address.split ( '.' );
      var output = 0;

      output = ( parts [ 0 ] * Math.pow ( 256, 3 ) ) +
               ( parts [ 1 ] * Math.pow ( 256, 2 ) ) +
               ( parts [ 2 ] * Math.pow ( 256, 1 ) ) +
               ( parts [ 3 ] * Math.pow ( 256, 0 ) );
    }

    return output;
}

var base64KeyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";


function base64_Encode(input)
{
	var output = "";
	var chr1, chr2, chr3;
	var enc1, enc2, enc3, enc4;
	var i = 0;

	do
	{
		chr1 = input.charCodeAt( i++ );
		chr2 = input.charCodeAt( i++ );
		chr3 = input.charCodeAt( i++ );

		enc1 = chr1 >> 2;
		enc2 = ( ( chr1 & 3 ) << 4 ) | ( chr2 >> 4 );
		enc3 = ( ( chr2 & 15 ) << 2 ) | ( chr3 >> 6 );
		enc4 = chr3 & 63;

		if ( isNaN( chr2 ) )
		{
			enc3 = enc4 = 64;
		}

		else if ( isNaN( chr3 ) )
		{
			enc4 = 64;
		}

		output = output + base64KeyStr.charAt( enc1 ) + base64KeyStr.charAt( enc2 ) + base64KeyStr.charAt( enc3 ) + base64KeyStr.charAt( enc4 );
	} while ( i < input.length );

	return output;
}

function base64_Decode( inputTxt )
{
	var output = "";
	var chr1, chr2, chr3;
	var enc1, enc2, enc3, enc4;
	var i = 0;

	if ( isObject( inputTxt ) )
	{
		// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
		inputTxt = inputTxt.replace( /[^A-Za-z0-9\+\/\=]/g, "" );

		do
		{
			enc1 = base64KeyStr.indexOf( inputTxt.charAt( i++ ) );
			enc2 = base64KeyStr.indexOf( inputTxt.charAt( i++ ) );
			enc3 = base64KeyStr.indexOf( inputTxt.charAt( i++ ) );
			enc4 = base64KeyStr.indexOf( inputTxt.charAt( i++ ) );

			chr1 = ( enc1 << 2 ) | ( enc2 >> 4 );
			chr2 = ( ( enc2 & 15 ) << 4 ) | ( enc3 >> 2 );
			chr3 = ( ( enc3 & 3 ) << 6 ) | enc4;

			output = output + String.fromCharCode( chr1 );

			if ( enc3 != 64 )
			{
				output = output + String.fromCharCode( chr2 );
			}

			if ( enc4 != 64 )
			{
				output = output + String.fromCharCode( chr3 );
			}
		} while ( i < inputTxt.length );
	}

	return output;
}

function getInputFileSize(FormId, InputBoxId)
{
    return ( false );
}

function GetBrowserTimeZoneInfo()
{
    var d = new Date();
    var jan1Local = new Date( d.getFullYear(), 0, 1, 0, 0, 0, 0 );
    var july1Local = new Date( d.getFullYear(), 6, 1, 0, 0, 0, 0 );
    var jan1GMTTemp = jan1Local.toGMTString();
    var july1GMTTemp = july1Local.toGMTString();
    var jan1GMT = new Date( jan1GMTTemp.substring( 0, jan1GMTTemp.lastIndexOf( " " ) - 1 ) );
    var july1GMT = new Date( july1GMTTemp.substring( 0, july1GMTTemp.lastIndexOf( " " ) - 1 ) );
    var janGMTDiffHour = ( jan1Local - jan1GMT ) / ( 1000 * 3600 );
    var julyGMTDiffHour = ( july1Local - july1GMT ) / ( 1000 * 3600 );

    var dst = 0;

    if ( janGMTDiffHour != julyGMTDiffHour )
    {
        dst = 1;
    }

    var res = new Array();
    res[ "stdHourOffset" ] = janGMTDiffHour;
    res[ "dst" ] = dst;

    return res;
}

function NumberFormat( nStr )
{
	nStr += '';
	x = nStr.split( '.' );
	x1 = x[ 0 ];
	x2 = x.length > 1 ? '.' + x[ 1 ] : '';
	var rgx = /(\d+)(\d{3})/;

	while ( rgx.test( x1 ) )
	{
		x1 = x1.replace( rgx, '$1' + ',' + '$2' );
	}
	return x1 + x2;
}

function checkOS()
{
	if ( navigator.userAgent.indexOf( 'IRIX' ) != -1 )
	{
		var OpSys = "Irix";
	}

	else if ( ( navigator.userAgent.indexOf( 'Win' ) != -1 ) && ( navigator.userAgent.indexOf( '95' ) != -1 ) )
	{
		var OpSys = "Windows95";
	}

	else if ( navigator.userAgent.indexOf( 'Win' ) != -1 )
	{
		var OpSys = "Windows3.1 or NT";
	}

	else if ( navigator.userAgent.indexOf( 'Mac' ) != -1 )
	{
		var OpSys = "Macintosh";
	}

	else
	{
		var OpSys = "other";
	}
	return OpSys;
}

function fixStateInput( oSi, oCi )
{
	if ( ( oCi.options[ oCi.selectedIndex ].text != "United States" ) ||
	     ( oCi.options[ oCi.selectedIndex ].text != "Canada" ) )
	{
		for ( i = 0; i < oSi.options.length; i++ )
		{
			if ( oSi.options[ i ].text == "NON USA/Canada" )
			{
				oSi.options[ i ].selected = true;
			}
		}
	}

	return (true);
}


function fixCountryInput( oSi, oCi )
{
	if ( ( oSi.options[ oSi.selectedIndex ].text != "NON USA/Canada" ) )
	{
		for ( i = 0; i < oCi.options.length; i++ )
		{
			if ( oCi.options[ i ].text == "United States" )
			{
				oCi.options[ i ].selected = true;
			}
		}
	}

	return (true);
}

function require_once( js_file )
{
    var oHead = document.getElementsByTagName("head").item(0);

    // Create the script tag
    var oScript = document.createElement("script");

    // Add script object attributes
    oScript.setAttribute("type", "text/javascript");
    oScript.setAttribute("src", jsFile );
    oScript.setAttribute("id", jsId);

    // Add the script to the head section
    this.headObj.appendChild(oScript);
}

function ToggleCheckboxStatus( checkboxPrefix, checked )
{
	var elements = document.getElementsByTagName( "input" );
	if ( elements == null )
		return;

	for ( var i = 0; i < elements.length; ++i )
	{
		if ( elements[ i ].type == "checkbox" && elements[ i ].name.indexOf( checkboxPrefix ) != -1 )
		{
			elements[ i ].checked = checked;
		}
	}
}

function myunescape (str)
{
	if (typeof str == "string")
	{
		// convert all + signs to %20
		str = str.replace( /\+/g, "%20" );

		return unescape (str);
	}

	return ( str );
}

function RedirectParent(url)
{
    if ( window.opener == null )
    {
        window.location.href = url;
    }
    else
    {
        window.opener.location.href = url;
        window.close();
    }
}

function flash_player_stats(key)
{
	var cookie_name = "wcc_flash_player_stats_"+key; 
	if (wcc_readcookie(cookie_name)==null)
	{
		var url = location.protocol+"//"+location.hostname+"/xml/flash_player_stats.php";
		var ajax = new oAjax( url, dummy );
	
		params  = "&"+key+"=1";
		params += "&major=" + FlashDetect.major;
		params += "&minor=" + FlashDetect.minor;
		params += "&revision=" + FlashDetect.revision;
		params += "&xhprof=0";
		ajax.update( params, "GET" );
		wcc_setcookie(cookie_name, -1, params);
	}
}

function track_pixel( aff_id, type, cell )
{
	url = "/ajax_track_pixel.php";

	params = {};
	params.aff_id = aff_id;
	params.type = type;
	params.cell = urlencode( cell );
	
	ele_name = "#track_pixel";
	
	$( ele_name ).load( url, params, this.track_pixel_callback );		
}

function track_pixel_callback( res_text, res_code, http_request )
{
	window.location = "/?show=signup_success";
}

function is_child_of(parent, child)
{
	if( child != null ) {			
		while( child.parentNode ) {
			if( (child = child.parentNode) == parent ) {
				return true;
			}
		}
	}
	
	return false;
}

function json_encode (mixed_val) {
    // http://kevin.vanzonneveld.net
    // +      original by: Public Domain (http://www.json.org/json2.js)
    // + reimplemented by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      improved by: Michael White
    // +      input by: felix
    // +      bugfixed by: Brett Zamir (http://brett-zamir.me)
    // *        example 1: json_encode(['e', {pluribus: 'unum'}]);
    // *        returns 1: '[\n    "e",\n    {\n    "pluribus": "unum"\n}\n]'
/*
        http://www.JSON.org/json2.js
        2008-11-19
        Public Domain.
        NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
        See http://www.JSON.org/js.html
    */
    var retVal, json = this.window.JSON;
    try {
        if (typeof json === 'object' && typeof json.stringify === 'function') {
            retVal = json.stringify(mixed_val); // Errors will not be caught here if our own equivalent to resource
            //  (an instance of PHPJS_Resource) is used
            if (retVal === undefined) {
                throw new SyntaxError('json_encode');
            }
            return retVal;
        }

        var value = mixed_val;

        var quote = function (string) {
            var escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
            var meta = { // table of character substitutions
                '\b': '\\b',
                '\t': '\\t',
                '\n': '\\n',
                '\f': '\\f',
                '\r': '\\r',
                '"': '\\"',
                '\\': '\\\\'
            };

            escapable.lastIndex = 0;
            return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
                var c = meta[a];
                return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
            }) + '"' : '"' + string + '"';
        };

        var str = function (key, holder) {
            var gap = '';
            var indent = '    ';
            var i = 0; // The loop counter.
            var k = ''; // The member key.
            var v = ''; // The member value.
            var length = 0;
            var mind = gap;
            var partial = [];
            var value = holder[key];

            // If the value has a toJSON method, call it to obtain a replacement value.
            if (value && typeof value === 'object' && typeof value.toJSON === 'function') {
                value = value.toJSON(key);
            }

            // What happens next depends on the value's type.
            switch (typeof value) {
            case 'string':
                return quote(value);

            case 'number':
                // JSON numbers must be finite. Encode non-finite numbers as null.
                return isFinite(value) ? String(value) : 'null';

            case 'boolean':
            case 'null':
                // If the value is a boolean or null, convert it to a string. Note:
                // typeof null does not produce 'null'. The case is included here in
                // the remote chance that this gets fixed someday.
                return String(value);

            case 'object':
                // If the type is 'object', we might be dealing with an object or an array or
                // null.
                // Due to a specification blunder in ECMAScript, typeof null is 'object',
                // so watch out for that case.
                if (!value) {
                    return 'null';
                }
                if ((this.PHPJS_Resource && value instanceof this.PHPJS_Resource) || (window.PHPJS_Resource && value instanceof window.PHPJS_Resource)) {
                    throw new SyntaxError('json_encode');
                }

                // Make an array to hold the partial results of stringifying this object value.
                gap += indent;
                partial = [];

                // Is the value an array?
                if (Object.prototype.toString.apply(value) === '[object Array]') {
                    // The value is an array. Stringify every element. Use null as a placeholder
                    // for non-JSON values.
                    length = value.length;
                    for (i = 0; i < length; i += 1) {
                        partial[i] = str(i, value) || 'null';
                    }

                    // Join all of the elements together, separated with commas, and wrap them in
                    // brackets.
                    v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']';
                    gap = mind;
                    return v;
                }

                // Iterate through all of the keys in the object.
                for (k in value) {
                    if (Object.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }

                // Join all of the member texts together, separated with commas,
                // and wrap them in braces.
                v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}';
                gap = mind;
                return v;
            case 'undefined':
                // Fall-through
            case 'function':
                // Fall-through
            default:
                throw new SyntaxError('json_encode');
            }
        };

        // Make a fake root object containing our value under the key of ''.
        // Return the result of stringifying the value.
        return str('', {
            '': value
        });

    } catch (err) { // Todo: ensure error handling above throws a SyntaxError in all cases where it could
        // (i.e., when the JSON global is not available and there is an error)
        if (!(err instanceof SyntaxError)) {
            throw new Error('Unexpected error type in json_encode()');
        }
        this.php_js = this.php_js || {};
        this.php_js.last_error_json = 4; // usable by json_last_error()
        return null;
    }
}

function json_decode (str_json) {
    // http://kevin.vanzonneveld.net
    // +      original by: Public Domain (http://www.json.org/json2.js)
    // + reimplemented by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      improved by: T.J. Leahy
    // +      improved by: Michael White
    // *        example 1: json_decode('[\n    "e",\n    {\n    "pluribus": "unum"\n}\n]');
    // *        returns 1: ['e', {pluribus: 'unum'}]
/*
        http://www.JSON.org/json2.js
        2008-11-19
        Public Domain.
        NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
        See http://www.JSON.org/js.html
    */

    var json = this.window.JSON;
    if (typeof json === 'object' && typeof json.parse === 'function') {
        try {
            return json.parse(str_json);
        } catch (err) {
            if (!(err instanceof SyntaxError)) {
                throw new Error('Unexpected error type in json_decode()');
            }
            this.php_js = this.php_js || {};
            this.php_js.last_error_json = 4; // usable by json_last_error()
            return null;
        }
    }

    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
    var j;
    var text = str_json;

    // Parsing happens in four stages. In the first stage, we replace certain
    // Unicode characters with escape sequences. JavaScript handles many characters
    // incorrectly, either silently deleting them, or treating them as line endings.
    cx.lastIndex = 0;
    if (cx.test(text)) {
        text = text.replace(cx, function (a) {
            return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
        });
    }

    // In the second stage, we run the text against regular expressions that look
    // for non-JSON patterns. We are especially concerned with '()' and 'new'
    // because they can cause invocation, and '=' because it can cause mutation.
    // But just to be safe, we want to reject all unexpected forms.
    // We split the second stage into 4 regexp operations in order to work around
    // crippling inefficiencies in IE's and Safari's regexp engines. First we
    // replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
    // replace all simple value tokens with ']' characters. Third, we delete all
    // open brackets that follow a colon or comma or that begin the text. Finally,
    // we look to see that the remaining characters are only whitespace or ']' or
    // ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
    if ((/^[\],:{}\s]*$/).
    test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
    replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
    replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

        // In the third stage we use the eval function to compile the text into a
        // JavaScript structure. The '{' operator is subject to a syntactic ambiguity
        // in JavaScript: it can begin a block or an object literal. We wrap the text
        // in parens to eliminate the ambiguity.
        j = eval('(' + text + ')');

        return j;
    }

    this.php_js = this.php_js || {};
    this.php_js.last_error_json = 4; // usable by json_last_error()
    return null;
}

function sprintf () {
    // http://kevin.vanzonneveld.net
    // +   original by: Ash Searle (http://hexmen.com/blog/)
    // + namespaced by: Michael White (http://getsprink.com)
    // +    tweaked by: Jack
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Paulo Freitas
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // *     example 1: sprintf("%01.2f", 123.1);
    // *     returns 1: 123.10
    // *     example 2: sprintf("[%10s]", 'monkey');
    // *     returns 2: '[    monkey]'
    // *     example 3: sprintf("[%'#10s]", 'monkey');
    // *     returns 3: '[####monkey]'
    var regex = /%%|%(\d+\$)?([-+\'#0 ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([scboxXuidfegEG])/g;
    var a = arguments,
        i = 0,
        format = a[i++];

    // pad()
    var pad = function (str, len, chr, leftJustify) {
        if (!chr) {
            chr = ' ';
        }
        var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);
        return leftJustify ? str + padding : padding + str;
    };

    // justify()
    var justify = function (value, prefix, leftJustify, minWidth, zeroPad, customPadChar) {
        var diff = minWidth - value.length;
        if (diff > 0) {
            if (leftJustify || !zeroPad) {
                value = pad(value, minWidth, customPadChar, leftJustify);
            } else {
                value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);
            }
        }
        return value;
    };

    // formatBaseX()
    var formatBaseX = function (value, base, prefix, leftJustify, minWidth, precision, zeroPad) {
        // Note: casts negative numbers to positive ones
        var number = value >>> 0;
        prefix = prefix && number && {
            '2': '0b',
            '8': '0',
            '16': '0x'
        }[base] || '';
        value = prefix + pad(number.toString(base), precision || 0, '0', false);
        return justify(value, prefix, leftJustify, minWidth, zeroPad);
    };

    // formatString()
    var formatString = function (value, leftJustify, minWidth, precision, zeroPad, customPadChar) {
        if (precision != null) {
            value = value.slice(0, precision);
        }
        return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar);
    };

    // doFormat()
    var doFormat = function (substring, valueIndex, flags, minWidth, _, precision, type) {
        var number;
        var prefix;
        var method;
        var textTransform;
        var value;

        if (substring == '%%') {
            return '%';
        }

        // parse flags
        var leftJustify = false,
            positivePrefix = '',
            zeroPad = false,
            prefixBaseX = false,
            customPadChar = ' ';
        var flagsl = flags.length;
        for (var j = 0; flags && j < flagsl; j++) {
            switch (flags.charAt(j)) {
            case ' ':
                positivePrefix = ' ';
                break;
            case '+':
                positivePrefix = '+';
                break;
            case '-':
                leftJustify = true;
                break;
            case "'":
                customPadChar = flags.charAt(j + 1);
                break;
            case '0':
                zeroPad = true;
                break;
            case '#':
                prefixBaseX = true;
                break;
            }
        }

        // parameters may be null, undefined, empty-string or real valued
        // we want to ignore null, undefined and empty-string values
        if (!minWidth) {
            minWidth = 0;
        } else if (minWidth == '*') {
            minWidth = +a[i++];
        } else if (minWidth.charAt(0) == '*') {
            minWidth = +a[minWidth.slice(1, -1)];
        } else {
            minWidth = +minWidth;
        }

        // Note: undocumented perl feature:
        if (minWidth < 0) {
            minWidth = -minWidth;
            leftJustify = true;
        }

        if (!isFinite(minWidth)) {
            throw new Error('sprintf: (minimum-)width must be finite');
        }

        if (!precision) {
            precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : undefined;
        } else if (precision == '*') {
            precision = +a[i++];
        } else if (precision.charAt(0) == '*') {
            precision = +a[precision.slice(1, -1)];
        } else {
            precision = +precision;
        }

        // grab value using valueIndex if required?
        value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];

        switch (type) {
        case 's':
            return formatString(String(value), leftJustify, minWidth, precision, zeroPad, customPadChar);
        case 'c':
            return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad);
        case 'b':
            return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
        case 'o':
            return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
        case 'x':
            return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
        case 'X':
            return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase();
        case 'u':
            return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad);
        case 'i':
        case 'd':
            number = (+value) | 0;
            prefix = number < 0 ? '-' : positivePrefix;
            value = prefix + pad(String(Math.abs(number)), precision, '0', false);
            return justify(value, prefix, leftJustify, minWidth, zeroPad);
        case 'e':
        case 'E':
        case 'f':
        case 'F':
        case 'g':
        case 'G':
            number = +value;
            prefix = number < 0 ? '-' : positivePrefix;
            method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];
            textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];
            value = prefix + Math.abs(number)[method](precision);
            return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform]();
        default:
            return substring;
        }
    };

    return format.replace(regex, doFormat);
}

function human_time( timestamp, display_ago, want_seconds, simple_labels )
{
	if ( display_ago == null )
		display_ago = false;
	
	if ( want_seconds == null )
		want_seconds = true;
	
	if ( simple_labels == null )
		simple_labels = true;
	
	d = new Date();
	t = d.getTime() / 1000;
	time_diff = t - timestamp;
	
	days		= Math.floor( time_diff / 86400 );
	hours		= Math.floor( ( time_diff % 86400 ) / 3600 );
	mins		= Math.floor( ( time_diff % 3600 ) / 60 );
	seconds		= Math.floor( ( time_diff % 3600 ) % 60 );
	update_time_fmt = "";
	
	labels = new Array();
	if ( !simple_labels )
	{
		labels[ "days" ] = "%d days";
		labels[ "hrs" ]  = "%d hrs";
		labels[ "mins" ] = "%d mins";
		labels[ "secs" ] = "%d secs";
	}
	else
	{
		labels[ "days" ] = "%dd";
		labels[ "hrs" ]  = "%dh";
		labels[ "mins" ] = "%dm";
		labels[ "secs" ] = "%ds";
	}

	if ( days != 0 )
		update_time_fmt += sprintf( labels[ "days" ], days );

	if ( hours != 0 )
	{
		if ( update_time_fmt != "" )
			update_time_fmt += ( simple_labels ) ? ( " " ) : ( ", " );
		
		update_time_fmt += sprintf( labels[ "hrs" ], hours );
	}

	if ( mins != 0 )
	{
		if ( update_time_fmt != "" )
			update_time_fmt += ( simple_labels ) ? ( " " ) : ( ", " );

		update_time_fmt += sprintf( labels[ "mins" ], mins );
	}

	if ( seconds != 0 && want_seconds )
	{
		if ( update_time_fmt != "" )
			update_time_fmt += ( simple_labels ) ? ( " " ) : ( ", " );

		update_time_fmt += sprintf( labels[ "secs" ], seconds );
	}

	if ( display_ago )
	{
		if ( update_time_fmt == "" )
			update_time_fmt = "(now)";
		else
			update_time_fmt += " ago";
	}
	
	return update_time_fmt;
}

function get_viewport()
{
	var res = null;
	if ( window.innerWidth )
	{
		res = new Array();
		res[ "width" ] = window.innerWidth;
		res[ "height" ] = window.innerHeight;
	}
	else if ( document.documentElement.offsetWidth )
	{
		res = new Array();
		res[ "width" ] = document.documentElement.offsetWidth;
		res[ "height" ] = document.documentElement.offsetHeight;		
	}
	else if ( document.body.clientWidth )
	{
		res = new Array();
		res[ "width" ] = document.body.clientWidth;
		res[ "height" ] = document.body.clientHeight;
	}
	
	return res;
}
