<!--	


// 팬지몰 네임스페이스 (패키지 사용) //
var PANSY = {} //전체
PANSY.INPUT = {}; //인풋관련 
PANSY.ROLLING = {} ; //롤링 관련 패키지
PANSY.VAILD={}; //폼검증모듈이 등록될 패키지.
PANSY.VAILD.RE={}; //정규식검증 관련
PANSY.ENC = {}; //엔코딩관련
PANSY.COMMON = {}; //기본적인 스크립트에 쓰일 함수들..
PANSY.WIN = {}; // 윈도우 창 관련
PANSY.FLASH = {}; //플래시관련
PANSY.AJAX = {}; //아작스 관련
PANSY.DND = {}; // 드래그앤드랍 관련
PANSY.IMAGE = {}; //이미지 관련
PANSY.CNI = {}; // 컨트롤 앤 인터페이스 .. 웹페이지상에서 사용자 조작과 관련된 것들.. 클릭시 디스플레이 된다던가.. 선택시에 뭔가 변경된다거나.. 이런것들..
PANSY.FORM = {}; // 폼과 관련된 것들.. 서브밋되거나 하는.. 동작들..


/////////////////////////////////////////////////////////////////////////////////////////////////////// 이벤트 관리
/*
	이벤트를 여러개 등록할 수 있는...
	엘리먼트에, 이벤트 배열을 가지고있고, 이벤트가 실행될때, 그 배열에서 꺼내서 하나씩 실행한다.
	해당 엘리먼트의 속성으로 함수들이 들어있기때문에, this 키워드를 해당 엘리먼트로 인식한다.
*/
PANSY.addEvent=function(elem,eventName,func){ 
	//elem : 이벤트를 등록할 엘리먼트..
	//eventName : 이벤트 이름이다.. onload, onclick 이런것들..
	// func : 등록할 함수 
	
	var existingFunc = null; //등록하려는 엘리먼트에 이미이벤트가 등록되어있고, 그 이벤트가 이벤트실행함수가 아닌경우.. 그 함수를 담아두기 위한 변수.
	
	//1. 해당 엘리먼트에 이벤트 배열이 등록되어있는지 검사하고, 등록안되어있으면 등록해줌.
	//2. 해당 엘리먼트의 해당 이벤트에 함수가 등록되어있는지 검사하고,  등록안되어있으면 등록해준다
	//3. 이벤트 배열에 넘겨준 함수를 등록함.
	
	//이벤트 함수 배열 있는지 검사하기 events 속성. - elem.events {} 로.. 그냥 연관배열이고, 거기에 이벤트명을 키값으로 각 Array 배열이 들어잇음.
	if( ! elem.events){
		elem.events = {}; //연관배열..
	}//end if
	//이벤트 명으로 어레이 배열있는지 검사한다.
	if(! elem.events[eventName]){ //없으면 배열생성
		elem.events[eventName]= new Array();
	}//end if
	
	var eventFuncs = elem.events[eventName]; //이벤트함수배열
	
	
	//등록된 이벤트 있는지 검사한다. 존재하는 경우.. 이것이 실제 우리가 쓰는 이벤트실행함수인지, 사용자 정의 함수인지 모르므로 그것도 구분한다.
	if(elem[eventName]){ 
		//기존 등록된 함수가 이벤트 실행함수인지 검사
		if(elem[eventName] != PANSY.executeEvent){  //아니면.. 기존 등록된 함수를 저장해두고, 이벤트 실행함수로 대체한다.
			existingFunc = elem[eventName];//기존 이벤트함수 저장.
			elem[eventName]= PANSY.executeEvent;//이벤트 실행함수 등록시켜줌.
		}//end if
	}else{ //존재하지 않는경우.. 함수를 이벤트 실행 함수 추가해준다.
		elem[eventName]= PANSY.executeEvent;//이벤트 실행함수 등록시켜줌.
	}//end if
	
	
	//기존 등록된 이벤트 함수 있으면 등록
	if(existingFunc != null){ //있는경우.
		eventFuncs[eventFuncs.length] =  existingFunc;//배열 맨끝에 추가함.
		
	}//end if
	
	//넘겨준 함수 등록
	eventFuncs[eventFuncs.length] = func ; //배열 맨끝에 등록함.
	
}//end function

PANSY.executeEvent=function(event){ //자신에 등록된 이벤트들을 찾아서 실행해주는 이벤트 실행함수. 이 함수가 실제적으로 엘리먼트의 이벤트함수로 쓰인다.
	//자신의 엘리먼트에 등록된 이벤트함수들 전부 실행해줌.
	event = event || window.event; // 파폭 ie .. 구분업이..
	
	var eventFuncs = this.events["on"+event.type];
	
	//등록되어있는지 검사
	if(! eventFuncs){ //배열이 등록안되어있으면 그냥 나감 종료.
		return;
	}// end if
	
	
	//하나씩 꺼내면서 실행하기
	for(var i =0; i<eventFuncs.length; i++){
		var func = eventFuncs[i]; //함수
		// 속에서 this 키워드 쓰게하려면 아무래도 엘리먼트의 속성으로 직접 등록이 되어야 하는 것같다.
		this.eventFunc = func;//임시로 여기에 등록하고 실행한다.
		this.eventFunc();//실행
	}//end for i
	
}//end func
/////////////////////////////////////////////////////////////////////////////////////////////////////// 이벤트 관리 끝




/////////////////////////////////////////////////////////////////////////////////////////////////////// 인풋객체관련 함수들 모음
PANSY.INPUT.getRadioValue=function(rdoName){ //라디오버튼의 선택값을 돌려준다.
	//frm  : 라디오버튼이 속한 폼 개체.
	//rdoName : 라디오버튼의 name 값
	
	var nodes = document.getElementsByName(rdoName); //노드배열 받아옴.
	
	for(var i = 0; i< nodes.length; i++){ //라디오버튼 수만큼 돔..
		
		if(nodes[i].checked == true){
			
			return nodes[i].value;
		}
	}//end for i
	
	//배열을 다돌동안 못찾으면.. 선택값이 없으면..
	return ""; //공백리턴
}//end func

PANSY.INPUT.checkBoxAll=function(chkName , chkAll){ //주어진 이름의 모든 체크박스를 , 주어진 체크박스의 상태에 따라 똑같이 움직이게한다. (체크박스 전체선택 및 해제) 온클릭이벤트에 걸어주면됨 
	//chkName : 선택대상이되는 체크박스의 네임
	//chkAll : 전체선택이될 체크박스
	
	var chkList = $n(chkName); //해당이름의 모든 체크박스 배열
	for(var i = 0; i< chkList.length; i++){ //라디오버튼 수만큼 돔..
		var chk = chkList[i];
		
		chk.checked = chkAll.checked;
	}//end for i
	
}//end func

PANSY.INPUT.checkBoxAll_title=function(title , chkAll){ // 위 함수가 , 이름이 무조건 같아야해서.. 이름이 다르더라도.. title로 구분할 수 있도록 함. 
	//title : 선택대상이되는 체크박스의 title
	//chkAll : 전체선택이될 체크박스
	
	var input_list = $t(document,"input"); //인풋
	for(var i = 0; i< input_list.length; i++){ //라디오버튼 수만큼 돔..
		var input = input_list[i];
		if(input.type=="checkbox" && input.title==title){ //타이틀이 동일한 체크박스
			input.checked = chkAll.checked;	
		}//end if		
	}//end for i
	
}//end func

PANSY.INPUT.isCheckedBox=function(chkName){ //주어진 이름의 체크박스가,  선택된게 있는지 검사함. 
	//chkName : 선택대상이되는 체크박스의 네임
	//하나라도 선택된게 있으면 트루 리턴시킴. 
	
	var chkList = $n(chkName); //해당이름의 모든 체크박스 배열
	for(var i = 0; i< chkList.length; i++){ //라디오버튼 수만큼 돔..
		var chk = chkList[i];
		if(chk.checked == true){
			return true;
		}//end if
		
	}//end for i
	return false;
}//end func


PANSY.INPUT.changeDisplayBySelect=function(slt){  // 현재 셀렉트 박스의 선택된 값에 의해서 ,  디스플레이시켜주는 오브젝트를 바꿔주는 이벤트 .. 셀렉트박스 오브젝트의 온체인지 에 이벤트 걸어주면된다.
	var display_obj_list = slt.display_obj_list;//디스플레이 배열 받아오기
	
	//등록된 배열없으면 종료
	if(! display_obj_list){
		return;
	}//end if
	//등록된 배열없으면 종료 끝
	
	//모든 디스플레이 종료
	for(key in display_obj_list){
		var display_obj = display_obj_list[key];
		if(display_obj){
			display_obj.style.display = "none";
		}//end if
	}//end for i
	//모든 디스플레이 종료 끝
	
	//선택 디스플레이 보여주기
	display_obj = display_obj_list[slt.value];
	if(display_obj){
		display_obj.style.display = "";
	}//end if
	//선택 디스플레이 보여주기 끝
}//end if

PANSY.INPUT.addDisplayObject=function(obj,val,display_obj){  //changeDisplayBySelect 와 함께 쓰일함수, 셀렉트오브젝트에, 값에 의해 변경될 오브젝트들을 등록시켜준다. //기본적으로 셀렉박스를 염두해두었지만, 다른 것에 써도 무방할 듯 하다
	//obj : 대상이되는 셀렉박스 나 기타 다른 인풋..
	//val : 선택값
	//display_obj : 디스플레이될 해당 오브젝트
	// 만약 선택값에 등로된 오브젝트가 없다면.. 아무것도 보여주지 안느다.
	
	if(! obj.display_obj_list){//해당 오브젝트에 배열등록되었는지 검사
		obj.display_obj_list = new Array(); //새로운 연관배열
	}//end if
	
	//해당 키값에 디스플레이 오브젝트 등록
	obj.display_obj_list[val] =display_obj;
	//해당 키값에 디스플레이 오브젝트 등록 끝
	
	
}//end if

/////////////////////////////////////////////////////////////////////////////////////////////////////// 인풋객체관련 함수들 모음 끝










//////////////////////////////////////////////////////////////////////////////////////////////////////////// 롤링 관련


/*
	롤링 기본적인 개념
	겉을 감싸고 있는 div 는 overflow:hidden; 으로 설정되어있어서, 자기 자신의 크기만큼만 보여주게되고..
	안쪽의 내용들은 새로운 div로 감싸서 바탕div에 등록해둔다.
	안쪽 div의 top ,left, 등을 조정해서 위치를 이동시킨다. 
*/

PANSY.ROLLING.arrRolling = {}; //롤링객체들이 저장될 배열..  타이머에 등록할때 필요함. 타이머의 tid 가 키값이다.

/*
	롤링기본객체 : 롤링에 관련된 기본적인 일을 처리해주는 기본객체.. 사용자가 직접 이 클래스를 사용할일은없다.
										각 롤링스타일별로 할일이 다르므로, 이 클래스를 상속받아서, do 메소드를 확장해주면 된다. 
	인수  :
		wrapperDiv  : 롤링되는 배경이될 .. 롤링내용을 감싸고잇는 div 이다. 이 div는 멈춰있는채로.. 그 속의 내용들이 롤링된다.  이 div는 width 값과 height 값이 설정되어있어야한다.
		speed : 타이머 속도를 받는다. 낮을수록 빠르다. 
*/
PANSY.ROLLING.RollingBase = function (wrapperDiv,speed){
	
	///////// 필드
	this.wrapperDiv = wrapperDiv; //배경 div 저장
	this.innerDiv = null; //div 객체생성.. 이 div 가 내용을 가지고서 움직일 div 임.
	this.speed = speed; //속도
	this.timer = null; //타이머..

	
	/////////생성자 일처리
	if(wrapperDiv){ //감싸주지않으면,  프로토타입상속할때 에러가남.. wraapperDiv 를 넘겨주지 않기때문에..
		wrapperDiv.style.overflow = "hidden"; // 오버플로 히든설정
		wrapperDiv.style.position = "relative"; // 포지션  설정..
		
		
		
	}//end if
	
	
}//end class

//////// 메소드 선언

PANSY.ROLLING.RollingBase.prototype.play=function(){ //타이머 시작시켜줌.. 동작을 실행한다
	
	//타이머 동작중이면나간다.
	if(this.timer) return;
	
	var obj = this;
	this.timer = setInterval( function(){
		obj.doRolling();
	}, this.speed);
	

}//end method


PANSY.ROLLING.RollingBase.prototype.stop=function(){ //타이머 멈춤.. 동작을 멈춘다
	clearInterval(this.timer); //타이머멈춤
	this.timer = null; //다시 널 입력해줌.
}//end method

PANSY.ROLLING.RollingBase.prototype.doRolling=function(){ //롤링 동작 처리...  밑에서 이 함수 재선언해서 사용한다.
	
}//end method
//메소드 선언 끝
	


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*
	

	계속적으로 한쪽방향으로 롤링되는 객체..
	위의 Base 클래스를 상속한다.  do 메소드를 재정의 하면 된다.
	
	방식 : 
		배경 div 속의 내용물들을 
	인수  :
		wrapperDiv : 배경 div - width ,height 설정되어있어야함.
		speed : 타이머호출되는 시간
		innerWidth : 안쪽 내용물의 길이를 설정한다. "100%" "150px" .. 반드시 줘야함.  - 왜인지는 잘 모르겠지만.. div객체를 생성해서 움직이도록하고.. top이나 left 를 옮기면.. width가 엉망이된다. 
		movingSize : 한번에 몇픽셀씩 움직일건지 speed 는 몇초에 한번 움직일건지 설정임..
		side : 어느 방향으로 롤링시킬지 . top/left/right/bottom 중의 하나다.
		
*/
PANSY.ROLLING.OneSideRolling = function(wrapperDiv,speed,innerWidth,movingSize,side){
	
	////////// 생성자 
	PANSY.ROLLING.RollingBase.call(this,wrapperDiv,speed); //상속처리..  부모 생성자호출한다고 생각하면 됨 . 이부분이없으면 단순 prototype 만으론.. 생성된 객체마다 고유한 메모리배당이안됨 
	
	
	//생성자부분 감싸주기
	if(wrapperDiv){
		
		/*
			구조 : 사용자가넘겨준 wrapperDiv 는 배경이고.. 그 안에 움직이는 판인 innerDiv  가 있음
			그 속에 반복되어도 끊기지 않기위해서 innerDiv_1,innerDiv_2 를 넣어두었음. 최종적으로 움직일때  사용하는건 innerDiv 임. 
		*/
		
		this.innerDiv =  $c("div");
		this.innerDiv.style.position="absolute";//포지션설정
		this.innerDiv.style.top="0px";//포지션설정
		this.innerDiv.style.left="0px";//포지션설정
		this.innerDiv.style.display="inline";//포지션설정
//		this.innerDiv.style.overflow="auto";//포지션설정
		
		
		
		

		this.innerDiv2 =  $c("div");
		this.innerDiv2.style.position="absolute";//포지션설정
		this.innerDiv2.style.top="0px";//포지션설정
		this.innerDiv2.style.left="0px";//포지션설정
		this.innerDiv2.style.display="inline";//포지션설정
//		this.innerDiv2.style.overflow="auto";//포지션설정
		
		this.innerDiv.innerHTML = wrapperDiv.innerHTML; // div 내용을 옮김
		

		
		wrapperDiv.innerHTML = ""; // 래퍼div에 내용삭제하고
		wrapperDiv.appendChild(this.innerDiv);//새로 생성한 div를 자식으로 넣어줌.
		wrapperDiv.appendChild(this.innerDiv2);//새로 생성한 div를 자식으로 넣어줌.
		
		
		this.innerDiv2.style.visibility = "hidden";
		
		
		
		this.innerDiv2.innerHTML=this.innerDiv.innerHTML; //두번째 div에도 내용복사
		
		//가로길이 설정..
		this.innerDiv.style.width=innerWidth;
		this.innerDiv2.style.width=innerWidth;
	
	
		//방향을 보고, innerDiv1 , 2 의 display 속성 변경해주기  //가로는 inline 세로는 block // 
		if(this.side =="left"){ 
			this.innerDiv.style.display="inline";
			this.innerDiv2.style.display="inline";
		}else if(this.side =="right"){ 
			this.innerDiv.style.display="inline";
			this.innerDiv2.style.display="inline";
		}else if(this.side =="top"){ 
			this.innerDiv.style.display="block";
			this.innerDiv2.style.display="block";
		}else if(this.side =="bottom"){ 
			this.innerDiv.style.display="block";
			this.innerDiv2.style.display="block";
		}//end if
		//방향을 보고, innerDiv1 , 2 의 display 속성 변경해주기  끝
		
		
		//이벤트 등록하기, 배경 div에 마우스가 올라오면 멈춘다. 나가면 동작한다. 
		var obj = this;
		PANSY.addEvent(this.wrapperDiv,"onmouseover",function(){ //오버
			obj.stop();
		});
		
		PANSY.addEvent(this.wrapperDiv,"onmouseout",function(){ //아웃
			obj.play();
		});
		//이벤트 등록하기, 배경 div에 마우스가 올라오면 멈춘다. 나가면 동작한다.  끝
		
		//방향구분
		if(side =="left"){ //왼쪽으로.. left를 마이너스시키면됨.
			this.side_style = "left";
			this.side_offset = "offsetLeft";
			this.side_offset_length="offsetWidth";
			this.isPlus = -1;
		}else if(side =="right"){ // 왼쪽으로 프러스
			this.side_style = "left";
			this.side_offset = "offsetLeft";
			this.side_offset_length="offsetWidth";
			this.isPlus = 1;
		}else if(side =="top"){ //위로 마이너스
			this.side_style = "top";
			this.side_offset = "offsetTop";
			this.side_offset_length="offsetHeight";
			this.isPlus = -1;
		}else if(side =="bottom"){ //위로 프러스
			this.side_style = "top";
			this.side_offset = "offsetTop";
			this.side_offset_length="offsetHeight";
			this.isPlus = 1;
		}//end if
		
		//방향구분 끝
	
	}//end if
	
	
	///////// 필드
	this.movingSize=movingSize; //한번에 얼마나 옮길지..
	this.side=side; //어느쪽으로 이동할건지.
	this.firstDiv=this.innerDiv2;
	this.lastDiv=this.innerDiv;
	
	
	
	///////// 메소드
	this.setMovingSize=function(movingSize){ //설정한다.
		this.movingSize = movingSize;
	}//end method
	
	this.setSide=function(side){ //설정한다.
		this.side = side;
	}//end method
	
}//end class

PANSY.ROLLING.OneSideRolling.prototype =  new PANSY.ROLLING.RollingBase(); // 상속
PANSY.ROLLING.OneSideRolling.prototype.doRolling=function(){ //롤링 동작 처리...
	//현재 화면에 보이지 않을경우.. offsetWidth 같은 값들을 익스플로러가 제대로 계산하지 못한다 0 으로 처리하는듯.. 그래서 이상하게됨.. 해당값이 0인지 검사한다
	if(this.firstDiv[this.side_offset_length] <= 0){
		return;
	}//end if
	//현재 화면에 보이지 않을경우.. offsetWidth 같은 값들을 익스플로러가 제대로 계산하지 못한다 0 으로 처리하는듯.. 그래서 이상하게됨.. 해당값이 0인지 검사한다 끝
	
	
	var side_len = 0; //증가할 길이..
	var side_len2 = 0; //증가할 길이..
	
	

	side_len = this.innerDiv[this.side_offset]; // 기존값 구하기	
	side_len2 = this.innerDiv2[this.side_offset]; // 기존값 구하기	
	
	
	this.innerDiv.style[this.side_style] = (Number(side_len) + (this.movingSize * this.isPlus))+"px";// 증가해서 적용시키기
	this.innerDiv2.style[this.side_style] = (Number(side_len2) + (this.movingSize * this.isPlus))+"px";// 증가해서 적용시키기
	
	
	//현재, div의 끝이 보이게되면, 앞이나 위의 div를 뒤로 붙여줌. 
	
	//isPlus 가 마이너스인경우와 프러스인경우의 계산이 달라진다.
	if(this.isPlus==1){
		var wrapperRemain = this.lastDiv[this.side_offset] ;
	}else{
		var wrapperRemain = this.wrapperDiv[this.side_offset_length] -  (this.lastDiv[this.side_offset_length] + this.lastDiv[this.side_offset]) ;//뒤의 div 마지막 부분이 지나왔는지 아닌지 판단하기 이 값이 0이상이면 뒤로 넘겨줘야한다.  // 배경이 보이는지 안보이는지를 판단함. 
	}//end if
	
	if(wrapperRemain > 0 ){//0보다 크면, 배경이 보이는것임.. 앞의 div를 뒤로 옮겨야한다.
		if(this.firstDiv.style.visibility=="hidden"){ this.firstDiv.style.visibility="";}//앞의 div : 맨처음에는 this.innerDiv2 ,가 들어있는데, 이게 맨첨에는 안보이도록되어있음. 확인해보고 안보이면 보이도록 설정함.
		
		//앞 div의 left 나 top 을 뒤의거의 뒤로 정함.
		
		if(this.isPlus==1){
			this.firstDiv.style[this.side_style] = this.lastDiv[this.side_offset] - this.firstDiv[this.side_offset_length]+"px";
		}else{
			this.firstDiv.style[this.side_style] = this.lastDiv[this.side_offset] + this.lastDiv[this.side_offset_length]+"px";
		}//end if
		
		
		//앞 뒤 div 바꿔줌
		var tempDiv = this.lastDiv ;
		this.lastDiv = this.firstDiv;
		this.firstDiv = tempDiv;
		
	}//end if
	
}//end method




/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////





/*
	상품진열 전용 롤링 임 . 상품이나 하나의 정보단위로 이동이 가능함. 
	배경 div에 들어있는 div 한개씩을 하나의상품기준으로 생각함 . 
	반드시 상품 하나씩을 div로 감싸줘야함. 
	최소한 상품을 2개이상은 등록해야 바로 작동한다.
	인수:
		wrapperDiv : 배경 div - width ,height 설정되어있어야함.
		speed : 타이머호출되는 시간
		movingSize : 한번에 몇픽셀씩 움직일건지 speed 는 몇초에 한번 움직일건지 설정임..
		side : 어느 방향으로 롤링시킬지 . top/left/right/bottom 중의 하나다.
*/

PANSY.ROLLING.DigitalRolling = function(wrapperDiv,speed,movingSize,side){
	

	
	
	
	////////// 생성자 
	PANSY.ROLLING.RollingBase.call(this,wrapperDiv,speed); //상속처리..  부모 생성자호출한다고 생각하면 됨 . 이부분이없으면 단순 prototype 만으론.. 생성된 객체마다 고유한 메모리배당이안됨 
	
	
	
	//생성자부분 감싸주기
	if(wrapperDiv){
		
		//배경 div 안에있는 div 태그들을 inline 설정해준다.
		var elem = wrapperDiv.firstChild; //첫번째 자식부터 마지막자식까지 검사함.. 바로 밑에 있는 자식들만 검사함.
		var prevDiv = null;
		while(elem){

			if(elem.tagName=="DIV"){ //div 태그만
				
				elem.style.position="absolute";//
				elem.style.top="0px";//
				elem.style.left="0px";//
				elem.style.display="inline";//

				this.firstDiv = !(this.firstDiv)?elem:this.firstDiv; //첫번째 div 설정 .. 비어있을때만설정.
				this.lastDiv = elem;//마지막 div로 설정함.
	
				//이전과다음설정
				elem.nextDiv = null;
				elem.prevDiv = prevDiv;
				if(prevDiv) prevDiv.nextDiv = elem; 
				
				//자신을 저장해둠
				prevDiv = elem;
				
			}//end if
			elem = elem.nextSibling;
		}//end while
		//배경 div 안에있는 div 태그들을 inline 설정해준다. 끝
		
		
	
	
		
		
		//이벤트 등록하기, 배경 div에 마우스가 올라오면 멈춘다. 나가면 동작한다. 
		var obj = this;
		PANSY.addEvent(this.wrapperDiv,"onmouseover",function(){ //오버
			obj.stop();
		});
		
		PANSY.addEvent(this.wrapperDiv,"onmouseout",function(){ //아웃
			obj.play();
		});
		//이벤트 등록하기, 배경 div에 마우스가 올라오면 멈춘다. 나가면 동작한다.  끝
		
		this.side_style=""; // 선택한방향의 스타일이름이 들어감.. left 나 top
		this.side_offset=""; // 선택한방향의 offset이름이 들어간다 offsetLeft , offsetTop
		this.side_offset_length=""; // 선택한방향의 offset이름이 들어간다 offsetWidth , offsetHeight
		this.isPlus = 1; //플러스인지 마이너스인지가 들어감 1 / -1 

		
		//방향구분
		if(side =="left"){ //왼쪽으로.. left를 마이너스시키면됨.
			this.side_style = "left";
			this.side_offset = "offsetLeft";
			this.side_offset_length="offsetWidth";
			this.isPlus = -1;
		}else if(side =="right"){ // 왼쪽으로 프러스
			this.side_style = "left";
			this.side_offset = "offsetLeft";
			this.side_offset_length="offsetWidth";
			this.isPlus = 1;
		}else if(side =="top"){ //위로 마이너스
			this.side_style = "top";
			this.side_offset = "offsetTop";
			this.side_offset_length="offsetHeight";
			this.isPlus = -1;
		}else if(side =="bottom"){ //위로 프러스
			this.side_style = "top";
			this.side_offset = "offsetTop";
			this.side_offset_length="offsetHeight";
			this.isPlus = 1;
		}//end if
		
		//방향구분 끝
		
		//이동거리구할때 필요함, 바로 전에 호출되었을때의 시간을 가지고있음
//		var today = new Date();
//		this.oldTime =today.getTime(); 
		//이동거리구할때 필요함, 바로 전에 호출되었을때의 시간을 가지고있음 끝
		
		//맨처음 생성되었을대, 겹쳐있지않고 펼쳐져있기
		this.hasExeFollowFirstDiv = false; //정상적으로 자리계산을 한번한적있는지를 저장함, 트루면 한적있는걸로 간주하고, 다시 계산안하고, 조금 더 나은방법으로 함. 
		this.followFirstDiv();
		//맨처음 생성되었을대, 겹쳐있지않고 펼쳐져있기 끝
	}//end if
	
	
	///////// 필드
	this.movingSize=movingSize; //한번에 얼마나 옮길지..
	this.side=side; //어느쪽으로 이동할건지.

	
	
	
	
	
	
}//end class

PANSY.ROLLING.DigitalRolling.prototype =  new PANSY.ROLLING.RollingBase(); // 상속
PANSY.ROLLING.DigitalRolling.prototype.doRolling=function(){ //롤링 동작 처리...
	
	//현재 화면에 보이지 않을경우.. offsetWidth 같은 값들을 익스플로러가 제대로 계산하지 못한다 0 으로 처리하는듯.. 그래서 이상하게됨.. 해당값이 0인지 검사한다
	if(this.firstDiv[this.side_offset_length] <= 0){
		return;
	}//end if
	//현재 화면에 보이지 않을경우.. offsetWidth 같은 값들을 익스플로러가 제대로 계산하지 못한다 0 으로 처리하는듯.. 그래서 이상하게됨.. 해당값이 0인지 검사한다 끝
	

	//나머지 div 따라가기
	this.followFirstDiv();
	
	
	//firstDiv가 화면에서 완전히 사라지면, firstDiv를 맨끝으로 옮김.
	
	//isPlus 가 마이너스인경우와 프러스인경우의 계산이 달라진다.
	var firstDivRemain = 0; //firstDiv 가 배경에 실제 보이는 부분을 계산한다. 0이하면 완전히 안보이는거다.
	if(this.isPlus==1){
		firstDivRemain =( this.wrapperDiv[this.side_offset_length]+this.firstDiv[this.side_offset_length]) - (this.firstDiv[this.side_offset_length] + this.firstDiv[this.side_offset]) ; //  (배경길이+첫번재길이) - 첫번째 좌표+첫번째길이 
	}else{
		firstDivRemain =this.firstDiv[this.side_offset_length] + this.firstDiv[this.side_offset]; //첫번째Div좌표 + 첫번째Div길이
	}//end if

	if(firstDivRemain <= 0 ){// 0이하면 완전히 안보이는거다. 
		
		this.nextDiv();
		
	}//end if

}//end method

///////// 메소드
PANSY.ROLLING.DigitalRolling.prototype.setMovingSize=function(movingSize){ //설정한다.
	this.movingSize = movingSize;
}//end method

PANSY.ROLLING.DigitalRolling.prototype.setSide=function(side){ //설정한다.
	this.side = side;
}//end method


PANSY.ROLLING.DigitalRolling.prototype.prevDiv=function(){ //이전 Div로 바꿔준다.
	//라스트를 첫번째로 
	var tempDiv = this.firstDiv ;
	
	
	this.firstDiv = this.lastDiv; //첫번재 설정
	this.lastDiv = this.lastDiv.prevDiv;//마지막 Div 설정
	
	this.firstDiv.prevDiv = null;
	this.firstDiv.nextDiv =  tempDiv ;
	
	tempDiv.prevDiv =  this.firstDiv ;
	this.lastDiv.nextDiv = null;
	
	this.hasExeFollowFirstDiv=false;
}//end method
PANSY.ROLLING.DigitalRolling.prototype.nextDiv=function(){ //다음 Div로 바꿔준다.
	//첫번째를 라스트로옮김
	var tempDiv = this.firstDiv ;
	this.firstDiv = this.firstDiv.nextDiv; //첫번재 설정
	this.firstDiv.prevDiv = null;
	
	tempDiv.prevDiv=this.lastDiv;  //기존 마지막div 처리
	this.lastDiv.nextDiv = tempDiv;
	
	this.lastDiv = tempDiv; //마지막설정;
	this.lastDiv.nextDiv=null;
	
	this.hasExeFollowFirstDiv=false;
}//end method

PANSY.ROLLING.DigitalRolling.prototype.followFirstDiv=function(){ //첫번째 Div를 따라서 , 나머지의 좌표를 구해주는 부분.
	//첫번째 div를 따라서 이동하는데, 계속 이것을 반복할경우 , 속도가 좀 느려지는 것 같아.. 처음 자리계산할때, 한번만 실행을 하고 ,  그 뒤는 실행하지 않는다.
	
	//현재 화면에 보이지 않을경우.. offsetWidth 같은 값들을 익스플로러가 제대로 계산하지 못한다 0 으로 처리하는듯.. 그래서 이상하게됨.. 해당값이 0인지 검사한다
	if(this.firstDiv[this.side_offset_length] <= 0){
		return;
	}//end if
	//현재 화면에 보이지 않을경우.. offsetWidth 같은 값들을 익스플로러가 제대로 계산하지 못한다 0 으로 처리하는듯.. 그래서 이상하게됨.. 해당값이 0인지 검사한다 끝
	
	if(this.hasExeFollowFirstDiv == true){ //자리계산한적있는 경우 - 모든아이템 계산한 픽셀대로 이동해줌 ( 자기전에 div 따라가는게 아님..)
		var movePx = this.movingSize * this.isPlus;//몇픽셀 이동할지 계산함. 
		var elem = this.firstDiv;
		while(elem){
			elem.style[this.side_style] = (Number(elem[this.side_offset]) + movePx)+"px";// 증가해서 적용시키기
			
			elem = elem.nextDiv;
		}//end while
	}else{//자리계산한적없는 경우
		var elem = this.firstDiv.nextDiv;
		while(elem){
			elem.style[this.side_style] = Number(elem.prevDiv[this.side_offset] + (elem.prevDiv[this.side_offset_length] * ( this.isPlus * -1) ) ) +"px";// 증가해서 적용시키기
			
			elem = elem.nextDiv;
		}//end while
		
		this.hasExeFollowFirstDiv = true;
	}//end if
}//end method

PANSY.ROLLING.DigitalRolling.prototype.prev=function(){ //이전 상품으로 이동한다.
	
	this.stop();//동작을 멈춘다.
	this.prevDiv();//현재 lastDiv  를 firstDiv로 바꾼다.
	//현재 firstDiv가 처음에보이도록 이동한다.
	
	this.firstDiv.style[this.side_style] = 0+"px";//맨처음으로 설정함.
	this.followFirstDiv(); //뒤의 div들 자리잡기
	
}//end method

PANSY.ROLLING.DigitalRolling.prototype.next=function(){ //다음 상품으로 이동한다.
	
	
	
	this.stop();//동작을 멈춘다.
	this.nextDiv();//현재 firstDiv 를 다음으로 바꾼다.
	//현재 firstDiv가 처음에보이도록 이동한다.
	
	this.firstDiv.style[this.side_style] = 0+"px";//맨처음으로 설정함.
	this.followFirstDiv(); //뒤의 div들 자리잡기
	
}//end method

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////






//////////////////////////////////////////////////////////////////////////// 한상품별로 , 롤링시켜주는데, DigitalRolling 의 속도문제 개선과, 움직이다 멈췃다 움직이는 기능이 추가됨. DigitalRolling 과는 상관없는 별개의 기능으로 만들어짐
//wrapperDiv : 감싸고 있는 div   , width , height 값 설정되어있어야 함. 항상 같은크기로 고정되어있어야 하기때문에.. 
   // wrapperDiv 안에 div하나를 하나의 상품으로 간주한다.  상품 div 또한 마찬가지로 , width,height 를 가지고있어야함
//speed : 롤링될때, 속도.. 낮을수록 빠름..
// movingSize : 한번이동시에 몇픽셀 움직일건지를 나타냄
//side : 방향
//rollingDigitCount : 멈췄다가 움직일때 몇개의 상품을 이동시키고 다시 멈출건지..   -1 이 들어오면, 멈추지않고 계속돈다는 의미임.
//delay :  멈췄다가 얼마만에 다시 움직일건지.. speed 와 같은 방식임.  1000 이 1초

PANSY.ROLLING.DigitalRolling2 = function (wrapperDiv,speed,movingSize,side,rollingDigitCount,delay){
	///////// 필드
	this.wrapperDiv = wrapperDiv; //배경 div 저장
	this.innerDiv = null; //div 객체생성.. 이 div 가 내용을 가지고서 움직일 div 임.
	this.speed = speed; //속도
	this.timer = null; //타이머..
	this.rolling_timer = null; //롤링타이머..
	this.movingSize=movingSize; //한번에 얼마나 옮길지..
	this.side=side; //어느쪽으로 이동할건지.
	this.rollingDigitCount = rollingDigitCount;
	this.delay = delay;
	
	this.digitCount = 0;//현재 몇개상품넘겼는지 기록할 플래그변수
	
	this.isset_innderDiv_start_point = false; //이너 div 의 시작 좌표가 설정되었는지.. 정방향일때는 괜찮은데, 역방향일때 좌표를 계산해줘야함. 
	
	/////////생성자 일처리
	if(wrapperDiv){ //감싸주지않으면,  프로토타입상속할때 에러가남.. wraapperDiv 를 넘겨주지 않기때문에..
		
		//방향구분
		this.side_style=""; // 선택한방향의 스타일이름이 들어감.. left 나 top
		this.side_offset=""; // 선택한방향의 offset이름이 들어간다 offsetLeft , offsetTop
		this.side_offset_length=""; // 선택한방향의 offset이름이 들어간다 offsetWidth , offsetHeight
		this.isPlus = 1; //플러스인지 마이너스인지가 들어감 1 / -1 
		
		if(side =="left"){ //왼쪽으로.. left를 마이너스시키면됨.
			this.side_style = "left";
			this.side_offset = "offsetLeft";
			this.side_offset_length="offsetWidth";
			this.isPlus = -1;
		}else if(side =="right"){ // 왼쪽으로 프러스
			this.side_style = "left";
			this.side_offset = "offsetLeft";
			this.side_offset_length="offsetWidth";
			this.isPlus = 1;
		}else if(side =="top"){ //위로 마이너스
			this.side_style = "top";
			this.side_offset = "offsetTop";
			this.side_offset_length="offsetHeight";
			this.isPlus = -1;
		}else if(side =="bottom"){ //위로 프러스
			this.side_style = "top";
			this.side_offset = "offsetTop";
			this.side_offset_length="offsetHeight";
			this.isPlus = 1;
		}//end if
		
		//방향구분 끝
		
		
		wrapperDiv.style.overflow = "hidden"; // 오버플로 히든설정
		wrapperDiv.style.position = "relative"; // 포지션  설정..
		
		// 움직일 div 생성
		this.innerDiv =  $c("div");
		this.innerDiv.style.position="absolute";//포지션설정
		this.innerDiv.style.top="0px";//
		this.innerDiv.style.left="0px";//
		this.innerDiv.style.display="block";//
		this.innerDiv.style.whiteSpace="nowrap";//
		
		// 움직일 div 생성 끝
		
		//움직이는 div에 내용을 복사하고 ,  래퍼div에 등록해줌
		this.innerDiv.innerHTML = wrapperDiv.innerHTML; // div 내용을 옮김
		wrapperDiv.innerHTML = ""; // 래퍼div에 내용삭제하고
		wrapperDiv.appendChild(this.innerDiv);//새로 생성한 div를 자식으로 넣어줌.
		//움직이는 div에 내용을 복사하고 ,  래퍼div에 등록해줌 끝
		
		//상품 div 태그들을 inline 설정해준다.
		var elem = this.innerDiv.firstChild; //첫번째 자식부터 마지막자식까지 검사함.. 바로 밑에 있는 자식들만 검사함.
		var prevDiv = null;
		while(elem){

			if(elem.tagName=="DIV"){ //div 태그만
				
//				elem.style.whiteSpace="nowrap";//
				elem.style.top="0px";//
				elem.style.left="0px";//
				if(this.side_style == "left"){ //가로면
					elem.style.display= document.all?"inline":"inline-block";// ie 에서는 inline 으로해야하고, 크롬에서는 inline-block 으로해야한다. 
				}else{//세로면
					elem.style.display="block";//
				}//end if 

				this.firstDiv = !(this.firstDiv)?elem:this.firstDiv; //첫번째 div 설정 .. 비어있을때만설정.
				this.lastDiv = elem;//마지막 div로 설정함.
	
				//이전과다음설정
				elem.nextDiv = null;
				elem.prevDiv = prevDiv;
				if(prevDiv) prevDiv.nextDiv = elem; 
				
				//자신을 저장해둠
				prevDiv = elem;
				
			}//end if
			elem = elem.nextSibling;
		}//end while
		//상품 div 태그들을 inline 설정해준다. 끝
		

		
		
		//이벤트 등록하기, 배경 div에 마우스가 올라오면 멈춘다. 나가면 동작한다. 
		var obj = this;
		PANSY.addEvent(this.wrapperDiv,"onmouseover",function(){ //오버
			obj.stop();
		});
		
		PANSY.addEvent(this.wrapperDiv,"onmouseout",function(){ //아웃
			obj.play();
		});
		//이벤트 등록하기, 배경 div에 마우스가 올라오면 멈춘다. 나가면 동작한다.  끝
		
		

		
		
		
	}//end if
	
}//end class 

PANSY.ROLLING.DigitalRolling2.prototype.play=function(){ //타이머 시작시켜줌.. 동작을 실행한다
	
	//타이머 동작중이면나간다.
	if(this.timer) return;
	
	var obj = this;
	this.timer = setTimeout( function(){
		obj.rolling_play(); //정해진시간뒤에 한번 실행.
	}, this.delay);

}//end method

PANSY.ROLLING.DigitalRolling2.prototype.stop=function(){ //타이머 멈춤.. 동작을 멈춘다
	clearTimeout(this.timer); //타이머멈춤
	this.timer = null; //다시 널 입력해줌.
	this.rolling_stop();//롤링타이머도 멈춰줌
}//end method<br>

PANSY.ROLLING.DigitalRolling2.prototype.rolling_play=function(){ //타이머 시작시켜줌.. 동작을 실행한다
	
	//타이머 동작중이면나간다.
	if(this.rolling_timer) return;
	
	var obj = this;
	this.rolling_timer = setInterval( function(){
		obj.doRolling();
	}, this.speed);

}//end method

PANSY.ROLLING.DigitalRolling2.prototype.rolling_stop=function(){ //타이머 멈춤.. 동작을 멈춘다
	clearInterval(this.rolling_timer); //타이머멈춤
	this.rolling_timer = null; //다시 널 입력해줌.
}//end method<br>


PANSY.ROLLING.DigitalRolling2.prototype.doRolling=function(){  // 몇개상품지나는지.. 카운트 하다가 정해진 숫자가가 다 지나가게되면 
	//div가 하나도 등록되지않은경우 (상품없는경우) 동작하지않고 나간다
	if(! this.firstDiv){
		return; 
	}//end if 
	//div가 하나도 등록되지않은경우 (상품없는경우) 동작하지않고 나간다 끝

	
	//현재 화면에 보이지 않을경우.. offsetWidth 같은 값들을 익스플로러가 제대로 계산하지 못한다 0 으로 처리하는듯.. 그래서 이상하게됨.. 해당값이 0인지 검사한다
	if(this.firstDiv[this.side_offset_length] <= 0){
		return;
	}//end if
	//현재 화면에 보이지 않을경우.. offsetWidth 같은 값들을 익스플로러가 제대로 계산하지 못한다 0 으로 처리하는듯.. 그래서 이상하게됨.. 해당값이 0인지 검사한다 끝
	
	//역방향인 경우 첫 좌표값 설정해주기
	if(this.isset_innderDiv_start_point == false && this.isPlus == 1){//역방향
		this.innerDiv.style[this.side_style] = (this.wrapperDiv[this.side_offset_length] - this.innerDiv[this.side_offset_length] )+"px";// 배경길이 - 실제안쪽길이
		this.isset_innderDiv_start_point = true;
	}else if(this.isset_innderDiv_start_point == false && this.isPlus == 0){ //정방향
		this.isset_innderDiv_start_point = true;
	}//end if
	//역방향인 경우 첫 좌표값 설정해주기 끝
	
	
	//innerDiv 이동시킴
	var side_len = 0; //증가할 길이..
	side_len = this.innerDiv[this.side_offset]; // 기존값 구하기	
	this.innerDiv.style[this.side_style] = (Number(side_len) + (this.movingSize * this.isPlus))+"px";// 증가해서 적용시키기
	//innerDiv 이동시킴 끝

	//isPlus 가 마이너스인경우와 프러스인경우의 계산이 달라진다.
	var firstDivRemain = 0; //firstDiv 가 배경에 실제 보이는 부분을 계산한다. 0이하면 완전히 안보이는거다.
	if(this.isPlus==1){
//		firstDivRemain =( this.wrapperDiv[this.side_offset_length]+this.firstDiv[this.side_offset_length]) - (this.firstDiv[this.side_offset_length] + this.firstDiv[this.side_offset]) ; //  (배경길이+첫번재길이) - 첫번째 좌표+첫번째길이 
		firstDivRemain = this.lastDiv[this.side_offset_length] - ( this.innerDiv[this.side_offset_length] - this.wrapperDiv[this.side_offset_length]  + this.innerDiv[this.side_offset]) ; // 마지막상품길이 - ( 실제안쪽전체길이 - 배경길이 + 실제안쪽길이 시작좌표)
//		alert(this.lastDiv[this.side_offset_length] + " / " + this.innerDiv[this.side_offset_length]+ " / " +  this.wrapperDiv[this.side_offset_length] + " / " + this.innerDiv[this.side_offset]);
	}else{
		firstDivRemain =this.firstDiv[this.side_offset_length] + this.innerDiv[this.side_offset]; //innerDiv좌표 + 첫번째Div길이
	}//end if

	//첫번째 상품이 완전히 사라졌을때 처리
	if(firstDivRemain <= 0 ){// 0이하면 완전히 안보이는거다. 
//		alert(firstDivRemain);
		//방향에따라서, 넥스트나 프리브
		if(this.isPlus==1){ //역방향
			this.prev(); //
		}else{//정방향
			this.next(); //
		}//end if
		//방향에따라서, 넥스트나 프리브 끝
		
		this.rolling_play();//넥스트나 프리브는 작동을 멈추게끔되어있음. 다시 작동시켜줌.
		
		// 정해진 숫자 넘겼는지 검사해서 멈출지 판단
		this.digitCount++; //넘어간 상품수 1증가
//		alert(this.rollingDigitCount + " / " +this.rollingDigitCount + " / " + this.digitCount);
		if(this.rollingDigitCount >= 0 && this.rollingDigitCount <= this.digitCount){ // 기준 카운트가 0이상이고.. (-1이오면 안멈추고계속함) , 현재넘어간수가 기준카운트 이상이면 멈춤
			this.rolling_stop(); //롤링멈춤
			this.digitCount = 0; //초기화
			
			this.timer = null;
			this.play(); //정해진 시간뒤에 다시 호출
		}//end if
		// 정해진 숫자 넘겼는지 검사해서 멈출지 판단 끝
		
	}//end if
	//첫번째 상품이 완전히 사라졌을때 처리
}//end method

PANSY.ROLLING.DigitalRolling2.prototype.prevDiv=function(){ //이전 Div로 바꿔준다.
	//div가 하나도없거나 하나 등록된경우..
	if((! this.lastDiv) || (! this.lastDiv.prevDiv)){
		return; 
	}//end if 
	//div가 하나도없거나 하나 등록된경우..끝
	
	//라스트를 첫번째로 
	var tempDiv = this.firstDiv ;
	this.firstDiv = this.lastDiv; //첫번재 설정
	this.lastDiv = this.lastDiv.prevDiv;//마지막 Div 설정
	
	this.firstDiv.prevDiv = null;
	this.firstDiv.nextDiv =  tempDiv ;
	
	tempDiv.prevDiv =  this.firstDiv ;
	this.lastDiv.nextDiv = null;
	
}//end method

PANSY.ROLLING.DigitalRolling2.prototype.nextDiv=function(){ //다음 Div로 바꿔준다.
	//div가 하나도없거나 하나 등록된경우..
	if((! this.firstDiv) || (! this.firstDiv.nextDiv)){
		return; 
	}//end if 
	//div가 하나도없거나 하나 등록된경우..끝
	
	//첫번째를 라스트로옮김
	var tempDiv = this.firstDiv ;
	this.firstDiv = this.firstDiv.nextDiv; //첫번재 설정
	this.firstDiv.prevDiv = null;
	
	tempDiv.prevDiv=this.lastDiv;  //기존 마지막div 처리
	this.lastDiv.nextDiv = tempDiv;
	
	this.lastDiv = tempDiv; //마지막설정;
	this.lastDiv.nextDiv=null;
}//end method


PANSY.ROLLING.DigitalRolling2.prototype.prev=function(){ //이전 상품으로 이동한다.
	
	this.stop();//동작을 멈춘다.
	
	this.innerDiv.insertBefore(this.lastDiv,this.firstDiv); //첫번째 상품 맨 끝으로 옮기기
	this.prevDiv();  // firstdiv 다음아이템으로 넘겨주기
	
	//방향에따라 좌표정해짐
	if(this.isPlus==1){ //역방향
		this.innerDiv.style[this.side_style] = (this.wrapperDiv[this.side_offset_length] - this.innerDiv[this.side_offset_length] )+"px";// 배경길이 - 실제안쪽길이
	}else{ //정방향
		this.innerDiv.style[this.side_style] = "0px";//innerDiv 다시 처음으로 위치이동	
	}//end if
	//방향에따라 좌표정해짐 끝
	
	
}//end method

PANSY.ROLLING.DigitalRolling2.prototype.next=function(){ //다음 상품으로 이동한다.
	
	this.stop();//동작을 멈춘다.
	
	this.innerDiv.appendChild(this.firstDiv); //첫번째 상품 맨 끝으로 옮기기
	this.nextDiv();  // firstdiv 다음아이템으로 넘겨주기
	
	//방향에따라 좌표정해짐
	if(this.isPlus==1){ //역방향
		this.innerDiv.style[this.side_style] = (this.wrapperDiv[this.side_offset_length] - this.innerDiv[this.side_offset_length] )+"px";// 배경길이 - 실제안쪽길이
	}else{ //정방향
		this.innerDiv.style[this.side_style] = "0px";//innerDiv 다시 처음으로 위치이동	
	}//end if
	//방향에따라 좌표정해짐 끝
	
}//end method

//////////////////////////////////////////////////////////////////////////// 한상품별로 , 롤링시켜주는데, DigitalRolling 의 속도문제 개선과, 움직이다 멈췃다 움직이는 기능이 추가됨. DigitalRolling 과는 상관없는 별개의 기능으로 만들어짐 끝




//////////////////////////////////////////////////////////////////////////////////////////////////////////// 롤링 관련 끝














///////////////////////////////////////////////////////////////////////////////////////////////// 동적 데이타 관리 
PANSY.Field  = function(name,value,isForm){ // 하나의 데이터에서 한가지 정보를 담고있을 객체..  디비로 치면 필드에 해당..
	// name : 필드 이름.
	// value : 필드 값, 
	// isForm  : 폼전송용 필드인지.. true 값이오면.. 폼전송용 필드임. 값을 안주거나 널이면 아님..
	
	
	this.name = name;
	this.value = value;
	this.hidden = null; //폼전송용 필드인경우.. 자신과 연결된 히든객체를 가지고 있는다.
	this.arrRelationObj  = new Object() ;  //연관배열로 사용하기 위함. 이 필드와 관련있는 객체들을등록해두고 , 필요할때 호출해서 쓴다, 주로 업데이트 펑션에서 씀.
	
	if(isForm == true){
		this.isForm = true;
	}else{
		this.isForm = false;
	}//end if
	
	this.getFormName = function(){ //폼전송 필드인 경우, 폼전송시 사용할 이름을 반환한다. 
			return "hdn"+name; // 앞에 hdn 붙여서 반환해준다.
	}//end func
	
	this.updateFunction = function(){}; //업데이트 함수.. 이 필드의 값이 변동될때, 같이 실행될 메소드.. 등록된 함수가 있으면 실행해준다.
	
	
	this.setValue=function(value){ //말그대로 값을 설정하는데,, 히든객체가 연결된경우.. 히든객체의 값도 같이 변경해준다.
		this.value= value;
		
		if(this.isForm == true && this.hidden != null){// 폼전송필드이고, 히든객체가 있는경우
		
			this.hidden.value = value;
		}//end if
		
		//폼전송값과 상관없이 디스플레이 적으로나.. 기타, 업뎃이 일어날때 다른처리를 해줘야하는 경우.
		//함수를 등록하고 그 함수를 실행시켜준다.
		//실제 사용할때는 이 함수를 재정의 해서 사용한다.
		this.updateFunction();
		
	}//end func
	
	this.addRelationObj=function(key, obj){ // 관계객체를 추가한다.
		this.arrRelationObj[key] = obj;
	}//end func
	
	this.getRelationObj=function(key){ //관계객체를 꺼내온다.
		return this.arrRelationObj[key]; //등록안되있으면 널이 나가겠지
	}//end func
	
}//end Object PANSY.Data

/**
PANSY.DataObject  : 
PANSY.DynamicDataObject   에서 사용하는 데이터 객체..

add , remove, get 메소드를 제공한다.
getFormDatas  : 폼데이터만 배열에담아 반환해준다.
*/
PANSY.DataObject = function(){ //생성자
	
	this.fields = new Array(); //배열.. 필드 객체들을 담고있을 배열이다, 필드객체의 name 값을 키값으로 갖고있는다. 1 차원배열.
	this.key = 0; //키값.. 배열내 키값과 동일하게 사용함.
	
	this.add = function(name,value,isForm){ // this.fields 에 필드 객체를 추가해준다.
		var field = new PANSY.Field(name,value,isForm); //데이타 객체 생성
		this.fields[name] = field; // 배열에 추가 - 아마이건.. 그냥 어레이객체 자체에 프로퍼티로 추가되는것같음
		this.fields[this.fields.length] = field; // 배열에 추가 - 이렇게해야 배열로 추가됨.. 
	}//end func
	
	this.remove= function(name){ //name 값으로 배열에서 삭제한다.
		var field = this.fields[name]; //데이타객체.
		
		for(var i = 0; i<this.fields.length;i++){ //모든 배열을 돌며 일일히 같은 객체인지 비교함.
			if(field == this.fields[i]){ //같은객체면.
				this.fields.splice(i,1); //배열에서 삭제
			}//end if	
		}//end for i
		
		this.fields[name] = null;// 네임값으로 된 프로퍼티삭제
	}//end func
	
	this.getField=function(name){ //name값으로 배열에서 필드객체를 반환해준다.
		var field = this.fields[name]; //데이타객체.
		if(field){ //데이타객체가 있으면..
			return field;
		}else{
			return null; //없으면 그냥 널 반환
		}//end if
	}//end func
	
	this.getValue=function(name){ // name 값으로 배열에서 값을 얻어다 준다.
		var field = this.fields[name]; //데이타객체.
		if(field){ //데이타객체가 있으면..
			return field.value;
		}else{
			return ""; //없으면 그냥 공백 반환.
		}//end if
		
	}//end func
	
	this.setValue=function(name,value){ //name, 값과 value 값으로 해당 필드를 저장한다.
		var field = this.fields[name]; //데이타객체.
		if(field){ //데이타객체가 있으면..
			field.setValue(value); //저장
		}else{
			
		}//end if
	}//end func
	
	this.addUpdateFunction=function(name, updateFunc){ //name 값에 해당하는 필드에, 업데이트함수를 추가해준다.
		var field = this.fields[name]; //데이타객체.
		if(field){ //데이타객체가 있으면..
			field.updateFunction = updateFunc; //저장
		}else{
			
		}//end if
		
	}//end func
	
	this.addRelationObject=function(name,strObjectKey,obj){ //해당 필드에, 관련되어있는.. 필드 자체에서 나중에 호출할 수 있는 객체들을 등록해둔다, 주로 위의 업데이트펑션에서 호출하기 위한 용도.
		//name : 필드네임 , strObjectKey: 해당필드에, 객체를 등록할 키값, obj : 등록할 객체
		var field = this.fields[name]; //데이타객체.
		if(field){ //데이타객체가 있으면..
			field.addRelationObj(strObjectKey,obj); //관계객체 저장.
		}else{
			
		}//end if
	}//end func
	
	this.getFormFields=function(){ // 배열에 등록된 데이터 객체중에 폼전송용 데이터만 따로 배열에 담아 돌려준다.
		var arrFormFields = new Array(); // 폼데이터담을 배열.
		
		for(var i = 0; i<this.fields.length;i++){ //모든 배열을 돌며 일일히  폼데이터인지 비교함.
			var field = this.fields[i];
			if(field.isForm){ //폼데이터이면..
				arrFormFields[arrFormFields.length]=field; //배열에 담음
			}//end if	
		}//end for i
		
		return arrFormFields;
	}//end func
	
	this.cloneObj = function(){ //객체의 클론을 새로 만들어서 돌려준다.
		var clone = new this.constructor();
		
		//필드 복사
		for (var i = 0; i < this.fields.length; i++){
			var field = this.fields[i];
			
			clone.add(field.name,field.value,field.isForm); 	//추가
		}//end for i
		
		return clone;
	}//end func
	
	
}// end Object PANSY.DataObject 









/**
PANSY.DynamicDataObject 
동적데이타객체...
하는일 및 특징: 웹 페이지에서 동적으로 데이터를 관리해준다. 단순히, 데이타 관리뿐 아니라, DB처리를 위한, 폼전송용 데이터를 작성해준다. 
                     추가 수정 및 삭제가 동적으로 이루어지며.. 해당 데이터 마다, 어떤 디비처리를 해줘야하는 지 등.. DB처리에 필요한 데이터가 같이 폼전송된다.
                     데이터 관리부분과, 표현해주는 디스플레이부분을 분리시키고, 어떤 모습으로 디스플레이 되던간에.. 폼전송되는 값은 동일하게 유지된다.
                     데이터의 값은 이 객체에서제공 되는 insert , update, delete 메소드만을 통해서 가능하며 ,
                     디스플레이 되는 부분에 Input 개체에 사용자가 어떤 값을 설정했다 하더라도.. update , insert 메소드를 호출하여 처리하지 않은 데이터는
                     최종적인 폼전송에 적용되지 않는다.
                     
                     데이터는 크게 두부분으로 나뉘게 된다.
                     1.폼전송에 쓰이는 데이터.. 중요한 값이다.. 
                     2. 폼전송에는 쓰이지 않지만, 디스플레이나, 데이터 관리를 위해 쓰이는 데이터..
                     내부적으로 이 객체의 전역변수 datas 에는 데이타 배열이 들어있게 되고,
                     
                     
                     이객체는 처음 생성시에, 해당 폼을 받아와서, 해당 폼개체 밑에 폼전송 데이터를 등록해둔다. 보이지 않는 div로 묶어서..
                     
                     한 페이지내에서 이 객체를 여러개 쓸 수 도 있때문에, 객체의 id값을 설정해줄 수 있다. id 값이 설정될 경우 모든 폼전송데이터의 name 맨 앞에 객체의 id 값이 붙게된다.
                     ex) DynamicDataObject.id 가 "123" 인경우.. 폼전송되는 데이터 hdnABC 의 이름은 최종적으로.. 123hdnABC 가 된다.
                     이 객체의 id 값은.. 폼전송값을 처리하는 서버측에서도 알필요가 있으므로 , 여러객체가 동일한 이름으로 전송된다. 
                     hdnDynamicDataObjectId[]  이렇게 이름을 작성해서 객체의 id 값들을 전송하게 되고, php측에서는 저것을배열로 처리하여, 이 객체의 개수와, 각각의 id 값을 알 수 있다.
                     
                     객체안에서의 데이터 키값은. 각 데이터마다 객체아이디|hdnDynamicDataKey[] 의 이름으로 배열로 작성되고 안에는 키값이 들어가게된다.
                     
                     폼전송데이터의 이름 규칙 : "객체id" + "폼전송데이터 name" + "객체 내에서 발급된 키값(순번)" : 각 값들의 구분으로 구분자 "|" 를 붙여준다.
                     
                     폼전송값의 이름은 자동적으로 hdn 이 붙으며, 객체내 키값은.. 객체가 가지고있는..arrDatas.length 가된다. (배열의 키값과 동일)
                     
                     객체에서 어느때에나 쓰이는 기본 필드 : 
                     		CmdType : insert, update, delete 중 하나의 값이 들어간다. 폼전송용.  (dontExecute 값도 들어갈 수 있는데, 디비처리할 필요없는 고어데이터라는 뜻 )
                     		IncValue : 디비처리할때 쓰일.. 해당데이터를 구별할 수 있는 유일키값..
                     		
                     	
                     		
                     
                     사용자가 설정하는 데이터 : 객체를 생성할때, PANSY.DataObject 객체를 생성해서, 각 데이터의 name과 폼전송여부를 설정해서 객체에 넘겨주게 되면, 객체는 그것으로, 데이터를 insert, update 처리 하게 된다.
                     
                     
                     
                     디스플레이 처리는.. 이객체를 생성할대, 생성자에. 디스플레이객체를 하나넘겨주게되고,
                     그 디스플레이 객체는 insertDisplay, updateDisplay, deleteDisplay 라는 이름의 메소드를 구현하고 있어야한다.
                     이 객체는 자신의 처리가 끝난뒤 자동적으로 디스플레이 메소드를 호출하게 되고, 각 디스플레이 객체에서 구현된 방법대로.. 디스플레이 시키게 된다.
                     
-------------------------------------------------------------------------------------------------------------------------------------------
사용법 : 1. 샘플 데이터를 작성한다 . 
					2. 디스플레이 객체 , 인서트 업데이트 삭제 등.. 메소드 재정의
					3. 디스플레이  객체 생성..
					4. DDO 객체 생성한다. 
           
*/
PANSY.DynamicDataObject = function(strId,objForm,objDataSample,objDisplay){ //생성자
	//strId : 이 객체의 아이디값.. 이 객체를여러개 사용할경우 서로 겹치면 안된다.
	//objForm : 폼객체.. 이객체의 폼전송 데이터들이 등록될 폼이다.
	//objDataSample : 데이터 이름 및.. 개수 등을 결정짓기 위해서.. 생성할때 넘겨받는.. 데이터 견본..PANSY.DataObject 객체임. 샘플데이터를 통해서, 필드 업뎃시에 자동실행함수를 인서트할때, 해당 필드에 등록해준다.
	//objDisplay : 디스플레이 객체 , insertDisplay, updateDisplay, deleteDisplay 라는 이름의 메소드를 구현하고 있어야한다.
	
	//전역변수 설정하기
	this.strId = strId; //이 객체의 아이디값..
	this.objForm = objForm; //폼전송이이루어질 폼객체
	this.objDataSample = objDataSample; //
	this.arrDatas = new Array(); //갖고있는 데이터 배열.. PANSY.DataObject 객체들의 배열이다. 
	this.objDisplay = objDisplay;
	
	//디스플레이객체에 이 객체를연결시켜줌
	objDisplay.objDDO = this;
	
	//폼객체에 폼데이터가 등록될 div 하나 등록함. 눈에 안보이는걸로
	var hiddenDiv = $c("div"); //div 한개 생성
	hiddenDiv.style.display="none"; //안보임..
	objForm.appendChild(hiddenDiv); //폼에 자식으로 추가함.
	
	this.hiddenDiv = hiddenDiv; //전역변수로 등록해둠. 쓰기 편하게.
	//폼객체에 폼데이터가 등록될 div 하나 등록함. 눈에 안보이는걸로 끝

	if(objDataSample.constructor != PANSY.DataObject ){ //PANSY.DynamicDataObject  객체인지 확인하는 작업 아니면 경고창
		alert("javascript : 동적객체 생성도중 문제가 발생했습니다. objDataSample이 PANSY.DynamicDataObject 객체가 아닙니다.");
	}//end if
	
	
	
	//hdnDynamicDataObjectId 설정하기
	var hdnDynamicDataObjectId = PANSY.createInputHidden("hdnDynamicDataObjectId[]",strId);
	hiddenDiv.appendChild(hdnDynamicDataObjectId);
	//hdnDynamicDataObjectId 설정하기 끝
}//end constructor PANSY.DynamicDataObject

PANSY.createInputHidden = function(name,value){ //히든객체를 하나 생성해서돌려준다.
	var  elem = $c("input");
	elem.type = "hidden";
	elem.name = name;
	elem.value = value;
	elem.id = name;
	return elem;
}//end func

PANSY.DynamicDataObject.prototype.insertData = function(strCmdType,strIncValue,objData){ //데이타를 추가한다.
	//objData  :  추가할 데이터 객체..
	//strCmdType : insert 나 update 중 하나를 입력한다. 디비처리 단계를 뜻한다. 아예 새로 등록될 데이터면 인서트를. 기존 등록되어있던 데이터면 업데이트를..
	//strIncValue : 디비처리과정에서 사용될.. 유일키값이다. 인서트시에는 없으므로, 공백이나 0이나.. 아무거나 입력해줘도 크게 상관없다.
	
	//데이터를 추가하고, 자신이 연결된 폼객체에 폼전송데이터를 히든객체로 추가시킨다.
	
	//객체복사 - 인자전달시에 같은 객체에 값만 바꿔 보낼경우를 대비해서.. 완전히 새로운 메모리로 생성한다.
	objData = objData.cloneObj();
	
	//주어진 데이터 객체에.. 기본 필드들을 추가한다.
	objData.add("CmdType",strCmdType,true); //디비처리 코드..
	objData.add("IncValue",strIncValue,true); //디비 유일키값
	
	
	//키값 설정
	objData.key = this.arrDatas.length;
	
	//데이터객체를 현재 객체의 배열에 추가.
	this.arrDatas[this.arrDatas.length] = objData;
	
	
	
	//폼에 폼전송 값들 히든객체로 등록.
	var objFormFields = objData.getFormFields(); //폼 전송 필드들만으로 된 데이터객체 얻어오기.
	for(var i =0; i<objFormFields.length;i++ ){
		var objField = objFormFields[i] ; //필드 하나..
		
		var strHdnName = this.strId+"|"+objField.getFormName()+"|"+objData.key; //히든객체 이름 짓기 히든객체 이름 앞에, 현재객체의 id값 붙여주기, 객체 내부 사용 키값 붙여주기.
		var hdn = PANSY.createInputHidden(strHdnName,objField.value);//히든객체 생성 , 
		
		this.hiddenDiv.appendChild(hdn);//폼에 추가 
		objField.hidden = hdn;//필드객체에 히든객체 추가
		
	}//end for i
	
	/// 데이터 키값배열 히든값에 저장하기
	var strHdnName2 = this.strId+"|"+"hdnDynamicDataKey[]";
	var hdn2 = PANSY.createInputHidden(strHdnName2,objData.key);//히든객체 생성 , 
	this.hiddenDiv.appendChild(hdn2);//폼에 추가 
	/// 데이터 키값배열 히든값에 저장하기 끝
		
		
	
	//전체 필드에.. 업뎃펑션 달아주기
	for(var i =0; i<objData.fields.length;i++ ){
		var objField = objData.fields[i]; //필드 하나
		
		if(this.objDataSample.getField(objField.name) != null ){ //샘플에 설정된 필드가 있는지 검사하고 있으면 함수복사해줌
			objField.updateFunction = this.objDataSample.getField(objField.name).updateFunction; //업뎃함수 추가 //이부분에서 에러남 이거 잡아야함.f
		}//end if
		
	}//end for i
	
	
	//디스플레이 실행
	this.objDisplay.insertDisplay(this,objData);// 데이타를 넘겨준다. 현재 이 객체도 같이넘겨줌
	
}//end method


PANSY.DynamicDataObject.prototype.updateData = function(key,name,value){ //데이터 정보를 동적으로 업데이트 시킨다.
	//key : 데이터 키값.. 
	//name : 업뎃할 데이터 이름..
	//value : 업뎃할 값..
	
	var objData = this.arrDatas[key];//업뎃할 데이터객체 가져오기
	
	objData.setValue(name,value);//	 업뎃..
	
	
	
	//디스플레이 실행
	this.objDisplay.updateDisplay(this,objData);// 데이타를 넘겨준다.
	
}//end method

PANSY.DynamicDataObject.prototype.deleteData = function(key){ //데이터 정보를 동적으로 삭제한다. //delete 가 예약어인지.. 싶어서 뒤에 Data 붙여줌.
	//key : 데이터 키값.. 
	
	//삭제에 두가지 방법이있다.
	// 동적으로 생성되어서 디비처리할 필요가없는 데이터인경우..  CmdType만 dontExecute 로 설정해주고.. 
	// 디비에서 삭제처리가 필요한 데이터인경우..  CmdType 을 delete 로 처리해준다.
	
	var objData = this.arrDatas[key];//삭제할 데이터객체 가져오기
	

	// insert 인지, update 인지 구분..
	if(objData.getValue("CmdType") == "insert" ){ //인서트
		objData.setValue("CmdType","dontExecute");//	 디비처리 필요없음
	}else if(objData.getValue("CmdType") == "update" ){ //업데이트
		objData.setValue("CmdType","delete");//	 삭제
	}//end if
	
	
	//디스플레이 실행
	this.objDisplay.deleteDisplay(this,objData);// 데이타를 넘겨준다. , 현재 이 객체도 같이넘김.
	
}//end method

/*
	테이블형태로 표시해주는 디스플레이임..
	사용자는 이곳에 선언된  insertDisplay() , updateDisplay(), deleteDisplay() 이 함수들을 사용하는곳에서 재 선언하여, 각 특성에 맞게 사용하면 됨.
*/
PANSY.DisplayTable=function(table){ //생성자
	//tbl : 디스플레이 시킬 테이블 객체..
	
	this.table = table; //테이블객체
	this.objDDO = null ;//연결된 DynamicDataObject 객체.. 초기 생성시엔 널값이고.. 나중에 연결될때 이안에 객체가들어가게됨.
	
}//end constructor PANSY.DisplayTable

PANSY.DisplayTable.prototype.insertDisplay=function(objDDO,objData){ // 추가될때 실행되는 메소드..

}//end method

PANSY.DisplayTable.prototype.updateDisplay=function(objDDO,objData){ // 수정될때 실행되는 메소드..

}//end method

PANSY.DisplayTable.prototype.deleteDisplay=function(objDDO,objData){ // 삭제될때 실행되는 메소드..

}//end method




/*
	Div 형태로  표시해주는 디스플레이임..
	사용자는 이곳에 선언된  insertDisplay() , updateDisplay(), deleteDisplay() 이 함수들을 사용하는곳에서 재 선언하여, 각 특성에 맞게 사용하면 됨.
*/
PANSY.DisplayDiv=function(div){ //생성자
	//tbl : 디스플레이 시킬 테이블 객체..
	
	this.div = div; //div객체
	this.objDDO = null ;//연결된 DynamicDataObject 객체.. 초기 생성시엔 널값이고.. 나중에 연결될때 이안에 객체가들어가게됨.
	
}//end constructor PANSY.DisplayTable

PANSY.DisplayDiv.prototype.insertDisplay=function(objDDO,objData){ // 추가될때 실행되는 메소드..

}//end method

PANSY.DisplayDiv.prototype.updateDisplay=function(objDDO,objData){ // 수정될때 실행되는 메소드..

}//end method

PANSY.DisplayDiv.prototype.deleteDisplay=function(objDDO,objData){ // 삭제될때 실행되는 메소드..

}//end method

///////////////////////////////////////////////////////////////////////////////////////////////// 동적 데이타 관리  끝










///// 폼 검증모듈 관련 함수들.. 




/*
	폼검증모듈 전체적인 사용법
	1. 폼검증모듈 작동시킬 폼을 사용설정한다. 
	    PANSY.VAILD.setFormVaildModule(Form);
	2. 폼안에 있는 input, select textarea 등의 엘리먼트에.. 검증식을 추가함.
	    검증식은 2가지가 있는데, 하나는 하나의 함수로 작성한다음 등록하는 방법 ( 함수는 검증성공 : 트루, 검증실패 : 펄스 를 리턴해줘야함)
	    나머지 하나는 비교구문이다. 보통 if 문안에 쓰이는 비교구문을 작성해서 그것만 등록할 수 있다. 이것도.. 검증성공을 트루, 검증실패를 펄스를 반환하도록 작성하면 된다.
	    * 두가지 방법모두 엘리먼트를 this 인자로 사용할 수 있다.
	    
	    검증함수 등록 법 : 
	    PANSY.VAILD.setVaildFunc(input,function(){
	    		검증함수 내용... 결과는 트루 펄스를 리턴해야함. 
	    });
	    검증구문 등록 법 : 
	    PANSY.VAILD.setVaildStruct(input,"this.value.length > 0","값을 입력해주십시오.");  등록할 엘리먼트, 검증비교구문 , 검증실패시 출력할 엘리먼트이다.  만약, 검증실패햇을경우 해당엘리먼트가 focus 함수가 있는 엘리먼트라면 실행해준다.
	    
	    
	3. 몇가지 자주쓰이는 검증상황들을 미리선언해놓고 자동으로 등록할 수도 있다.
	    PANSY.VAILD.setAutoVaild(input,상수값); //상수값들은..  |  로 이어서 준다. 
	    
	    자동검증 등록법:
	    PANSY.VAILD.setAutoVaild(input,PANSY.VAILD.IS_EMPTY+PANSY.VAILD.IS_BLANK);
	    
	 4. 에러메세지를 띄울때, 어떤 엘리먼트인지 알려주기 위해서 엘리먼트 이름을 설정해두고 사용할 수 있다.
	    PANSY.VAILD.setNameE(input,"주민등록번호"); 
	    검증함수나.. 검증 구문 같은곳에서 this.elemName 으로 설정된 이름을 가져다 쓸 수 있다.
	    
	 5. 엘리먼트 이름이 설정되어있지 않은경우.. title 프로퍼티가 설정되어있다면 그것을 이름으로 인식하고.. 그값을 이름으로 대신 사용한다.
	
*/


/*
	자동검증 검증추가 방법 : 
	밑의 상수를 추가하고.  ( 상수번호는.. 2의 제곱으로 증가하면 됨.)
	해당 번호로.  함수를 추가해주면됨. PANSY.VAILD.arrAutoVaild[번호]  = func;
	
	이때, 쓰이는 함수는.. 검증함수로 작성되면된다. 엘리먼튼 내에서 실행된다는 가정하에 this 인자를 사용할 수 있다. 트루리턴은.. 검증에 문제없는것.. 펄스리턴은 문제있는 것..
*/
PANSY.VAILD.IS_EMPTY = 1; // 입력된값이 있는지..
PANSY.VAILD.IS_BLANK  = 2; //입력된 값이 공백으로만 이루어졌는지..
PANSY.VAILD.IS_INT  = 4; //입력된 값이 오직 숫자인지 소수점도 안됨 오직 숫자만   - 기호 됨.
PANSY.VAILD.IS_DECIMAL  = 8; //소수점을 포함한 숫자도 가능함. - 기호 됨.
PANSY.VAILD.IS_PHONENUM  = 16; //전화번호 검증.. 3자리 이상 숫자만..
PANSY.VAILD.IS_DATE8  = 32; //8짜리 날짜 검증

PANSY.VAILD.arrAutoVaild ={};
PANSY.VAILD.arrAutoVaildSimple ={};

PANSY.VAILD.arrAutoVaild[1] = function(){ //입력값이 있는지 없는지 검증함.
	if(this.value.length < 1){ //길이가 0이면..
		alert(this.elemName+" : 입력된 값이 없습니다.");
		if(this.focus){ //포커스 있으면 포커스옮겨줌.
			this.focus();
		}//end if
		return false;
	}//end if
	return true;
};
PANSY.VAILD.arrAutoVaildSimple[1] = function(){ //입력값이 있는지 없는지 검증함.
	if(this.value.length < 1){ //길이가 0이면..
		return false;
	}//end if
	return true;
};

PANSY.VAILD.arrAutoVaild[2] = function(){ //입력된 값이 공백으로만 이루어졌는지..
	var re = /^\s*$/g; //공백문자로만 이루어짐..
	
	if(re.test(this.value)){ //공백문자로만 이루어진경우
		alert(this.elemName+" :  공백이아닌 다른 값을 입력하셔야 합니다.");
		if(this.focus){ //포커스 있으면 포커스옮겨줌.
			this.focus();
		}//end if
		return false;
	}//end if
	return true;
};
PANSY.VAILD.arrAutoVaildSimple[2] = function(){ //입력된 값이 공백으로만 이루어졌는지..
	var re = /^\s*$/g; //공백문자로만 이루어짐..
	
	if(re.test(this.value)){ //공백문자로만 이루어진경우
		return false;
	}//end if
	return true;
};

PANSY.VAILD.arrAutoVaild[4] = function(){ //오직 숫자
	var re = /^-?[0-9]+$/g; //숫자만인지..
	
	if( ! re.test(this.value)){ //숫자말고 다른것이 섞인경우
		alert(this.elemName+" :  숫자만 입력이 가능합니다. 공백도 제거해주세요.");
		if(this.focus){ //포커스 있으면 포커스옮겨줌.
			this.focus();
		}//end if
		return false;
	}//end if
	return true;
};
PANSY.VAILD.arrAutoVaildSimple[4] = function(){ //오직 숫자
	var re = /^-?[0-9]+$/g; //숫자만인지..
	
	if( ! re.test(this.value)){ //숫자말고 다른것이 섞인경우
		return false;
	}//end if
	return true;
};

PANSY.VAILD.arrAutoVaild[8] = function(){ //오직 숫자인데.. 소수점 가능..
	var re = /^-?[0-9]+(\.[0-9]+)?$/g; //숫자만인지.. 소수점가능
	
	if( ! re.test(this.value)){ //숫자말고 다른것이 섞인경우
		alert(this.elemName+" :  소수점을 포함한 숫자만 입력이 가능합니다. 공백도 제거해주세요.");
		if(this.focus){ //포커스 있으면 포커스옮겨줌.
			this.focus();
		}//end if
		return false;
	}//end if
	return true;
};
PANSY.VAILD.arrAutoVaildSimple[8] = function(){ //오직 숫자인데.. 소수점 가능..
	var re = /^-?[0-9]+(\.[0-9]+)?$/g; //숫자만인지.. 소수점가능
	
	if( ! re.test(this.value)){ //숫자말고 다른것이 섞인경우
		return false;
	}//end if
	return true;
};

PANSY.VAILD.arrAutoVaild[16] = function(){ //전화번호.. 3자리이상 오직 숫자
	
	var re = /^[0-9]+$/g; //숫자만인지..
	
	if( ! re.test(this.value)){ //숫자말고 다른것이 섞인경우
		alert(this.elemName+" :  숫자만 입력이 가능합니다. 공백도 제거해주세요.");
		if(this.focus){ //포커스 있으면 포커스옮겨줌.
			this.focus();
		}//end if
		return false;
	}else if( this.value.length < 3 ){ //자리수가 3자리 안되는경우..
		alert(this.elemName+" : 3자리 이상 숫자를 입력하셔야 합니다.");
		if(this.focus){ //포커스 있으면 포커스옮겨줌.
			this.focus();
		}//end if
		return false;
	}//end if
	return true;
};
PANSY.VAILD.arrAutoVaildSimple[16] = function(){ //전화번호.. 3자리이상 오직 숫자
	
	var re = /^[0-9]+$/g; //숫자만인지..
	
	if( ! re.test(this.value)){ //숫자말고 다른것이 섞인경우
		return false;
	}else if( this.value.length < 3 ){ //자리수가 3자리 안되는경우..
		return false;
	}//end if
	return true;
};


PANSY.VAILD.arrAutoVaild[32] = function(){  //날짜 8자리형식.. 8자리 오직 숫자
	
	var re = /^[0-9]+$/g; //숫자만인지..
	
	if( ! re.test(this.value)){ //숫자말고 다른것이 섞인경우
		alert(this.elemName+" :  숫자만 입력이 가능합니다. 공백도 제거해주세요.");
		if(this.focus){ //포커스 있으면 포커스옮겨줌.
			this.focus();
		}//end if
		return false;
	}else if( this.value.length != 8 ){ //자리수가 8자리가 아닌경우
		alert(this.elemName+" : 8자리 숫자를 입력하셔야 합니다. ex) 20110101");
		if(this.focus){ //포커스 있으면 포커스옮겨줌.
			this.focus();
		}//end if
		return false;
	}//end if
	return true;
};
PANSY.VAILD.arrAutoVaildSimple[32] = function(){ //날짜 8자리형식.. 8자리 오직 숫자
	
	var re = /^[0-9]+$/g; //숫자만인지..
	
	if( ! re.test(this.value)){ //숫자말고 다른것이 섞인경우
		return false;
	}else if( this.value.length != 8 ){ //자리수가 8자리가 아닌경우
		return false;
	}//end if
	return true;
};


/*
	setAutoVaild 함수 사용할때, 상수를 넘겨주는 부분은..
	예를들어,  검증1 상수의 값이 1이고, 검증2 상수의값이 2 , 검증3 상수값이 4이면..
	사용자가 검증1,검증2를 사용하고 싶다고하면 3을 넘겨주면 됨. 
*/



PANSY.VAILD.setAutoVaild = function(elem,code){ // 미리 선언된 검증들을 간편하게 등록해주는 함수. 
	//elem : 검증을 등록할 엘리먼트 . . . . .
	//code : 미리선언된 검증 상수들.. 여러 상수의 조합이 올 수 있다. 
	
	
	var c = 1 ; //코드분석에 필요한 값.. 이 값을 2제곱 시키면서.. 주어진 코드와 앤드연산을 한다.
	//코드를 분석해서.. 엘리먼트에 검증함수 등록해줌 
	while(code > 0  ){ // 0보다 큰 동안..
		if((code & c) == c){ //현재 단계의 값이 있는지 검사..
//			alert(c);
			
			//현재값의 검증함수 등록해줌.
			if(PANSY.VAILD.arrAutoVaild[c]){ //함수가 있으면 등록해줌.
				 PANSY.VAILD.setVaildFunc(elem,PANSY.VAILD.arrAutoVaild[c]);
			}//end if
			
			code = code - c; //코드값에서 현재값 제거해줌.
		}//end if
		c = c << 1; //2제곱.. 
	}//end while
	
	
	/////////////////////// 자동검증 등록할때, 이름이 설정안되어있으면 title 프로퍼티를.. 설정해준다.
	if( ! elem.elemName){ //설정안된경우..
		elem.elemName = elem.title; //타이틀 프로퍼티 넣어줌. 
	}//end if
	
}//end func


/**
*callAutoVaild : 잠깐.. 해당 엘리먼트에 자동검증함수를 등록하지 않고, 검증해서, 결과만 받아오는.. 함수임. 
  setVaildFunc 안에서 검증할때 간편하게 하기위해서 사용됨.
*/
PANSY.VAILD.callAutoVaild = function(elem,code){ // 미리 선언된 검증들을 간편하게 등록해주는 함수. 
	//elem : 검증을 등록할 엘리먼트 . . . . .
	//code : 미리선언된 검증 상수들.. 여러 상수의 조합이 올 수 있다. 
	//리턴값 : true / false
	
	/////////////////////// 자동검증 등록할때, 이름이 설정안되어있으면 title 프로퍼티를.. 설정해준다.
	if( ! elem.elemName){ //설정안된경우..
		elem.elemName = elem.title; //타이틀 프로퍼티 넣어줌. 
	}//end if
	
	var c = 1 ; //코드분석에 필요한 값.. 이 값을 2제곱 시키면서.. 주어진 코드와 앤드연산을 한다.
	//코드를 분석해서.. 엘리먼트에 검증함수 등록해줌 
	while(code > 0  ){ // 0보다 큰 동안..
		if((code & c) == c){ //현재 단계의 값이 있는지 검사..
//			alert(c);
			
			//현재값의 검증함수 등록해줌.
			if(PANSY.VAILD.arrAutoVaild[c]){ //함수가 있으면 등록해줌.
				 var result = PANSY.VAILD.arrAutoVaild[c].call(elem); //컨텍스트를 엘리먼트로 바꾸고 실행함.. 결과를 받아온다.
				 if(result == false){
				 		return false;
				 }//end if
			}//end if
			
			code = code - c; //코드값에서 현재값 제거해줌.
		}//end if
		c = c << 1; //2제곱.. 
	}//end while
	
	return true;//여기까지왔으면 검증전부통과한것임.
	
	
}//end func



/*
	간단한 오토검증의 경우.. 다양한상황에서 사용할 수 가 없어서.. 같은구조로..
	다른기능없이.. 검증결과만 돌려주는 .. 함수임..
*/


PANSY.VAILD.callAutoVaildSimple = function(elem,code){ // 미리 선언된 검증들을 간편하게 등록해주는 함수. 
	//elem : 검증을 등록할 엘리먼트 . . . . .
	//code : 미리선언된 검증 상수들.. 여러 상수의 조합이 올 수 있다. 
	//리턴값 : true / false
	
	var c = 1 ; //코드분석에 필요한 값.. 이 값을 2제곱 시키면서.. 주어진 코드와 앤드연산을 한다.
	//코드를 분석해서.. 엘리먼트에 검증함수 등록해줌 
	while(code > 0  ){ // 0보다 큰 동안..
		if((code & c) == c){ //현재 단계의 값이 있는지 검사..
//			alert(c);
			
			//현재값의 검증함수 등록해줌.
			if(PANSY.VAILD.arrAutoVaildSimple[c]){ //함수가 있으면 등록해줌.
				 var result = PANSY.VAILD.arrAutoVaildSimple[c].call(elem); //컨텍스트를 엘리먼트로 바꾸고 실행함.. 결과를 받아온다.
				 if(result == false){
				 		return false;
				 }//end if
			}//end if
			
			code = code - c; //코드값에서 현재값 제거해줌.
		}//end if
		c = c << 1; //2제곱.. 
	}//end while
	
	return true;//여기까지왔으면 검증전부통과한것임.
	
	
}//end func




/*
	엘리먼트의 이름을 지정한다. name 프로퍼티말고... 검증에러 발생했을때 사용자에게 어떤 엘리먼트인지 알려주기 위한 이름.. 
	엘리먼트의 elemName 이라는 프로퍼티에 저장해두고, 필요한곳에서 불러다 쓰게 된다.
*/
PANSY.VAILD.setNameE = function(elem,name){ // 주어진 엘리먼트에 이름값을 저장해둔다.
	elem.elemName = name;
}//end func



/*
	엘리먼트에 등록되는 isVaild 구조 : 
	isVaild 에는 함수와, 검증구문 2가지를 등록할 수 있는데, 
	함수의 경우.. isVaildFuncs 배열에 등록되게 되고..
	구문의경우 isVaildStructs 배열에 등록되게 된다.
	
	최종적으로 외부에서 호출하게되는 isVaild 함수는 공통적으로 작성을 하게되는데...
	isVaildFuncs , isVaildStruct 배열을 불러다가 모두 실행시키고, 중간에 하나라도 false 값이 나오게 되면 false 를 리턴시키게 된다. 
*/

//엘리먼트에 검증함수 연결해주는 함수 - 여기에 넘겨져 오는 함수는 검증결과를 트루 / 펄스로 반환해줘야 한다.  그리고 엘리먼트의 프로퍼티로 연결되므로 this 인자 사용가능하다
PANSY.VAILD.setVaildFunc = function (elem,func){ //엘리먼트와 함수를 받아옴
	PANSY.VAILD.initFuncIsVaild(elem); //초기화
	
	elem.isVaildFuncs[elem.isVaildFuncs.length] = func; // 함수추가
}//end func
//엘리먼트에 검증함수 연결해주는 함수 끝

//엘리먼트에 검증구문 추가해주는 함수. - 검증구문은 , 이프문에 들어갈 조건식인데, this 인자를 사용할 수 있고, 결과값이 true 가 나오게되면, 검증성공.. false 면 검증실패로 간주함.
PANSY.VAILD.setVaildStruct =  function (elem,struct , errMsg){ // struc : ex ) " txt1.value.length > 0 "  : txt1의 길이가 0보다 커야한다. , errMsg : 검증실패했을때, 나올 메세지.. 빈값을 주게되면 메세지없음.
	PANSY.VAILD.initFuncIsVaild(elem);// 초기화
	
	//구문객체만들기.. 구문과 에러메세지를 가지고있다.
	var obj = {};
	obj["struct"] = struct;
	obj["errMsg"] = errMsg;
	
	elem.isVaildStructs[elem.isVaildStructs.length] = obj; // 구문추가
}//end func

PANSY.VAILD.initFuncIsVaild = function (elem){ //엘리먼트에 , isVaild 함수가 셋팅안되어잇는지를 검사하고  초기화 작업을 해준다. 셋팅되어있으면 아무작업안하고 나간다. 
	//isVaild 함수 , isVaildFuncs , isVaildStructs, 
	
	//isVaild 설정되어있는지 검사
	if(! elem.isVaild){ //설정안된 경우.. 
		
		//isVaild 함수설정
		elem.isVaild = function(){ // 검증성공 : true , 검증실패 : false
			
			// 함수 실행
			for(var i = 0; i < elem.isVaildFuncs.length; i++){
				// this 인자를 위해서 복사해서 사용함.
				elem.funcTemp = elem.isVaildFuncs[i];
								
				if(  elem.funcTemp() == false ){ //결과가 펄스면 중단시킴....
					return false;
				}//end if
				
			}//end for i
			
			//구문실행
			for(var i = 0; i < elem.isVaildStructs.length; i++){
				var obj  =elem.isVaildStructs[i]; //검증구문객체
				
				if( ! (eval(obj["struct"])) ){ //트루면 이상없는거기때문에 ! 붙여줌.
					if(obj["errMsg"] != ""){
						alert(obj["errMsg"]);//에러메세지 있으면 찍어줌.
					}//end if
					if(elem.focus){//포커스있으면 실행함
						elem.focus();
					}//end if
					return false;
				}//end if
			}//end for i
			
			return true;
		}//end func isVaild	
		
		//isVaildFuncs 배열설정.
		elem.isVaildFuncs = new Array(); //배열
		
		//isVaildStructs 배열설정.
		elem.isVaildStructs = new Array(); //배열
		
	}//end if
	
}//end func
//엘리먼트에 검증구문 추가해주는 함수. 끝


// 기존 방식에서는 form 객체의 submit 함수는 onSubmit을 호출하지 않는다. 그래서 기존 폼의 submit() 함수대신 내가만든 임의의 함수를 지정하고 강제로 온 서브밋을 호출한다.
/// 폼 검증 모듈 등록함수
// 사용법 : PANSY.VAILD.setFormVaildModule(Form);
PANSY.VAILD.setFormVaildModule = function (frm){ //주어진 폼객체를 폼 검증 모듈사용할 수 있게 준비해준다.
	
	frm.onsubmit = PANSY.VAILD.formVaildSubmit;//온서브밋 이벤트 달기
	
	frm.oldSubmit = frm.submit; //기존 서브밋 함수. 혹시라도 함수안에서 디스 인자를 사용하거나 할 수 있어서 최대한 비슷한 환경을 만들어주기 위해서 . .. 프로퍼티로 등록해줌.
	
	//새 서브밋함수 달아주기
	frm.submit = function(){
		if (! this.onsubmit()){ //온서브밋함수호출하고.. 리턴 결과에따라서 서브밋결정 - false 면 .. 서브밋 안함.
			return;
		}//end if
		this.oldSubmit(); //기존 서브밋함수 호출해줌
	}//end func
	
}//end func


///// 서브밋 함수 - 폼의 온서브밋에 걸어주면 됨.  폼 자신이 가지고 있는 모든 인풋 엘리먼트, 셀렉트, 텍스트 박스 엘리먼트에 대하여 검증한다.
/**
검증방법 : 각 엘리먼트들은 isVaild 라는 프로퍼티에 검증 함수를 가지고 있게되고.. isVaild 를 호출하여 입력된 값이 올바름 여부를 판단하게 된다.
              isVaild 프로퍼티는 검증할 필요가 있는경우에만 추가하게되고 검증필요가 없게 된 경우에는 추가 하지않는다 . 
사용방법 : document.frm1.onsubmit = PANSY.VAILD.formVaildSubmit;
*/

PANSY.VAILD.formVaildSubmit = function (){
	
	
	//내부 함수.. 주어진 엘리먼트 배열에 대해서 , isVaild 함수를 호출해줌. 
	function callFuncIsVaild(elems){
		
		for(var i = 0 ; i < elems.length; i++){
			if(elems[i].isVaild){ //함수가 등록되어있으면 실행함
				
				if( ! elems[i].isVaild() ){ //검증결과가 false 인경우. 
					return false;
				}//end if 검증결과
			}//end if
		}//end for i
		
		return true;
	}//end Inner func callFuncIsVaild
	
	
	
	//모든 인풋태그
	var inputs = $t(this,"input");
	
	//모든 텍스트에어리어
	var textareas = $t(this,"textarea");
	
	//모든  셀렉박스
	var selects = $t(this,"select");
	
	
	//검증..
	return callFuncIsVaild(inputs) && callFuncIsVaild(textareas) && callFuncIsVaild(selects) ;
	
}//end func

//// 서브밋 함수 끝 


////////////////////////////////////////////////////////////// 정규식검증함수 

PANSY.VAILD.RE.isEmail = function(email){ //이메일 검증 트루펄스만 리턴한다 . 
	var re =/^[0-9a-zA-Z_-]+([0-9a-zA-Z_-]+)*@[0-9a-zA-Z_-]+(\.[0-9a-zA-Z_-]+)+$/; //이메일
	
	if(re.test(email)){ //
		return true;
	}else{
		return false;
	}//end if
}//end func
PANSY.VAILD.RE.isNumber = function(number){ //숫자만있는지 확인  마이너스표시 맨앞에 가능함.
	var re = /^-?[0-9]+$/g; //숫자만인지..
	
	if(re.test(number)){ //
		return true;
	}else{
		return false;
	}//end if
}//end func
PANSY.VAILD.RE.isDecimal = function(number){ // 소수점 가능한 숫자인지 검증.. 앞에 마이너스 표시 가능..
	var re = /^-?[0-9]+(\.[0-9]+)?$/g; //숫자만인지.. 소수점가능
	
	if(re.test(number)){ //
		return true;
	}else{
		return false;
	}//end if
}//end func
PANSY.VAILD.RE.isDate8 = function(number){ //숫자로만이루어진 8글자인지.. : 날짜인지..
	var re = /^-?[0-9]+$/g; //숫자만인지..
	
	if(re.test(number) && number.length == 8){ // 딱 숫자 8자리인경우만..
		return true;
	}else{
		return false;
	}//end if
}//end func
////////////////////////////////////////////////////////////// 정규식검증함수 끝



///// 폼 검증모듈 관련 함수들..  끝




//////////////////////////////////////////////////////////// 엔코딩관련함수들


PANSY.ENC.urlencode = function (clearString) {
  var output = '';
  var x = 0;
  clearString = clearString.toString();
  var regex = /(^[a-zA-Z0-9_.]*)/;
  while (x < clearString.length) {
    var match = regex.exec(clearString.substr(x));
    if (match != null && match.length > 1 && match[1] != '') {
    output += match[1];
      x += match[1].length;
    } else {
      if (clearString[x] == ' ')
        output += '+';
      else {
        var charCode = clearString.charCodeAt(x);
        var hexVal = charCode.toString(16);
        output += '%' + hexVal.toUpperCase();
      }
      x++;
    }
  }
  return output;
}//end func
//////////////////////////////////////////////////////////// 엔코딩관련함수들 끝

//////////////////////////////////////////////////////////// 윈도우 관련 함수


PANSY.WIN.autoResizing = function (addWidth,addHeight) { //현재 윈도우창의 크기를.. 자동적으로 , 창내용에맞게 맞춰준다 . 
	//addWidth : 제목이나..  그런것들로.. scrollWidth 나 Height 보다 실제로는 더 커야하는경우가 있다.. 그럵경우 추가해줄 길이..
	var w = document.body.scrollWidth + addWidth;
	var h = document.body.scrollHeight + addHeight;
	window.resizeTo(w,h);
}//end func
//////////////////////////////////////////////////////////// 윈도우 관련 함수 끝


////////////////////////////////////////////////////////////////////// 플래시 관련함수



PANSY.FLASH.printFlash = function(url,width,height){ // object 태그를 해당자리에 바로 출력해준다. 
	// url : 플래시파일 url
	// width / height : 가로 / 세로길이
	
	var str = "";
	str +=	"<object ";
	str +=	"		classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" ";
	str +=	"		codebase=\"http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0\" ";
	str +=	"		width=\""+width+"\" height=\""+height+"\"";
	str +=	">";
	str +=	"		<param name=\"movie\" value=\""+url+"\">";
		 
	str +=	"	   <!--[if !IE]> <--> ";
	str +=	"	   <object type=\"application/x-shockwave-flash\" data=\""+url+"\" width=\""+width+"\" height=\""+height+"\">";
	str +=	"	   </object>";
	str +=	"	   <!--> <![endif]-->";
	str +=	"</object>";
	
	
	document.write(str);
}//end func
////////////////////////////////////////////////////////////////////// 플래시 관련함수 끝

//////////////////////////////////////////////////////////// 기본적인 자주사용될 함수 


PANSY.COMMON.getNumberStringFixPosition = function(num,pos){ //정해진 자리의 숫자를 문자열로 표시해준다. // 결과값 문자열임. 
	//num : 숫자
	//pos : 자릿수 .. 100 자리.. 3을 넘겨주면됨.
	var sNum = num+"";//문자열로 변환
	var len = sNum.length;//길이
	
	return PANSY.COMMON.strRepeat("0",(pos-len) ) +num ;
	
}//end func

PANSY.COMMON.strRepeat = function(str,cnt){ //주어진 문자열을반복해서 돌려준다.
	//str 반복할 문자열
	//cnt 반복횟수
	var strR = "";
	for(var  i=0; i<cnt ; i++){
		strR += str;
	}//end for i
	
	return strR;
}//end func
//////////////////////////////////////////////////////////// 기본적인 자주사용될 함수 끝

//////////////////////////////////////////////////////////// AJAX


PANSY.AJAX.getXmlHttpRequest = function ( options ) {// 익스플로러 6때문에, 추가된 부분
	var xml = null;
    if(window.XMLHttpRequest){ //있는경우 
    	 xml = new XMLHttpRequest();
    }else{
    	try{
    		xml = new ActiveXObject("Msxml12.XMLHTTP");	
    	}catch(e){
    		try{
    			xml = new ActiveXObject("Microsoft.XMLHTTP");	
    		}catch(e){
    			xml = false;
    		}//end try catch
    	}//end try catch
    }//end if
    
    return xml;
}//end func

PANSY.AJAX.ajax = function ( options ) {

    // Load the options object with defaults, if no
    // values were provided by the user
    options = {
        // The type of HTTP Request
        type: options.type || "POST",

        // The URL the request will be made to
        url: options.url || "",

        // How long to wait before considering the request to be a timeout
        timeout: options.timeout || 5000,

        // Functions to call when the request fails, succeeds,
        // or completes (either fail or succeed)
        onComplete: options.onComplete || function(){},
        onError: options.onError || function(){},
        onSuccess: options.onSuccess || function(){},

        // The data type that'll be returned from the server
        // the default is simply to determine what data was returned from the
        // and act accordingly.
        data: options.data || ""
    };

    // Create the request object

    var xml =PANSY.AJAX.getXmlHttpRequest();

    // Open the asynchronous POST request
    xml.open(options.type, options.url , true);

    // We're going to wait for a request for 5 seconds, before giving up
    var timeoutLength = options.timeout;

    // Keep track of when the request has been succesfully completed
    var requestDone = false;

    // Initalize a callback which will fire 5 seconds from now, cancelling
    // the request (if it has not already occurred).
    setTimeout(function(){
         requestDone = true;
    }, timeoutLength);

    // Watch for when the state of the document gets updated
    xml.onreadystatechange = function(){
        // Wait until the data is fully loaded,
        // and make sure that the request hasn't already timed out
        if ( xml.readyState == 4 && !requestDone ) {

            // Check to see if the request was successful
            if ( httpSuccess( xml ) ) {

                // Execute the success callback with the data returned from the server
                options.onSuccess( httpData( xml, options.type ) );

            // Otherwise, an error occurred, so execute the error callback
            } else {
                options.onError();
            }

            // Call the completion callback
            options.onComplete();

            // Clean up after ourselves, to avoid memory leaks
            xml = null;
        }
    };

    // Establish the connection to the server
    //서버에전송함, 겟과 포스트로 분기함
    if(options.type=="POST" ){ //포스트인경우
	    	xml.setRequestHeader(
	    "Content-Type", "application/x-www-form-urlencoded");

			// Make sure the browser sends the right content length of the serialized data –
			// Mozilla-based browsers sometimes have trouble with this
			if ( xml.overrideMimeType )
			    xml.setRequestHeader("Connection", "close");
			
			// Establish the connection to the server and send the serialized data
			xml.send( PANSY.AJAX.serialize( options.data ) );
    }else{ //겟인경우
    		xml.send();
    }//end if
	 //서버에전송함, 겟과 포스트로 분기함 끝
	
    // Determine the success of the HTTP response
    function httpSuccess(r) {
        try {
            // If no server status is provided, and we're actually 
            // requesting a local file, then it was successful
            return !r.status && location.protocol == "file:" ||

                // Any status in the 200 range is good
                ( r.status >= 200 && r.status < 300 ) ||

                // Successful if the document has not been modified
                r.status == 304 ||

                // Safari returns an empty status if the file has not been modified
                navigator.userAgent.indexOf("Safari") >= 0 && typeof r.status == "undefined";
        } catch(e){}

        // If checking the status failed, then assume that the request failed too
        return false;
    }

    // Extract the correct data from the HTTP response
    function httpData(r,type) {
        // Get the content-type header
        var ct = r.getResponseHeader("content-type");

        // If no default type was provided, determine if some
        // form of XML was returned from the server
        var data = !type && ct && ct.indexOf("xml") >= 0;

        // Get the XML Document object if XML was returned from
        // the server, otherwise return the text contents returned by the server
        data = type == "xml" || data ? r.responseXML : r.responseText;

        // If the specified type is "script", execute the returned text
        // response as if it was JavaScript
        if ( type == "script" )
            eval.call( window, data );

        // Return the response data (either an XML Document or a text string)
        return data;
    }

}//end func

PANSY.AJAX.serialize=function(a) { //주어진 정보를 포스트전송할 수 있도록 직렬화해준다. 배열로넘겨지면, 폼데이터라고 간주하고 처리하고 아닌경우는. 키 : 값 으로 이루어진 객체라고 생각하고 처리함.
    // The set of serialize results
    var s = [];
		
    // If an array was passed in, assume that it is an array
    // of form elements
    if ( a.constructor == Array ) {
        // Serialize the form elements
        for ( var i = 0; i < a.length; i++ )
            s.push( a[i].name + "=" + encodeURIComponent( a[i].value ) );
			
    // Otherwise, assume that it's an object of key/value pairs
    } else {

        // Serialize the key/values
        for ( var j in a )
            s.push( j + "=" + encodeURIComponent( a[j] ) );

    }
		
    // Return the resulting serialization
    return s.join("&");
}//end func

/*
	json 으로 받을경우, 제대로된 결과인지 검사함
	- php 에서 에러난경우 에러코드같은게 찍힐 수 가 있어서..
*/
PANSY.AJAX.is_ok_json = function(json){
	var re = /^\s*\{.*\}\s*$/g; // 앞뒤 공백제외하고.. { } 으로 감싸고있는지만 검사
	
	if(re.test(json)){ //정상
		return true;
	}else{
		return false;
	}//end if
}//end func

//////////////////////////////////////////////////////////// AJAX 끝


/////////////////////////////////////////////////////////////////// 드래그앤드롭


PANSY.DND.dragObject = null; //현재 드래그되고있는 엘리먼트를 저장한다
PANSY.DND.mouseOffset = null; //드래그되는 엘리먼트의 왼쪽위 시작위치를 저장해둔다.(클라이언트 기준)

PANSY.DND.mousePoint = function(x,y){ //마우스 좌표를 저장함
	this.x = x;
	this.y = y;
}//end func

PANSY.DND.getMousePosition = function(evnt){ //마우스 위치를 돌려줌 (클라이언트 기준 ) // 마우스이벤트를 받아옴.
//	var x = parseInt(evnt.clientX);
//	var  y =parseInt(evnt.clientY);
	var x = parseInt(evnt.screenX);
	var  y =parseInt(evnt.screenY);
	
	return new PANSY.DND.mousePoint(x,y);
}//end func

PANSY.DND.getMouseOffset = function(target,evnt){ // 주어진 엘리먼트의 오프셋 위치를 찾는다. 엘리먼트의 왼쪽 위 시작 포인트를 찾는다. 화면으로부터(client 단위) 
	evnt = evnt || window.event;
	var mousePos = PANSY.DND.getMousePosition(evnt); //이벤트가 일어난 클라이언트 좌표
	
	var x = mousePos.x - target.offsetLeft;
	var y = mousePos.y - target.offsetTop;
	
	return new PANSY.DND.mousePoint(x,y);
}//end func

PANSY.DND.mouseUp = function(evnt){ //드래그종료
	PANSY.DND.dragObject = null;
	document.onmousemove = function(){};
}//end func

PANSY.DND.mouseMove = function(evnt){ //드래그 중.. 이동캡쳐
	var dragObject =  PANSY.DND.dragObject ;
	if (! dragObject ) return;
	evnt = evnt || window.event;
	var mousePos = PANSY.DND.getMousePosition(evnt); //이벤트가 일어난 클라이언트 좌표
	
	/*
		추가된 기능
		드래그 오브젝트 자체에, x 나 y 둘중 하나의 방향으로만 드래그되도록 설정할 수 있고, 
		사용하려면 해당오브젝트의 obj.dnd_dont_move_x = true 설정해준다 . 
		사용하려면 해당오브젝트의 obj.dnd_dont_move_y = true 설정해준다 . 
		자기 부모 엘리먼트의 영역밖으로 이동하지 못하게 할 수 있다. 
		사용하려면 해당오브젝트의 obj.dnd_dont_move_parent_area = true 설정해준다 . 
	*/
	//드래그 가능하면 새로운 절대좌표 설정
	if(dragObject ){
		dragObject.style.position = "absolute"; //포지션 설정
		
		var move_y = mousePos.y - PANSY.DND.mouseOffset.y ;//계산된 좌표
		var move_x = mousePos.x - PANSY.DND.mouseOffset.x  ;//계산된 좌표
		
		//부모영역을 벗어났는지 판단
		if(dragObject.dnd_dont_move_parent_area == true){
			var parent_obj =  dragObject.parentElement;
			var limit_y = parent_obj.offsetHeight - dragObject.offsetHeight; //최대이동할 수 있는 한계치를 계산한다 //부모에서 자신의 길이를 뺀다
			var limit_x = parent_obj.offsetWidth - dragObject.offsetWidth; //최대이동할 수 있는 한계치를 계산한다 //부모에서 자신의 길이를 뺀다
			var is_over_parent_area_x = false;
			if(move_y < 0){
				move_y =0;
			}//end if
			if(move_x < 0){
				move_x = 0;
			}//end if
			if(move_y > limit_y){
				move_y =limit_y;
			}//end if
			if(move_x > limit_x){
				move_x =limit_x;
			}//end if
		}//end if
		//부모영역을 벗어났는지 판단 끝
		
		if(dragObject.dnd_dont_move_y != true ){//세로이동못하게 막은거아니면 세로 이동
			dragObject.style.top = move_y + "px"; // 현재 마우스위치에서, 처음 마우스클릭되었을때의 위치를 뺀것으로 이동한다.
			
		}//end if
		if(dragObject.dnd_dont_move_x != true ){//가로이동못하게 막은거아니면 세로 이동
			dragObject.style.left = move_x + "px"; // 현재 마우스위치에서, 처음 마우스클릭되었을때의 위치를 뺀것으로 이동한다.
		}//end if 
		
		//드래그되고나서, 혹시, 처리할 이벤트 등록된거있으면 처리 - obj.dnd_mousemove 에 등록된거있으면 호출해준다.
		if(dragObject.dnd_mousemove){
			dragObject.dnd_mousemove();
		}//end if
		//드래그되고나서, 혹시, 처리할 이벤트 등록된거있으면 처리 끝
		
		return false; //이거의미모르겟다 시간없어서 그냥 배낀다
	}//end if
}//end func

PANSY.DND.makeDraggable  = function(item){ //주어진 엘리먼트에, 마우스다운이벤트로 걸어준다.
	if(item){
		PANSY.addEvent(item,"onmousedown",function(evnt){ //마우스 다운이벤트 걸어줌
			PANSY.DND.dragObject = this;
			PANSY.DND.mouseOffset = PANSY.DND.getMouseOffset(this,evnt);
			
			//타이머등록
//			PANSY.DND.dragObject.dnd_timer = setInterval( PANSY.DND.mouseMove, 500);
			//타이머등록 끝
			document.onmousemove = PANSY.DND.mouseMove;
			return false;
		});
//		PANSY.addEvent(item,"onmousemove",PANSY.DND.mouseMove); //마우스 무브 이벤트 걸어줌
		item.onselectstart = function(){return false;};//선택안되게 설정해줌
	}//end if
}//end func

PANSY.DND.captureStarted = false; //마우스 캡쳐 시작되었는지.. 여부.. 
PANSY.DND.captureStart = function(){//마우스 이벤트 캡쳐할 수 있도록 도큐먼트의 이벤트를 걸어줌 //드래그앤드롭실행되기전에 한번만 해주면 되는데, 여러번 실행해도 한번만 실행되도록 되어있다.
	if(PANSY.DND.captureStarted == false){
//		PANSY.addEvent(document,"onmousemove",PANSY.DND.mouseMove); //도큐먼트 자체에 하면  상관없는 부분에 마우스있을때도 일처리하느라, 다른 스크립트를 진행못시킨다.
		PANSY.addEvent(document,"onmouseup",PANSY.DND.mouseUp);
		PANSY.DND.captureStarted = true;
	}//end if
}//end func

/////////////////////////////////////////////////////////////////// 드래그앤드롭 끝

//////////////////////////////////////////////////////////// 이미지관련


PANSY.IMAGE.autoLimitResize = function(img,size){ // 이미지태그의 온로드 에 넣어두면, 알아서 지정해둔 크기 이상으로 큰경우는 자동으로 사이즈를 줄여준다.  //ex <img onload="PANSY.IMAGE.autoLimitResize(this,300);" />
	//img  : 이미지개체
	//size : 제한할 가로 사이즈
	
	//기본적으로 onload 에 가져오면 가로사이즈를 가져오지만, 
	// 현재 디스플레이가 안된경우에는 온로드되어도, 사이즈가없다.
	//그런경우에는 디스플레이되는순간 onresize 이벤트가 실행된다. 
	
	//이미 리사이즈 한번 실행된경우에는 다시 실행안함. 
	if(img.hasLimitResizing==true){
		return;
	}//end if
	//이미 리사이즈 한번 실행된경우에는 다시 실행안함.  끝
	
	// width 가 0이아닐때까지 계속 가져옴. - 온로드되었는데도, 0인경우는 디스플레이가 안된 경우..
	if(img.width < 1){ //1보다 작음
		img.onresize = function(){
			PANSY.IMAGE.autoLimitResize(img,size);
		};
		return;
	}//end if
	// width 가 0이아닐때까지 계속 가져옴.  끝
	
	//사이즈 검사
	if(size < img.width){
		img.height = img.height*size /img.width ;  //가로 크기 설정 되기 전에 설정해야 함		
		img.width = size; //제한사이즈로 변경
	}//end if
	//사이즈 검사 끝
	
	img.hasLimitResizing = true;//리사이징 실행된걸로 기록
	
}//end func


//이미지 마우스 오버시에 다른이미지 보여주기
// 사용법 : 이미지의 onload 에 이 함수등록해주면된다. <img src="" onload="PANSY.IMAGE.setOverImage(this,'src'); />"
PANSY.IMAGE.setOverImage = function(img,over_img_src){
	//img : 이미지태그 ..
	// over_img_src : 마우스 오버되었을때, 변경될 이미지주소,
	
	img.original_src = img.src; //원본 이미지주소
	img.over_img_src = over_img_src; //오버이미지주소 저장함
	img.is_over_img = false;//마우스 오버로 이미지 변경되었는지 기록할 플래그변수 설정 ,  true/false 값설정되고, 마우스오버되어서 이미지 변경된 상태면 트루가 들어감
	
	//마우스 오버이벤트
	PANSY.addEvent(img,"onmouseover",function(){
//		alert('on : ' + this.is_over_img );
		//오버중이 아닌지 검사
		if(this.is_over_img == true){ //오버중인경우
			return;
		}//end if
		//오버중이 아닌지 검사 끝
		
		this.original_src = this.src; //원본주소저장해두고
		this.src = this.over_img_src; //오버이미지로 변경
		this.is_over_img = true ; //플래그설정
//		alert('on2 : ' + this.is_over_img );
	});
	//마우스 오버이벤트 끝
	
	//마우스 아웃이벤트
	PANSY.addEvent(img,"onmouseout",function(){
//		alert('out : ' + this.original_src );
		//오버중인지 검사
		if(this.is_over_img == false){ //오버중이 아닌 경우
			return;
		}//end if
		//오버중인지 검사 끝
		
		this.src = this.original_src; //원본이미지로 변경
		this.is_over_img = false ; //플래그설정
		
	});
	//마우스 아웃이벤트 끝
	
	img.onload = function(){}; //온로드 내용지워주기. 안지워주면 이미지 변경될때마다 온로드 계속 실행됨.
}//end func

/*
	이미지를 라디오버튼 처럼 사용할 수 있도록 해준다. 
	마우스 오버시, 이미지전환 효과를 추가해주고
	실제 값은 히든 변수에 저장한다.
	해당 히든변수에 등록된 라디오 버튼들의 리스트를 관리해준다. 
	
	인자
		hdn : 선택값이 들어갈 히든변수 개체
		img : 버튼으로 사용할 이미지 개체 
		value : 버튼 선택시 히든변수에 설정될 값
		over_img_src : 마우스 오버되거나 선택되었을때 표시될 이미지
	사용법
	
*/
PANSY.IMAGE.setImgRadioButton = function(img,hdn,value,over_img_src){ // 
	
	//해당 히든변수에 리스트 추가하기
	if(! hdn.img_radio_button){ //설정안된경우 처음에 설정
		hdn.img_radio_button = {};
		hdn.img_radio_button.buttons = new Array();//이미지 배열
//		hdn.img_radio_button.selected_value = null; //기존에 선택된 값
		
		hdn.img_radio_button.choice = function(choice_value){ //등록된 것중 하나를 선택했을때 실행될 함수. 이미지에 온클릭에 걸어주면 됨.  // choice_value : 선택하는 값
			var img_choice = hdn.img_radio_button.buttons[choice_value];
			var img_selected = hdn.img_radio_button.buttons[hdn.value]; //기존에 선택된 값 에 해당하는 이미지
			if(img_choice){ //등록된 이미지가 있을때만 실행됨
				hdn.value = choice_value; //현재 선택한 값 설정
				img_choice.src = img_choice.	over_img_src; //오버이미지로 변경
				img_choice.is_selected = true; // 선택된걸로 설정
			}//end if
			
			if(img_selected){// 선택된 이미지 있을시에만 실행
				img_selected.src = img_selected.original_src; //일반이미지로 변경
				img_selected.is_selected = false; // 선택안된걸로 설정
			}//end if
			
		}//end func
		
	}//end if
	
	hdn.img_radio_button.buttons[value] = img;
	//해당 히든변수에 리스트 추가하기 끝
	
	//이미지 변수설정
	img.original_src = img.src; //원본 이미지주소
	img.over_img_src = over_img_src; //오버이미지주소 저장함
	img.is_over_img = false;//마우스 오버로 이미지 변경되었는지 기록할 플래그변수 설정 ,  true/false 값설정되고, 마우스오버되어서 이미지 변경된 상태면 트루가 들어감
	img.is_selected = false ; //현재 이미지 가 선택되었는지 true / false
	//이미지 변수설정 끝
	
	//이미지에 온클릭 걸어주기
	img.onclick = function(){
		hdn.img_radio_button.choice(value);
	}//end onclick
	//이미지에 온클릭 걸어주기 끝
	
	//마우스 오버이벤트
	img.onmouseover = function(){
		//오버중이 아닌지 검사
		if(this.is_over_img == true || this.is_selected == true ){ //오버중인경우 나 선택된 경우에는 동작안함.
			return;
		}//end if
		//오버중이 아닌지 검사 끝
		
		this.src = this.over_img_src; //오버이미지로 변경
		this.is_over_img = true ; //플래그설정
	};
	//마우스 오버이벤트 끝
	
	//마우스 아웃이벤트
	img.onmouseout = function(){
		//오버중인지 검사
		if(this.is_over_img == false || this.is_selected == true){ //오버중이 아닌 경우 나 선택된 경우에는 동작안함.
			return;
		}//end if
		//오버중인지 검사 끝
		
		this.src = this.original_src; //원본이미지로 변경
		this.is_over_img = false ; //플래그설정
	};
	//마우스 아웃이벤트 끝
	
}//end class


//클릭하면 이미지 보여 주기 
function viewImage(imgUrl){
	var img_tmp = new Image();
	img_tmp.src=imgUrl;
	W = img_tmp.width;
	H = img_tmp.height;
	O="width="+W+",height="+H;
	
	imgWin=window.open("","",O);
	imgWin.document.write("<html><head><title>이미지 확대 보기</title></head>");
	imgWin.document.write("<body topmargin=0 leftmargin=0>");
	imgWin.document.write("<img src="+imgUrl+" onclick='self.close()' style=cursor:hand>");
	imgWin.document.close();
	
}
//////////////////////////////////////////////////////////// 이미지관련 끝


/////////////////////////////////////////////////////////// 컨트롤 앤 인터페이스 

/*
	스위치 디스플레이를 토글기능으로 사용함. - 버튼에 맞게 사용함
	단순히 1버튼을 클릭할때마다 보였다 안보였다하는 토글기능,
	버튼의 텍스트를 변경해준다. 
	
	인자
		btn : 토글버튼으로 사용할 버튼 객체
		display_obj : 토글시킬 디스플레이요소 객체
		on_text : 활성시 텍스트
		off_text : 비활성시 텍스트
*/
PANSY.CNI.set_toggle_button=function(btn,display_obj,on_text,off_text){
	//버튼 개체에 switch_display 설정해줌
	PANSY.CNI.set_switch_display(btn);
	btn.switch_display.set_toggle(); //토글 설정
	//버튼 개체에 switch_display 설정해줌 끝
	
	//디스플레이요소 등록
	btn.switch_display.add("toggle",display_obj);
	//디스플레이요소 등록 끝
	
	//버튼 설정
	btn.switch_display.add_real_button("toggle",btn,on_text,off_text);
	//버튼 설정 끝
}//end func

/*
셀렉트 선택값에 의해서, 디스플레이가 변경됨
SwitchDisplay 를 이용함.
인자
	select_obj : 셀렉트 개체를 넘겨줌.
	
사용법 : 
			//스위치 디스플레이 설정
			PANSY.CNI.PANSY.CNI.set_switch_display_on_select($("sltAutoYes"));
			
			//디스플레이 설정
			$("sltAutoYes").switch_display.add("1",$("trAutoYes_1_Sort"));
			$("sltAutoYes").switch_display.add("1",$("trAutoYes_1_RD"));
			$("sltAutoYes").switch_display.add("1",$("trAutoYes_1_Brand"));
			$("sltAutoYes").switch_display.add("1",$("trAutoYes_1_Cate"));
			
			//처음 한번 실행해줌
			$("sltAutoYes").switch_display.display($("sltAutoYes").value);
*/
PANSY.CNI.set_switch_display_on_select = function(select_obj){
	//셀렉트 개체에 switch_display 설정해줌
	PANSY.CNI.set_switch_display(select_obj);
	//셀렉트 개체에 switch_display 설정해줌 끝
	
	//온체인지 등록
	PANSY.addEvent(select_obj,"onchange",function(){
		this.switch_display.display(this.value);
	});
	//온체인지 등록 끝
}//end func

/*
set_switch_display
스위치 디스플레이 객체를 생성해서, 해당 객체에 스위치 디스플레이 객체를 속성으로 저장해준다
ex ) make_switch_display_obj(obj);
       obj.switch_display.add();
       obj.switch_display.display("key");
인자
	obj : 스위치 디스플레이 객체로 사용할 객체.. select 나 button , image 같은 것들이 될 수 도 있고.. 사용자가 생성한 object 일 수 도 있음.. 어떤 객체든지 상관없이 이식 가능..
*/
PANSY.CNI.set_switch_display =   function (obj){
	var switch_display = new PANSY.CNI.SwitchDisplay();
	obj.switch_display = switch_display;
}//end method

/*
SwitchDisplay
특정 키값에 해당하는 디스플레이요소를 등록해두었다가
키값이 선택되었을때, 해당하는 디스플레이 요소를 display: 시켜줌
그 외의 키값에 등록된 디스플레이 요소들은 display:none 됨.

ex ) 탭기능.. 토글기능 등.. 에 활용됨

사용법
	//디스플레이요소 등록
	tab_obj.add("tab1",$("divTabDP_1"));
	tab_obj.add("tab2",$("divTabDP_2"));
	tab_obj.add("tab3",$("divTabDP_3"));
	tab_obj.add("tab4",$("divTabDP_4"));
	tab_obj.add("tab5",$("divTabDP_5"));

	//버튼 등록
	tab_obj.add_button("tab1",$("a_tab_image_1"));
	tab_obj.add_button("tab2",$("a_tab_image_2"));
	tab_obj.add_button("tab3",$("a_tab_image_3"));
	tab_obj.add_button("tab4",$("a_tab_image_4"));
	tab_obj.add_button("tab5",$("a_tab_image_5"));
	
	//이미지 버튼 등록
	tab_obj.add_image_button("tab1",$("img_tab_image_1"),"/img/on.gif","/img/off.gif");
	tab_obj.add_image_button("tab2",$("img_tab_image_2"),"/img/on.gif","/img/off.gif");
	tab_obj.add_image_button("tab3",$("img_tab_image_3"),"/img/on.gif","/img/off.gif");
	tab_obj.add_image_button("tab4",$("img_tab_image_4"),"/img/on.gif","/img/off.gif");
	tab_obj.add_image_button("tab5",$("img_tab_image_5"),"/img/on.gif","/img/off.gif");
	
	//초기선택 탭
	tab_obj.display("tab1");
	
*/
PANSY.CNI.SwitchDisplay = function(){
	
	this.key_list = new Array(); //등록된 키 리스트 , 연관배열로 사용
	this.selected_key = null; //현재 선택된 키값.. 문자열 "" 도 키값으로 있을 수 있어서, 널값으로 선택된게 없는 것을 구분한다.
	this.first_key = null; //첫번째 키
	this.last_key = null; //마지막 키
	
	this.is_toggle = false ; //토글기능인지 설정함. 같은 키값이 선택되었을때, 토글이 아니면, 계속 같은 디스플레이가 나오지만, 토글인경우는 현재 보이는 디스플레이가 off 되고 아무것도 표시안해준다.
	
	this.timer = null; //타이머가 저장됨
	this.delay = 5000; // 타이머 딜레이.. 기본 5초
	
	
	/*
		탭진열자동변경에 관한 설정들..
		delay : 타이머딜레이
	*/
	this.timer_config = function(delay){
		this.delay = delay;
	}//end method
	
	/*
		일정한 시간에 맞춰서, 탭진열을 변경해줌.
	*/
	this.play = function(){
		//타이머 동작중이면나간다.
		if(this.timer) return;
		
		var obj = this;
		this.timer = setTimeout( function(){
			//다음 키 선택
			if(obj.selected_key){ //선택된게 있으면
				obj.display(obj.selected_key.next.key);
			}else{// 없으면 첫번째 키값
				obj.display(obj.first_key.key);
			}//end if
			//다음 키 선택 끝
			
			obj.stop();
			obj.play();
		}, this.delay);
	}//end method
	/*
		탭진열을 시간에맞춰 넘기는것을 멈춤
	*/
	this.stop = function(){
		//타이머 동작중이 아니면 나간다.
		if(! this.timer) return;
		
		clearTimeout(this.timer); //타이머멈춤
		this.timer = null; //다시 널 입력해줌.
	}//end method
	
	/*
	디스플레이 요소 추가
	같은 키값으로 등록을 여러번 해도됨
	인자
		key : 키값
		display_obj : 디스플레이 요소
	*/
	this.add = function(key,display_obj){
		//키 리스트에 등록된 키값 있는지 검사 후 등록
		if( ! this.key_list[key] ){ //없는 경우
			this.key_list[key] = new PANSY.CNI.SwitchKey(key);
			
			//둥근 고리처럼.. 마지막 키의 넥스트는 첫번째 키를 가리키고 있음..
			//첫번째 비었으면 설정
			if(! this.first_key){
				this.first_key = this.key_list[key];
				this.key_list[key].prev = this.key_list[key];
				this.key_list[key].next = this.key_list[key]; //모두 자기자신을 가리킴.. 1개일때...
			}else{ //한개라도 있는경우..
				this.key_list[key].next = this.last_key.next ; //기존 마지막의 다음을 새로운거로 옮기고
				this.last_key.next = this.key_list[key]; //기존마지막의 다음을 새로운거로 하고,
				this.key_list[key].prev = this.last_key; //새로운거의 이전을 기존마지막으로 하고
				this.key_list[key].next.prev = this.key_list[key]; //새로운거의 다음의 이전을 새로운거로 지정해줌. 
			}//end if
			//첫번째 비었으면 설정 끝

			this.last_key = this.key_list[key];//마지막으로 설정
		}//end if
		//키 리스트에 등록된 키값 있는지 검사 후 등록 끝
		
		key_obj = this.key_list[key];//키 객체
		
		key_obj.add_display_obj(display_obj); //키 객체에 디스플레이 요소 추가함.
	}//end method
	
	/*
	특정 키에 해당하는 디스플레이 요소들을 디스플레이 시킴
	기존 디스플레이 되고 있던 키값들은 디스플레이 해지
	인자
		key : 선택된 키값
	*/
	this.display = function(key){
		//토글기능이면, 같은경우 디스플레이 해지만 하고 종료
		
		if(this.is_toggle && this.selected_key != null && this.selected_key.key == key){ //토글이고, 같은 키인경우  // 널검사안하면 초기값이 null 이라서 에러난다.
			this.selected_key_display_none();//선택된 키 디스플레이 해지
			return;	
		}//end if
		//토글기능이면, 같은경우 디스플레이 해지만 하고 종료 끝
		
		this.selected_key_display_none();//선택된 키 디스플레이 해지
		
		
		//선택된 키 디스플레이설정
		var key_obj = this.key_list[key];
		if(key_obj){// 등록된 키있으면
			key_obj.display();
			this.selected_key = key_obj;
		}//end if
		//선택된 키 디스플레이설정 끝
		
		
	}//end method
	
	/*
	현재 선택된 키를 디스플레이 해지시킴
	*/
	this.selected_key_display_none = function(){
		if(this.selected_key != null){//현재 선택된 키값 있는 경우만..
			this.selected_key.display_none(); //디스플레이 해지.
			this.selected_key = null; //다시 선택된거 없는걸로 설정함.
		}//end if	
	}//end method
	
	/*
		토글기능을 설정한다
	*/
	this.set_toggle = function(){
		this.is_toggle = true;	
	}//end method
	
	/*
	버튼을 등록한다.
	인자
		key : 버튼과 연결될 키값
		button_obj : 버튼으로 사용될 오브젝트.. onclick 사용할 수 있으면 된다. 
	반환값
		생성된 button 객체
	*/
	this.add_button = function(key,button_obj){
		var button = new PANSY.CNI.SwitchButton(button_obj,key,this);
		
		// 키 객체에 버튼 등록
		if( this.key_list[key] ){ //있는 경우
			this.key_list[key].add_button(button);
		}//end if
		// 키 객체에 버튼 등록 끝
		
		return button;
	}//end method
	
	/*
	이미지 버튼을 등록한다.
	인자
		key : 버튼과 연결될 키값
		button_obj : 버튼으로 사용될 오브젝트.. onclick 사용할 수 있으면 된다. 
		on_img_src: 활성이미지
		off_img_src: 비 활성 이미지
	*/
	this.add_image_button = function(key,button_obj,on_img_src,off_img_src){
		var button = this.add_button(key,button_obj);
		button.set_image_button(on_img_src,off_img_src); //이미지 버튼으로 설정함.
	}//end method
	
	/*
	진짜 버튼을 등록한다.
	인자
		key : 버튼과 연결될 키값
		button_obj : 버튼으로 사용될 오브젝트.. onclick 사용할 수 있으면 된다. 
		on_text: 활성텍스트
		off_text: 비 활성 텍스트
	*/
	this.add_real_button = function(key,button_obj,on_text,off_text){
		var button = this.add_button(key,button_obj);
		button.set_real_button(on_text,off_text); //이미지 버튼으로 설정함.
	}//end method
	

	
}//end class

/*
SwitchKey
SwitchDisplay 에서 사용하는 특정 키값에 대해서 관리하는 클래스
인자
	key : 키 이름
*/
PANSY.CNI.SwitchKey = function(key){
	
	this.key = key;// 키값
	this.display_obj_list = new Array(); //등록된 디스플레이요소 리스트 , 순차배열
	this.button_list = new Array(); //등록된 버튼 객체들.. 리스트
	
	this.prev = null; //이전의 키
	this.next = null; //다음 키
	
	/*
	디스플레이 요소 추가
	인자
		display_obj : 디스플레이 요소
	*/
	this.add_display_obj = function(display_obj){
		this.display_obj_list[this.display_obj_list.length]  = display_obj;
		
		display_obj.style.display="none";//처음에는 무조건 안보이도록 추가함
	}//end method
	
	/*
	등록된 요소들 디스플레이 시킴
	*/
	this.display = function(){
		for(var i = 0; i < this.display_obj_list.length; i++){
			display_obj =  this.display_obj_list[i]; //디스플레이 요소
			display_obj.style.display = "";
		}//end for i
		
		//등록된 버튼 on 처리
		for(var i = 0; i < this.button_list.length; i++){
			button =  this.button_list[i]; //디스플레이 요소
			button.on();
		}//end for i
		//등록된 버튼 on 처리 끝
	}//end method
	
	/*
	등록된 요소들 디스플레이해지
	*/
	this.display_none = function(){
		for(var i = 0; i < this.display_obj_list.length; i++){
			display_obj =  this.display_obj_list[i]; //디스플레이 요소
			display_obj.style.display = "none";
		}//end for i
		
		//등록된 버튼 off 처리
		for(var i = 0; i < this.button_list.length; i++){
			button =  this.button_list[i]; //디스플레이 요소
			button.off();
		}//end for i
		//등록된 버튼 off 처리 끝
	}//end method
	
	/*
	버튼 객체 등록
	인자
		button : 버튼객체
	*/
	this.add_button = function(button){
		this.button_list[this.button_list.length]  = button;
	}//end method
	
}//end class

/*
SwitchButton
등록된 오브젝트가 클릭되면, switch display 의 display 함수를 호출해서.. 디스플레이요소를 변경해준다. 

인자
	button_obj : 버튼으로 쓰일 오브젝트 ex) img 나.. div span 등.. onclick 사용할 수있는 요소는 다 됨. 
	key : 버튼 눌렷을때 표시될 디스플레이 키값
	switch_display : SwitchDisplay 객체.. 버튼이 눌렷을때, onclick 안에서 사용해야함.
*/
PANSY.CNI.SwitchButton = function (button_obj,key,switch_display){
	this.button_obj = button_obj; //버튼으로 쓰일 오브젝트
	this.key = key; //키값
	this.switch_display = switch_display;
	
	this.button_type = "normal"; //normal , img , button
	this.on_img_src = ""; //버튼 타입 img 일때 활성이미지
	this.off_img_src = ""; //버튼 타입 img 일때 비활성이미지
	
	this.on_text = ""; //버튼 타입 button 일때 활성텍스트
	this.off_text = ""; //버튼 타입 button 일때 비활성텍스트
	
	//온클릭 등록
	PANSY.addEvent(button_obj,"onclick",function(){
		switch_display.display(key);
	});
	//온클릭 등록 끝
	
	/*
	이미지 버튼으로 설정해줌
	기본적으로는 onclick 만사용하는 버튼이지만, 이 함수를 사용해주면 button_obj 가 이미지라고 가정하고 src 속성을 이용해서, 이미지까지 표시해준다.
	
	인자 
		on_img_src : 활성화 이미지
		off_img_src : 비활성 이미지
	*/
	this.set_image_button = function(on_img_src,off_img_src){
		this.button_type = "img"; // 버튼타입 이미지로 설정
		
		this.on_img_src = on_img_src;
		this.off_img_src = off_img_src;
		
		this.button_obj.src = off_img_src;//기본적으로 처음에는 오프이미지로 등록
	}//end method
	
	/*
	버튼객체를 버튼으로 설정해줌
	기본적으로는 onclick 만사용하는 버튼이지만, 이 함수를 사용해주면 button 의 value 속성을 이용해서 텍스트를 on/off 별로 다르게 표시해준다. 
	
	인자 
		on_text : 활성화 텍스트
		off_text : 비활성화 텍스트
	*/
	this.set_real_button = function(on_text,off_text){
		this.button_type = "button"; // 버튼타입 이미지로 설정
		
		this.on_text = on_text;
		this.off_text = off_text;
		
		this.button_obj.value = off_text;//기본적으로 처음에는 오프 텍스트
	}//end method
	
	/*
	버튼 on 처리 SwitchKey 에서 해당 키 선택되었을대 호출해줌
	*/
	this.on = function(){
		if(this.button_type == "img"){//img 인 경우만
			this.button_obj.src = this.on_img_src;
		}else if(this.button_type == "button"){//
			this.button_obj.value = this.on_text;
		}//end if
	}//end method
	
	/*
	버튼 off 처리 SwitchKey 에서 해당 키 선택되었을대 호출해줌
	*/
	this.off = function(){
		if(this.button_type == "img"){//img 인 경우만
			this.button_obj.src = this.off_img_src;
		}else if(this.button_type == "button"){//
			this.button_obj.value = this.off_text;
		}//end if
	}//end method
	
}//end class




/*
	div 영역을 세로 길이 조정가능한 영역으로 만들어준다.
	정해진 영역보다 커지면, 스크롤바가 생기고.. 세로길이는 맨 하단을 드래그함으로써 조정가능하다..
	
	인자
		div_outline : 테두리가 생길 div
		init_height : 처음 세로길이
		bottom_btn_height : 드래그되는 하단버튼의 높이
		div_bottom_btn : 드래그되는 하단 버튼부분 .. 값을 안넘겨주거나 null 값 넘겨주면 기본적인 모양생성해서 넣어준다.
	반환
		없음
		
	사용예
		PANSY.CNI.set_adjust_div_height($("div_id"),600,20);
*/
PANSY.CNI.set_adjust_div_height = function(div_outline,init_height,bottom_btn_height,div_bottom_btn){
//	bottom_btn_height = 16; //하단 드래그될 버튼부분 높이 지정
	
	//안쪽 div 생성
	var div_in = $c("div");
	div_in.style.height = (init_height - bottom_btn_height) + "px";
	div_in.style.overflowY ="auto";
	//안쪽 div 생성 끝
	
	//내용옮기기
	div_in.innerHTML = div_outline.innerHTML;
	div_outline.innerHTML = "";
	//내용옮기기 끝
	
	div_outline.appendChild(div_in);//div_in을 div_outline 속으로 옮기기
	
	//하단 조절 버튼 생성
	if(! div_bottom_btn){ //넘겨준게없는경우
		div_bottom_btn = $c("div"); 
		div_bottom_btn.style.fontSize = "9pt";
		div_bottom_btn.style.backgroundColor = "#585858";
		div_bottom_btn.style.color = "#E6E6E6";
		div_bottom_btn.style.textAlign = "center";
		div_bottom_btn.style.borderTop = "1px solid #848484";
		div_bottom_btn.style.borderBottom = "2px solid #2E2E2E";
		div_bottom_btn.innerHTML="↕::: 드래그시 세로길이조절 :::↕";
	}//end if
	div_bottom_btn.style.height = bottom_btn_height + "px";
	div_bottom_btn.style.position = "absolute";
	div_bottom_btn.style.top = (init_height - bottom_btn_height) +"px";
	div_bottom_btn.style.left = "0px";
	div_bottom_btn.style.width = "100%";
	div_bottom_btn.style.cursor = "s-resize";
	//하단 조절 버튼 생성 끝
	
	//div_outline 스타일설정
	div_outline.style.position="relative";
//	div_outline.style.height=init_height+"px";
	//div_outline 스타일설정 끝
	
	
	
	//하단조절버튼 높이만큼 공백 div 설정해줌
	var div_bottom_blank = $c("div");
	div_bottom_blank.style.height = bottom_btn_height + "px";
	div_outline.appendChild(div_bottom_blank);//하단조절버튼 추가
	//하단조절버튼 높이만큼 공백 div 설정해줌 끝
	
	div_outline.appendChild(div_bottom_btn);//하단조절버튼 추가
	
	//드래그 버튼부분에 이벤트 추가
	div_bottom_btn.dnd_mousemove = function(){
		if(div_bottom_btn.offsetTop > 0){// 너무 위쪽으로 이동하지못하도록 막음
			div_in.style.height = div_bottom_btn.offsetTop + "px";
		}else{//너무 위로갔음
			PANSY.DND.mouseUp(); //드래그 종료
		}//end if
	}//end if
	//드래그 버튼부분에 이벤트 추가 끝
	
	PANSY.DND.captureStart(); //드래그앤드롭 캡쳐시작
	div_bottom_btn.dnd_dont_move_x=true;//드래그 세로만 움직이도록 설정
//	div_bottom_btn.dnd_dont_move_parent_area = true;//부모영역벗어나지 못하도록 설정
	PANSY.DND.makeDraggable(div_bottom_btn);//드래그 사용하도록 설정
	
}//end func


/////////////////////////////////////////////////////////// 컨트롤 앤 인터페이스  끝

/////////////////////////////////////////////////////////// 폼 (서브밋 ) 관련

/*
	가장 흔하게 쓰이는 선택값 적용 검색결과전체적용 서브밋..
	
	사용하는 곳에서는 서브밋에 사용할 폼이 작성되어있어야 한다. 
	<form method="POST" name="frmBundle" action=""/>
		<input type="hidden" name="cmdType" value=""/>
		<input  type="hidden" name="hdnChkInc" value=""/>
		
		같이 포스트 전송시킬 다른 값이 있다면, 히든변수로 더 넣어주면 된다.
	</form>
	
	인자
		config : 오브젝트로 만들어서, 여기에 여러가지 정보를 담아넘겨주게 된다.
			.form_id : 서브밋에 사용할 폼의 아이디값
			.type : 서브밋의 타입을 설정한다 . select : 선택된 것만.. search_all : 검색결과전체..
			.add_cmdType : 위의 type + add_cmdType 으로 cmdType 변수가 전송된다. aaa 를 넘길경우 , select_aaa / search_all_aaa 이런식..
			.form_action : 폼의 액션값을 넘겨줘야함. 넘길때, 현재 겟변수까지 다 붙은 주소를 넘겨줘야 검색결과적용이 제대로 작동함.
			.chk_name : 선택하는 체크박스의 이름
			.hdn_inc_list_name : 체크된 번호들이 문자열로 연결되어 저장될 폼안의 히든변수 이름..ex ) hdnChkInc
			.msg1 : "검색된 모든 ?? 에 적요하시겠습니까? " 에 해당하는 메세지
			.msg2 : "선택하신 모든 ?? 에 적용하시겠습니까? " 에 해당하는 메세지
			.msg3 : "선택된 ??이 없습니다. " 에 해당하는 메세지
			
	사용 예
	function submitBundle(){
		PANSY.FORM.select_or_search_submit({
			"form_id" : "frmBundle",
			"type" : $("slt_bundle").value,
			"add_cmdType" : "save",
			"form_action":"LabellussoOrderList.php<?=getGETParams()?>",
			"chk_name":"chkSelect[]",
			"hdn_inc_list_name":"hdnChkInc",
			"msg1":"검색된 모든 주문건에 대해서 해당 정보들을 입력하시겠습니까 ? ",
			"msg2":"선택된 모든 주문건에 대해서 해당 정보들을 입력하시겠습니까 ? ",
			"msg3":"선택된 주문이 없습니다"
		});
	}//end func
	
	<form method="POST" name="frmBundle" action=""/>
		<input type="hidden" name="cmdType" value=""/>
		<input  type="hidden" name="hdnChkInc" value=""/>
	</form>
*/
PANSY.FORM.select_or_search_submit = function (config){
	
	var f = $(config.form_id);
	var type = config.type;
	
	f.cmdType.value = type +"_"+config.add_cmdType; //cmdType 설정
	f.action = config.form_action; //액션 설정
	
	//검증
	if(type=="search_all"){ //전체
		
		if (! confirm(config.msg1)) return;
		
	}else if(type=="select"){//선택
		
		//선택된 체크박스들.. 히든변수에 ,로 구분지어서 넣어주기
		if (! confirm(config.msg2)) return;
		
		//체크박스에 사용된값을 . 히든값으로 옮겨넣음.
		//체크박스 존재하는지 검사.
		var chk_list = $n(config.chk_name); //선택할 체크박스 리스트
		var hdn = f[config.hdn_inc_list_name]; //옮겨담을 히든변수


		
		//체크박스 만큼 돌면서.. 선택된값있는지 검사한다.
		hdn.value ="";
		for(var i =0;i<chk_list.length;i++){
			if(chk_list[i].checked) {
				
				hdn.value += chk_list[i].value+","; //PMInc 값을 컴마로 구분함.
			}
		}//end for i
		
		if(hdn.value == ""){
			alert(config.msg3 );
			return;
		}//end if
//		alert(hdn.value);
	}//end if
	
	f.submit();
}//end func

/////////////////////////////////////////////////////////// 폼 (서브밋 ) 관련 끝

//-->  
