/**
 * @module global
 */

try
{
	document.domain = 'kaixin.com';
} catch ( e ){}


/**
 * 这个生成文档的时候有问题
 * 下面这些方法都是全局函数，不用加命名空间便可调用
 * @class window
 * @static
 */

/**
 * @method isUndefined
 * @param {Any} object
 * @return {Boolean}
 */

function isUndefined( object )
{
	return typeof object == 'undefined';
}

/**
 * @method isString
 * @param {Any} object
 * @return {Boolean}
 */

function isString( object )
{
    return typeof object == 'string';
}

/**
 * @method isElement
 * @param {Any} object
 * @return {Boolean}
 */

function isElement( object )
{
	return object && object.nodeType == 1;
}

/**
 * @method isFunction
 * @param {Any} object
 * @return {Boolean}
 */

function isFunction( object )
{
	return typeof object == 'function';
}

/**
 * @method isObject
 * @param {Any} object
 * @return {Boolean}
 */

function isObject( object )
{
	return typeof object == 'object';
}

/**
 * @method isArray
 * @param {Any} object
 * @return {Boolean}
 */

function isArray( object )
{
	//return object !== null && typeof object == 'object' && 'splice' in object && 'join' in object;
    return Object.prototype.toString.call( object ) === '[object Array]';
}

/**
 * @method isNumber
 * @param {Any} object
 * @return {Boolean}
 */

function isNumber( object )
{
	return typeof object == 'number';
}

/**
 * extend an object
 * @method $extend
 * @param {Object} object the object for extend
 * @param {Object} src the object will copy from
 */

function $extend( object , src )
{
	if( !src ) return object;
	for ( var p in src )
	{
		object[ p ] = src[ p ];
	}
	return object;
}

/**
 * create an DOM element
 * @method $element
 * @param {String} tagName
 * @return {HTMLElement}
 */

(function()
{
	var cache = {};
	
	$element = function( tagName )
	{
		tagName = tagName.toLowerCase();
		if ( !cache[ tagName ] )
		{
			cache[ tagName ] = document.createElement( tagName );
		}
		return $( cache[ tagName ].cloneNode( false ) );
	};
})();

/**
 * short cut for document.getElementById
 * @method $
 * @param {String} id
 * @return {HTMLElement}
 */

function $( id )
{
	var el;
	if ( isString( id ) || isNumber( id ) )
	{
		el = document.getElementById( id + '' );
	}
	else
	{
		el = id;
	}
	if ( !el ) return null;
	if( !el._extendLevel ) XN.element.extend( el );
	return el;
}

xn_getEl = $;

if( !Function.prototype.bind )
{
	Function.prototype.bind = function( object )
	{ 
		var method = this;
		return function()
		{ 
			method.apply( object , arguments ); 
		} 
	};
}

/*
 * patch for old version
 */

ge = getEl = $;
$xElement = $element;
$X = $;
/*
 * patch end
 */
/**
 * @module core
 */

/**
 * @class XN
 * @static
 */

/**
 * 动态加载文件
 * <br>
 * 动态加载某一文件<br>
 * XN.loadFile( 'http://xnimg.cn/kaixin/js/test.js' );<br>
 *
 * 一定要在页面中写入一个如下的标签<br>
 * &lt;script vsrc="http://xnimg.cn/kaixin/js/test.js?ver=$revxxx$"&gt;&lt;/script&gt;<br>
 *  这样loadFile函数将根据此标签获取正确的版本号，并在请求此文件时为其添加<br>
 *  
 *  http://xnimg.cn/kaixin/156454/js/test.js<br>
 *
 * @method loadFile
 * @param {String} file
 * @param {Function} callBack
 */


var XN = {

	/**
	 * based on YAHOO.namespace
     * @namespace XN
	 * @method namespace
	 * @param  {String*} arguments 1-n namespaces to create 
	 * @return {Object}  A reference to the last namespace object created
	 */

	namespace : function()
	{
	    var a = arguments, o = null, i, j, d;
	    for ( i = 0 ; i < a.length ; i++ )
		{
	        d = a[ i ].split( '.' );
	        o = XN;
	
	        for ( j = ( d[0] == 'XN' ) ? 1 : 0; j < d.length; j++ )
			{
	            o[ d[ j ] ] = o[ d[ j ] ] || {};
	            o = o[ d[ j ] ];
	        }
	    }
	    return o;		
	}
};


XN.namespace( 'ui' );
XN.namespace( 'util' );
XN.namespace( 'app' );
XN.namespace( 'page' );
XN.namespace( 'config' );

/*
 * patch for old version
 */

XN.APP = XN.App = XN.app;
XN.PAGE = XN.Page = XN.page;
XN.CONFIG = XN.Config = XN.config;

/*
 * patch end
 */
/**
 * @namespace XN
 * @property DEBUG_MODE
 * @type {Boolean}
 */

XN.DEBUG_MODE = false;

/**
 *  log message if the browser has console object
 * @method log
 * @param {Any} s
 */

/**
 * @class debug
 * @static
 */

XN.debug =
{
	/**
	 * log message if the browser has console object
	 * @method log
	 * @param {Any} s
	 */
	
	log : function(){},
	
	/**
	 * debug mode on
	 * @method on
	 */
	
	on : function()
	{
		XN.DEBUG_MODE = true;
		if ( window.console && console.log )
		{
			XN.debug.log = function( s )
			{
				console.log( s );
			}
		}
	},
	
	/**
	 * debug mode off
	 * @method off
	 */
	
	off : function()
	{
		XN.debug.log = function(){};
	}
};

XN.log = function( s )
{
	XN.debug.log( s );
}

/*
 * patch for old version
 */

XN.DEBUG = XN.Debug = XN.debug;
XN.debug.On = XN.debug.on;
XN.debug.Off = XN.debug.off;
/*
 * patch end
 */
/**
 * @module core
 */

/**
 * @namespace XN
 * @class env
 * @static
 */

XN.env =
{	
	/**
	 * @property domain
	 * @type {String}
	 * @default 'kaixin.com'
	 */
	
	domain : 'kaixin.com',
	
	/**
	 * @property staticRoot
	 * @type {String}
	 * @default 'http://xnimg.cn/'
	 */
	
	staticRoot : 'http://xnimg.cn/kaixin/',
	
	/**
	 * @property swfRoot
	 * @type {String}
	 * @default 'http://static.kaixin.com'
	 */
	
	swfRoot : 'http://static.kaixin.com/',
	
	/**
	 * @property wwwRoot
	 * @type {String}
	 * @default 'http://kaixin.com/'
	 */
	
	wwwRoot : 'http://kaixin.com/'
};

/*
 *  patch for old version
 */

XN.ENV = XN.Env = XN.env;

/*
 * patch end
 */
/**
 * @module core
 */

/**
 * @namespace XN
 * @class array
 * @static
 */

XN.array =
{
	
	/**
	 * build query string from array
	 * @namespace XN.array
	 * @method toQueryString
	 * @param {Array | hash} a
	 * @return {String}
	 */
	
	toQueryString : function( a , key )
	{
		var rt = [],t;
		for ( var k in a )
		{
			t = a[ k ];
			if ( isFunction( t ) ) continue;
			if ( isObject( t ) )
			{
				rt.push( arguments.callee( t , k ) );
			}
			else
			{
				if ( /^\d+$/.test( k ) )
				{
					rt.push( ( key || k ) + '=' + encodeURIComponent( t ) );
				}
				else
				{
					rt.push( k + '=' + encodeURIComponent( t ) );
				}	
			}
		}
		return rt.join( '&' );
	},
	
	/**
	 * Iterates over the array
	 * the callback function will receive index and value as the parameters
	 * @namespace XN.array
	 * @method each
	 * @param {Array} a
	 * @param {Function} func callback function
	 */
	
	each : function( a , func )
	{
        if ( !a ) return;

		if ( !isUndefined( a.length ) || !isUndefined( a[ 0 ] ) )
		{
			for ( var i = 0 , j = a.length; i < j; i++ )
			{
				if ( func.call( a , i , a[ i ] ) === false ) break;
			}
		}
		else
		{
			for ( var key in a )
			{
				if( !isFunction( a[ key ] ) )
				{
					if ( func.call( a , key , a[ key ] ) === false ) break;
				}
			}
		}
	},
	
	/**
	 * check if an array has item equal the value param
	 * @namespace XN.array
	 * @method include
	 * @param {Array} a
	 * @param {Any} value
	 * @return {Boolean}
	 */
	
	include : function( a , value )
	{
		var r = false;
		
		XN.array.each( a , function( i , v )
		{
			if ( v === value )
			{
				r = true;
				return false;
			}
		} );
		
		return r;
	},
	
	/**
	 * build array from an object like arguments
	 * @namespace XN.array
	 * @method build
	 * @param {Object} obj
	 * @return {Array}
	 */
	
	build : function( o )
	{
		var rt = [];
		for (var i = 0,j = o.length;i < j;i++)
		{
			rt.push( o[ i ] );
		}
		return rt;
	}
};

/*
 * patch for old version
 */

XN.ARRAY = XN.Array = XN.array;

/*
 * patch end
 */
/**
 * @module core
 */

/**
 * @namespace XN
 * @class string
 * @static
 */

XN.string = {
	/**
	 * replace '\n' with '<br />'
	 * @namespace XN.string
	 * @method nl2br
	 * @param {String} str
	 * @return {String}
	 */
	
	nl2br : function( str )
	{
		return str.replace( /([^>])\n/g , '$1<br />');
	},
	
	/**
	 * trim whitespace
	 * @namespace XN.string
	 * @method trim
	 * @param {String} str
	 * @return {String}
	 */
	
	trim : function( str )
	{
		return str.replace( /^\s+|\s+$/g , '' );
	},
	
	/**
	 * trim whitespace leftside
	 * @namespace XN.string
	 * @method ltrim
	 * @param {String} str
	 * @return {String}
	 */
	
	ltrim : function( str )
	{
		return str.replace( /^\s+/ , '' );
	},
	
	/**
	 * trim whitespace rightside
	 * @namespace XN.string
	 * @method rtrim
	 * @param {String} str
	 * @return {String}
	 */
	
	rtrim : function( str )
	{
		return str.replace( /\s+$/ , '' );
	},
	
	strip : function( str )
	{
    	return XN.string.trim( str );
	},
	
	/**
	 * remove tag like '<...>'
	 * @namespace XN.string
	 * @method stripTags
	 * @param {String} str
	 * @return {String}
	 */
	
	stripTags: function( str )
	{
		return str.replace( /<\/?[^>]+>/igm, '' );
	},
	
	/**
	 * replace char like '<','>' to '&lt;'...
	 * @namespace XN.string
	 * @method escapeHTML
	 * @param {String} str
	 * @return {String}
	 */
	
	escapeHTML : function(str)
	{
		return str.replace( /&/g ,'&amp;' )
		.replace( /</g , '&lt;' )
		.replace( />/g , '&gt;' );
	},
	
	/**
	 * replace '&lt;'... to '<'...
	 * @namespace XN.string
	 * @method unescapeHTML
	 * @param {String} str
	 * @return {String}
	 */
	
	unescapeHTML : function(str)
	{
		return str.replace( /&lt;/g ,'<' )
		.replace( /&gt;/g , '>' )
		.replace( /&nbsp;/g ,' ' )
		.replace( /&quot;/g , '"' )
		.replace( /&amp;/g , '&' );
	},
	
	/**
	 * if str include the keyword will return true 
	 * @namespace XN.string
	 * @method include
	 * @param {String} str
	 * @param {String} key the keyword
	 * @return {Boolean}
	 */
	
	include : function( str , key )
	{
		return str.indexOf( key ) > -1;
	},

	/**
	 * wether str starts with the keyword
	 * @namespace XN.string
	 * @method startsWith
	 * @param {String} str
	 * @param {String} key the keyword
	 * @return {Boolean}
	 */
		
	startsWith : function( str , key )
	{
		return str.indexOf( key ) === 0;
	},

	/**
	 * wether str ends with the keyword
	 * @namespace XN.string
	 * @method endsWith
	 * @param {String} str
	 * @param {String} key the keyword
	 * @return {Boolean}
	 */
	
	endsWith : function( str , key )
	{
	    var d = str.length - key.length;
	    return d >= 0 && str.lastIndexOf( key ) === d;	
	},
	
	/**
	 * check if the string is 'blank',meaning either empty or containing only whitespace
	 * @namespace XN.string
	 * @method isBlank
	 * @param {String} str
	 * @return {Boolean}
	 */
	
	isBlank : function( str )
	{
		return /^\s*$/.test(str);
	},
	
	/**
	 * wether a string is an email address
	 * @namespace XN.string
	 * @method isEmail
	 * @param {String} str
	 * @return {Boolean}
	 */
	
	isEmail : function( str )
	{
		return /^[A-Z_a-z0-9-\.]+@([A-Z_a-z0-9-]+\.)+[a-z0-9A-Z]{2,4}$/.test( str );
	},
	
	/**
	 * wether a string is mobile phone number
	 * @namespace XN.string
	 * @method isMobile
	 * @param {String} str
	 * @return {Boolean}
	 */
	
	isMobile : function( str )
	{
        return /^((\(\d{2,3}\))|(\d{3}\-))?((1[345]\d{9})|(18[89]\d{8}))$/.test(str);
	},
	
	/**
	 * @namespace XN.string
	 * @method isUrl
	 * @param {String} str
	 * @return {Boolean}
	 */	
	 
	isUrl : function(str)
	{
		return /^(http:|ftp:)\/\/[A-Za-z0-9]+\.[A-Za-z0-9]+[\/=\?%\-&_~`@[\]\':+!]*([^<>\"])*$/.test(str);
	},
	
	/**
	 * @namespace XN.string
	 * @method isIp
	 * @param {String} str
	 * @return {Boolean}
	 */
	 	
	isIp : function( str )
	{
		return /^(0|[1-9]\d?|[0-1]\d{2}|2[0-4]\d|25[0-5]).(0|[1-9]\d?|[0-1]\d{2}|2[0-4]\d|25[0-5]).(0|[1-9]\d?|[0-1]\d{2}|2[0-4]\d|25[0-5]).(0|[1-9]\d?|[0-1]\d{2}|2[0-4]\d|25[0-5])$/.test(str);
	},
	
	/**
	 * @namespace XN.string
	 * @method isNumber
	 * @param {String} str
	 * @return {Boolean}
	 */
	
	isNumber : function( str )
	{
		return /^\d+$/.test( str );
	},

	/**
	 * @namespace XN.string
	 * @method isZip
	 * @param {String} str
	 * @return {Boolean}
	 */
	
	isZip : function( str )
	{
		return /^[1-9]\d{5}$/.test( str );
	},
	
	/**
	 * @namespace XN.string
	 * @method isEN
	 * @param {String} str
	 * @return {Boolean}
	 */
	
	isEN : function( str )
	{
		return /^[A-Za-z]+$/.test( str );
	},

	/**
	 * @namespace XN.string
	 * @method isJSON
	 * @param {String} str
	 * @return {Boolean}
	 */
	
	isJSON : function( str )
	{
		if ( !isString( str ) || str === '') return false;
		str = str.replace( /\\./g , '@' ).replace( /"[^"\\\n\r]*"/g , '' );
		return ( /^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/ ).test( str );	
	},
    
    /**
     * get parameters from url
     * @method getQuery
     * @param {String} key
     * @param {String} url
     * @return {String | Array}
     */

    getQuery : function( key , url )
    {
        url = url || window.location.href;
        if ( url.indexOf( '#' ) !== -1 )
            url = url.substring( 0 , url.indexOf( '#' ) );
        var rts = [],rt;
        queryReg = new RegExp( '(^|\\?|&)' + key + '=([^&]*)(?=&|#|$)' , 'g' );
        while ( ( rt = queryReg.exec( url ) ) != null )
        {
            rts.push( decodeURIComponent( rt[ 2 ] ) );
        }
        if ( rts.length == 0 ) return null;
        if ( rts.length == 1 ) return rts[ 0 ];
        return rts;
    },
    
    /**
     * set parameters for url
     * @method setQuery
     * @param {String} key
     * @param {String | Array} value
     * @param {String} url
     * @return {String}
     */

    setQuery : function( key , value , url )
    {
        
        url = url || window.location.href;
        var hash = '';

        if ( url.indexOf( '#' ) !== -1 )
            hash = url.substring( url.indexOf( '#' ) );
        
        url = url.replace( hash , '' );
        url = url.replace( new RegExp( '(^|\\?|&)' + key + '=[^&]*(?=&|#|$)' , 'g' ) , '' );
        value = isArray( value ) ? value : [ value ];
        
        for ( var i = value.length - 1;i >= 0;i --)
        {
            value[ i ] = encodeURIComponent( value[ i ] );
        }

        var p = key + '=' + value.join( '&' + key + '=' );
        return url + ( /\?/.test( url ) ? '&' : '?' ) + p + hash;
    }
};

/*
 *  patch for old version
 */

XN.String = XN.STRING = XN.string;

XN.string.isNum = XN.string.isNumber;

window.isJSON = XN.string.isJSON;

/*
 * patch end
 */
/**
 * @namespace XN
 * @class func
 * @static
 */

(function()
{
	runOnceFunc = {};
	
	XN.func = {
		
		/**
		 * refer to an empty function
		 * @property empty
		 * @type {Function}
		 */
		
		empty : function(){},
		
		/**
		 * run a function only once
		 * @method runOnce
		 * @param {Function} func
		 * @return {Any} the result the func return
		 */
		
		runOnce : function( func )
		{
			if( runOnceFunc[ func ] )return null;
			runOnceFunc[ func ] = true;
			return func();
		}
	};
})();

/*
 *  patch for old version
 */

XN.FUNC = XN.Func = XN.func;

/*
 * patch end
 */
/**
 * @module core
 */

(function()
{
	
	
	/**
	 * @namespace XN
	 * @class browser
	 * @static
	 */
	
	XN.browser = {
		
		/**
		 * @property IE
		 * @type {Boolean}
		 */
		
		IE : !!( window.attachEvent && !window.opera ),
		
		/**
		 * @property IE6
		 * @type {Boolean}
		 */
		
		IE6 : navigator.userAgent.indexOf( 'MSIE 6.0' ) > -1,
		
		/**
		 * @property IE7
		 * @type {Boolean}
		 */
		
		IE7 : navigator.userAgent.indexOf( 'MSIE 7.0' ) > -1,
		
		/**
		 * @property Opera
		 * @type {Boolean}
		 */
		
		Opera : !!window.opera,
		
		/**
		 * @property WebKit
		 * @type {Boolean}
		 */
		
		WebKit : navigator.userAgent.indexOf( 'AppleWebKit/' ) > -1,
		
		/**
		 * @property Gecko
		 * @type {Boolean}
		 */
		
		Gecko : navigator.userAgent.indexOf( 'Gecko' ) > -1 && navigator.userAgent.indexOf( 'KHTML' ) == -1,
		
		/**
		 * copy string to clipboard
		 * @param {String} str
		 */
		
		copy : function( o )
		{
            function onfail()
            {
                if ( isElement( o ) )
                {
                    o.select();
                }
            }
            
            var str;

			if ( isElement( o ) )
            {
                str = o.value;
            }
            else
            {
                str = o;
            }
			
			if ( window.clipboardData && clipboardData.setData )
			{
				if ( clipboardData.setData( 'text', str ) ) return true;
			}
			else
			{
				XN.DO.alert({
                    message : '您的浏览器不支持脚本复制,请尝试手动复制',
                    callBack : function()
                    {
                        onfail();
                    }
                });

				return false;
			}
			
			XN.DO.alert({
                message : '您的浏览器设置不允许脚本访问剪切板',
                callBack : function()
                {
                    onfail();
                }
            });


			return false;
		}
	};
})();
/*
 * patch for old version
 */

XN.BROWSER = XN.Browser = XN.browser;

/*
 * patch end
 */
/**
 * @module core
 */

/**
 * @namespace XN
 * @class cookie
 * @static
 */

XN.cookie = {
	
	/**
	 * get cookie
	 * @method get
	 * @param {String} name
	 */
	
	get : function( name )
	{
		var nameEQ = name + '=';
		var ca = document.cookie.split(';');
		for ( var i=0;i < ca.length; i++ )
		{
			var c = ca[ i ];
			while ( c.charAt(0) == ' ' ) c = c.substring( 1 , c.length );
			if ( c.indexOf( nameEQ ) == 0 ) return decodeURIComponent( c.substring( nameEQ.length , c.length ) );
		}
		return null;
	},
	
	/**
	 * set Cookie
	 * @method set
	 * @param {String} name
	 * @param {String} value
	 * @param {Int} days
	 * @param {String} path
	 * @param {String} domain
	 * @param {Boolean} secure
	 */
	
	set : function( name , value , days , path , domain , secure )
	{
		var expires;
		if ( isNumber( days ) )
		{
			var date = new Date();
			date.setTime( date.getTime() + ( days * 24 * 60 * 60 * 1000 ) );
			expires = date.toGMTString();
		}
		else if ( isString( days ) )
		{
			expires = days;
		}
		else
		{
			expires = false;
		}
		
		document.cookie = name + '=' + encodeURIComponent( value ) +
				(expires ? ';expires=' + expires  : '') +
				(path ? ';path=' + path : '') +
				(domain ? ';domain=' + domain : '') +
				(secure ? ';secure' : '');
	},
	
	/**
	 * delete Cookie
	 * @method del
	 * @param {String} name
	 * @param {String} path
	 * @param {String} domain
	 * @param {Boolean} secure
	 */
	
	del : function( name , path , domain , secure )
	{
		XN.cookie.set( name , '' , -1 , path , domain , secure );
	}
};

/*
 * patch for old version
 */

XN.COOKIE = XN.Cookie = XN.cookie;

/*
 * patch end
 */
/**
 * @namespace XN
 * @class event
 * @static
 */

(function()
{
	var browser = XN.browser;
	
	XN.event =
	{
		/**
		 * @method isCapsLockOn
		 * @param {Object} e the event object
		 * @return {Boolean}
		 */
		
		isCapsLockOn : function( e )
		{
			var c = e.keyCode || e.which;
			var s = e.shiftKey;
			if ( ( ( c >= 65 && c <= 90 ) && !s ) || ( (c >=97 && c <= 122) && s) ) return true;
			return false;
		},
		
		/**
		 * get event src element
		 * @method element
		 * @param {Object} e the event object
		 * @return {HTMLElement}
		 */
		
		element : function( e )
		{
			var n = e.target || e.srcElement;
			return This.resolveTextNode( n );
		},
		
		/**
		 * get related element of event as 'mouseover'
		 * @method relatedTarget
		 * @param {Object} e
		 * @return {HTMLElement}
		 */
		
		relatedTarget: function( e ) {
			var t = e.relatedTarget;
			if ( !t )
			{
			    if ( e.type == 'mouseout' || e.type == 'mouseleave' )
				{
			        t = e.toElement;
			    }
				else if ( e.type == 'mouseover' )
				{
			        t = e.fromElement;
			    }
			}	
			return This.resolveTextNode( t );
		},
		
		resolveTextNode: function( n )
		{
			try
			{
			    if ( n && 3 == n.nodeType ) 
				{
			        return n.parentNode;
			    }
			} catch(e) {}
			
			return n;
		},
		
		/**
		 * get mouse pointer pose x
		 * @method pointerX
		 * @param {Object} event
		 * @return {Int}
		 */
		
		pointerX : function( event )
		{
			return event.pageX || ( event.clientX + ( document.documentElement.scrollLeft || document.body.scrollLeft ) );
		},
		
		/**
		 * get mouse pointer pose y
		 * @method pointerY
		 * @param {Object} event
		 * @return {Int}
		 */
		
		pointerY : function( event )
		{
			return event.pageY || ( event.clientY + ( document.documentElement.scrollTop || document.body.scrollTop ) );
		},
		
		/**
		* 判断当前页面是否是标准模式
		*/
		
		isStrictMode:document.compatMode!="BackCompat",
		
		/**
		 * get page height
		 * @method pageHeight
		 * @return {Int}
		 */
		
		pageHeight : function()
		{
			return this.isStrictMode ? Math.max(document.documentElement.scrollHeight,document.documentElement.clientHeight) : Math.max(document.body.scrollHeight,document.body.clientHeight);
		},
		
		/**
		 * get page width
		 * @method pageWidth
		 * @return {Int}
		 */
		
		pageWidth : function()
		{
	  		return this.isStrictMode ? Math.max(document.documentElement.scrollWidth,document.documentElement.clientWidth) : Math.max(document.body.scrollWidth,document.body.clientWidth);
		},
		
		/**
		 * get inner width of window
		 * @method winWidth
		 * @return {Int}
		 */
		
		winWidth	: function()
		{
			return this.isStrictMode ?  document.documentElement.clientWidth : document.body.clientWidth;
		},
		
		/**
		 * get inner height of window
		 * @method winHeight
		 * @return {Int}
		 */
		
		winHeight : function()
		{
			return this.isStrictMode ? document.documentElement.clientHeight : document.body.clientHeight;
		},
		
		/**
		 * get scrollTop of document
		 * @method scrollTop
		 * @return {Int}
		 */
		
		scrollTop : function()
		{
            if ( XN.browser.WebKit )
            {
                return window.pageYOffset;
            }
			
            return this.isStrictMode ? document.documentElement.scrollTop : document.body.scrollTop;
		},
		
		/**
		 * get scrollLeft of document
		 * @method scrollLeft
		 * @return {Int}
		 */
		
		scrollLeft:function()
		{
            if ( XN.browser.WebKit )
            {
                return window.pageXOffset;
            }

			return this.isStrictMode ? document.documentElement.scrollLeft : document.body.scrollLeft;
		},
		
		/**
		 * stop event bubble
		 * @method stop
		 * @param {Object} event
		 */
    	
		stop	:null,
		
		addEvent	: null,
		delEvent	: null,
		
		/**
		 * enable custom event for an object
		 * @param {Object} obj
		 * @return {Object}
		 */
		enableCustomEvent : function( obj )
		{
			$extend( obj , 
			{
				addEvent : function( type , func )
				{
					if( !this._customEventListeners ) this._customEventListeners = {};
					var funcs = this._customEventListeners;
					if( isUndefined( funcs[type] ) )
					{
						funcs[ type ] = [];
					}
					funcs[ type ].push( func );
					return this;
				},
				delEvent : function( type , func ) 
				{
					var funcs = this._customEventListeners[ type ];
					if ( funcs )
					{
						for( var i = funcs.length - 1; i >= 0;i-- )
						{
							if( funcs[i] == func )
							{
								funcs[i] = null;
								break;
							}
						}
					}
					return this;
				},
				fireEvent : function( type )
				{
					if( !this._customEventListeners || !this._customEventListeners[ type ] )return;
					var funcs = this._customEventListeners[ type ],ars = XN.array.build( arguments );
					ars.shift();
					for( var i = 0, j = funcs.length; i < j; i++ )
					{
						if( funcs[ i ] )
                        {
							try
                            {
                                funcs[ i ].apply( this , ars );
                            }
                            catch( ox )
                            {
                                if ( XN.DEBUG_MODE ) throw ox;
                            }
                        }
					}
				}
			});
			
			return obj;
		}		
	};
	
	var This = XN.event;
	
	if ( browser.IE )
	{
		This.stop = function( event )
		{
			event.returnValue = false;
			event.cancelBubble = true;			
		}
	}
	else
	{
		This.stop = function( event )
		{
			event.preventDefault();
			event.stopPropagation();		
		}
	}
	
	var ismouseleave = function( event , element )
	{
		var p = event.relatedTarget;
		while ( p && p != element ) try { p = p.parentNode; } catch(error) { p = element; }
		return p !== element;
	}
	
	if (window.attachEvent && !browser.Opera)
	{
		This.addEvent = function( element , name , func )
		{
            element = $( element );
			if (name == 'keypress') name = 'keydown';
			if (name == 'input' ) name = 'propertychange';
			element.attachEvent( 'on' + name , func );
            return element;
		};
		This.delEvent =  function( element , name , func )
		{
            element = $( element );
			if (name == 'keypress') name = 'keydown';
			if (name == 'input' ) name = 'propertychange';
			element.detachEvent( 'on' + name , func );
            return element;
		};
	}
	else if ( window.addEventListener )
	{
		
		/**
		 * add event for element
		 * @namespace XN.event
		 * @method addEvent
		 * @param {HTMLElement | String} element
		 * @param {String} name
		 * @param {Function} func
		 * @param {Boolean} useCapture
		 * @return {HTMLElement}
		 */
		
		This.addEvent = function( element , name , func , useCapture )
		{
			element = $( element );
			if ( name == 'mouseleave' )
			{
				element.onmouseleave = function( e )
				{
                    e = e || window.event;
					if ( ismouseleave( e , element ) && func ) func.call( element , e );
				};
				element.addEventListener( 'mouseout' , element.onmouseleave , useCapture );
				return element;
			}
			if ( name == 'keypress' && browser.WebKit ) name = 'keydown';
			element.addEventListener( name , func , useCapture );
			return element;
		};
		
		/**
		 * del event 
		 * @method delEvent
		 * @param {HTMLElement | String} element
		 * @param {String} name
		 * @param {Function} func
		 * @param {Boolean} useCapture
		 * @return {HTMLElement}
		 */
		
		This.delEvent = function(element,name,func,useCapture) {
			element = $(element);
			if ( name == 'mouseleave' )
			{
				element.removeEventListener( 'mouseout' , element.onmouseleave , useCapture );
				return element;
			}
			if ( name == 'keypress' && browser.WebKit ) name = 'keydown';
			element.removeEventListener( name , func , useCapture );
			return element;
		};
	}
    
})();

/*
 * patch for old version
 */

XN.EVENT = XN.Event = XN.event;

/*
 * patch end
 */
/**
 * @namespace XN
 * @class dom
 * @static
 */

(function()
{
	var Event = XN.event;
	var array = XN.array;
	var browser = XN.browser;
	
	var domLoaded = false;
	
	var domloadHooks = [];
	
	
	function runHooks()
	{
		if( !domloadHooks )return;

        XN.array.each( domloadHooks , function( i , v )
		{
			try
			{
                v();
			}
			catch( e )
			{
				if( XN.DEBUG_MODE ) throw e;
			}
		} );
	}

	var shadowElement = null;
	
	function createShadow( opacity )
	{
        opacity = opacity || 0.3;
		
        var el = $element( 'div' );
		
        shadowElement = el;
		
        el.setStyle( [ 'position:absolute;',
                        'top:0;',
                        'left:0;',
                        'background:#000;',
                        'z-index:2000;',
                        'opacity:' + opacity + ';',
                        'filter:alpha(opacity=' + ( opacity * 100 ) + ');'
                    ].join( '' ));
		//hack ie6
		//if ( XN.browser.IE6 )
        //{
			el.innerHTML= [ '<iframe width="100%" height="100%" frameBorder="0" style="position:absolute;top:0;left:0;z-index:1;"></iframe>',
                            '<div style="position:absolute;top:0;left:0;width:100%;height:100%;background-color:#000000;z-index:2;height:expression(this.parentNode.offsetHeight);"></div>' ].join( '' );
		//}		
		
        function resize()
        {
		    el.hide();
            el.style.height = XN.event.pageHeight() + 'px';
		    el.style.width = XN.event.pageWidth() + 'px';
			el.show();					
        }
		
        resize();

        XN.event.addEvent( window , 'resize',function(e)
        {
			if ( shadowElement && shadowElement.style.display != "none" )
            {
                try
                {
                    resize();
				}
				catch(e){}
            }
		});
		
		document.body.appendChild( el );
	}
	
	XN.dom = {
		
		/**
		 * disable user interface
		 * @method disable
		 * @param {Float} opacity
		 */
		
		disable : function( opacity )
		{
			if ( !shadowElement ) createShadow( opacity );
			/*if ( XN.browser.IE6 )
            {
				document.getElementsByTagName("html")[0].style.overflow="hidden";
				document.body.style.overflow="hidden";
			}*/
		},
		
		/**
		 * enable user interface
		 * @method enable
		 */
		
		enable : function()
		{
            if ( shadowElement )
            {
				/*if ( XN.browser.IE6 )
                {
					document.getElementsByTagName("html")[0].style.overflow="";
					document.body.style.overflow="";
				}*/

				shadowElement.remove();
				shadowElement = null;
			}
		},
		
		/**
		 * insert element after another
		 * @method insertAfter
		 * @param {HTMLElement} element
		 * @param {HTMLElement} targetElement
		 */
		
		insertAfter : function( element , targetElement )
		{
			element = $( element );
			targetElement = $( targetElement );
			
			var parent = targetElement.parentNode;
			if ( parent.lastChild == targetElement )
			{
				parent.appendChild( element );
			}
			else
			{
				parent.insertBefore( element, targetElement.nextSibling );
			}
		},
		
		/**
		 * get elements by classname
		 * @param {String} className
		 * @param {HTMLElement | String} element
		 * @param {String} tagName
         * @return {Array}
		 */
		
		getElementsByClassName : function( className , element , tagName )
		{ 
			var c = ( $( element ) || document ).getElementsByTagName( tagName || '*' ) || document.all; 
			var elements = []; 
			var _exp = new RegExp("(^|\\s)" + className + "(\\s|$)");
			
			array.each( c , function( i , v )
			{
				if ( _exp.test( v.className ) ) elements.push( v );
			} );
			
	  		return elements; 
		},
		
		/**
		 * registor dom load event
		 * @method readyDo
		 * @param {Function} f
		 */
		
		ready : function( f )
		{
			domLoaded ? f() : domloadHooks.push( f );
		},
		
		/**
		 * preload Image
		 * @method preloadImg
		 * @param {String | Array} src
		 */
		
		preloadImg : function( src )
		{
			src = isArray( src ) ? src : [ src ];
			array.each( src , function( i , v )
			{
				new Image().src = v;
			} );
		}
	};
	
	if ( browser.WebKit )
	{
		var timer = setInterval( function()
		{
			if( /loaded|complete/.test( document.readyState ) )
			{
				domLoaded = true;
				runHooks();
				clearInterval( timer );
			}
		} , 10 ); 
	}
	else if ( document.addEventListener )
	{
		document.addEventListener( 'DOMContentLoaded' , function()
		{
			domLoaded = true;
			runHooks();
		} , false );
	}
	else
	{
		var timer = setInterval( function()
		{
            try
			{
                document.body.doScroll('left');
                clearInterval( timer );
                domLoaded = true;
				runHooks();
            } catch (e) {}
        } , 20 ); 
	}
})();


/*
 *  patch for old version
 */

XN.DOM = XN.Dom = XN.dom;
XN.dom.readyDo = XN.dom.ready;

XN.dom.ready( function()
{
    $ = ge = getEl = xn_getEl;
});

XN.dom.ready( function()
{
	if ( XN.config.parentDomain && XN.config.parentDomain == top.location.host ) return;


	try
	{
		top.location.href.indexOf( 'x' );
	}
	catch ( e )
	{
		try
		{
			top.location = self.location;
		} catch ( e ){}
	}
});

/*
 * patch end
 */



(function()
{
    var files = {};
    var version = {};
    
    function hasLoad( file )
    {
        return !!getFile( file );
    }

    function getFile( file )
    {
        return files[ encodeURIComponent( file ) ];
    }
    
    function mark( file )
    {
        var obj = {};
        obj.file = file;
        obj.isLoad = true;
        obj.isLoaded = true;
        files[ encodeURIComponent( file ) ] = obj;
    }

    function addFile( file )
    {
        var obj = {};
        obj.file = file;
        obj.isLoaded = false;
        XN.EVENT.enableCustomEvent( obj );
        
        obj.addEvent( 'load' , function()
        {
            this.isLoaded = true;
        });

        files[ encodeURIComponent( file ) ] = obj;

        var el = $element( 'script' );
        el.type="text/javascript";
        el.src = file;

        obj.element = el;
        
        if ( XN.Browser.IE )
        {
            el.onreadystatechange = function()
            {
                if ( ( this.readyState == 'loaded' || this.readyState == 'complete' ) && !this.hasLoad )
                {
                    this.hasLoad = true;
                    getFile( file ).fireEvent( 'load' );
                }
            }
        }else{
            el.onload = function()
            {
                getFile( file ).fireEvent( 'load' );
            };
        }

        document.getElementsByTagName( 'head' )[ 0 ].appendChild( el );
    }

    function loadFile( file , callBack )
    {
        file = getFullName( file );
        
        if ( /\.js(\?|$)/.test( file ) )
        {
            if ( !hasLoad( file ) )
            {
                addFile( file );
            }
            
            if ( !callBack ) return;
            if ( getFile( file ).isLoaded )
            {
                callBack.call( getFile( file ) );
            }
            else
            {
                getFile( file ).addEvent( 'load' , callBack );
            }
        }
        else if ( /\.css(\?|$)/.test( file ) )
        {
            if ( hasLoad( file ) ) return;
            mark( file );
            var el = $element( 'link' );
            el.rel = 'stylesheet';
            el.type = 'text/css';
            el.href = file;
            document.getElementsByTagName( 'head' )[ 0 ].appendChild( el );
            if ( callBack ) callBack.call( getFile( file ) );
        }
    }
    
    function getFullName( file )
    {
        XN.func.runOnce( loadVersion );
        if ( !version[ file ] ) return file;
        return version[ file ].file;
    }

    function getVersion( file )
    {
        var match;
        if ( match = new RegExp( '(' + XN.env.staticRoot + ')' + '(a?\\d+)/([^\?]*)' ).exec( file ) )
        {
            version[ match[ 1 ] + match[ 3 ] ] = {
                file : file,
                version : match[ 2 ]
            };
        }
        else if ( match = new RegExp( '(.*)\\?ver=(\d+)(\..*)' ).exec( file ) )
        {
            version[ match[ 1 ] ] = {
                file : file,
                version : match[ 2 ]
            };
        }
    }
    
    XN.getFileVersion = function( files )
    {
        XN.array.each( files , function( i , v )
        {
            getVersion( v );
        });
    };

    XN.loadFile = function( file , callBack )
    {
        loadFile( file , callBack );
    };
    
    
    XN.loadFiles = function( files , callBack )
    {
        var f = files.length;
        
        function isAllLoad()
        {
            f --;
            if ( f === 0 && callBack ) callBack();
        }

        XN.array.each( files , function( i , v )
        {
            XN.loadFile( v , isAllLoad );
        });
    };

    XN.getVersion = function( file )
    {
        getVersion( file );
    }

    function loadVersion()
    {

        XN.array.each( document.getElementsByTagName( 'script' ) , function( i , v )
        {
            if ( v.src )
            {
                mark( v.src );
                getVersion( v.src );
            }

            if ( v.getAttribute( 'vsrc' ) ) getVersion( v.getAttribute( 'vsrc' ) );
        } );

        XN.array.each( document.getElementsByTagName( 'link' ) , function( i , v )
        {
            if ( v.rel && v.rel == 'stylesheet' )
            {
                mark( v.href );
                getVersion( v.href );
            }

            if ( v.getAttribute( 'vhref' ) ) getVersion( v.getAttribute( 'vhref' ) );
        } );

        XN.log( 'load file version:' );
        XN.log( version );

    }

    XN.dynamicLoad = function( file )
    {
        XN.array.each( file.funcs , function( i , func )
        {
            window[ func ] = function()
            {
                var ars = arguments;
                
                window[ func ] = null;
                if ( file.file )
                {
                    file.files = [ file.file ];
                }

                XN.loadFiles( file.files , function()
                {
                    window[ func ].apply( null , ars );
                    if ( file.callBack ) file.callBack.call( null );
                });
            };    
        });
    };

    XN.namespace( 'img' );
    XN.img.getVersion = function( file )
    {
        XN.func.runOnce( loadVersion );
        if ( !version[ file ] ) return '';
        return version[ file ].version;
    };

    XN.img.getFullName = function( file )
    {
        return getFullName( file );
    };
})();
/**
 * @namespace XN
 * @class element
 * @static
 */

(function()
{
	var addEvent = XN.event.addEvent;
	var delEvent = XN.event.delEvent;
	var browser = XN.browser;

	XN.element = {
        
        /**
         * 清空元素的innerHTML
         * @method clear
         * @param {HTMLElement | String} element
         * @return {HTMLElement}
         */

	    clear : function( element )
        {
            element = $( element );
            element.innerHTML = '';
            return element;
        },

		/**
		 * simple hover
		 * @method hover
		 * @param {HTMLElement | String} element the element hover on
		 * @param {String} className hover class
		 * @param {HTMLElement | String} hover add class to
		 */
		
		hover : function( element , className , hover )
		{
			element = $( element );
			hover =  hover ? $( hover ) : element;
			
			addEvent( element , 'mouseover' , function()
			{
				hover.addClass( className );
			} , false );
			
			addEvent( element ,'mouseleave' , function()
			{
				hover.delClass(className);
			}, false );
            
            return element;
		},
		
		/**
		 * scroll page to element
		 * @method scrollTo
		 * @param {HTMLElement} element
		 * @param {String} effect
		 */
		
		/*
		 *  rewrite later
		 */
		
		scrollTo : function(element,effect) {
			element = $(element);
			effect = effect || 'normal';
			switch(effect){
				case 'slow':
				XN.EFFECT.scrollTo(element);
				break;
				default:
				window.scrollTo(0,element.realTop());
				break;
			}
			return element;
		},
		
		/**
		 * check if an element is visible
		 * @method visible
		 * @param {HTMLElement | String} element
		 * @return {Boolean}
		 */
		
		visible : function( element )
		{
			element = $( element );
			return element.style.display != 'none' && element.style.visibility != 'hidden';
		},
		
        /**
         * 来回开关一个元素的某个样式
         * <pre>
         *  &lt;div onclick="$(this).toggleClass('expand');"&gt;&lt;/div&gt;
         * </pre>
         * @method toggleClass
         * @param {HTMLElement | String} element
         * @return {HTMLElement}
         */

        toggleClass : function( element , className )
        {
            if ( This.hasClassName( element , className ) )
            {
                This.delClass( element , className );
            }
            else
            {
                This.addClass( element , className );
            }
            return $( element );
        },

		/**
		 * check if an element has given className
		 * @method hasClassName
		 * @param {HTMLElement | String} element
		 * @param {String} className
		 * @return {Boolean}
		 */
		
		hasClassName : function( element , className )
		{
			return new RegExp( '(^|\\s+)' + className + '(\\s+|$)' ).test( $( element ).className );
		},
	    	
		/**
		 * add classname to an element
		 * @method addClass
		 * @param {HTMLElement | String} element
		 * @param {String} className
		 * @return {HTMLElement}
		 */
		
		addClass : function( element , className )
		{
			element = $(element);
			if ( This.hasClassName( element , className ) )return element;
			element.className += ' ' + className;
			return element;
		},
		
		/**
		 * del className from an element
		 * @method delClass
		 * @param {HTMLElement | String} element
		 * @param {String} className
		 * @return {HTMLElement}
		 */
		
		delClass : function( element , className )
		{
			element = $(element);
			element.className = element.className.replace( new RegExp( '(^|\\s+)' + className + '(\\s+|$)' , 'g' ) , '' );
			return element;
		},
		
		/**
		 * show an element
		 * @method show element
		 * @param {HTMLElement | String} element
		 * @param {String} effect
		 * @return {HTMLElement}
		 */
		
		/*
		 * rewrite later
		 */
		
		show : function (element,effect){
			element = $(element);
			if(element.style.display != 'none')return;
			effect = effect || 'normal';
		 	switch(effect){
				case 'normal':
				element.style.display = '';
				break;
				case 'fade':
				XN.EFFECT.fadeIn(element,function(e){
					e.style.display = '';
				});
				break;
				case 'slide':
				XN.EFFECT.slideOpen(element);
				break;
				case 'delay':
				setTimeout(function(){
					element.style.display = '';
				},2000);
				break;
			}
			return element;
		},
		
		/**
		 * hide an element
		 * @method hide
		 * @param {HTMLElement} element
		 * @param {String} effect
		 * @return {HTMLElement}
		 */
		
		/*
		 * rewrite later
		 */
		
		hide : function (element,effect){
			element = $(element);
			if(element.style.display == 'none')return;
			effect = effect || 'normal';
		 	switch(effect){
				case 'normal':
				element.style.display = 'none';
				break;
				case 'fade':
				XN.EFFECT.fadeOut(element,function(e){
					e.style.display = 'none';
				});
				break;
				case 'slide':
				XN.EFFECT.slideClose(element);
				break;
				case 'delay':
				setTimeout(function(){
					element.style.display = 'none';
				},2000);
				break;
			}
			return element;
		},
		
		/**
		 * remove element from the DOM
		 * @method remove
		 * @param {HTMLElement | String} element
		 * @return {HTMLElement}
		 */
		
		remove : function( element )
		{
			var element = $(element);
			element.parentNode.removeChild( element );
			return element;
		},
		
		/**
		 * set style for an element
		 * @method setStyle
		 * @param {HTMLElement | String} element
		 * @param {String} style
		 * @return {HTMLElement}
		 */
		
		setStyle : function( element , style )
		{
			var element = $(element);
			element.style.cssText += ';' + style;
			return element;
		},
		
		/**
		 * get style by style name
		 * @param {HTMLElement | String} element
		 * @param {String} name
		 * @return {String}
		 */
		
		getStyle : function( element , style )
		{
			element = $(element);
			
			style = style == 'float' ? 'cssFloat' : style;
			
			var value = element.style[ style ];
			
			if ( !value )
			{
				var css = document.defaultView.getComputedStyle( element , null );
				value = css ? css[style] : null;
			}
			
			if ( style == 'opacity' ) return value ? parseFloat( value ) : 1.0;
			
			return value == 'auto' ? null : value;
		},
		
		/**
		 * @method addEvent
		 * @return {HTMLElement}
		 * @see XN.event.addEvent
		 */
		
		addEvent : function()
		{
			addEvent.apply( null , arguments );
			return arguments[0];
		},
		
		/**
		 * @method delEvent
		 * @return {HTMLElement}
		 * @see XN.event.delEvent
		 */
		
		delEvent : function()
		{
			delEvent.apply( null , arguments );
			return arguments[0];
		},
		
		/**
		 * add Child node to element
		 * @method addChild
		 * @param {HTMLElement | String} father
		 * @param {HTMLElement | String | XN.ui.element | XN.net.xmlhttp} child
		 * @return {HTMLElement}
		 */
		
		addChild : function( father , child )
		{
			father = $( father );
			
			if ( isString( child ) )
			{
				var element = ( child.substring( 0 , 1 ) == '#' ) ? $( child.substring( 1 , child.length ) ) : child;
				if( isString( element ) )
				{
					father.innerHTML += element;
				}
				else
				{
						father.appendChild( element );
				}
			}
			else if ( isElement( child ) )
			{
				father.appendChild( child );
			}
			else if( child.iAmUIelement )
			{
				father.appendChild( $( child.frame ) );
			}
			else if( child.iAmXmlhttp )
			{
				child.fillTo = father;
				father.startLoading();
			}
			return father;
		},
		
		/**
		 * 
		 * @method delChild
		 * @param {HTMLElement | String} father
		 * @param {HTMLElement | String | XN.ui.element } child
		 * @return {HTMLElement}
		 */
		
		delChild : function( father , child )
		{
			child = $( child );
			child.remove();
			return $( father );
		},
		
		/**
		 * @method setContent
		 * @param {HTMLElement | String} element
		 * @param {HTMLElement | String | XN.ui.element | XN.net.xmlhttp} c
		 * @return {HTMLElement}
		 */
		
		setContent : function( element , c )
		{
			element = $( element );
			element.innerHTML = '';
			element.addChild( c );
			return element;
		},
		getPosition : function( element , parentE )
		{
			parentE = $( parentE ) || document.body;
			element = $( element );
			var rl = 0;
			var rt = 0;
			var p = element;
            //fix ie7 未指明的错误
            try{
			    while ( p && p != parentE )
			    {
			    	rl += p.offsetLeft;
			    	rt += p.offsetTop;
		    		p = p.offsetParent;
			    }
            }catch(e){}
			return { 'left' : rl , 'top' : rt };
		},
		
        /**
         * 获取元素的绝对左边距
         * @method realLeft
         * @param {HTMLElement | String} element
         * @return {Int}
         */

		realLeft : function( element , p )
		{
			return This.getPosition( element , p || null ).left;
		},
		
		/**
         * 获取元素的绝对上边距
         * @method realTop
         * @param {HTMLElement | String} element
         * @return {Int}
         */

        realTop : function( element , p )
		{
			return This.getPosition( element , p || null ).top;
		},
        
        /**
         * 直接append HTML
         * @method appendHTML
         * @param {String} str
         * @return {HTMLElement}
         */
        
        appendHTML : function( element, str )
        {
            element = $( element );
            var f = document.createDocumentFragment();
            var t = $element( 'div' );
		    t.innerHTML = str;
		    while( t.firstChild )
            {
			    f.appendChild( t.firstChild );
		    }
            element.appendChild( f );
            return element;
        },

        /**
         * 在一个div内显示loading的图标,用于ajax动态加载数据
         * 
         * <pre>
         * $( 'message' ).startLoading( 'loading...' );
         * </pre>
         * @method startLoading
         * @param {HTMLElement | String} element
         * @param {String} msg loading时的提示信息
         * @return {HTMLElement}
         */

        startLoading : function( element , msg )
        {
            element = $( element );
            element.innerHTML = '<center><img src=\"' + XN.ENV.staticRoot + 'img/indicator.gif\" />' + (msg || '加载中...') + '</center>';
            return element;
        },
        
        stopLoading:function( element )
        {
            element = $( element );
            return element;
        },
        
        /**
         * eval js in innerHTML
         * @method eval_inner_JS
         * @param {String | HTMLElement} el
         */
        
        eval_inner_JS : function( el )
        {
            var js = $( el ).getElementsByTagName( 'script' );
            XN.array.each( js, function( i, s )
            {
                if ( s.src )
                {
                    XN.loadFile( s.src );
                }
                else
                {
                    var inner_js = '__inner_js_out_put = [];\n';
                    inner_js += s.innerHTML.replace( /document\.write/g, '__inner_js_out_put.push' );
                    eval( inner_js );
                    if ( __inner_js_out_put.length !== 0 )
                    {
                        var tmp = document.createDocumentFragment();
                        $( tmp ).appendHTML( __inner_js_out_put.join( '' ) );
                        s.parentNode.insertBefore( tmp, s );
                    }
                }
            });
        }
	};
	
	XN.element.extend = function( element )
	{
		if ( element._extendLevel )return element;
		var cache = This.extend.cache;
		for ( var m in This )
		{
			if ( !( m in element ) )
			{
				element[ m ] = cache.findOrStore( This[ m ] );
			}
		}
		return element;
	};
	
	XN.element.extend.cache = {
	  findOrStore : function( value )
	  {
	  	return this[ value ] = this[ value ] || function()
		{
	  		return value.apply( null , [ this ].concat( XN.array.build( arguments ) ) );
		};
	  }		
	};
	
	var This = XN.element;
	
	if( browser.IE )
	{
		XN.element.getStyle = function( element , style )
		{
		    element = $( element );
		    style = ( style == 'float' || style == 'cssFloat' ) ? 'styleFloat' : style;
		    var value = element.style[ style ];
		    if ( !value && element.currentStyle ) value = element.currentStyle[ style ];
		
		    if ( style == 'opacity' )
			{
		      if (value = ( element.getStyle('filter') || '' ).match( /alpha\(opacity=(.*)\)/ ) )
		        if ( value[ 1 ] ) return parseFloat( value[ 1 ] ) / 100;
		      return 1.0;
		    }
		
		    if ( value == 'auto' )
			{
		      if ( (style == 'width' || style == 'height' ) && ( element.getStyle( 'display' ) != 'none') )
		        return element[ 'offset'+ ( style == 'width' ? 'Width' : 'Height' ) ] + 'px';
		      return null;
		    }
		    return value;			
		}
	}

    /**
     * 设置元素透明度
     * <pre>
     *  XN.element.setOpacity( el , 0.3 );
     *  or
     *  $( el ).setOpactiy( 0.3 );
     * </pre>
     * @method setOpacity
     * @param {Float} opacity
     * @return {HTMLElement}
     */
    if ( document.addEventListener )
    {
        XN.element.setOpacity = function( element , opacity )
        {
            element = $( element );
            element.style.opacity = opacity;
            return element;
        };
    }
    else
    {
        XN.element.setOpacity = function( element , opacity )
        {
            element = $( element );
            element.style.zoom = 1;
            element.style.filter = 'Alpha(opacity=' + Math.ceil( opacity * 100 ) + ')';
            return element;            
        };
    }
})();

/*
 *  patch for old version
 */

XN.ELEMENT = XN.Element = XN.element;

/*
 * patch end
 */
/**
 * @namespace XN
 * @class net
 * @static
 */

XN.namespace( 'net' );


XN.net.proxys = {};

/**
 * send form by xmlhttp<br />
 * the params is like {url:'',form:'',method:'',onSuccess:'',onError:''}
 * @namespace XN.net 
 * @method sendForm 
 * @param {Object} params
 * @return {XN.net.xmlhttp}
 * @requires xn.form.js
 */

XN.net.sendForm = function( params )
{
    XN.log( 'send form' );
	params.data = XN.FORM.serialize( params.form );
	return new XN.net.xmlhttp( params );
};



/**
 * 参数形式
 * <pre>
 * {
 *  url:'',
 *  data:'',
 *  useCache:true,
 *  method:'get',
 *  onComplete:functoin,//请求完成回调
 *  onSuccess:function,//请求成功回调
 *  onError:''//请求失败回调
 *  }
 *
 *  注意: 302重定向属于失败状态
 *  
 *  callBack = function(r)
 *  {
 *      if ( r.status == 302 )
 *      {
 *      }
 *  }
 *  
 *  回调函数可以通过r.status判断是否重定向
 *  </pre>
 * @namespace XN.net
 * @class xmlhttp
 * @constructor
 * @param {Object} params
 */

XN.net.xmlhttp = function( params )
{
    var This = this;

    if ( !XN.net.cache )
    {
         XN.net.cache = new XN.util.cache()
    }

	/*
	 * patch for old version
	 */
	var ars = arguments;
	if ( ars.length > 1 )
	{
		this.url = ars[ 0 ] || null;
		this.data = ars[ 1 ] || '';
		this.onSuccess = ars[ 2 ];
		$extend( this , ars[ 3 ] );
		init( window );
		return this;
	}
	/*
	 * patch end
	 */
	
	$extend( this , params );

    var cache;
	
    if ( this.useCache && ( cache = XN.net.cache.get( this.url + encodeURIComponent( this.data ) ) ) )
    {
        this.transport = {};
        this.transport.responseText = cache;
        setTimeout( function()
        {
            This._onComplete( );
            This._onSuccess( );
        }, 0 );
        return this;
    }

    function getDomain( link )
    {
        var a = $element( 'a' );
        a.href = link;
        return a.hostname;
    }



    if ( /^http/.test( this.url ) )
    {
        var cd = getDomain( window.location.href );
        var nd = getDomain( this.url );
        
        if ( cd != nd )
        {
            if ( XN.net.proxys[ nd ] )
            {
                init( XN.net.proxys[ nd ] );
                return This;
            }
            else
            {
                var iframe = $element( 'iframe' ).hide();
                document.body.appendChild( iframe );
                iframe.src = 'http://' + nd + '/ajaxProxy.html?ver=2';
                XN.event.addEvent( iframe , 'load' , function()
                {
                    try
                    {
                        init( iframe.contentWindow );
                        XN.net.proxys[ nd ] = iframe.contentWindow;
                    }
                    catch(e){}
                });
                return This;
            }
        }
        else
        {
            init( window );
        }
    }
    else
    {
        init( window );
    }
    
    function init( w )
    {
        This.transport = This.getTransport( w );

        if ( This.url && This.url !=='' )
        {
            This.send( This.method );
        }    
    }

};

XN.net.xmlhttp.prototype =
{
	url : null,
	data : '',
	onSuccess : null,
	onFailure : null,
	onError : null,
	fillTo : null,
	method : 'post',
	asynchronous : true,
	transport : null,
	headers : null,
	iAmXmlhttp:true,
    useCache : false,
	
	
	/**
	 * 取消当前请求
	 * @method abort
	 */
	
	abort:function(){
		this.transport.abort();
	},

	send:function( method )
	{
		var _url;
	    

		if ( method == 'get' && this.data !== '' )
		{
			_url = this.url + (/\?/.test(this.url) ? '&' : '?') + this.data;			
		}
		else
		{
			_url = this.url;
		}
		

		if( this.asynchronous )
		{
			this.transport.onreadystatechange = this.onStateChange.bind( this );
		}
		
		this.transport.open( method , _url , this.asynchronous );
		
		this.transport.setRequestHeader( 'Content-Type' , 'application/x-www-form-urlencoded' );
		
		if ( this.headers !== null )
		{
			for ( var i in this.headers )
			{
				this.transport.setRequestHeader( i ,this.headers[ i ] );
			}
		}
		
		this.transport.send( method == 'post' ? ( this.data || '' ) : null );
	},
	
    _onSuccess : function( obj )
    {
        var transport = this.transport;
        if ( this.fillTo !== null )
        {
            try{this.fillTo.stopLoading();}catch(e){}
            this.fillTo.innerHTML = transport.responseText;
        }
        try
        {
            if ( this.onSuccess ) this.onSuccess.call( null , transport );
        }
        catch( e )
        {
            if ( XN.DEBUG_MODE ) throw e;
        }
    },
    
    _onComplete : function( obj )
    {
        var transport = this.transport;
        try
        {
            if ( this.onComplete ) this.onComplete.call( null , transport );
        }
        catch( e )
        {
            if ( XN.DEBUG_MODE ) throw e;
        }
    },

	onStateChange : function()
	{
		var transport = this.transport;
		if ( transport.readyState == 4 )
		{

			this._onComplete();
			if( transport.status == undefined || transport.status == 0 || ( transport.status >= 200 && transport.status < 300) )
			{
                if ( this.useCache )
                {
                    XN.net.cache.add( this.url + encodeURIComponent( this.data ) , this.transport.responseText );
                }
                this._onSuccess();
			}
			else
			{
				(this.onError || this.onFailure || XN.func.empty ).call( null , transport );
			}
		}
	}
};
if ( XN.browser.IE )
{
	XN.net.xmlhttp.prototype.getTransport = function( w )
	{
        if ( w !== window )
        {
            return w.getTransport();
        }
        try
        {
            return new ActiveXObject( 'Msxml2.XMLHTTP' );
        }
        catch( e )
        {
            return new ActiveXObject( 'Microsoft.XMLHTTP' );
        }
	};
}
else
{
	XN.net.xmlhttp.prototype.getTransport = function( w )
	{
        if ( w !== window )
        {
            return w.getTransport();
        }
		return new XMLHttpRequest();
	};	
}

/*
 * patch for old version
 */

XN.NET = XN.Net = XN.net;

XN.net.ajax = XN.net.xmlhttp;

$extend( XN.net.xmlhttp.prototype , 
{
	get : function( url , data , onSuccess , params )
	{
		this.url = url;
		this.data = data;
		this.onSuccess = onSuccess;
		$extend( this , params );
		this.send( 'get' );
	},
	post : function( url , data , onSuccess , params )
	{
		this.url = url;
		this.data = data;
		this.onSuccess = onSuccess;
		$extend( this , params );
		this.send( 'post' );		
	}
} );

if ( typeof Ajax == 'undefined' )
{
	Ajax = {};
	Ajax.Request = function( url , o )
	{
		var p = o.parameters;
		o[ 'url' ] = url;
		o[ 'data' ] = p;
		delete o.parameters;
		return new XN.net.xmlhttp( o );
	} 
}

/*
 * patch end
 */
/**
 * @module core
 */

/**
 * @namespace XN
 * @class template
 * @static
 */

XN.template = {};

/**
 * @namespace XN.template
 * @method mediaPlayer
 * @param {Object} o
 * @return {String}
 */

XN.template.mediaPlayer = function( o )
{
	return [ 
	'<object classid="CLSID:22d6f312-b0f6-11d0-94ab-0080c74c7e95" width="' + (o.width || '352') + '" height="' + (o.height || '70') + '" >\n',
	'<param name="autostart" value="' + (o.autostart || '1')+'" >\n',
	'<param name="showstatusbar" value="' + (o.showstatusbar || '1')+ '">\n',
	'<param name="filename" value="'+ o.filename +'">\n',
	'<embed type="application/x-oleobject" codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=5,1,52,701" ',
	'flename="mp"',
	'autostart="' + (o.autostart || '1') + '" showstatusbar="' + (o.showstatusbar || '1') + '" ',
	'src="' + o.filename + '" width="' + (o.width || '352') + '" height="' + (o.height || '70') + '"></embed>'
	].join( '' );
};

/**
 * @namespace XN.template
 * @method  flashPlayer
 * @param {Object} o
 * @return {String}
 */

XN.template.flashPlayer = function( o )
{
	return '<embed src="' + XN.ENV.staticRoot + '/swf/player.swf?url=' + o.filename + '&Rwid=' + (o.width || '450') + '&Autoplay=' + (o.autostart || '1')+ '" wmode="' + (o.wmode || 'transparent') +'" loop="false" menu="false" quality="high" scale="noscale" salign="lt" bgcolor="#ffffff" width="' + (o.width || '450') + '" height="' + (o.height || '30') + '" align="middle" allowScriptAccess="sameDomain" allowFullScreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />';
};

/**
 * @namespace XN.template
 * @method flash
 * @param {Object} o
 * @return {String}
 */

XN.template.flash = function( o )
{
	return '&nbsp;<embed src="' + o.filename + '" type="application/x-shockwave-flash" ' +
	'width="' + (o.width || '320') + '" height="' + (o.height || '240') + '" allowFullScreen="true" wmode="' + (o.wmode || 'transparent') + '" allowScriptAccess="sameDomain"></embed>';
};

/*
 * patch for old version
 */

XN.Template = XN.TEMPLATE = XN.template;

/*
 * patch end
 */

/**
 * @module core
 */

/**
 * 常用功能的封装
 * @namespace XN
 * @class util
 * @static
 */

XN.namespace( 'util' );


/**
 * data cache class
 * @namespace XN.util
 * @class cache
 * @constructor
 * @param {Object} params
 */

XN.util.cache = function( params )
{
	$extend( this , params );
	this._cacheData = [];
};

XN.util.cache.prototype =
{
	
	/**
	 * @property cacheLength
	 * @type {Int}
	 */
	
	cacheLength : null,
	
	_cacheData : null,
	
	/**
	 * check if the cahe key exist
	 * @method isExist
	 * @param {String | Int} key
	 * @return {Boolean}
	 */
	
	isExist : function( key )
	{
		return this.get( key );
	},
	
	/**
	 * add a cache data
	 * @method add
	 * @param {String | Int} key
	 * @param {Any} value
	 */
	
	add : function( key ,value )
	{
		
		if ( !isUndefined( this.isExist( key ) ) ) return;
	
		
		if ( this.cacheLength && this.cacheLength == this._cacheData.length )
		{
			this._cacheData.shift();
		}
		
		this._cacheData.push( {
			'key'	:	key,
			'value':	value
		} );
	},
	
	/**
	 * get cache data by key
	 * @method get
	 * @param {String | Int} key
	 * @return {Any}
	 */
	
	get : function( key )
	{

		for ( var i = this._cacheData.length - 1 ; i >= 0 ; i-- )
		{
			if( this._cacheData[i].key == key )
			{			
				return this._cacheData[i].value;
			}
		}		
	},
	
	/**
	 * clear cache
	 * @method clear
	 */
	
	clear : function(){
		this._cacheData = [];
	}	
};

/*
 * patch for old version
 */

XN.UTIL = XN.Util = XN.util;

/*
 * patch end
 */

/**
 * json格式的ajax数据源
 * <pre>
 *  参数形式如下
 *  <pre>
 *  {
 *      url:'',//查询的url
 *      queryParam:'query',//查询的参数名
 *      attachParam:'',//附加参数
 *      rootKey:null//如果不指定，则认为整个json即为查询结果
 *  }
 *  </pre>
 * </pre>
 *
 * @namespace XN.util
 * @class DS_JSON
 * @constructor
 * @param {Object} params
 */

XN.util.DS_JSON = function( p )
{
	$extend( this , p );
};

XN.util.DS_JSON.prototype  =
{
	DS_TYPE : 'JSON',
	url : null,
	queryParam : 'query',
	attachParam : '',
	rootKey : null,
	_request : null,

    /**
     * 查询数据
     * @method query
     * @param {String} v 查询的字符串
     * @param {Function} callBack 回调函数
     */

	query : function( v , callBack )
	{
        //XN.log( v );
        //XN.log( callBack );
		var This = this;
		
		try{
			this._request.abort();
		}catch(e){}
		
		function parseDS_JSON( r )
		{
			r = r.responseText;
			var pp;
			try{
				var rt = XN.JSON.parse( r );
				if ( This.rootKey && rt[ This.rootKey ] )
				{
					pp = rt[ This.rootKey ];
				}
				else
				{
					pp = rt;
				}
            }
			catch( e )
			{
				pp = [];
			}

			callBack( pp );
		}
		
		this._request = new XN.net.xmlhttp(
		{
			url : this.url,
			data : this.queryParam + '=' + encodeURIComponent( v ) + '&' + this.attachParam,
			method : 'get',
            onSuccess : parseDS_JSON
		});
	}
};

XN.ui.DS_JSON = XN.util.DS_JSON;


/**
 * 用于好友选择器的好友数据源
 * <pre>
 * 参数形式如下
 * {
 *  url:''//请求的url
 * }
 * </pre>
 * @namespace XN.util
 * @class DS_friends
 * @constructor
 * @param {Object} params
 */

/**
 * 如果指定了此属性，将在此网络内查询好友
 * @property net
 * @type {String}
 */

/**
 * 如果指定了此属性，将在此分组内查询好友
 * @property group
 * @type {String}
 */


/**
 * 查询好友
 * @method query
 * @param {String} name
 * @param {Function} callBack
 */

XN.util.DS_friends = function( p )
{
    var ds = new XN.util.DS_JSON( p );
    ds.queryParam = 'p';
    ds.rootKey = 'candidate';
    ds.net = '';
    ds.group = '';
    ds.param = XN.json.build( p.param || {} );

    var limit =  isUndefined( p.limit ) ? 24 : p.limit;

    ds.query = function( name , callBack )
    {
        XN.log( 'start query' );
        
        //只允许查询字母和汉字
        name = name.replace( /[^a-zA-Z\u0391-\uFFE5]/g , '' );
        
        if ( XN.string.isBlank( name ) && this.group == '' && this.net == '' )
        {
            callBack( [] );
            return;
        }

        var p = [
            '{"init":false,',
            '"qkey":"' + this.qkey + '",',
            '"uid":true,',
            '"uname":true,',
            '"uhead":true,',
            '"limit":' + limit + ',',
            '"param":' + this.param + ',',
            '"query":"' +  name  + '",',
            '"group":"' + this.group + '",',
            '"net":"' + this.net + '"',
            '}'
        ].join( '' );

        XN.util.DS_JSON.prototype.query.call( this , p , callBack );
    }
    return ds;
};


XN.ui.DS_friends = XN.util.DS_friends;

/**
 * 从数组创建数据源
 * <pre>
 * 参数形式如下
 *  {
 *      data:a,//创建源的数组
 *      searchKey:'name'//要搜索的字段
 *  }
 * </pre>
 * @namespace XN.util
 * @class DS_Array
 * @constructor
 * @param {Object} params
 */

/**
 * 查询数组
 * @method query
 * @param {String} v 查询的字符串
 * @param {Function} callBack
 */

XN.util.DS_Array = function( p )
{
	$extend( this , p );
	this.init();
};

XN.util.DS_Array.prototype =
{
	DS_TYPE : 'array',
	data : null,
	searchKey : null,
	
	init : function()
	{
		var key = this.searchKey,
		index = this._index = [];
		
		XN.array.each( this.data , function( i , v )
		{
			index.push( v[ key ] );
		} );
	},
	
	query : function( v , callBack )
	{
		callBack( this._search( v ) );
	},
	
	_search : function( v )
	{
		var keys = this._index,
		data = this.data,
		rt = [],
		reg = new RegExp( '^' + v , 'i' );
		XN.array.each( keys , function( i , v )
		{
			if ( reg.test( v ) ) rt.push( data[ i ] );
		} );
		return rt;
	}
};

XN.ui.DS_Array = XN.util.DS_Array;


/**
 * xml格式的ajax数据源
 * <pre>
 * 参数形式如下: 
 *  {
 *      url:''//查询的url地址
 *  }
 * </pre>
 * @namespace XN.util
 * @class DS_XHR
 * @constructor 
 * @param {Object} params
 */

/**
 * 查询数据源
 * @method query
 * @param {String} v
 * @param {Function} callBack
 */

XN.util.DS_XHR = function( p )
{
	$extend( this , p );
};

XN.util.DS_XHR.prototype =
{
	url : null,
	queryParam : 'query',
	_request : null,
	
	query : function( v , callBack )
	{
		var This = this;
		
		try{
			this._request.abort();
		}catch(e){}
		
		function parseDS_XML( r )
		{
			r = r.responseXML;
			var rt = [];
			function getResult( r )
			{
				var tmp = {};
				XN.array.each( r.childNodes , function( i , v )
				{
					tmp[ v.tagName.toLowerCase() ] = v.firstChild.nodeValue;
				} );
				return tmp;
			}
			try{
				var rs = r.getElementsByTagName( 'Result' );
				XN.array.each( rs , function( i , v )
				{
					rt.push( getResult( v ) );
				} );
			}
			catch( e )
			{
				rt = [];
			}
			callBack( rt );
		}
		
		this._request = new XN.net.xmlhttp( {
			url : this.url,
			data : this.queryParam + '=' + encodeURIComponent( v ),
			onSuccess : parseDS_XML
		} );
	}
};

XN.ui.DS_XHR = XN.util.DS_XHR;

/*
XN.util.action = function(){
	this._successCode = [];
	this._errorCode = [];
	this._filters = [];
};

XN.util.action.prototype = 
{
	reqeustURI : null,
	method : 'post',
	_request : null,
	
	abort : function()
	{
		try
		{
			this._request.abort();
		} catch( e ){}
	},
	
	getErrorMessage : function( code )
	{
		if ( !code ) return false;
		return this._errorCode[ code ];
	},
	
	addErrorCode : function( code , msg )
	{
		this._errorCode[ code ] = msg;
	},
	
	getSuccessMessage : function( code )
	{
		if ( !code ) return false;
		return this._successCode[ code ];
	},
	
	addSuccessCode : function( code , msg )
	{
		this._successCode[ code ] = msg;
	},
	
	isSuccess : function( rt )
	{
		return !!this._successCode[ rt.code ];
	},
	
	applyFilter : function( obj )
	{
		var filters = this._filters;
		for ( var i = 0; i < filters.length; i++ )
		{
			obj = filters[ i ].call( null , obj );
			if ( isString( obj ) ) return obj;
		}
		return obj;
	},
	
	addFilter : function( func )
	{
		this._filters.push( func );
	},
	
	exe : function( params )
	{
		var rt = this.applyFilter( params );

        if ( isString( rt ) )
		{
			this.fireEvent( 'checkError' , rt );
			return;
		}
		
		this.fireEvent( 'netRequest' , rt );
		
		this._sendRequest( XN.array.toQueryString( rt ) );
	},
	
	_sendRequest : function( params )
	{
		var This = this;
		this._reqeust = new XN.NET.xmlhttp(
		{
			url : this.reqeustURI,
			data : params,
			method : this.method,
			onComplete : function()
			{
				This.fireEvent( 'netComplete' );
			},
			onSuccess : function( r )
			{
                r = r.responseText;
				try
				{
					var rt = XN.string.isJSON( r ) ? XN.JSON.parse( r ) : r;
					if ( This.isSuccess( rt ) )
					{
						This.fireEvent( 'success' , rt );
					}
					else
					{
						This.fireEvent( 'error' , rt );
					}
				}
				catch( e )
				{
					This.fireEvent( 'error' );
				}
			},
			onError : function()
			{
				This.fireEvent( 'error' );
			}
		} );
	}
};

XN.EVENT.enableCustomEvent( XN.util.action.prototype );
*/

/**
 * 全局热键
 * @class hotKey
 * @static
 * @namespace XN.util
 */

(function()
{
    var funcs = {};

    XN.util.hotKey = {

        /**
         * 添加热键
         * <pre>
         * XN.util.hotKey.add( '27' , callBack );
         * XN.util.hotKey.add( 'ctrl+27' , callBack );
         * </pre>
         * @method add
         * @param {String} key
         * @param {Function} func
         * @obj {Object} obj
         */

        add : function( key , func , obj )
        {
            key = String( key ).toLowerCase();
            var ctrl = false;
            var alt = false;
            var shift = false;
            var _code = null;

            if ( /^\d+$/.test( key ) )
            {
                _code = parseInt( key );
            }
            else
            {
                ctrl = /ctrl|ctr|c/.test( key );
                alt = /alt|a/.test( key );
                shift = /shift|s/.test( key );
                if ( /\d+/.test( key ) )
                {
                    _code = parseInt( /\d+/.exec( key )[ 0 ] );
                }
                else
                {
                    _code = false;
                }
            }

            funcs[ key ] = funcs[ key ] || {};

            funcs[ key ][ func ] = function( e )
            {
                e = e || window.event;
                code = e.keyCode;
                if ( ctrl && !e.ctrlKey ) return;
                if ( alt && !e.altKey ) return;
                if ( shift && !e.shiftKey ) return;
                if ( _code && code !== _code ) return;
                func.call( obj || null );
                XN.event.stop( e );
            };
            XN.event.addEvent( document , 'keydown' , funcs[ key ][ func ] );
        },
        
        /**
         * 删除热键
         * <pre>
         * XN.util.hotKey.del( '27' , callBack );
         * </pre>
         * @method del
         * @param {String} key
         * @param {Function} func
         */
        
        del : function( key , func )
        {
            key = String( key ).toLowerCase();
            XN.event.delEvent( document , 'keydown' , funcs[ key ][ func ] );
            delete funcs[ key ][ func ];
        }
    };
})();

/*
XN.dom.ready(function()
{
    XN.util.hotKey.add( 'ctrl-alt-shift-74' , function()
    {
        XN.DO.alert('ahahaha');
    } );
});
*/

(function()
{
    var id = 0;
    XN.util.createObjID = function()
    {
      id ++;
      return id;
    };
})();
/**
 * alert && confirm
 * @namespace XN
 * @class DO
 * @static
 */

XN.DO = XN.Do = {};

(function(){

    var currentAlert = null;
    var currentTimer = null;
    
    /**
     *  友好的alert
     *  <pre>
     *  参数形式如下: 
     *  {
     *      title:'',//对话框标题
     *      mesage:'',//提示信息
     *      type:'',//对话框的样式
     *      widith:int,//宽度
     *      height:int,//高度
     *      button:'',//按钮文字
     *      callBack:function,//回调函数
     *      autoHide:0,//自动关闭时间
     *      X:int,
     *      Y:int
     *  }
     *  </pre>
     *  @method alert
     *  @param {Object} params
     *  @return {XN.ui.dialog}
     */

    XN.DO.alert = function( message , title , type , X , Y , w , h , callBack )
    {
        try
        {
            currentAlert.remove();
        }catch( e ){}


        var params = {
            type : 'normal',
            width : 400,
            button : '确定',
            callBack : XN.func.empty,
            autoHide : 0,
            params : {
                addIframe : true
            }
        };

        if ( !isString( message ) ) $extend( params , message );
        
        /*
         * patch for old version
         */
        if ( isString( message ) || arguments.length > 1 )
        {
            var ars = arguments;
            XN.array.each( [ 'message' , 'title' , 'type' , 'X' , 'Y' , 'width' , 'height' , 'callBack' ] , function( i , v )
            {
                if ( ars[ i ] ) params[ v ] = ars[ i ];
            } );
        }
        /*
         * patch end
         */
        
        var dialog = new XN.ui.dialog( params.params )
        .setType( params.type )
        .setTitle( params.title || ( params.type == 'error' ? '错误提示' : '提示' ) )
        .setBody( params.msg || params.message || '' )
        .setWidth( params.width )
        .setHeight( params.height )
        .setX( params.X )
        .setY( params.Y )
        .addButton(
        {
            text : ( params.yes || params.button ),
            onclick : function()
            {
                return params.callBack.call( dialog );
            }
        } ).show();

        
        currentAlert = dialog;
        
        if ( params.noFooter )
        {
            dialog.footer.hide();
        }
        
        if ( params.noHeader )
        {
            dialog.header.hide();
        }
        
        try{
            dialog.getButton( params.button ).focus();
        }catch(e){}

        if ( params.autoHide )
        {
            dialog.autoHide( params.autoHide );
            /*currentTimer = setTimeout( function()
            {
                currentAlert.hide();
            } , params.autoHide * 1000 );
            */
        }
        
        return dialog;
    };

    var currentConfirm = null;

    /**
     * 友好的confirm
     * <pre>
     * 参数形式如下: 
     * {
     *  title:'',//标题
     *  message:'',//提示信息
     *  type:'',//样式
     *  width:int,//宽度
     *  height:int,//高度
     *  submit:'',//确定按钮的文字
     *  cancel:'',//取消按钮的样式
     *  focus: '',//聚焦的按钮'submit'or'cancel'
     *  callBack : function,//回调函数
     * }
     *  
     * </pre>
     * @method confirm
     * @param {Object} params
     * @return {XN.ui.dialog}
     */

    XN.DO.confirm = function( message,title,callBack,yes,no,X,Y,w,h )
    {
        
        try
        {
            currentConfirm.remove();
        }catch( e ){}

        var params = {
            type : 'normal',
            width : 400,
            yes : '确定',
            no : '取消',
            callBack : XN.func.empty,
            focus : null,
            params : {
                addIframe : true
            }
        };

        if ( !isString( message ) ) $extend( params , message );
            
        /*
         * patch for old version
         */
        if ( isString( message ) || arguments.length > 1 )
        {
            var ars = arguments;
            XN.array.each( [ 'message' , 'title' , 'callBack' , 'yes' , 'no' , 'X' , 'Y' , 'w' , 'h' ] , function( i , v )
            {
                if ( ars[ i ] ) params[ v ] = ars[ i ];
            } );
        }
        /*
         * patch end
         */

        var dialog = new XN.ui.dialog( params.params )
        .setType( params.type )
        .setTitle( params.title || ( params.type == 'error' ? '错误提示' : '提示' ) )
        .setBody( params.msg || params.message || '' )
        .setWidth( params.width )
        .setHeight( params.height )
        .setX( params.X )
        .setY( params.Y )
        .addButton(
        {
            text : ( params.submit || params.yes ),
            onclick : function()
            {
                return params.callBack.call( dialog , true );
            }
        } )
        .addButton(
        {
            text : ( params.cancel || params.no ),
            onclick : function()
            {
                return params.callBack.call( dialog , false );
            }
        } ).show();
        
        dialog.getButton( params.cancel || params.no ).addClass( 'gray' );
        
        if ( params.focus == 'submit' )
        {
            params.focus = params.submit; 
        }
        else if ( params.focus == 'cancel' )
        {
            params.focus = params.cancel;
        }

        dialog.getButton( params.focus || params.submit || params.yes ).focus();
        
        currentConfirm = dialog;
        
        return dialog;
    };

    /**
     * 显示一段信息后自动关闭
     * <pre>
     * 使用方法
     * XN.DO.showMessage( '动感超人' , 'haha' , 3 );
     * </pre>
     * @method showMessage
     * @param {String} msg
     * @param {String} title
     * @param {Int} time 自动关闭时间
     */

    XN.DO.showMessage = XN.DO.showMsg = function( msg , title , time )
    {
        var dialog =  XN.DO.alert({
            msg : msg,
            title : ( title || '提示' ),
            noFooter : true,
            autoHide : ( time || 2 )
        });

        //dialog.refresh();

        return dialog;
    };
    
    /**
     * 显示一段出错信息后自动关闭
     * <pre>
     * 使用方法
     * XN.DO.showError( '出错信息' , '出错了' , 3 );
     * </pre>
     * @method showError
     * @param {String} msg
     * @param {String} title
     * @param {Int} time 自动关闭时间
     */

    XN.DO.showError = function( msg ,title , time )
    {
        var dialog =  XN.DO.alert({
            msg : msg,
            type : 'error',
            title : (title || '错误提示'),
            noFooter : true,
            autoHide : (time || 2)
        });
        
        //dialog.refresh();

        return dialog;
    };
})();
/*
 *  based on YUI:YAHOO.lang.JSON 
 */
XN.json = {
	_ESCAPES : /\\["\\\/bfnrtu]/g,
	_VALUES  : /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
	_BRACKETS : /(?:^|:|,)(?:\s*\[)+/g,
	_INVALID  : /^[\],:{}\s]*$/,
	_SPECIAL_CHARS : /["\\\x00-\x1f\x7f-\x9f]/g,
	_PARSE_DATE : /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/,
	_CHARS : {
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '"' : '\\"',
        '\\': '\\\\'
    },
    dateToString : function (d) {
        function _zeroPad(v) {
            return v < 10 ? '0' + v : v;
        }

        return '"' + d.getUTCFullYear()   + '-' +
            _zeroPad(d.getUTCMonth() + 1) + '-' +
            _zeroPad(d.getUTCDate())      + 'T' +
            _zeroPad(d.getUTCHours())     + ':' +
            _zeroPad(d.getUTCMinutes())   + ':' +
            _zeroPad(d.getUTCSeconds())   + 'Z"';
    },
    stringToDate : function (str) {
        if (XN.JSON._PARSE_DATE.test(str)) {
            var d = new Date();
            d.setUTCFullYear(RegExp.$1, (RegExp.$2|0)-1, RegExp.$3);
            d.setUTCHours(RegExp.$4, RegExp.$5, RegExp.$6);
            return d;
        }
    },
	parse:function(str){
        return eval('(' + str + ')');
	},
	build:function(o,w,d){
	    var m = XN.JSON._CHARS,str_re = XN.JSON._SPECIAL_CHARS,pstack = [];
		var _char = function (c) {
            if (!m[c]) {
                var a = c.charCodeAt();
                m[c] = '\\u00' + Math.floor(a / 16).toString(16) +
                                           (a % 16).toString(16);
            }
            return m[c];
    	};
		var _string = function (s) {
            return '"' + s.replace(str_re, _char) + '"';
        };
		var _date = XN.JSON.dateToString;
        var _stringify = function (o,w,d) {
            var t = typeof o,
                i,len,j,k,v,vt,a;
            if (t === 'string') {
                return _string(o);
            }
            if (t === 'boolean' || o instanceof Boolean) {
                return String(o);
            }
            if (t === 'number' || o instanceof Number) {
                return isFinite(o) ? String(o) : 'null';
            }
            if (o instanceof Date) {
                return _date(o);
            }
            if (isArray(o)) {
                for (i = pstack.length - 1; i >= 0; --i) {
                    if (pstack[i] === o) {
                        return 'null';
                    }
                }
                pstack[pstack.length] = o;

                a = [];
                if (d > 0) {
                    for (i = o.length - 1; i >= 0; --i) {
                        a[i] = _stringify(o[i],w,d-1) || 'null';
                    }
                }
                pstack.pop();

                return '[' + a.join(',') + ']';
            }

            if (t === 'object') {
                if (!o) {
                    return 'null';
                }
                for (i = pstack.length - 1; i >= 0; --i) {
                    if (pstack[i] === o) {
                        return 'null';
                    }
                }
                pstack[pstack.length] = o;

                a = [];
                if (d > 0) {
                    if (w) {
                        for (i = 0, j = 0, len = w.length; i < len; ++i) {
                            if (typeof w[i] === 'string') {
                                v = _stringify(o[w[i]],w,d-1);
                                if (v) {
                                    a[j++] = _string(w[i]) + ':' + v;
                                }
                            }
                        }
                    } else {
                        j = 0;
                        for (k in o) {
                            if (typeof k === 'string' && typeof o[k] != 'undefined') {
                                v = _stringify(o[k],w,d-1);
                                if (v) {
                                    a[j++] = _string(k) + ':' + v;
                                }
                            }
                        }
                    }
                }
                pstack.pop();
                return '{' + a.join(',') + '}';
            }
            return undefined; 
        };
		d = d >= 0 ? d : 1/0;
		return _stringify(o,w,d);
	}
};

/*
 * patch for old version
 */

XN.JSON = XN.Json = XN.json;

/*
 * patch end
 */

/*
 * for im
 */

(function()
{
    writepipe = function( uin , nick )
    {
        if ( uin > 0 )
        {
            var s = GetCookie( '_pipe' );
            if ( s ) s += ':';
            SetCookie( '_pipe' , s + uin + ':' + escape( nick ) , null , '/' , 'kaixin.com' );
        }

        var wi_state = GetCookie( '_wi' );

        if ( 'opening' == wi_state )
        {
        }
        else if( 'running' == wi_state )
        {
        }
        else
        {				
            SetCookie( '_wi' , 'opening' , null , '/' , XN.ENV.domain );
            
            window.wiw=window.open(
                    'http://kaixin.com/webpager.do?toid=' + uin ,
                    '_blank',
                    'height=600,width=650,resizable=yes,location=yes'
            );
            
            if ( window.wiw_checker )
                window.clearInterval( window.wiw_checker );
            
            window.wiw_checker=window.setInterval(
                function()
                {
                    if ( window.wiw.closed )
                    {
                        window.clearInterval( window.wiw_checker );
                        SetCookie( '_wi' , '' , null , '/' , XN.ENV.domain );
                    }
                },
                1000);
            return true;
        }

        try
        {
            if ( window.wiw )
                window.wiw.focus();
        }
        catch(e){}
        return false;
    }

    talkto = function( uin , nick , tiny , doing )
    {
        try
        {
            var a=new ActiveXObject( 'xntalk.Application' );
            if ( a )
            {
                a.openChat( '' , uin );
                return true;
            }
        }catch(e){}

        if ( top.frames['imengine'].gPagerType == 4 )
        {
            if ( top.frames['imengine'].imHelper.isLoginUser() )
            {
                var tabs = top.frames['imengine'].imui.chatTabs;
                tabs.onActivateWidget( uin, nick, tiny, doing );
                tabs.switchFocus( uin );
                return true;
            }
        }

        try
        {
            writepipe(uin,nick);
        }catch(e){}
    }

    jump_and_download = function( link )
    {
      if ( XN.BROWSER.IE )
      {
        window.open( link , 'download_window', 'toolbar=0,location=no,directories=0,status=0,scrollbars=0,resizeable=0,width=1,height=1,top=0,left=0');
        window.focus();
      }
    }
    
})();

function GetCookieVal(_70){
var _71=document.cookie.indexOf(";",_70);
if(_71==-1){
_71=document.cookie.length;
}
return unescape(document.cookie.substring(_70,_71));
}
function GetCookie(_72){
var arg=_72+"=";
var _74=arg.length;
var _75=document.cookie.length;
var i=0;
while(i<_75){
var j=i+_74;
if(document.cookie.substring(i,j)==arg){
return GetCookieVal(j);
}
i=document.cookie.indexOf(" ",i)+1;
if(i==0){
break;
}
}
return null;
}

function SetCookie(_78,_79){
var _7a=SetCookie.arguments;
var _7b=SetCookie.arguments.length;
var _7c=(_7b>2)?_7a[2]:null;
var _7d=(_7b>3)?_7a[3]:null;
var _7e=(_7b>4)?_7a[4]:null;
var _7f=(_7b>5)?_7a[5]:false;
document.cookie=_78+"="+escape(_79)+((_7c==null)?"":("; expires="+_7c.toGMTString()))+((_7d==null)?"":("; path="+_7d))+((_7e==null)?"":("; domain="+_7e))+((_7f==true)?"; secure":"");
}


/*
 * for im end
 */
 var IMHack={};
(function(){
	//util method
	var addEvent=function(element, type, handler) {
	  if (!handler.$$guid) handler.$$guid = addEvent.guid++;
	  if (!element.events) element.events = {};
	  var handlers = element.events[type];
	  if (!handlers) {
		handlers = element.events[type] = {};
		if (element["on" + type]) {
		  handlers[0] = element["on" + type];
		}
	  }
	  handlers[handler.$$guid] = handler;
	  element["on" + type] = handleEvent;
	};

	addEvent.guid = 1;

	var removeEvent=function(element, type, handler) {
	  if (element.events && element.events[type]) {
		delete element.events[type][handler.$$guid];
	  }
	};

	var handleEvent=function(event) {
	  event = event || window.event;
	  var handlers = this.events[event.type];
	  for (var i in handlers) {
		this.$$handleEvent = handlers[i];
		this.$$handleEvent(fixEvent(event));
	  }
	};

	var fixEvent=function(event){
		if(event.cancelBubble)
			event.stopPropagation=function(){
				event.cancelBubble=true;
			};
		return event;
	};
	
	var css=function(ele,prop){
		for(i in prop)
			ele.style[i]=prop[i];
	};
	
	var dimension=function(obj){
		var memory={display:obj.style.display,visible:obj.style.visibility};
		css(obj,{display:"",visible:"visibility"});
		var dim={w:obj.offsetWidth,h:obj.offsetHeight};
		css(obj,memory);
		return dim;
	};
	
	var getElementsByClass=function(context,searchClass) {
		return XN.DOM.getElementsByClassName(searchClass,context);
	};
	
	//logic method
	var fixedEle=null;
	var timer=null;
	var reLocation=function(){
		css(fixedEle,{display:"none"});
		clearTimeout(timer);
		timer=setTimeout(function(){
			var dim=dimension(fixedEle);
			var top=XN.EVENT.scrollTop()+XN.EVENT.winHeight()-25;
			css(fixedEle,{display:"block",top:top+"px",right:"0px"});
		},500);
	}		
	IMHack.hackToolBar=function(){
		fixedEle=document.getElementById("wpiroot");
		css(fixedEle,{position:"absolute",right:0});
		addEvent(window,"scroll",reLocation);
		addEvent(window,"resize",reLocation);
	}
	IMHack.hackWidget=function(ele){
		var widget=ele.getElementsByTagName("div")[0];
		css(widget,{position:"absolute",bottom:"23px"});
		if(getElementsByClass(ele,"buddy-list").length>0)
			css(widget,{right:"-62px"});
		else if(getElementsByClass(ele,"notifications").length>0)
			css(widget,{right:"-31px"});
		else if(getElementsByClass(ele,"status-control").length>0)
			css(widget,{right:"-1px"});
		else if((/\bm-chat-button-chattab\b/.test(ele.className))){
			css(ele,{position:"relative"});
			css(getElementsByClass(ele,"m-chat-window")[0],{position:"absolute",right:"-2px",bottom:"23px"});				
		}
		else
			css(widget,{right:0});
	}
})();

if ( XN.browser.Gecko )
{
    if ( XN.string.getQuery( 'debug_mode' ) )
    {
        XN.debug.on();
    }
}
//广告系统
(function()
{
    if ( window.XN )
    {
        var domain = XN.env.domain;
        var getCookie = XN.cookie.get;
        var $element = window.$element;
        var ready = XN.dom.ready;
        var each = XN.array.each;
        var isBlank = XN.string.isBlank;
        var $ = xn_getEl;
    }

    /*XN.dom.ready(function()
    {
        $( 'banner' ).hide();
    });
    */

    var loadURI = 'http://shaft.jebe.xiaonei.com/show';
    var staticURI = 'http://jebe.xnimg.cn/';
    
    function buildAD( obj )
    {
      
        XN.log( obj ); 
        
        var html = [];

        var templete = {};

        templete[ 1 ] = function( ad )
        {
            return '<a target="_blank" href="' + ad.click_url + '">'
                + ad.text1.replace( /%%\(.*?\)(.*?)%%/g, '<span style="color:red">$1</span>' )
                + '</a>'; 
        };

        templete[ 2 ] = function( ad )
        {
            
            if ( ad.media_uri && !/^http:\/\//.test( ad.media_uri ) )
            {
                ad.media_uri = staticURI + ad.media_uri;
            }
            
            if ( /\.swf$/.test( ad.media_uri ) )
            {
                var html = '<div style="position:relative;">'; 
                
                html += '<embed src="' + ad.media_uri;
                
                var if_click  = parseInt( ad.flash_click_type , 0 );

                if ( isNaN( if_click ) )
                {
                    if_click = 0;
                }

                if ( if_click == 1 )
                {
                    html += '?' + ad.flash_click_value + '=' + encodeURIComponent( ad.click_url ); 
                }

                html += '" type="application/x-shockwave-flash" ' +
	'width="' + ad.width + '" height="' + ad.height + '" wmode="transparent" >';

                html += '</embed>';
                
                if ( if_click == 0 )
                {
                    html += '<div style="' + (XN.browser.IE ? 'filter:alpha(opacity=1);background-color:#fff;' : '' ) + 'width:' + ad.width + 'px; height: ' + ad.height + 'px;cursor:pointer;position: absolute; left: 0px; top: 0px; z-index: 999;" onclick="window.open(\'' + ad.click_url + '\');"></div>';
                }
                
                html += '</div>';

                return html;
            }
            else
            {
	            return [
                    '<a target="_blank" href="' + ad.click_url + '">',
                        '<img width="' + ad.width + '"',
                        'height="' + ad.height + '"',
                        'src="' + ad.media_uri+ '"',
                        ' />',
                    '</a>'
                ].join( '' );
            }  
        };

        templete[ 3 ] = function( ad )
        {
            return '';
        };
        
        each( obj.ads , function( i , v )
        {
            html.push( templete[ v.format ]( v ) );
        });
        
        var div = $( 'ad' + obj.adzoneid );
        if ( !div ) return;

        div.innerHTML = html.join( '' );
    }
    
    window.render_jebe_ads = function( json )
    {
        if ( $( 'banner' ) ) $( 'banner' ).show();
        if ( $( 'bannerBottom' ) ) $( 'bannerBottom' ).show();

        XN.array.each( ['1000010001','1000010002','1000010003','1000010004','1000010005','1000010006','1000010007'] , function( i , v )
        {
            var el = $( 'ad' + v );
            if ( el ) el.show();
        });

        var ads = json.result;//eval( '(' + json + ')' ).result;
        each( ads , function( i , v )
        {
            buildAD( v );    
        });

    };

    window.load_jebe_ads = function( s, r )
    {
        if ( !s ) return;

        ready(function()
        {
            function checkLoad()
            {
                setTimeout(function()
                {
                    
                    XN.array.each( ['1000010001','1000010002','1000010003','1000010004','1000010005','1000010006','1000010007'] , function( i , v )
                    {
                        var el = $( 'ad' + v );
                        if ( !el ) return;
                        if ( isBlank( el.innerHTML ) ) el.hide();
                    });
                    
                    var tl = $( 'ad1000010001' ),
                    tr = $( 'ad1000010002' );

                    if ( tl && tr && isBlank( tl.innerHTML ) && isBlank( tr.innerHTML ) )
                    {
                        if ( $( 'banner' ) ) $( 'banner' ).hide();
                    }
                
                 } , 1000 );
            }

            var p = getCookie( 'userid' );
            if ( !p || isBlank( p ) ) p = '';
            var sc = $element( 'script' );
            sc.type = 'text/javascript';
            var src = loadURI + '?userid=' + encodeURIComponent( p );
            if ( r ) src += '&r=' + r;
            sc.src = src;

            if ( XN.browser.IE )
            {
                sc.onreadystatechange = function()
                {
                    if ( ( this.readyState == 'loaded' || this.readyState == 'complete' ) )
                    {
                        checkLoad();
                    }
                }
            }
            else
            {
                sc.onload = function()
                {
                    checkLoad();
                };
            }
            
            setTimeout( checkLoad , 10 * 1000 );
            document.body.appendChild( sc );
        });
    };

})();

XN.USER = XN.User = {};
XN.USER.me = function( parameters )
{
};
currentUser = {};

XN.EVENT.enableCustomEvent( currentUser );

XN.USER.addFriendAction = function( p )
{
    this.config = {
        commentLength : 45,
        needComment : true,
        requestURI : '/ajax_request_friend.do'
    };
    $extend( this.config , p );
};

XN.USER.addFriendAction.prototype = {
    getConfig : function( key )
    {
        return this.config[ key ];
    },
    send : function( id , why , from , icode)
    {
        var This = this;
        
        if ( this.getConfig( 'needComment' ) )
        {
            if ( XN.STRING.isBlank( why ) )
            {
                this.fireEvent( 'checkError' , '您输入的信息不能为空' );
                return;
            }
        }

        if ( why.length > this.getConfig( 'commentLength' ) )
        {
            this.fireEvent( 'checkError' , '您输入的信息不能超过' + this.getConfig( 'commentLength' ) + '个字符' );
            return;
        }
         
        if ( icode !== 0 && icode.length != 4 ){
        	this.fireEvent( 'checkError' , '请输入验证码!!!' );
            return;
        }

        var data = 'id=' + id + '&why=' + why +'&from=' + from;
        if ( icode !== 0 ) data += "&icode=" +icode;

        this.fireEvent( 'beforePost' );
        
        if ( icode !== 0 ) $("rfl_div").hide();

        new XN.NET.xmlhttp(
        {
            url : this.getConfig( 'requestURI' ),
            'data' : data,
            onSuccess : function( r )
            {
                r = r.responseText;
                This.fireEvent( 'success' , id , r , from );
                
                if ( !window.currentUser ) return;
                
                if ( currentUser.fireEvent )
                    currentUser.fireEvent( 'addFriendSuccess' , id , r ,from );

                if ( currentUser.onaddFriendSuccess )
                    currentUser.onaddFriendSuccess( id , r );
            },
            onError : function()
            {
                This.fireEvent( 'error' , id , from );
                
                if ( !window.currentUser ) return;
                currentUser.fireEvent( 'addFriendError' , id , r , from );
            }
        });
    }
};

XN.EVENT.enableCustomEvent( XN.USER.addFriendAction.prototype );


/*
 * patch for old version
 */

XN.DOM.readyDo(function(){
	
	//对话框引用
	var dialog=null;
	
	//当前操作的用户
	var user=null;
	
	//操作进行中提示对话框
	function loadingDialog(){
		
		dialog=XN.DO.confirm({
			title : '将' + user.name + '加为好友?',
			msg : '<div style="font-size: 14px;  height:100px; line-height: 1.8em; padding-left: 20px;" class="clearfix"><div style="padding: 4px; background: transparent url('+XN.ENV.staticRoot+'imgpro/bg/picholder59.gif) no-repeat scroll 0% 0%;width: 59px; height: 59px; float: left;"><a href="#" style="background: transparent url('+user.head_url+') no-repeat scroll center center;height: 50px; width: 50px; display: block;">&nbsp;</a></div><div style="margin-left: 10px; height: 30px; float: left;width:240px;font-size:12px;"><h3 style="margin-top:15px;"><img style="display:block;float:left;margin:5px 10px 0 0;" src=\"' + XN.ENV.staticRoot + '/img/indicator.gif\" />Loading...</h3></div></div>',
			width : 400
		});
		dialog.footer.style.display="none";
	}
	
	//拼接对话框的内容	
	function getMessage(speak,type,gender,icode){
		var showSpeak=speak == "" ? "none" : "block";
		var isTrueName=(type & 1);
		var isTrueImg=(type & 2);
		var text=(isTrueName ? "" : '<a style="font-size:12px;" target="_blank" href="http://www.kaixin.com/BasicInfo.do">真名</a>')+(isTrueImg ? "" : '<a style="font-size:12px;" target="_blank" href="http://head.upload.kaixin.com/Upload.do?from=friend">真头像</a>');
		var showLink=(text.length>0) ? "" : "none";
		//对话框内部的message(需要根据不同的条件拼接)
		var html=['<div style="padding:4px;color:#EF4223;background-color:#FEFFCF;margin-bottom:10px;zoom:1;">需要通过<em>',
				  user.name,
				  '</em>的验证才能加',
				  gender,
				  '为好友！</div>',
				  '<div style="padding: 4px; background: transparent url(',
				  XN.ENV.staticRoot,
				  'imgpro/bg/picholder59.gif) no-repeat scroll 0% 0%;width: 59px; height: 59px; float: left;"><a href="#" style="background: transparent url(',
				  user.head_url,
				  ') no-repeat scroll center center; height: 50px; width: 50px; display: block;">&nbsp;</a></div>',
				  '<div id="addFriendAlert" style="float: left;width:265px;">',
				  '<h4 style="display:',
				  showSpeak,
				  ';margin-bottom:10px;">',
				  user.name,
				  '说: <span style="font-weight: 400;">',
				  speak,
				  '</span></h4>',
				  '<p style="margin: 0 0 10px 0;">',
				  '<textarea id="addFriendMessage" style="border: 1px solid #B8D4E8; width: 100%; height:50px;color: gray;" title="附加信息(选填，45字内)" onfocus="if(this.value==this.title)this.value=\'\';" onblur="if(this.value==\'\')this.value=this.title;">附加信息(选填，45字内)</textarea>',
				  '</p>',
				  '<div style="display:',
				  showLink,
				  ';clear:both;text-align:center;">使用'+text+'，对方更容易通过你的好友请求</div>',
				  '</div><div style="clear:both;">',
				  //验证码部分
				  icode?'<div style="clear: both;"/><div id="rfl_div" style="padding:10px;clear:both"><img id="verifyPic" align="middle" src="http://icode.kaixin.com/getcode.do?t=request_friend&r=' + Math.random() + '" />&nbsp;<a onclick="var el=$(\'verifyPic\');if(XN.BROWSER.IE6){new Image().src=el.src+\'x\';}el.src+=\'x\';">看不清楚 换一张</a>&nbsp;<input type="text" class="input-text" size="8" id="request_friend_icode" name="icode" /></div>':'',
				  '</div>'];
		return html.join("")
	}
	
	//填写好友申请对话框
	function requestDialog(speak,type,gender,icode){
		dialog=XN.DO.confirm({
			title : '将' + user.name + '加为好友?',
			msg : getMessage(speak,type,gender,icode),
			width : 400,
			callBack : function( r ){
				if (r){
					var obj=$('addFriendMessage')
					var why=obj.value==obj.title ? "" : obj.value;
					if ( icode )
                    {
                        var ic = $('request_friend_icode').value;
                    }
                    else
                    {
                        var ic = 0;
                    }
					getAction().send( user.id , why , user.from , ic);
				}
			}
		});
		dialog.footer.style.display="";
	}
	
	//发送请求时提示信息
	function beforePost(){
        $( 'addFriendAlert' ).innerHTML = '正在发送请求...';
        dialog.footer.hide();
		try
        {
            dialog.preventHide();
        }
        catch(e)
        {
            dialog.show();
        }
    }
    
	//推荐好友
	function recommendFriend(){
		if(typeof showRecommendedFriendDialog!="undefined")
			showRecommendedFriendDialog(user.id,user.name,1,true);
		else{
			XN.loadFile( $( 'st_for_r_f' ).getAttribute( 'vhref' ) );
			XN.loadFile( $( 'js_for_r_f' ).getAttribute( 'vsrc' ) ,function(){
				showRecommendedFriendDialog(user.id,user.name,1,true);
			});
		}
	}
	
	//请求成功后放入处理(判定是否需要推荐流程)
    function success(id, message){
        var This = this;
        if (isJSON(message))
            var msg = XN.JSON.parse( message );
        else
            var msg = {code:0,targetfriendcount:100,message:message};

        if ( msg.code == 0 || msg.code == 1 ){
			//推荐好友
			if(msg.targetfriendcount<=12){
				dialog.hide();
				recommendFriend();
			}
			else{
				$( 'addFriendAlert' ).innerHTML = msg.message;
				setTimeout(function(){dialog.hide();}, 1500);
			}
			//兼容旧方法
			if(user.action){
				try{
					eval(user.action);
				}catch(e){}
			}				
			//是否有回调
			if(user.callback)
				user.callback(user.id);
        }
		else{
			dialog.hide();
			XN.DO.alert({
				title:"好友申请失败",
				message:"<p style='padding:10px;'>"+msg.message+" 你可以发<a href='http://msg.kaixin.com/message/compose.do?id="+user.id+"' target='_blank'>短消息</a>，请求对方加你为好友 </p>"
			});
		}
    }
	
	//初始化User
	function initUser(args){
		if ( !/^\d+$/.test( args[ 0 ] ))
			user = {id:args[1],name:args[2],head_url:args[3],star:true,from:args[4],action:args[5]};
		else
			user = {id:args[0],name:args[1],head_url:args[2],star:args[3],from:args[4],callback:args[5]};
	}
	
	//返回当前用户对应的Action
	function getAction(){
		var action = new XN.USER.addFriendAction({
			needComment : false
		});
		action.addEvent( 'beforePost' , beforePost );
		action.addEvent( 'success' , success );
		action.addEvent( 'checkError' , function(message){
			dialog.hide();
			XN.DO.showError(message,"错误提示",2);
			setTimeout(function(){
				dialog.show();
			},2000);
		});    
		action.addEvent( 'error', function( id , message ){
			dialog.hide();
			XN.DO.showError( message );
		});	
		
		return action;
	}
	
	//对外的好友申请接口
	window.showRequestFriendDialog = function(uid,name,head,star,from,action){
		//初始化用户
		initUser(arguments);
		//加载好友提示语
		loadingDialog();
		new XN.NET.xmlhttp({
			url:"/GetFriendCue.do",
			method:"get",
			data:'id=' + user.id,
			onSuccess:function(r){
				try{
					var result=XN.JSON.parse(r.responseText);				
					var speak=result.type==0 ? "" : result.content;
					var type=result.isTrue;
					var gender=result.ta===false ? "她" : "他";
					var icode=result.icode;
					requestDialog(speak,type,gender,icode);
				}catch(e){					
					requestDialog("",3,"TA",false);
				}
			},
			onError:function(r){
				dialog.hide();
				//XN.DO.showError('网络通信失败,请重试');
				requestDialog("",3,"TA",false);
			}
		});
	};
});
