function uiSendFriendClass( anchorId , contentId ){

	var c1 = jml.obj
	var c2 = jml.xml.node
	var c3 = jml.events;
	var c5 = jml.server;
	var c4 = new uiLayerClass();
	var c6 = new characterCount( 'sendFriendComment' , 'cCounSendFriend1' , 1500 );
	
	var host ;
	var evaluation = { interaction : false , sector : false } ;
	var elements = { anchor : null , layer : null } ;
	var delay = { interaction : { current : 0 , limit : 4 } , sectors : { current : null , limit : 300 } } ;

	var __interval;
	var __timeOut;
	var visible = false ;
	var firstRun = true ;
	var anchorId = anchorId || null ;
	var contentId = contentId || null ;

	if( !isset( anchorId ) || !isset( contentId ) ) return null ;

	c4.onCreate = function( layer ){
	
		if( !isset( elements.layer ) ) elements.layer = layer.container ;
		if( !isset( elements.layer ) ) return ;
		setPosition();
		
		if( firstRun ){
			setAction() ;
			firstRun = false ;
		}
		
		hideAllExceptPosition( 0 );
		
	} ;

	function initialize(){
		if( !isset( elements.anchor ) ) elements.anchor = getObj( anchorId ) ;
		if( !isset( elements.anchor ) ) return null ;
		c3.add( elements.anchor , "click" , open );
	} ;
	
	function open(){
		if( visible ) return ;
		visible = true ;
		initializeEvaluation() ;
		if( isset( elements.layer ) ){
			c4.show() ;
			c4.onCreate() ;
		}
		else{
			c4.create( contentId , 350 , 370 , false , 'expand' , 'expand' ) ;
			c6.init() ;
		}
	} ;
	
	function close(){
		clearEvaluation() ;
		c4.hide() ;
		visible = false ;
		
		if( typeof formValidator == "function" ){ new formValidator().clearError() ; }		
		
	}
	
	function initializeEvaluation(){
		evaluation.sector = true ;	
		clearEvaluation();
		c3.add( document , 'mousemove', evaluateSectors );	
		__interval = setInterval( evaluateInteraction , delay.sectors.limit ) ;		
	} ;
	
	function clearEvaluation(){
		c3.remove( document , 'mousemove', evaluateSectors );
		clearInterval( __interval );
	} ;	
	
	function evaluateSectors( eventObject ){
		if( delay.interaction.current == delay.interaction.limit ){
			evaluation.sector = c3.hitTest( eventObject , [ elements.anchor , elements.layer ] ).on ; 
			delay.interaction.current = 0 ;
		}else{ delay.interaction.current ++ ; }		
	} ;
	
	function evaluateInteraction(){
		if( !evaluation.sector && !evaluation.interaction ) close() ;
	} ;
	
	function setPosition(){
		var x1 = elements.anchor ;
		if( isset( x1 ) ){
		
			var n1 = c1.get( x1 , "offsetLeft" );
			var n2 = c1.get( x1 , "offsetTop" );
			var n3 = c1.get( x1 , "offsetWidth" ) -1 ;
			var n4 = c1.get( x1 , "offsetHeight" ) - 1 ;
			
			if( typeof host.position == 'string' ){
				var a = host.position.split('');
				var x = 0 , y = 0 ;
				for( var i = 0 ; i < a.length ; i++ ){
					var p = a[ i ] ;
					if( p == 'B' ) y = n2 + n4 ;
					if( p == 'T' ) y = n2 ;
					if( p == 'L' ) x = n1 ;
					if( p == 'D' ) x = n1 + n3 ;					
				}
				c4.setPosition( x , y ) ;
			}
		}
	} ;
	
	function hideAllExceptPosition( n ){
		var x1 = c2.byPath( '0.0.0.1' , elements.layer ) ;
		if( isset( x1 ) ){
			for( var i = 0; i < c2.length( x1 ) ; i++ ){
				var x2 = c2.byPosition( i , x1 );
				if( isset( x2 ) ) c1.set( x2 , 'display' , i == n? 'block' : 'none' ) ;
			}
		}
	} ;
	
	function setAction( remove ){
		var remove = remove || false ;
		var s1 = remove ? 'remove' : 'add' ;
		var a1 = getAllElements();
		for( var i = 0 ; i < a1.length ; i++ ){
			var o = a1[ i ] ;
			c3[ s1 ]( o , 'focus' , setToTrue ) ;
			c3[ s1 ]( o , 'keydown' , setToTrue ) ;
			c3[ s1 ]( o , 'blur' , delayBlur ) ;
		}
	} ;	

	function getAllElements(){
		var formObj = c2.byName( 'form' , elements.layer )[0];
		if( !isset( formObj ) ) return null ;
		return formObj.elements ;
	} ;

	function setToTrue(){
		clearTimeout( __timeOut );
		evaluation.interaction = true ;
	} ;
	function setToFalse(){ evaluation.interaction = false ; } ;
	function delayBlur(){ __timeOut = setTimeout( setToFalse , 200 ); } ;
	function delayClose(){ __timeOut = setTimeout( close , 1500 ); } ;

	function sendData(){
		hideAllExceptPosition( 1 );
		if( !isset( host.gatewayUrl ) ){
			hideAllExceptPosition( 3 ) ;
			return ;
		}
		var o = {} , a = getAllElements() ;
		for( var i = 0 ; i < a.length ; i++ ){
			var e = a[ i ] ;
			if( isset( e ) ) o[ e.name ] = e.value ;
			if( e.name=='sendCopy' && e.checked==false ) o[ e.name ] = 'off';
		}
		var cx = new c5.connection() ;
		cx.url = host.gatewayUrl ;
		cx.data = o ;
		cx.onLoad = function( data ) {
			var dta = decode( data );
			if( dta.result_code == 1 ){
				hideAllExceptPosition( 2 ) ;
				delayClose();
				try{ elements.anchor.focus(); }catch( e ){}
			}else{
				hideAllExceptPosition( 3 ) ;
				delayClose();
				try{ elements.anchor.focus(); }catch( e ){}
			}
		} ;
		cx.onError = function(id, msg) { hideAllExceptPosition( 3 ) ; } ;
		cx.connect() ;
	} ;

	return {
		constructor : function(){ return host = this ; },
		initialize : initialize , 
		sendData : sendData ,
		close : close ,
		position : 'DT' ,
		setPosition : null ,
		gatewayUrl : null
	}.constructor() ;
}
function characterCount(s1,s2,l) {
	var s1=s1,s2=s2,l=l,o1=null,o2=null,c2=jml.obj,c3=jml.events,dCache;
	function update(){
		var s=o1.value,n=s.length;
		if(n>l) n=l;
		if(n>=l){
			n=l;
			s=s.substr(0,l);
			c2.set(o1,'value',s);
		}
		c2.set(o2,'innerHTML', l - n );
	}
	this.init = function(){
		o1=getObj(s1);
		o2=getObj(s2);
		if(!isset(s1)||!isset(s2)) return;
		o1.maxlength=l;
		c3.add(o1,'change',update);
		c3.add(o1,'keyup',update);
		update();
	}
}
