﻿var CErr = function ()
{
	this.Description = "";
	this.Control = null;
}

var CConst =
{
	ServerVariableName:
	{
		Ip: "{{ServerVariableName.Ip}}",
		MemberKey: "{{ServerVariableName.MemberKey}}"
	}
};

var NumberFormatType =
{
	Currency : "#,##0",
	CurrencyUs : "#,##0.00",
	Percent : "#0.00%",
	ZipCode: "000",
	None : ""
};

//event.keyCode 상수
var Keys =
{
	BACKSPACE: 8, TAB: 9, ENTER: 13, SHIFT: 16,
	CTRL: 17, ALT: 18, PAUSE: 19, CAPS: 20,
	ESC: 27, PAGEUP: 33, PAGEDN: 34, END: 35,
	HOME: 36, LEFT: 37, UP: 38, RIGHT: 39,
	DOWN: 40, INSERT: 45, DELETE: 46,
	n0: 48, n1: 49, n2: 50, n3: 51, n4: 52,
	n5: 53, n6: 54, n7: 55, n8: 56, n9: 57,
	A: 65, B: 66, C: 67, D: 68, E: 68, F: 70, G: 71, H: 72, I: 73, J: 74, K: 75,
	L: 76, M: 77, N: 78, O: 79, P: 80, Q: 81, R: 82, S: 83, T: 84, U: 85, V: 86,
	W: 87, X: 88, Y: 89, Z: 90,
	WINLEFT: 91, WINRIGHT: 92, SELECT: 93, NUM0: 96,
	NUM1: 97, NUM2: 98, NUM3: 99, NUM4: 100,
	NUM5: 101, NUM6: 102, NUM7: 103, NUM8: 104,
	NUM9: 105, MULTIPLY: 106, ADD: 107, SUBTRACT: 109,
	DECIMAL: 110, DIVIDE: 111, F1: 112, F2: 113,
	F3: 114, F4: 115, F5: 116, F6: 117,
	F7: 118, F8: 119, F9: 120, F10: 121,
	F11: 122, F12: 123, NUMLOCK: 144, SCROLLLOCK: 145,
	SEMICOLON: 186, EQUAL: 187, COMMA: 188, DASH: 189,
	PERIOD: 190, FORWARDSLASH: 191, GRAVEACCENT: 192,
	OPENBRACKET: 219, BACKSLASH: 220, CLOSEBRACKET: 221,
	QUOTE: 222,
	LF: 10,	CR: 13,	CLICK: 229
};

var NodeType =
{
	ELEMENT_NODE: 1,
	ATTRIBUTE_NODE: 2,
	TEXT_NODE: 3,
	CDATA_SECTION_NODE: 4,
	ENTITY_REFERENCE_NODE: 5,
	ENTITY_NODE: 6,
	PROCESSING_INSTRUCTION_NODE: 7,
	COMMENT_NODE: 8,
	DOCUMENT_NODE: 9,
	DOCUMENT_TYPE_NODE: 10,
	DOCUMENT_FRAGMENT_NODE: 11,
	NOTATION_NODE: 12
};

function CloneObject(Obj)
{
	if (Obj == null || typeof(Obj) != 'object')
		return Obj;

	var ObjNew = Obj.constructor();

	for (var Key in Obj)
		ObjNew[Key] = CloneObject(Obj[Key]);

	return ObjNew;
} 

//function IsIE()
//{
//	return document.all;
//}
//function IsNN6()
//{
//	return document.getElementById && !document.all;
//}

//=========================
//마우스 이벤트 순서: onmousedown, onmouseup, onclick
var CControl = new Object();
CControl.RemoveAllOptions = function (Sel)
{
	//한번에 제거하는 메쏘드는 없음.
	while (Sel.options.length > 0)
	{
		Sel.options.remove(0);
	}
}
	
/*
--설명
특정 컨트롤이 속한 폼을 찾아 리턴함.
runat="server"인 form의 경우 client에서 이름을 알 수 없으므로
현재 컨트롤을 가진 폼을 찾기 위함.
*/
CControl.GetParentForm = function (Elem)
{
	while (true)
	{
		Elem = Elem.parentElement;
		if (Elem.tagName == "FORM")
		{
			return Elem;
		}
		else if (Elem == null)
		{
			return null;
		}
		else if (Elem.tagName == "BODY")
		{
			return null;
		}
	}
}

/*
--예제
//다음은 숫자 입력만 허용함.
public static function t_keypress()
{
	event.keyCode = CControl.FilterKeyCode(event.keyCode, "0123456789");
}
*/
CControl.FilterKeyCode = function (KeyCode, KeyList, IsFromKeyDownUp)
{
	if (IsFromKeyDownUp)
	{
		if (CControl.ContainsControlKey(KeyCode))
		{
			return KeyCode;
		}
	}
	else
	{
		//엔터키
		if (KeyCode == 13)
		{
			return KeyCode;
		}
	}

	var sKey = String.fromCharCode(KeyCode);
	if (KeyList.indexOf(sKey) != -1)
	{
		return KeyCode;
	}

	return 0;
}
	
/*
--설명
radio, checkbox 컨트롤의 배열 중 선택된 value 값을 콤마로 구분해서 리턴함.
*/
CControl.GetCheckedValue = function (aRadChk)
{
	aRadChk = CControl.IfNotArrayControlConvertToArray(aRadChk);

	var ValueList = "";
	for (var i = 0, i2 = aRadChk.length; i < i2; i++)
	{
		if (aRadChk[i].checked)
		{
			ValueList += "," + aRadChk[i].value;
		}
	}
	if (ValueList != "")
	{
		ValueList = ValueList.substring(1);
	}

	return ValueList;
}
	
/*
--설명
컨트롤을 읽기 전용으로 설정하거나 해제함.
readOnly 속성이 없는 select의 경우는 disabled 속성을 이용하면 되나
submit할 때 값을 읽을 수 없으므로 이전 값이 다시 선택되도록 함.
*/
CControl.SetReadOnly = function (Ctl, IsReadOnly, IsChangeBackColor, UseScriptForSelect)
{
	var BackColor = IsReadOnly ? "#dddddd" : "white";

	Ctl = CControl.IfNotArrayControlConvertToArray(Ctl);

	for (var i = 0, i2 = Ctl.length; i < i2; i++)
	{
		switch (Ctl[i].type)
		{
			case "text":
			case "password":
				Ctl[i].readOnly = IsReadOnly;

				if (IsChangeBackColor)
				{
					Ctl[i].style.backgroundColor = BackColor;
				}
				break;
			case "textarea":
				Ctl[i].readOnly = IsReadOnly;

				if (IsChangeBackColor)
				{
					Ctl[i].style.backgroundColor = BackColor;
				}
				break;
			case "select-one":
				if (UseScriptForSelect)
				{
					if (IsReadOnly)
					{
						Ctl[i].setAttribute("OldIndex", Ctl[i].selectedIndex);
						CEvent.AddEvent(Ctl[i], "onchange",
								function(e)
								{
									var Src = CEvent.GetSrc(e);
									Src.selectedIndex = parseInt(Src.getAttribute("OldIndex"), 10);
								}
							);
					}
					else
					{
						Ctl[i].removeAttribute("OldIndex");
						Ctl[i].onchange = "";
					}
				}
				else
				{
					Ctl[i].disabled = IsReadOnly;
				}

				if (IsChangeBackColor)
				{
					Ctl[i].style.backgroundColor = BackColor;
				}
				break;
			case "button":
			case "checkbox":
				//Ctl[i].disabled = IsReadOnly;
				//disabled 설정하면 회색이 자동으로 됨.
				break;
			default:
				switch (Ctl[i].tagName)
				{
					case "IMG":
						Ctl[i].disabled = IsReadOnly;
						break;
				}
				break;
		}
	}
}

/*
--설명
태그 이름과 속성 이름, 속성 값에 해당하는 첫번째 컨트롤을 리턴함.
--예제
var Src = event.srcElement;
var TagName = "label";
var AttribName = "for";
var AttribValue = Src.id;
var Elem = CControl.GetFirstElementHasElemAttrib(TagName, AttribName, AttribValue);
alert(Elem.innerText);
*/
CControl.GetFirstElementHasElemAttrib = function (TagName, AttribName, AttribValue)
{
	var aElems = document.getElementsByTagName(TagName);
	for (var i = 0, i2 = aElems.length; i < i2; i++)
	{
		//<label for="ral_0">에서 for 값을 읽지 못해 주석.
		//if (aElems[i].getAttribute(AttribName) == AttribValue)


		var Elem = aElems[i];
		var Attr = Elem.attributes[AttribName];
		if (Attr == null)
			continue;

		if (Attr.nodeValue != AttribValue)
			continue;

		return Elem;
	}

	return null;
}

/*
--설명
NodeParent 안에 지정된 태그이름을 가진 노드를 리턴함.
*/
CControl.GetFirstChildHasTag = function (NodeParent, TagName)
{
	for (var i = 0, i2 = NodeParent.childNodes.length; i < i2; i++)
	{
		NodeCur = NodeParent.childNodes[i];
		if (NodeCur.tagName)
		{
			if (NodeCur.tagName == TagName.toUpperCase())
			{
				return NodeCur;
			}
		}
	}

	return null;
}

/*
--설명
Elem을 가지고 있는 TABLE Element를 리턴함.
*/
CControl.GetParentElement = function (Elem, TagName)
{
	while (Elem.parentElement != null)
	{
		Elem = Elem.parentElement;
		if (Elem.tagName == TagName.toUpperCase())
		{
			return Elem;
		}
	}

	return null;
}

CControl.GetPreviousElementNode = function (Elem)
{
	var x = Elem.previousSibling;
	while ((x != null) && (x.nodeType != NodeType.ELEMENT_NODE))
	{
		x = x.previousSibling;
	}
	return x;
}
CControl.GetNextElementNode = function (Elem)
{
	var x = Elem.nextSibling;
	while ((x != null) && (x.nodeType != NodeType.ELEMENT_NODE))
	{
		x = x.nextSibling;
	}
	return x;
}

/*
--설명
제목행을 제외한 행의 개수를 설정함.
*/
CControl.SetTableRowLength = function (tbl, Rows)
{
	if ((tbl.rows.length - 1) > Rows)
	{
		while ((tbl.rows.length - 1) > Rows)
		{
			tbl.deleteRow(tbl.rows.length - 1);
		}
	}
	else
	{
		var Cols = tbl.rows[0].cells.length;
		for (var rw = 0, rw2 = Rows; rw < rw2; rw++)
		{
			Row = tbl.insertRow();
			for (var cl = 0, cl2 = Cols; cl < cl2; cl++)
			{
				Row.insertCell();
			}
		}
	}
}

CControl.ScrollBottom = function (Div)
{
	if (Div.scrollTop != null)
	{
		Div.scrollTop = Div.scrollHeight - Div.clientHeight;
	}
}

CControl.CopySelectedValue = function (Sel)
{
	if (Sel.selectedIndex == -1) {
		alert("변수를 선택하지 않았습니다.");
		return;
	}

	var Value = "{{" + Sel.options[Sel.selectedIndex].value + "}}";
	CControl.CopyText(Value);
}
CControl.CopyTextBoxValue = function (Txt)
{
	var Value = Txt.value;
	window.clipboardData.setData("Text", Value);
}
CControl.CopyText = function (Text)
{
	window.clipboardData.setData("Text", Text);
}


/*
--설명
하나라도 체크된 것이 있으면 모두 해제, 모두 해제되어있어야만 모두 선택함.
--예제
<input type=checkbox id=chkAdmin>
<span id=spnAdmin style="cursor: hand;" onclick="CControl.ToggleChecked(document.getElementById("chkAdmin"))">관리자 여부</span>
*/
CControl.ToggleChecked = function (Chk)
{
	var aChk = CControl.IfNotArrayControlConvertToArray(Chk);

	var IsChecked = false;
	for (var i = 0, i2 = aChk.length; i < i2; i++)
	{
		if (aChk[i].type != "checkbox") return;
		if (aChk[i].disabled) return;

		if (aChk[i].checked)
		{
			IsChecked = true;
			break;
		}
	}

	for (var i = 0, i2 = aChk.length; i < i2; i++)
	{
		aChk[i].checked = !IsChecked;
	}
}

/*
--설명
img 태그의 이미지 크기가 한계를 넘었다면 한계를 넘지 않도록 조절함.
*/
CControl.ResizeImage = function (Img, WidthLimit, HeightLimit)
{
	var w = Img.width;
	var h = Img.height;
	
	//		if (!HeightLimit)
	//		{
	//			alert("!")
	//			var HRate = (h / w);
	//			HeightLimit = (WidthLimit * HRate);
	//			alert(HRate + "-" + HeightLimit)
	//		}

	if ((w <= WidthLimit) && (h <= HeightLimit))
	{
		return;
	}

	if (w > WidthLimit)
	{
		var HRate = h / w;
		w = WidthLimit;
		h = w * HRate;
	}
	if (h > HeightLimit)
	{
		var WRate = w / h;
		h = HeightLimit;
		w = h * WRate;
	}

	Img.width = w;
	Img.height = h;
}

CControl.IfNotArrayControlConvertToArray = function (Ctl)
{
	if (Ctl[0] == null)
	{
		return new Array(Ctl);
	}
	else if (Ctl[0].tagName == "OPTION")
	{
		//option은 select의 배열처럼 취급되므로
		return new Array(Ctl);
	}
	else
	{
		return Ctl;
	}
}

CControl.GetControlToMove = function (Ctl, IsNext)
{
	for (var i = 0, i2 = document.all.length; i < i2; i++)
	{
		if (Ctl == document.all[i])
		{
			if (IsNext)
			{
				for (var j = (i + 1), j2 = document.all.length; j < j2; j++)
				{
					if (CControl.CanFocusable(document.all[j]))
					{
						return document.all[j];
					}
				}
			}
			else
			{
				for (var j = (i - 1), j2 = 0; j >= j2; j--)
				{
					if (CControl.CanFocusable(document.all[j]))
					{
						return document.all[j];
					}
				}
			}
		}
	}
}

CControl.CanFocusable = function (Ctl)
{
	if (Ctl.disabled)
	{
		return false;
	}
	
	switch (Ctl.tagName)
	{
		case "TEXTAREA":
		case "SELECT":
			return true;
		case "INPUT":
			switch (Ctl.type)
			{
				case "text":
				case "password":
					return true;
				default:
					return false;
			}
	}
	
	return false;
}

CControl.CenterControl = function (Ctl)
{
	var FullWidth = CControl.GetBodyClientWidth();
	var FullHeight = CControl.GetBodyClientHeight();
	
	if (Ctl.style.position != "absolute") Ctl.style.position = "absolute";
	
	Ctl.style.left = (FullWidth - Ctl.offsetWidth) / 2;
	Ctl.style.top = (FullHeight - Ctl.offsetHeight) / 2;
}
CControl.GetBodyClientHeight = function ()
{
	if (window.innerHeight != window.undefined) return window.innerHeight;
	if (document.compatMode == 'CSS1Compat') return document.documentElement.clientHeight;
	if (document.body) return document.body.clientHeight;
	return window.undefined;
}
CControl.GetBodyClientWidth = function ()
{
	if (window.innerWidth != window.undefined) return window.innerWidth;
	if (document.compatMode == 'CSS1Compat') return document.documentElement.clientWidth;
	if (document.body) return document.body.clientWidth;
	return window.undefined;
}

CControl.ContainsControlKey = function (Key)
{
	switch (Key)
	{
		case Keys.HOME:
		case Keys.END:
		case Keys.LEFT:
		case Keys.UP:
		case Keys.RIGHT:
		case Keys.DOWN:
		case Keys.TAB:
		case Keys.CR:
		case Keys.LF:
		case Keys.SHIFT:
		case Keys.CTRL:
		case Keys.ALT:
		case Keys.CLICK:
			return true;
		default:
			return false;
	}
}

//http://www.howtocreate.co.uk/tutorials/javascript/browserspecific
CControl.GetPosition = function GetPosition(oElement)
{
	function getNextAncestor(oElement)
	{
		var actualStyle;
		if (window.getComputedStyle)
		{
			actualStyle = getComputedStyle(oElement, null).position;
		} else if (oElement.currentStyle)
		{
			actualStyle = oElement.currentStyle.position;
		} else
		{
			//fallback for browsers with low support - only reliable for inline styles
			actualStyle = oElement.style.position;
		}
		if (actualStyle == 'absolute' || actualStyle == 'fixed')
		{
			//the offsetParent of a fixed position element is null so it will stop
			return oElement.offsetParent;
		}
		return oElement.parentNode;
	}

	if (typeof (oElement.offsetParent) != 'undefined')
	{
		var originalElement = oElement;
		for (var posX = 0, posY = 0; oElement; oElement = oElement.offsetParent)
		{
			posX += oElement.offsetLeft;
			posY += oElement.offsetTop;
		}
		if (!originalElement.parentNode || !originalElement.style || typeof (originalElement.scrollTop) == 'undefined')
		{
			//older browsers cannot check element scrolling
			return { X: posX, Y: posY };
		}
		oElement = getNextAncestor(originalElement);
		while (oElement && oElement != document.body && oElement != document.documentElement)
		{
			posX -= oElement.scrollLeft;
			posY -= oElement.scrollTop;
			oElement = getNextAncestor(oElement);
		}
		return { X: posX, Y: posY };
	}
	else
	{
		return { X: oElement.x, Y: oElement.y };
	}
}

CControl.GetMousePosition = function GetMousePosition(evt)
{
	var X = 0;
	var Y = 0;

	if (evt.pageX)
	{
		X = evt.pageX;
		Y = evt.pageY;
	}
	else if (evt.clientX)
	{
		X = evt.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
		Y = evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
	}

	return { X: X, Y: Y };
}

CControl.GetMousePositionRelative = function (Target, e)
{
	e = e || window.event;

	var TargetPos = CControl.GetPosition(Target);
	var MousePos = CControl.GetMousePosition(e);
	return {X:MousePos.X - TargetPos.X, Y:MousePos.Y - TargetPos.Y};
}


CControl.GetAllChildHasTag = function (TagName)
{
	var oCtl = new Array();
	_GetAllChildHasTag(document, TagName, oCtl);
	return oCtl;
}
function _GetAllChildHasTag(ParentElem, TagName, oCtl)
{
	for (var i = 0; i < ParentElem.childNodes.length; i++)
	{
		var Elem = ParentElem.childNodes[i];
		if ((Elem.nodeType == NodeType.ELEMENT_NODE) && (Elem.tagName.toLowerCase() == TagName.toLowerCase()))
		{
			oCtl.push(Elem);
		}

		_GetAllChildHasTag(Elem, TagName, oCtl);
	}
}

/*
--설명
닷넷에서 만든 RadioButtonList의 모든 radio를 리턴함.
*/
CControl.GetDotNetRadioButtonListItems = function (ClientID)
{
	var aRadio = new Array();
	for (var i = 0, i2 = 100; i < i2; i++)
	{
		var RadioCur = document.getElementById(ClientID + "_" + i);
		if (RadioCur)
			aRadio[i] = RadioCur;
		else
			break;
	}
	
	return aRadio;
}


//FireFox에서도 되도록 DOM을 사용함.
CControl.RaiseEvent = function (Src, EventName)
{
	if (document.all)
	{
		//EventName: onchange, onclick...
		if (EventName.substr(0, 2).toLowerCase() != "on")
		{
			EventName = "on" + EventName;
		}

		Src.fireEvent(EventName);
	}
	else
	{
		//EventName: change, click...
		if (EventName.substr(0, 2).toLowerCase() == "on")
		{
			EventName = EventName.substr(2);
		}

		var e = document.createEvent("HTMLEvents");
		//event.initEvent(type, bubbles, cancelable)
		e.initEvent(EventName, false, false);
		Src.dispatchEvent(e);
	}
}

/*
--설명
닷넷에서 만든 RadioButtonList의 선택된 Item의 Value와 Text를 리턴함.
--예제
var Itm = CControl.GetDotNetRadioButtonListSelectedItem("<퍼센트 = ral.ClientID 퍼센트>");
if (Itm != null)
{
	alert(Itm.Src.id + "." + Itm.Value + "." + Itm.Text);
}
*/
CControl.GetDotNetRadioButtonListSelectedItem = function (ClientID)
{
	var Obj = new Object();
	Obj.Src = null;
	Obj.Text = "";
	Obj.Value = "";
	
	var aInput = document.getElementsByTagName("input");
	for (var i = 0, i2 = aInput.length; i < i2; i++)
	{
		var Input = aInput[i];
		if (Input.id.substr(0, ClientID.length) != ClientID)
			continue;
		
		if (!Input.checked)
			continue;
		
		Obj.Src = Input;
		Obj.Value = Input.attributes["value"].nodeValue;
		
		var lbl = CControl.GetFirstElementHasElemAttrib("label", "for", Input.id);
		if (lbl)
		{
			Obj.Text = lbl.innerHTML;
		}
	}
	if (Obj.Value == "")
		return null;
	
	
	return Obj;
}

/*
--설명
닷넷의 GridView의 ItemTemplate 안에 만들어진 모든 CheckBox를 배열로 만들어 리턴함.
CheckBox의 ClientID는 행이 전부 표시되기 전에는 알수 없으므로 GridView의 ClientID와 
CheckBox의 서버에서 지정한 ID를 조합해서 CheckBox의 ClientID를 추리함.
--예제
aStmt.Add("var " + chkSelectArrayName + " = CControl.GetDotNetGridViewCheckBoxItems('" + grv.ClientID + "', '" + chkSelectId + "');");
*/
CControl.GetDotNetGridViewCheckBoxItems = function (GridViewClientID, CheckBoxServerId)
{
	//ctl00_cphContentBody_grvList_ctl02_chkSelect

	var aCheckBox = new Array();

	var aInput = document.getElementsByTagName("input");
	for (var i = 0, i2 = aInput.length; i < i2; i++)
	{
		var Input = aInput[i];

		if (Input.type != "checkbox")
			continue;

		if (!CFindRep.StartsWith(Input.id, GridViewClientID + "_"))
			continue;

		if (!CFindRep.EndsWith(Input.id, "_" + CheckBoxServerId))
			continue;

		aCheckBox.push(Input);
	}

	return aCheckBox;
}

/*
--설명
Ctl의 type에 따라 값을 리턴함.
*/
CControl.GetControlValueByType = function (Ctl)
{
	var Value = null;
	switch (Ctl.type)
	{
		case "text":
		case "password":
		case "textarea":
		case "hidden":
			Value = Ctl.value;
			break;
		case "select-one":
			Value = Ctl.options[Ctl.selectedIndex].value;
			break;
		case "checkbox":
		case "radio":
			Value = Ctl.checked;
			break;
	}

	return Value;
}

//=========================
var CEvent = new Object();
CEvent.AddEvent = function (Obj, EventName, Handler)
{
	if (CFindRep.StartsWith(EventName, "on", true))
	{
		EventName = EventName.substring(2);
	}

	if (Obj.addEventListener)
	{
		Obj.addEventListener(EventName, Handler, false);
		return true;
	}
	else if (Obj.attachEvent)
	{
		var r = Obj.attachEvent("on" + EventName, Handler);
		return r;
	}
	else
	{
		alert("Event handler could not be attached");
		return false;
	}
}

/*
--설명
기본적으로 지시사항이 표시되고, focus를 받으면 지시사항이 사라지게 하는 기능 구현.
--예제
CEvent.ApplyInstructionImageToText(txtLogInId, "url(/images/member/txt_log_in_id.gif) no-repeat 5px 1px");
*/
CEvent.ApplyInstructionImageToText = function (Txt, background)
{
	if (Txt.value == "")
	{
		Txt.style.background = background;
	}

	CEvent.AddEvent(
		Txt,
		"focus",
		function (e)
		{
			var Src = CEvent.GetSrc(e);
			Src.style.background = "";
		}
	);
	CEvent.AddEvent(
		Txt,
		"blur",
		function (e)
		{
			var Src = CEvent.GetSrc(e);
			if (!Src.value)
				Src.style.background = background;
		}
	);
}

//CEvent.ApplyInstructionToText = function (Txt, Instruction)
//{
//	if (Txt.value == "")
//	{
//		Txt.value = Instruction;
//	};
//	
//	CEvent.AddEvent(
//		Txt,
//		"focus",
//		function(event)
//		{
//			var Value = event.value;
//			if (Value == Instruction)
//			{
//				Value = "";
//			}
//			event.value = Value;
//		}
//	);
//	
//	CEvent.AddEvent(
//		Txt,
//		"blur",
//		function()
//		{
//			var Value = event.value;
//			if (Value == "")
//			{
//				Value = Instruction;
//			}
//			event.value = Value;
//		}
//	);
//}

/*
--설명
이메일 제공회사를 선택하면 @ 다음 란을 입력할 수 없고,
직접입력을 선택하면 @ 다음 란을 입력할 수 있는 기능 구현
*/
CEvent.ApplyEmailProviderSelection = function (txtEmail1, txtEmail2, selEmailProvider)
{
	//var txtEmail1Name = txtEmail1.name;
	//var txtEmail2Name = txtEmail2.name;

	CEvent.AddEvent(
		txtEmail1,
		"onchange",
		function()
		{
			var Value = selEmailProvider.value;
			if (Value == "custom")
			{
				txtEmail2.value = "";
				txtEmail2.readOnly = false;
			}
			else
			{
				txtEmail2.value = Value;
				txtEmail2.readOnly = true;;
			}

			txtEmail1.focus();
		}
	);
}

/*
--설명
length 속성만큼 문자열이 찼을 때 다음 컨트롤로 focus를 이동시킬 Text 컨트롤 배열
*/
CEvent.ApplyWhenMaxMoveToNext = function (aText)
{
	var ProcName = "ApplyWhenMaxMoveToNext";
	
	aText = CControl.IfNotArrayControlConvertToArray(aText);
	
	for (var i = 0, i2 = aText.length; i < i2; i++)
	{
		var TextCur = aText[i];
		if (TextCur.tagName != "INPUT")
		{
			alert(ProcName + " aText의 tagName이 INPUT이 아닙니다.");
			return;
		}
		
		if ((TextCur.type != "text") && (TextCur.type != "password"))
		{
			alert(ProcName + " aText의 type이 text, password가 아닙니다.");
			return
		}

		CEvent.AddEvent(
			aText[i],
			"onkeyup",
			function(Evt)
			{
				var Evt = window.event || Evt;
				var Txt = Evt.srcElement || Evt.target;
				
				//Shift+Tab, Tab 키로 이동할 수 있으므로 Shift(16), Tab(9) 키가 눌러져 있다면 빠져나감.
				if (Evt.keyCode == 16) return;
				if (Evt.keyCode == 9) return;
				
				//클릭했을 때도 keyCode가 229가 되므로 빠져나감.
				if (Evt.keyCode == 229) return;

				if (Txt.value.length >= Txt.maxLength)
				{
					var TxtNext = CControl.GetControlToMove(Txt, true);
					if (TxtNext)
					{
						TxtNext.focus();

						//다음 컨트롤에 값이 있다면 전체선택을 할 수 있게 함.
						if (
							((TxtNext.tagName == "INPUT") && (TxtNext.type == "text"))
							|| ((TxtNext.tagName == "INPUT") && (TxtNext.type == "password"))
							)
						{
							TxtNext.select();
						}
					}
				}
			}
		);
		
	}
}

/*
--설명
숫자만 입력을 허용함
*/
CEvent.ApplyFilterNumber = function (MinValue, MaxValue, Format, aText)
{
	var ProcName = "ApplyFilterNumber";

	aText = CControl.IfNotArrayControlConvertToArray(aText);

	for (var i = 0, i2 = aText.length; i < i2; i++)
	{
		var TextCur = aText[i];
		if (TextCur.tagName != "INPUT")
		{
			alert(ProcName + " aText의 tagName이 INPUT이 아닙니다.");
			return;
		}

		if ((TextCur.type != "text") && (TextCur.type != "password"))
		{
			alert(ProcName + " aText의 type이 text, password가 아닙니다.");
			return
		}

		if (!isNaN(MinValue))
			TextCur.setAttribute("MinValue", MinValue);
		if (!isNaN(MaxValue))
			TextCur.setAttribute("MaxValue", MaxValue);

		TextCur.setAttribute("Format", Format);

		switch (Format)
		{
			case NumberFormatType.Currency:
			case NumberFormatType.CurrencyUs:
			case NumberFormatType.Percent:
				if (TextCur.style.textAlign != "right")
				{
					TextCur.style.textAlign = "right";
				}
				break;
		}

		CEvent.AddEvent(
			TextCur,
			"onkeypress",
			function(Evt)
			{
				var Evt = window.event || Evt;
				var Src = Evt.srcElement || Evt.target;

				var Format = Src.getAttribute("Format");
				var Filter = CEvent.GetFilter(Format);
				Evt.keyCode = CControl.FilterKeyCode(Evt.keyCode, Filter);
			}
		);

		CEvent.AddEvent(
			TextCur,
			"onfocus",
			function(Evt)
			{
				var Evt = window.event || Evt;
				var Src = Evt.srcElement || Evt.target;

				if (Src.value.indexOf(",") != -1)
				{
					Src.value = CFindRep.ReplaceAll(Src.value, ",", "");
				}

				if (CFindRep.EndsWith(Src.value, "%"))
				{
					Src.value = CType.ConvertPercentToFloat(Src.value);
				}
			}
		);

		CEvent.AddEvent(
			TextCur,
			"onblur",
			function(Evt)
			{
				var Evt = window.event || Evt;
				var Src = Evt.srcElement || Evt.target;

				var MinValue = (Src.getAttribute("MinValue") == null) ? NaN : CFindRep.IfNotNumberThen0(Src.getAttribute("MinValue"));
				var MaxValue = (Src.getAttribute("MaxValue") == null) ? NaN : CFindRep.IfNotNumberThen0(Src.getAttribute("MaxValue"));
				var Format = Src.getAttribute("Format");
				var IsCountable = CEvent.GetCountableFormat(Format);
				var Filter = CEvent.GetFilter(Format);

				var Value = Src.value;
				//eval에서 계산할 수 있도록 콤마 제거
				Value = CFindRep.ReplaceAll(Value, ",", "");

				if (Value == "")
					return;

				var nValue = NaN;
				if (IsCountable)
				{
					if (CFindRep.Contains4Operator(Value))
					{
						try
						{
							nValue = eval(Value);
						}
						catch (ex) { }
					}
					else
					{
						try
						{
							if (Format == NumberFormatType.CurrencyUs)
							{
								nValue = parseFloat(Value);
							}
							else if (Format == NumberFormatType.Percent)
							{
								nValue = CType.ConvertPercentToFloat(Value);
							}
							else
							{
								nValue = parseInt(Value, 10);
							}
						}
						catch (ex) { }
					}

					if (isNaN(nValue))
					{
						Src.value = "";
						return;
					}

					if (!isNaN(MinValue))
					{
						if (nValue < MinValue)
						{
							alert(nValue + " 값이 허용된 최소값인 " + MinValue + "보다 작습니다.");
							Src.focus();
							return;
						}
					}

					if (!isNaN(MaxValue))
					{
						if (nValue > MaxValue)
						{
							alert(nValue + " 값이 허용된 최대값인 " + MaxValue + "보다 큽니다.");
							Src.focus();
							return;
						}
					}

					Value = nValue;
				}
				else
				{
					if (CFindRep.HasValueNotInList(Value, Filter))
					{
						Src.value = CFindRep.RemoveExcept(Src.value, Filter);
						return;
					}
				}

				if (Format == "")
				{
					Src.value = Value;
				}
				else
				{
					Src.value = CFindRep.Format(Value, Format);
				}
			}
		);

	}
}
CEvent.GetCountableFormat = function (Format)
{
	var IsCountable = false;
	switch (Format)
	{
		case NumberFormatType.Currency:
		case NumberFormatType.CurrencyUs:
		case NumberFormatType.Percent:
			IsCountable = true;
			break;
		default:
			break;
	}

	return IsCountable;
}
CEvent.GetFilter = function (Format)
{
	var Filter = "0123456789";
	switch (Format)
	{
		case NumberFormatType.Currency:
		case NumberFormatType.CurrencyUs:
		case NumberFormatType.Percent:
			Filter += ".+-*/%";
			break;
	}

	return Filter;
}

CEvent.ApplyFilterTime = function (txtHour, txtMinute, txtSecond)
{
	var ProcName = "ApplyFilterTime";
	
	txtHour.setAttribute("MinValue", 0);
	txtHour.setAttribute("MaxValue", 23);

	txtMinute.setAttribute("MinValue", 0);
	txtMinute.setAttribute("MaxValue", 59);

	txtSecond.setAttribute("MinValue", 0);
	txtSecond.setAttribute("MaxValue", 59);
	
	var aText = new Array(txtHour, txtMinute, txtSecond);
	for (var i = 0, i2 = aText.length; i < i2; i++)
	{
		var TextCur = aText[i];
		if (TextCur.tagName != "INPUT")
		{
			alert(ProcName + " aText의 tagName이 INPUT이 아닙니다.");
			return;
		}
		
		if ((TextCur.type != "text") && (TextCur.type != "password"))
		{
			alert(ProcName + " aText의 type이 text, password가 아닙니다.");
			return
		}

		CEvent.AddEvent(
			TextCur,
			"onkeypress",
			function(Evt)
			{
				var Evt = window.event || Evt;
				Evt.keyCode = CControl.FilterKeyCode(Evt.keyCode, "0123456789");
			}
		);
		
		CEvent.AddEvent(
			TextCur,
			"onchange",
			function(Evt)
			{
				var Evt = window.event || Evt;
				var Src = Evt.srcElement || Evt.target;
				
				var Value = parseInt(Src.value, 10);
				var MinValue = parseInt(Src.getAttribute("MinValue"), 10);
				var MaxValue = parseInt(Src.getAttribute("MaxValue"), 10);

				if (isNaN(Value))
				{
					Src.value = "";
				}
				else if ((Value < MinValue) || (Value > MaxValue))
				{
					Src.value = "";
				}
			}
		);
		
		CEvent.AddEvent(
			TextCur,
			"onkeyup",
			function(Evt)
			{
				var Evt = window.event || Evt;
				var Src = Evt.srcElement || Evt.target;
				
				if (CControl.ContainsControlKey(Evt.keyCode))
				{
					return;
				}

				//{잘못된 값이면 이동 못해야 하므로 이동 전에 먼저 체크함.
				var Txt = Src;
				var Value = parseInt(Txt.value, 10);
				var MinValue = parseInt(Txt.getAttribute("MinValue"), 10);
				var MaxValue = parseInt(Txt.getAttribute("MaxValue"), 10);

				if (isNaN(Value))
				{
					Txt.value = "";
				}
				else if ((Value < MinValue) || (Value > MaxValue))
				{
					Txt.value = "";
				}
				//}


				if (Txt.value.length >= Txt.maxLength)
				{
					var TxtNext = CControl.GetControlToMove(Txt, true);
					if (TxtNext)
					{
						TxtNext.focus();

						//다음 컨트롤에 값이 있다면 전체선택을 할 수 있게 함.
						if (
							((TxtNext.tagName == "INPUT") && (TxtNext.type == "text"))
							|| ((TxtNext.tagName == "INPUT") && (TxtNext.type == "password"))
							)
						{
							TxtNext.select();
						}
					}
				}
				
			}
		);
		
	}
}

/*
--설명
숫자만 입력을 허용함
*/
CEvent.ApplyFormula = function (aText, Formula)
{
	var ProcName = "ApplyFormula";
	
	aText = CControl.IfNotArrayControlConvertToArray(aText);
	
	for (var i = 0, i2 = aText.length; i < i2; i++)
	{
		var TextCur = aText[i];
		if (TextCur.tagName != "INPUT")
		{
			alert(ProcName + " aText의 tagName이 INPUT이 아닙니다.");
			return;
		}
		
		if ((TextCur.type != "text") && (TextCur.type != "password"))
		{
			alert(ProcName + " aText의 type이 text, password가 아닙니다.");
			return
		}
		
		TextCur.setAttribute("Formula", Formula);
		
		CEvent.AddEvent(
			TextCur,
			"onfocus",
			function(Evt)
			{
				var Evt = window.event || Evt;
				var Src = Evt.srcElement || Evt.target;
				
				var Formula = Src.getAttribute("Formula");
				if (!Formula)
					return;				

				var Value = Src.value;
				//이미 값이 있다면 빠져나감.
				if (Value)
					return;
				
				var Result = "";
				try
				{
					Result = eval(Formula);
				}
				catch (ex) { }
				
				if (Result)
				{
					Result = CMath.Round(Result, 0);
					Src.value = CFindRep.Format(Result, NumberFormatType.Currency);
					Src.select();
				}
			}
		);
		
	}	
}

/*
--설명
포커스를 받거나 키 입력하면 너비가 커짐.
*/
CEvent.ApplyResizeByValue = function (Ctl, MinSize, MaxSize)
{
	CEvent.AddEvent(Ctl,
		"onfocus",
		function(e)
		{
			var Src = CEvent.GetSrc(e);

			if (Src.getAttribute("SizeOri") == null)
			{
				var Size = (Src.size ? Src.size : 10);
				Src.setAttribute("SizeOri", Size);
			}

			Src.size = __GetNewSize(Src, MinSize, MaxSize);
		}
	);

	CEvent.AddEvent(Ctl,
		"onkeydown",
		function(e)
		{
			var Src = CEvent.GetSrc(e);

			Src.size = __GetNewSize(Src, MinSize, MaxSize);
		}
	);

	CEvent.AddEvent(Ctl,
		"onblur",
		function(e)
		{
			var Src = CEvent.GetSrc(e);

			var SizeOri = Src.getAttribute("SizeOri");
			Src.size = SizeOri;
		}
	);
}
function __GetNewSize(Ctl, MinSize, MaxSize)
{
	var LenH = CTwoByte.LenH(Ctl.value);
	var Len = Ctl.value.length;
	//유니코드 문자가 없는 경우엔 size가 입력된 텍스트 너비보다 작을 경우 있어
	//3을 더함.
	var SizeNew = (LenH > Len) ? LenH : (Len + 3);
	
	if (SizeNew < MinSize)
	{
		SizeNew = MinSize;
	}
	else if (SizeNew > MaxSize)
	{
		SizeNew = MaxSize;
	}
	
	return SizeNew;
}

CEvent.GetKey = function (e)
{
	var e = e || window.event;
	return (e.keyCode ? e.keyCode : e.which);
}
CEvent.GetSrc = function (e)
{
	var e = e || window.event;
	return (e.srcElement || e.target);
}

//=========================
var CFindRep = new Object();

/*
--설명
1 -> a, 2 -> b로 변경한 값을 리턴함.
*/
CFindRep.ConvertNumberToAlpha = function (Number, ToUpperCase) {
	return String.fromCharCode(Number + (ToUpperCase ? 64 : 96));
}

/*
--설명
C#의 string.Format 함수와 같은 기능을 함.
*/
CFindRep.StringFormat = function (Format)
{
	for (var i = 1; i < arguments.length; i++)
	{
		var exp = new RegExp('\\{' + (i - 1) + '\\}', 'gm');
		Format = Format.replace(exp, arguments[i]);
	}
	return Format;
}

/*
--설명
클라이언트의 자바스크립트 문자열이 서버로 전송될 때 원래의 문자열 그대로
도착할 수 있도록 특수문자열은 %로 시작하는 문자열로 인코딩함.
--예제
ReplaceSpecialChar("#x@") --> "%23x%40"
*/
CFindRep.ReplaceSpecialChar = function (value)
{
	var value2 = "";
	var c = "";

	for (var i = 0; i < value.length; i++)
	{
		c = value.substr(i, 1);
		if (c == "!") c = "%21";
		else if (c == "#") c = "%23";
		else if (c == '"') c = "%22";
		else if (c == "$") c = "%24";
		else if (c == "%") c = "%25";
		else if (c == "&") c = "%26";
		else if (c == "(") c = "%28";
		else if (c == ")") c = "%29";
		else if (c == "@") c = "%40";
		else if (c == "+") c = "%2b";
		else if (c == ",") c = "%2c";
		else if (c == "-") c = "%2d";
		else if (c == ".") c = "%2e";
		else if (c == "/") c = "%2f";
		else if (c == ":") c = "%3a";
		else if (c == "<") c = "%3c";
		else if (c == "=") c = "%3d";
		else if (c == ">") c = "%3e";
		else if (c == "?") c = "%3f";
		else if (c == "[") c = "%5b";
		else if (c == "]") c = "%5d";
		else if (c.charCodeAt(0) == 13) c = "%0d";
		else if (c.charCodeAt(0) == 10) c = "%0a";
		else if ((c.charCodeAt(0) >= 0) && (c.charCodeAt(0) <= 5)) c = "%0" + c.charCodeAt(0);

		value2 += c;
	}
	
	return value2;
}

/*
--설명
문자열 앞의 스페이스 제거
*/
CFindRep.TrimStart = function (Value)
{
	var c = "";
	var NewValue = "";

	var aToTrim = CFindRep._GetToTrim(arguments);

	for (var i = 0; i < Value.length; i++)
	{
		c = Value.charAt(i);
		if (CArray.IndexOf(aToTrim, c, false) == -1)
		{
			NewValue = Value.substr(i, Value.length - i);
			break;
		}
	}

	return NewValue;
}
/*
--설명
문자열 뒤의 스페이스 제거
*/
CFindRep.TrimEnd = function (Value)
{
	var c = "";
	var NewValue = "";

	var aToTrim = CFindRep._GetToTrim(arguments);

	for (var i = (Value.length - 1); i >= 0; i--)
	{
		c = Value.charAt(i);
		if (CArray.IndexOf(aToTrim, c, false) == -1)
		{
			NewValue = Value.substr(0, i + 1);
			break;
		}
	}

	return NewValue;
}
/*
--설명
문자열 앞뒤의 스페이스 제거
*/
CFindRep.Trim = function (Value)
{
	var c = "";
	var NewValue = "";

	NewValue = CFindRep.TrimEnd(CFindRep.TrimStart(Value));

	return NewValue;
}
CFindRep._GetToTrim = function (arguments)
{
	var aToTrim = [];
	for (var i = 1; i < arguments.length; i++)
	{
		aToTrim.push(arguments[i]);
	}
	if (aToTrim.length == 0)
		aToTrim.push(" ");

	return aToTrim;
}

CFindRep.TrimSpecific = function (Value, aToTrim)
{
	var IsFound = true;
	while (IsFound == true)
	{
		IsFound = false;

		for (var i = 0; i < aToTrim.length; i++)
		{
			var ToTrimLength = aToTrim[i].length;
			if (ToTrimLength > Value.length)
				continue;

			if (Value.substr(0, ToTrimLength).toLowerCase() == aToTrim[i])
			{
				IsFound = true;
				Value = Value.substr(ToTrimLength);
			}
			if (Value.substr(Value.length - ToTrimLength).toLowerCase() == aToTrim[i])
			{
				IsFound = true;
				Value = Value.substr(0, Value.length - ToTrimLength);
			}
		}
	}

	return Value;
}

CFindRep.TrimWhiteBrPNbsp = function (Value)
{
	var aToTrim = ["\r", "\n", "\t", " ", "<br>", "<br/>", "<br />", "<p>", "</p>", "&nbsp;"];
	Value = TrimSpecific(Value, aToTrim);

	return Value;
}

/*
설명
오른쪽에서 num개만큼의 문자열을 리턴함.
VB의 Right 함수와 같음.
*/
CFindRep.Right = function (Value, Length)
{
	return Value.substr(Value.length - Length);
}
CFindRep.Left = function (Value, Length)
{
	return Value.substr(0, Length);
}

CFindRep.StartsWith = function (Value, Find, IgnoreCase)
{
	if (IgnoreCase)
	{
		return (Value.substr(0, Find.length).toLowerCase() == Find.toLowerCase());
	}
	else
	{
		return (Value.substr(0, Find.length) == Find);
	}
}
CFindRep.EndsWith = function (Value, Find, IgnoreCase)
{
	if (IgnoreCase)
	{
		return (Value.substr((Value.length - Find.length), Find.length).toLowerCase() == Find.toLowerCase());
	}
	else
	{
		return (Value.substr((Value.length - Find.length), Find.length) == Find);
	}
}

/*
--설명
JScript의 replace는 첫번째 문자열만 변경하므로 만듦.
--다음의 코드는 Find가 특수문자를 포함할 때 잘못 작동하므로 보류
eval("var x = Value.replace(/" + Find + "/gi, Replace);");
return x;
*/
CFindRep.ReplaceAll = function (Value, Find, Replace)
{
	//Value가 숫자인 경우, indexOf가 null을 리턴하므로 무한루핑을 하게 됨.
	Value = Value + "";
	
	var aNewValue = new Array();
	var nStart = 999;
	while (nStart != -1)
	{
		nStart = Value.indexOf(Find);
		if (nStart != -1)
		{
			aNewValue[aNewValue.length] = Value.substr(0, nStart) + Replace;
			Value = Value.substr(nStart + Find.length);
		}
		else
		{
			aNewValue[aNewValue.length] = Value;
			break;
		}
	}
	
	return aNewValue.join("");
}
/*
--설명
루프를 돌면서 Replace를 하면 속도가 느리고 내용이 클 경우 브라우저에서 스크립트 중단 메세지가 표시될 수 있으므로 사용함.
--다음의 코드는 Find가 특수문자를 포함할 때 잘못 작동하므로 보류
eval("var x = Value.replace(/" + Find + "/gi, Replace);");
return x;
*/
CFindRep.ReplaceAll2 = function (Value, Find, Replace)
{
	Value = Value + "";

	if (this.IsArray(Find))
	{
		for (var i = 0; i < Find.length; i++)
		{
			var FindCur = Find[i];
			var ReplaceCur = Replace[i];
			Value = this.ReplaceAll2(Value, FindCur, ReplaceCur);
		}

		return Value;
	}
	else
	{
		return Value.split(Find).join(Replace);
	}
}

/*
--설명
유일한 문자열을 가져오기 위해 현재 시간을 리턴함.
*/
CFindRep.GetUniqueIdByNow = function ()
{
	var DateInfo = CDateTime.GetDateTimeInfo(new Date());
	return
		DateInfo.yyyy + DateInfo.mm + DateInfo.dd
		+ DateInfo.hh + DateInfo.nn + DateInfo.ss + DateInfo.iii;
}
/*
--설명
아스키코드가 0부터 47인 경우는 눈에 보이지 않는 문자열임.
(예: 스페이스, 줄바꿈, null, 탭 등...)
이러한 문자열만으로 구성되었다면 실제로는 DB에 입력되지 않아야 하므로
이러한 문자열을 삭제한 나머지 문자열의 길이가 있는 경우 DB에 입력될
수 있다고 볼 수 있음.
--예제
alert(CFindRep.RemoveInvisible("안\n\n녕")); //안녕 -> 줄바꿈은 없어지므로 '안'과 '녕'이 붙음.
alert(CFindRep.RemoveInvisible("\t\n")); //"" -> 탭과 줄바꿈은 없어지므로 빈 문자열을 리턴함.
*/
CFindRep.RemoveInvisible = function (str)
{
	var ascii = 0;
	var newStr = "";
	
	if(str == null) return "";
	
	for(var i = 0; i < str.length; i++)
	{
		ascii = str.charCodeAt(i);
		if(ascii < 0 || ascii > 47)
		{
			newStr = newStr + str.charAt(i);
		}
	}
	
	return newStr;
}
/*
--설명
Except 문자열에 없는 문자는 Value에서 삭제한 후 리턴함.
--예제
CFindRep.RemoveExcept("1abc234", "0123456789")
-> "1234"
*/
CFindRep.RemoveExcept = function (Value, Except)
{
	var NewValue = "";
	var c = "";
	
	for (var i = 0; i < Value.length; i++)
	{
		c = Value.charAt(i);
		if (Except.indexOf(c) != -1)
		{
			NewValue += c;
		}
	}

	return NewValue;
}	
CFindRep.Repeat = function (Value, Num)
{
	var ValueList = "";
	
	for(var i = 0; i < Num; i++)
	{
		ValueList += Value;
	}
	
	return ValueList;
}	
/*
--설명
VB의 Format 함수와 같은 기능을 함.
*/
CFindRep.Format = function (Value, Format)
{
	var IsDecimalPlace2 = ((Format == NumberFormatType.CurrencyUs) || (Format == NumberFormatType.Percent));
	var IsPercent = CFindRep.EndsWith(Format, "%");

	Value += "";
	//콤마 삭제
	Value = Value.replace(/,/gi, "");
	//퍼센트 값을 실제값으로 변환
	if (CFindRep.EndsWith(Value, "%"))
	{
		Value = CType.ConvertPercentToFloat(Value);
	}
	
	if (IsPercent)
	{
		Value = (parseFloat(Value) * 100).toString();
	}
	
	var x = "", x1 = "", x2 = "";
	if (IsDecimalPlace2)
	{
		x = Value.split(".");
		x1 = x[0];
		
		if (x.length > 1)
		{
			x2 = Math.round(parseFloat("0." + x[1]) * 100).toString();
		}
		else
		{
			x2 = "0";
		}
	}
	else
	{
		x1 = Math.round(Value).toString();
	}
	
	if ((Format == NumberFormatType.Currency) || (Format == NumberFormatType.CurrencyUs))
	{
		var rgx = /(\d+)(\d{3})/;
		while (rgx.test(x1))
		{
			x1 = x1.replace(rgx, "$1" + "," + "$2");
		}
	}
	else if (Format == "000")
	{
		if (x1.length < 3)
		{
			x1 = CFindRep.PadLeft(x1, 3, "0");
		}
	}
	
	if (IsDecimalPlace2)
	{
		x2 = "." + CFindRep.PadRight(x2, 2, "0");
	}
	
	return x1 + x2 + (IsPercent ? "%" : "");
}	

/*
--설명
List의 문자열 중에 없는 문자열이 Value에 있는 지 확인함.
--예제
HasValueNotInList("12a", "01234567890") //true
HasValueNotInList("123", "01234567890") //false
*/
CFindRep.HasValueNotInList = function (Value, List)
{
	var IsFound = false;
	for (var i = 0, i2 = Value.length; i < i2; i++)
	{
		var c = Value.charAt(i);
		if (List.indexOf(c) == -1)
		{
			return true;
		}
	}
}

CFindRep.PadLeft = function (Value, Length, Pad)
{
	return CFindRep.Right(CFindRep.Repeat(Pad, Length) + Value, Length);
}
CFindRep.PadRight = function (Value, Length, Pad)
{
	return CFindRep.Left(Value + CFindRep.Repeat(Pad, Length), Length);
}

CFindRep.Contains4Operator = function (Value)
{
		//+,- 등의 기호는 계산을 위해 입력하는 것이므로 빠져나감.
		var aOp = new Array("+", "-", "*", "/");
		for (var i = 0, i2 = Value.length; i < i2; i++)
		{
			var c = Value.charAt(i);
			var PosOp = CArray.IndexOf(aOp, c, false);
			if (PosOp != -1)
			{
				return true;
			}
		}
		
		return false;
}

CFindRep.IfNotNumberThen0 = function (Value)
{
	//소수점 있는 경우 생겨 주석.
	//var i = parseInt(Value, 10);
	var i = parseFloat(Value);
	if (isNaN(i))
	{
		return 0;
	}
	else
	{
		return i;
	}
}

CFindRep.IfNotNumberThen = function (Value, DefaultValue)
{
	//소수점 있는 경우 생겨 주석.
	//var i = parseInt(Value, 10);
	var i = parseFloat(Value);
	if (isNaN(i))
	{
		return DefaultValue;
	}
	else
	{
		return i;
	}
}

//null이면 0 길이 문자열을 리턴하고, 아니면 원래 값을 리턴함.
CFindRep.IfNullThenEmpty = function (Value)
{
	return (Value != null) ? Value : "";
}
CFindRep.IfNullOrEmptyThen = function (Value, DefaultValue)
{
	return Value ? Value : DefaultValue;
}

CFindRep.GetNumOccurred = function (Value, ToFind)
{
	var Num = -1;

	var Pos = -(ToFind.length);

	do
	{
		Pos = Value.indexOf(ToFind, Pos + (ToFind.length));
		Num++;
	} while (Pos != -1);

	return Num;
}

/*
--설명
숫자 1을 ①로 변환함.
--예제
var s = "일2③④5";
alert(CFindRep.GetCircledNumByRealNum(s)); //일②③④⑤
*/
CFindRep.GetCircledNumByRealNum = function (Value)
{
	var aValue = new Array();

	for (var i = 0; i < Value.length; i++)
	{
		var c = Value.charAt(i);
		switch (c)
		{
			case "1":
				aValue.push("①"); break;
			case "2":
				aValue.push("②"); break;
			case "3":
				aValue.push("③"); break;
			case "4":
				aValue.push("④"); break;
			case "5":
				aValue.push("⑤"); break;
			case "6":
				aValue.push("⑥"); break;
			case "7":
				aValue.push("⑦"); break;
			case "8":
				aValue.push("⑧"); break;
			case "9":
				aValue.push("⑨"); break;
			default:
				aValue.push(c); break;
		}
	}

	return aValue.join("");
}

CFindRep.GetIeVersion = function ()
{
	var version = 999; // we assume a sane browser
	if (navigator.appVersion.indexOf("MSIE") != -1)
	// bah, IE again, lets downgrade version number
		version = parseFloat(navigator.appVersion.split("MSIE")[1]);
		
	return version;
}

CFindRep.IsArray = function (Value)
{
	if (Value.constructor.toString().indexOf("Array") == -1)
		return false;
	else
		return true;
}

CFindRep.DeleteTag = function (Value, TagName)
{
	TagName = TagName.toLowerCase();
	var aTag = new Array("<" + TagName + ">", "</" + TagName + ">", "<" + TagName + "/>", "<" + TagName + " />");
	var IsFound = true;
	while (IsFound == true)
	{
		IsFound = false;

		for (var i = 0; i < aTag.length; i++)
		{
			if (Value.toLowerCase().indexOf(aTag[i]) != -1)
			{
				IsFound = true;
				Value = ReplaceAll(Value, aTag[i], "");
			}
		}
	}

	return Value;
}

/*
--설명
Value에 숫자 형식이 아닌 항목이 있으면 0으로 만들어 배열로 리턴함.
*/
CFindRep.SplitInt = function (Value, Delim)
{
	var aValue = Value.split(Delim);

	var aValueInt = new Array();
	for (var i = 0; i < aValue.length; i++)
	{
		if (!aValue[i])
			aValue[i] = 0;

		aValueInt.push(parseInt(aValue[i], 10));
	}

	return aValueInt;
}

CFindRep.IfTrueThen1FalseThen0 = function (Value)
{
	return (Value == true) ? "1" : "0";
}

//=========================
var CFile = new Object();

/*
--설명
경로와 파일 이름 중에서 경로 이름만 리턴함.
*/
CFile.GetPathName = function (PathFile, PathSep)
{
	if (PathSep == null) PathSep = "/";

	//오른쪽에서 왼쪽으로 첫번째 / 기호를 찾음.
	//그 앞의 모든 문자열은 경로이므로 그것을 리턴함.
	var Pos = PathFile.lastIndexOf(PathSep);
	if (Pos == -1)
	{
		return PathFile;
	}
	else
	{
		return PathFile.substr(0, Pos);
	}
}
/*
--설명
경로와 파일 이름 중에서 파일 이름만 리턴함.
*/
CFile.GetFileName = function (PathFile, PathSep)
{
	if (PathSep == null) PathSep = "/";
	
	var Pos = PathFile.lastIndexOf(PathSep);
	if (Pos == -1)
	{
			return PathFile;
		}
	else
	{
		return PathFile.substr(Pos + 1);
	}
}
/*
--설명
확장자가 포함된 파일 이름에서 파일 이름만을 리턴함.
*/
CFile.GetFileFromFileExt = function (FileExt)
{
	var PosDot = FileExt.lastIndexOf(".");
	if (PosDot == -1)
	{
		return FileExt;
	}
	else
	{
		return FileExt.substr(0, PosDot);
	}
}
/*
--설명
확장자가 포함된 파일 이름에서 확장자를 리턴함.
*/
CFile.GetExtension = function (FileExt)
{
	var PosDot = FileExt.lastIndexOf(".");
	if (PosDot == -1)
	{
		return "";
	}
	else
	{
		return FileExt.substr(PosDot + 1);
	}
}
/*
--설명
C:\Temp\Sub 폴더가 있을 때 가장 마지막 폴더 이름인 'Sub'를 리턴함.
--예제
GetLastPath("C:\Temp\1234")
--> 1234
*/
CFile.GetLastPath = function (PathFile, PathSep)
{
	if (PathSep == null) PathSep = "/";

	if (PathFile.substr(PathFile.length - 1, 1) == PathSep)
		PathFile = PathFile.substr(0, PathFile.length - 1);
	
	var PosStart = PathFile.lastIndexOf(PathSep) + 1;
	if (PosStart == 0)
	{
		return "";
	}
	
	return PathFile.substr(PosStart);
}
/*
--설명
Url에서 서버의 주소만을 가져오기 위함.
--예제
GetServerURL("http://www.microsoft.com/vbasic/ado/")
-> http://www.microsoft.com
*/
CFile.GetServerUrl = function (Url)
{
	//http://에 있는 //의 위치를 알아냄
	var SlashPos = Url.indexOf("//");
	
	var SlashPos = Url.indexOf("/", SlashPos + 2);
	if (SlashPos != -1)
	{
		return Url.substr(0, SlashPos);
	}
	else
	{
		return Url;
	}
}
/*
--설명
'Name=박&Age=30'이란 문자열이 있을 때
key 인수에 name을 넘기면 '박'이 리턴됨.
--예제
var Name = CFile.GetParameter(document.URL, "Name");
*/
CFile.GetParameter = function (UrlParam, Key)
{
	if (UrlParam == "") return "";

	var Param = CFile.GetParamFromUrlParam(UrlParam);
	return CFile.GetParameter2(Param, Key);
}
CFile.GetParamFromUrlParam = function (UrlParam)
{
	var Pos = UrlParam.indexOf("?");
	if (Pos == -1) return "";
	
	return UrlParam.substr(Pos + 1);
}
CFile.GetUrlFromUrlParam = function (UrlParam)
{
	var Pos = UrlParam.indexOf("?");
	if (Pos == -1) return UrlParam;
	
	return UrlParam.substr(0, Pos);
}
CFile.GetParameter2 = function (Param, Key)
{
	var aParam = CFile.GetAllParameterInArray(Param);
	for (var i = 0, i2 = aParam.length; i < i2; i++)
	{
		var oKeyValue = aParam[i];
		if (oKeyValue.Key.toLowerCase() == Key.toLowerCase())
		{
			return oKeyValue.Value;
		}
	}

	return "";
}
CFile.GetAllParameterInArray = function (Param)
{
	var aParamNew = new Array();

	var aParam = Param.split("&");
	for (var i = 0, i2 = aParam.length; i < i2; i++)
	{
		var aKeyValue = aParam[i].split("=");
		
		var oKeyValue = new Object();
		oKeyValue.Key = aKeyValue[0];
		oKeyValue.Value = aKeyValue[1];

		aParamNew.push(oKeyValue);
	}

	return aParamNew;
}

CFile.SetParameter = function (UrlParam, Key, Value)
{
	var Param = CFile.GetParamFromUrlParam(UrlParam);
	var ParamNew = CFile.SetParameter2(Param, Key, Value);

	return CFile.GetUrlFromUrlParam(UrlParam) + "?" + ParamNew;
}
CFile.SetParameter2 = function (Param, Key, Value)
{
	var aParam = Param.split("&");
	var IsFound = false;
	for (var i = 0, i2 = aParam.length; i < i2; i++)
	{
		var aKeyValue = aParam[i].split("=");
		if (aKeyValue[0].toLowerCase() == Key.toLowerCase())
		{
			aKeyValue[1] = Value;
			aParam[i] = aKeyValue.join("=");

			IsFound = true;

			break;
		}
	}

	if (!IsFound)
	{
		aParam.push(Key + "=" + Value);
	}

	var ParamNew = aParam.join("&");

	return ParamNew;
}

/*
--설명
쿠키의 값을 읽어옴.
예를 들어 'name=박;age=30'이란 문자열이 있을 때
key 인수에 name을 넘기면 '박'이 리턴됨.
*/
CFile.GetCookie = function (Key)
{
	var dc = document.cookie;
	
	var prefix = Key + "=";
	var begin = dc.indexOf("; " + prefix);
	if (begin == -1)
	{
		begin = dc.indexOf(prefix);
		if (begin != 0) return "";
	}
	else
	{
		begin += 2;
	}
	
	var end = document.cookie.indexOf(";", begin);
	if (end == -1)
	{
		end = dc.length;
	}
	
	return unescape(dc.substring(begin + prefix.length, end));
}
/*
--설명
쿠키의 값을 설정함. expiredays는 현재로부터 며칠 후에 쿠키 값이 사라지는 지를 지정함.
*/
CFile.SetCookie = function (key, value, expiredays, domain)
{
	var todayDate = new Date();
	todayDate.setDate(todayDate.getDate() + expiredays);
	
	var cookie = key + "=" + value + "; path=/; expires=" + todayDate.toGMTString() + ";";
	if (domain)
	{
		cookie += " domain=" + domain + "; ";
	}
	
	document.cookie = cookie;
}

CFile.Combine = function (Path1, Path2, DirectorySeparator)
{
	var s = new String();
	
	if (Path1.charAt(Path1.length - 1) == DirectorySeparator)
	{
		Path1 = Path1.substr(0, Path1.length - 1);
	}
	if (Path2.charAt(0) == DirectorySeparator)
	{
		Path2 = Path2.substr(1);
	}

	return Path1 + DirectorySeparator + Path2;
}


//=========================
var CValid = new Object();

/*
--설명
다음 규칙에 맞는 유효한 아이디인 지 확인함.
길이는 MinLength부터 MaxLength까지, 영어와 숫자만 가능, 첫자는 영어만 가능.
*/
CValid.IsId = function (Id, MinLength, MaxLength, IsAllowHangul, oRet)
{
	var AlphaList = "abcdefghijklmnopqrstuvwxyz";
	var NumList = "1234567890";
	var AlphaNumList = AlphaList + NumList;

	if (!Id)
	{
		oRet.ErrMsg = "아이디를 입력하지 않았습니다.";
		return false;
	}

	Id = Id.toLowerCase();

	var Len = CTwoByte.LenH(Id);

	if ((Len < MinLength) || (Len > MaxLength))
	{
		oRet.ErrMsg = "아이디는 " + MinLength + " ~ " + MaxLength + "자 사이만 가능합니다";
		return false;
	}

	var FirstChar = Id.charAt(0);
	
	if (IsAllowHangul)
	{
		var IsHangul = CTwoByte.IsHangul(FirstChar);
		var IsAlpha = (AlphaList.indexOf(FirstChar) != -1);
		if (!IsHangul && !IsAlpha)
		{
			oRet.ErrMsg = "아이디의 첫번째는 영어와 한글만 가능합니다.";
			return false;
		}

		for (var i = 0, i2 = Id.length; i < i2; i++)
		{
			var c = Id.charAt(i);

			var IsHangul = CTwoByte.IsHangul(c);
			var IsAlphaOrNum = (AlphaNumList.indexOf(c) != -1);

			if (!IsHangul && !IsAlphaOrNum)
			{
				oRet.ErrMsg = "아이디는 한글, 영문, 숫자만 가능합니다.";
				return false;
			}
		}
	}
	else
	{
		if (AlphaList.indexOf(FirstChar) == -1)
		{
			oRet.ErrMsg = "아이디의 첫번째는 영어만 가능합니다";
			return false;
		}

		for (var i = 0, i2 = Id.length; i < i2; i++)
		{
			c = Id.charAt(i);

			var IsAlphaOrNum = (AlphaNumList.indexOf(c) != -1);
			
			if (!IsAlphaOrNum)
			{
				oRet.ErrMsg = "아이디는 영어와 숫자만 가능합니다";
				return false;
			}
		}
	}

	switch (Id)
	{
		case "sys":
		case "system":
		case "admin":
		case "administrator":
		case "master":
		case "webmaster":
		case "developer":
		case "관리자":
		case "운영자":
		case "개발자":
			oRet.ErrMsg = Id + "는 시스템에서 사용되므로 허용되지 않는 아이디입니다.";
			return false;
	}

	return true;
}

/*
--설명
다음 규칙에 맞는 유효한 패스워드인 지 확인함.
길이는 MinLength부터 MaxLength까지, 영어와 숫자만 가능
*/
CValid.IsPassword = function (Password, MinLength, MaxLength, oRet)
{
	var alphaList = "abcdefghijklmnopqrstuvwxyz";
	var numList = "1234567890";
	var allowedList = alphaList + numList;


	Password = Password.toLowerCase();

	if (Password.length < MinLength || Password.length > MaxLength)
	{
		oRet.ErrMsg = "비밀번호는 " + MinLength + " ~ " + MaxLength + "자 사이만 가능합니다";
		return false;
	}

	for (var i = 0; i <= Password.length - 1; i++)
	{
		var c = Password.charAt(i);
		if (allowedList.indexOf(c) == -1)
		{
			oRet.ErrMsg = "비밀번호는 영어와 숫자만 가능합니다";
			return false;
		}
	}

	//같은 번호의 반복 여부
	var c0 = Password.charAt(0);
	var IsAllSame = true;
	for (var i = 1, i2 = Password.length; i < i2; i++)
	{
		var c = Password.charAt(i);
		if (c != c0)
		{
			IsAllSame = false;
			break;
		}
	}
	if (IsAllSame)
	{
		oRet.ErrMsg = "비밀번호에 모두 같은 값이 사용되었습니다.(예: 1111)";
		return false;
	}

	//순서대로 증가되는 번호의 여부
	var n0 = Password.charCodeAt(0);
	var IsIncremental = true;
	for (var i = 1, i2 = Password.length; i < i2; i++)
	{
		var n = Password.charCodeAt(i);
		if ((n - i) != n0)
		{
			IsIncremental = false;
			break;
		}
	}
	if (IsIncremental)
	{
		oRet.ErrMsg = "비밀번호에 순서대로 증가되는 값이 사용되었습니다.(예: 1234)";
		return false;
	}

	return true;
}

CValid.IsDateYYYYMMDD = function (YYYYMMDD, FromYear, ToYear, oRet)
{
	if (YYYYMMDD.length != 10)
	{
		oRet.ErrMsg = "YYYY-MM-DD 형식이 아닙니다.";
		return false;
	}

	var aYmd = YYYYMMDD.split("-");
	if (aYmd.length != 3)
	{
		oRet.ErrMsg = "YYYY-MM-DD 형식이 아닙니다.";
		return false;
	}

	var Year = aYmd[0];
	var Month = aYmd[1];
	var Day = aYmd[2];
	return CValid.IsDate(Year, Month, Day, FromYear, ToYear, oRet);
}

/*
--설명
해당 년, 월, 일이 날짜 형식인 지 확인함
--예제
var Year = 2000, Month = 2, Day = 30;
alert(CValid.IsDate(Year, Month, Day, 1900, 2999)); //false
*/
CValid.IsDate = function (Year, Month, Day, FromYear, ToYear, oRet)
{
	var d = new Date();

	if (isNaN(Year))
	{
		oRet.ErrMsg = "연도가 숫자 형식이 아닙니다";
		return false;
	}

	if (FromYear)
	{
		if (Year < FromYear)
		{
			oRet.ErrMsg = "연도는 " + FromYear + "년부터 가능합니다";
			return false;
		}
	}

	if (ToYear)
	{
		if (Year > ToYear)
		{
			oRet.ErrMsg = "연도는 " + ToYear + "년까지 가능합니다";
			return false;
		}
	}

	if (isNaN(Month))
	{
		oRet.ErrMsg = "월이 숫자 형식이 아닙니다";
		return false;
	}
	if ((Month < 1) || (Month > 12))
	{
		oRet.ErrMsg = "월은 1부터 12까지만 가능합니다";
		return false;
	}

	if (isNaN(Day))
	{
		oRet.ErrMsg = "일이 숫자 형식이 아닙니다";
		return false;
	}
	var LastDay = CDateTime.GetLastDay(Year, Month)
	if (Day < 1 || Day > LastDay)
	{
		oRet.ErrMsg = "일은 1부터 " + LastDay + "까지만 가능합니다";
		return false;
	}

	return true;
}

CValid.IsTimeHHNN = function (HHNN, Is24, oRet)
{
	if (HHNN.length != 5)
	{
		oRet.ErrMsg = "HH:NN 형식이 아닙니다.";
		return false;
	}

	var aHM = HHNN.split(":");
	if (aHM.length != 2)
	{
		oRet.ErrMsg = "HH:NN 형식이 아닙니다.";
		return false;
	}

	var Hour = aHM[0];
	var Minute = aHM[1];
	return CValid.IsTime(Hour, Minute, 0, Is24, oRet);
}
CValid.IsTimeNNSS = function (NNSS, oRet)
{
	if (NNSS.length != 5)
	{
		oRet.ErrMsg = "NN:SS 형식이 아닙니다.";
		return false;
	}

	var aMS = NNSS.split(":");
	if (aMS.length != 2)
	{
		oRet.ErrMsg = "NN:SS 형식이 아닙니다.";
		return false;
	}

	var Minute = aMS[0];
	var Second = aMS[1];
	return CValid.IsTime(0, Minute, Second, true, oRet);
}
/*
--설명
해당 시, 분, 초가 시간 형식인 지 확인함
--예제
var hour = 13, minute = 25, second = 30;
alert(isTime(hour, minute, second, true)); //false
*/
CValid.IsTime = function (hour, minute, second, Is24, oRet)
{
	var minHour = 1;
	var maxHour = 12;

	//24시가 기준이면 0시부터 23시가 한계값이 됨.
	if (Is24)
	{
		minHour = 0;
		maxHour = 23;
	}

	if (isNaN(hour))
	{
		oRet.ErrMsg = "시간이 숫자 형식이 아닙니다";
		return false;
	}
	if (hour < minHour || hour > maxHour)
	{
		oRet.ErrMsg = "시간은 " + minHour + "부터 " + maxHour + "까지만 가능합니다";
		return false;
	}

	if (isNaN(minute))
	{
		oRet.ErrMsg = "분이 숫자 형식이 아닙니다";
		return false;
	}
	if (minute < 0 || minute > 59)
	{
		oRet.ErrMsg = "분은 0부터 59까지만 가능합니다";
		return false;
	}

	if (isNaN(second))
	{
		oRet.ErrMsg = "초가 숫자 형식이 아닙니다";
		return false;
	}
	if (second < 0 || second > 59)
	{
		oRet.ErrMsg = "초는 0부터 59까지만 가능합니다";
		return false;
	}

	return true;
}

CValid.IsDateType = function (d)
{
	var IsDateType = true;

	try
	{
		var y = d.getFullYear();
	}
	catch (ex)
	{
		IsDateType = false;
	}

	return IsDateType;
}

/*
--설명
주민등록번호의 첫번째 자리가 제대로 입력되었는 지 확인하기 위함.
--예제
alert(IsJumin1("710131")); //true
alert(IsJumin1("710132")); //false -> 1월 32일은 없으므로.
*/
CValid.IsJumin1 = function (value, oRet)
{
	if (!value)
	{
		oRet.ErrMsg = "주민등록번호의 첫번째 자리를 입력하지 않았습니다.";
		return false;
	}

	//주민등록번호 전체가 숫자인 지 확인
	if (isNaN(value))
	{
		oRet.ErrMsg = "주민등록번호는 숫자만 허용됩니다";
		return false;
	}

	//주민등록번호가 6자리인 지 확인
	if (value.length != 6)
	{
		oRet.ErrMsg = "주민등록번호의 첫번째 자리는 6자리여야 합니다";
		return false;
	}

	//첫번째 부분은 생년월일이므로 날짜 형식인 지 확인
	var year = "20" + value.substr(0, 2);
	var month = value.substr(2, 2);
	var day = value.substr(4, 2);
	if (!CValid.IsDate(year, month, day, 0, 0, oRet))
	{
		oRet.ErrMsg = "주민등록번호의 첫번째 자리의 " + oRet.ErrMsg;
		return false;
	}

	return true;
}
/*
--설명
주민등록번호의 두번째 자리가 제대로 입력되었는 지 확인하기 위함.
--예제
alert(IsJumin2("1121513")); //true
alert(IsJumin2("5121513")); //false -> 첫번째 자리는 1부터 4까지만 있으므로.
*/
CValid.IsJumin2 = function (value, oRet)
{
	if (!value)
	{
		oRet.ErrMsg = "주민등록번호의 두번째 자리를 입력하지 않았습니다.";
		return false;
	}

	//주민등록번호 전체가 숫자인 지 확인
	if (isNaN(value))
	{
		oRet.ErrMsg = "주민등록번호는 숫자만 허용됩니다";
		return false;
	}

	//주민등록번호가 7자리인 지 확인
	if (value.length != 7)
	{
		oRet.ErrMsg = "주민등록번호의 두번째 자리는 7자리여야 합니다";
		return false;
	}

	//첫째 자리는 성별(1, 3: 남, 2, 4: 여)임.
	if (value.charAt(0) < 1 || value.charAt(0) > 4)
	{
		oRet.ErrMsg = "주민등록번호의 두번째 부분의 첫번째 자리는 성별을 나타내므로 1부터 4까지만 가능합니다."
		return false;
	}

	return true;
}

/*
--설명
우편번호의 첫번째, 두번째 자리가 제대로 입력되었는 지 확인하기 위함.
--예제
alert(isZip("435")); //true -> 3자리이면서 숫자이므로 맞음.
alert(isZip("43")); //false -> 3자리가 아니므로 틀림.
*/
CValid.IsZip = function (value, oRet)
{
	//우편번호 전체가 숫자인 지 확인
	if (isNaN(value))
	{
		oRet.ErrMsg = "우편번호는 숫자만 허용됩니다";
		return false;
	}

	//우편번호가 3자리인 지 확인
	if (value.length != 3)
	{
		oRet.ErrMsg = "우편번호는 3자리여야 합니다";
		return false;
	}

	return true;
}

/*
--설명
0보다 큰 정수만 있는지 확인하기 위함.
*/
CValid.IsIntegerUnsigned = function (Value)
{
	var c;
	var NumLists = "0123456789";

	for (var i = 0; i < Value.length; i++)
	{
		c = Value.charAt(i);
		if (NumLists.indexOf(c) == -1)
		{
			return false;
		}
	}

	return true;
}

/*
--설명
value 안에 숫자값이 들어있는 지 확인하기 위함.
--예제
alert(IsCharOnly("하이")); //true
alert(IsCharOnly("하2")); //false -> 숫자 2가 들어갔으므로.
*/
CValid.IsCharOnly = function (value, oRet)
{
	var c;
	var numLists = "0123456789";

	for (var i = 0; i < value.length; i++)
	{
		c = value.charAt(i);
		if (numLists.indexOf(c) != -1)
		{
			oRet.ErrMsg = "숫자는 허용되지 않습니다";
			return false;
		}
	}

	return true;
}

CValid.IsNumberOnly = function (Value)
{
    //스페이스의 경우 isNaN이 false를 리턴하므로 parseInt로 추가 검사함.
    if (isNaN(Value) || isNaN(parseInt(Value)))
	{
		return false;
	}

	return true;
}

CValid.IsMoreThan0 = function (Value)
{
	if (!CValid.IsNumberOnly(Value))
	{
		return false;
	}

	var n = parseInt(Value, 10);
	if (n <= 0)
	{
		return false;
	}

	return true;
}

/*
--설명
전화번호가 형식에 맞게 제대로 입력되었는 지 확인하기 위함.
--예제
alert(isPhone("016-731-0343")); //true -> 숫자와 대시만으로 이뤄졌으므로 맞음.
alert(isPhone("02d7310343")); //false -> 전화번호에 허용되지 않는 알파벳이 들어갔으므로 틀림.
--추가코드
RemoveExcept() 함수
*/
CValid.IsPhone = function (value, oRet)
{
	var textAllowed = "0123456789-)";
	for (var i = 0; i <= value.length - 1; i++)
	{
		var c = value.charAt(i);
		if (textAllowed.indexOf(c) == -1)
		{
			oRet.ErrMsg = "전화번호는 다음 문자열만 허용됩니다\n" + textAllowed;
			return false;
		}
	}

	value = CFindRep.RemoveExcept(value, "0123456789");
	if (value.length < 6)
	{
		oRet.ErrMsg = "전화번호는 최소한 6자리 이상의 숫자로 구성되어야 합니다";
		return false;
	}

	return true;
}

/*
--설명
휴대폰 번호가 형식에 맞게 제대로 입력되었는 지 확인하기 위함.
--추가코드
RemoveExcept() 함수
*/
CValid.IsMobile = function (value, oRet)
{
	var textAllowed = "0123456789-)";
	for (var i = 0; i <= value.length - 1; i++)
	{
		var c = value.charAt(i);
		if (textAllowed.indexOf(c) == -1)
		{
			oRet.ErrMsg = "휴대폰 번호는 다음 문자열만 허용됩니다\n" + textAllowed;
			return false;
		}
	}

	value = CFindRep.RemoveExcept(value, "0123456789");
	if (value.length < 10)
	{
		oRet.ErrMsg = "휴대폰 번호는 최소한 10자리 이상의 숫자로 구성되어야 합니다";
		return false;
	}

	var companyNum = "010,011,016,017,018,019";
	if (companyNum.indexOf(value.substr(0, 3)) == -1)
	{
		oRet.ErrMsg = "휴대폰 번호는 " + companyNum + "으로 시작해야 합니다";
		return false;
	}

	return true;
}

/*
--설명
이메일 주소가 형식에 맞는 지 확인함.
다음의 규칙에 따라 E-Mail 주소를 얻음.

단어는 알파벳, 숫자, 밑줄(_), 대시(-)만 허용함.

@를 찾음.
@ 왼쪽의 단어를 찾음.
@ 오른쪽으로 점으로 끝나는 단어를 찾음.
점 오른쪽의 단어를 찾음.

각 단어의 길이는 1 이상이어야 함.
1, 2번째 단어의 시작은 점으로 시작할 수 없음.
1, 2번째 단어의 시작 다음부터는 허용된 문자열이어야 함.
3번째 단어는 영어와 숫자와 점(.)만 허용함.
--예제
var errMsg = "";

if(!IsEmail("kk1965@mail.cc2.cau.ac.kr")) {
	alert(errMsg);
}
else {
	alert("yes");
}
*/
CValid.IsEmail = function (Email, oRet)
{
	var textAllowed = "abcdefghijklmnopqrstuvwxyz"
					+ "1234567890_-";
	var textAlpha = "abcdefghijklmnopqrstuvwxyz";
	var textNumeric = "1234567890";

	if (!Email)
	{
		oRet.ErrMsg = "이메일을 입력하지 않았습니다.";
		return false;
	}

	//www.daum.net에서는 Email id가 _-로 시작할 수 있으므로 .만 허용하지 않음.
	//var textNotInFirst = "._-";
	var textNotInFirst = ".";

	var posApos = 0, leftOne = "", c = "";

	Email = Email.toLowerCase();

	var pos1st = 0;

	var posApos = Email.indexOf("@", pos1st + 1);
	if (posApos == -1)
	{
		oRet.ErrMsg = "이메일에 @ 기호가 없으므로 잘못된 이메일 형식입니다";
		return false;
	}
	var pos2nd = posApos + 1;

	var posDot = Email.indexOf(".", pos2nd + 1);
	if (posDot == -1)
	{
		oRet.ErrMsg = "이메일의 '아이디@서버주소.도메인형식'의 서버주소와 도메인형식 사이에는"
					+ " 점(.)이 있어야 합니다";
		return false;
	}
	var pos3rd = posDot + 1;

	var word1st = Email.substring(pos1st, pos2nd - 1);
	var word2nd = Email.substring(pos2nd, pos3rd - 1);
	var word3rd = Email.substring(pos3rd, Email.length);

	if (textNotInFirst.indexOf(word1st.charAt(0)) != -1)
	{
		oRet.ErrMsg = "이메일의 '아이디@서버주소.도메인형식'의 아이디 첫번째 부분에는 '._-' 기호가 허용되지 않습니다";
		return false;
	}
	if (textNotInFirst.indexOf(word2nd.charAt(0)) != -1)
	{
		oRet.ErrMsg = "이메일의 '아이디@서버주소.도메인형식'의 서버주소 첫번째 부분에는 '._-' 기호가 허용되지 않습니다";
		return false;
	}

	/*
	아이디 부분에는 어떤 문자열이든 모두 허용되므로 체크하지 않음.
	for(var i = 0; i <= word1st.length - 1; i++) {
	c = word1st.charAt(i);
	if(textAllowed.indexOf(c) == -1) {
	errMsg = "이메일의 '아이디@서버주소.도메인형식'의 아이디 부분에는 다음 문자열만 허용됩니다\n"
	+ textAllowed;
	return false;
	}
	}
	*/
	for (var i = 0; i <= word2nd.length - 1; i++)
	{
		var c = word2nd.charAt(i);
		if (textAllowed.indexOf(c) == -1)
		{
			oRet.ErrMsg = "이메일의 '아이디@서버주소.도메인형식'의 서버주소 부분에는 다음 문자열만 허용됩니다\n"
					+ textAllowed;
			return false;
		}
	}

	var text = textAlpha + textNumeric + ".";
	for (var i = 0; i <= word3rd.length - 1; i++)
	{
		var c = word3rd.charAt(i);
		if (text.indexOf(c) == -1)
		{
			oRet.ErrMsg = "이메일의 '아이디@서버주소.도메인형식'의"
						+ " 도메인형식 부분에는 알파벳 기호와 점(.)만 허용됩니다"
			return false;
		}
	}

	if (Email.indexOf("@@") != -1)
	{
		oRet.ErrMsg = "Email에 '@' 문자열이 연속으로 2개 이상 있습니다.";
		return false;
	}
	else if (Email.indexOf("..") != -1)
	{
		oRet.ErrMsg = "Email에 '.' 문자열이 연속으로 2개 이상 있습니다.";
		return false;
	}

	return true;
}

/*
--설명
다음 규칙에 따라 검사함.
2자 이상 63자 이하
도메인 네임의 마지막은 대시로 끝날 수 없음.
*/
CValid.IsDomain = function (domain, oRet)
{
	var textAllowed = "abcdefghijklmnopqrstuvwxyz"
					+ "1234567890_-";
	var textAlpha = "abcdefghijklmnopqrstuvwxyz";
	var textNotInFirst = "._-";
	//var textNotInLast = "-";

	var posDot = 0, leftOne = "", c = "";

	domain = domain.toLowerCase();
	if (domain.substr(0, 7) == "http://")
	{
		domain = domain.substr(7);
	}

	var pos1st = 0;

	var posDot = domain.indexOf(".", pos1st + 1);
	if (posDot == -1)
	{
		oRet.ErrMsg = "점(.)이 없으므로 잘못된 도메인 형식입니다";
		return false;
	}
	var pos2nd = posDot + 1;

	var posDot = domain.indexOf(".", pos2nd + 1);
	if (posDot == -1)
	{
		oRet.ErrMsg = "도메인은 최소한 2개 이상의 점(.)으로 이루어져야 합니다";
		return false;
	}
	var pos3rd = posDot + 1;

	var word1st = domain.substring(pos1st, pos2nd - 1);
	var word2nd = domain.substring(pos2nd, pos3rd - 1);
	var word3rd = domain.substring(pos3rd, domain.length);

	if (textNotInFirst.indexOf(word1st.charAt(0)) != -1)
	{
		oRet.ErrMsg = "도메인의 첫번째 부분의 앞자리에는 '._-' 기호가 허용되지 않습니다";
		return false;
	}
	if (textNotInFirst.indexOf(word2nd.charAt(0)) != -1)
	{
		oRet.ErrMsg = "도메인의 두번째 부분의 앞자리에는 '._-' 기호가 허용되지 않습니다";
		return false;
	}
	if (textNotInFirst.indexOf(word3rd.charAt(0)) != -1)
	{
		oRet.ErrMsg = "도메인의 세번째 부분의 앞자리에는 '._-' 기호가 허용되지 않습니다";
		return false;
	}

	for (var i = 0; i <= word1st.length - 1; i++)
	{
		var c = word1st.charAt(i);
		if (textAllowed.indexOf(c) == -1)
		{
			oRet.ErrMsg = "도메인 이름의 첫번째 부분은 다음 문자열만 허용됩니다\n"
						+ textAllowed;
			return false;
		}
	}
	for (var i = 0; i <= word2nd.length - 1; i++)
	{
		var c = word2nd.charAt(i);
		if (textAllowed.indexOf(c) == -1)
		{
			oRet.ErrMsg = "도메인 이름의 두번째 부분은 다음 문자열만 허용됩니다\n"
					+ textAllowed;
			return false;
		}
	}
	var text = textAllowed + "./";
	for (var i = 0; i <= word3rd.length - 1; i++)
	{
		var c = word3rd.charAt(i);
		if (text.indexOf(c) == -1)
		{
			oRet.ErrMsg = "도메인 이름의 세번째 부분은 다음 문자열만 허용됩니다\n"
					+ text;
			return false;
		}
	}

	return true;
}

/*
--설명
카드번호가 맞는 지 여부를 검사함.
*/
CValid.IsCreditCardNo = function (No1, No2, No3, No4, oRet)
{
	var aNo = new Array(No1, No2, No3, No4);
	for (var i = 0; i < aNo.length; i++)
	{
		if (!aNo[i])
		{
			oRet.ErrMsg = "카드번호의 " + (i + 1) + "번째를 입력하지 않았습니다.";
			return false;
		}

		if (isNaN(aNo[i]))
		{
			oRet.ErrMsg = "카드번호의 " + (i + 1) + "번째가 숫자 형식이 아닙니다.";
			return false;
		}

		if (aNo[i].length != 4)
		{
			oRet.ErrMsg = "카드번호의 " + (i + 1) + "번째가 4자리가 아닙니다.";
			return false;
		}
	}

	return true;
}

CValid.IsNumberFixedLength = function (Value, Length)
{
	if (!Value)
	{
		return false;
	}
	if (isNaN(Value))
	{
		return false;
	}
	if (Value.toString().length != Length)
	{
		return false;
	}

	return true;
}

//=========================
var CDateTime = new Object();

CDateTime.DateMinValueForDb19000101 = new Date(1900, 0, 1);

CDateTime.GetHHNNSSBySeconds = function (Seconds)
{
	var h = parseInt((Seconds / 3600), 10);
	var n = parseInt(((Seconds - (h * 3600)) / 60), 10);
	var s = Seconds % 60;
	var hh = (h < 10) ? "0" + h : h;
	var nn = (n < 10) ? "0" + n : n;
	var ss = (s < 10) ? "0" + s : s;
	
	var o = new Object();
	o.h = h;
	o.n = n;
	o.s = s;
	o.hh = hh;
	o.nn = nn;
	o.ss = ss;
	o.hhnnss = hh + ":" + nn + ":" + ss;
	
	return o;
}

CDateTime.GetSecondsByHHNNSS = function (HHNNSS)
{
	var aTime = HHNNSS.split(":");
	if (aTime.length != 3)
		return 0;

	var h = parseInt(aTime[0], 10);
	var n = parseInt(aTime[1], 10);
	var s = parseInt(aTime[2], 10);

	return (h * 60 * 60) + (n * 60) + s;
}

CDateTime.GetHHNNSSIIIByMilliSeconds = function (MilliSeconds)
{
	var i = MilliSeconds % 1000;
	var s = Math.floor(MilliSeconds / 1000) % 60;
	var n = Math.floor(MilliSeconds / 1000 / 60) % 60;
	var h = Math.floor(MilliSeconds / 1000 / 60 / 60) % 24;

	var hh = (h < 10) ? "0" + h : h;
	var nn = (n < 10) ? "0" + n : n;
	var ss = (s < 10) ? "0" + s : s;
	var iii = "";
	if (i < 10)
		iii = "00" + i;
	else if (i < 100)
		iii = "0" + i;
	else
		iii = i;

	var o = new Object();
	o.h = h;
	o.n = n;
	o.s = s;
	o.i = i;
	o.hh = hh;
	o.nn = nn;
	o.ss = ss;
	o.iii = iii;
	o.hhnnss = hh + ":" + nn + ":" + ss;
	o.hhnnssiii = hh + ":" + nn + ":" + ss + ":" + iii;

	return o;
}

CDateTime.GetDateTimeInfo = function (dt)
{
	var y = dt.getFullYear();
	var m = (dt.getMonth() + 1);
	var d = dt.getDate();

	var mm = (m < 10) ? "0" + m : m;
	var dd = (d < 10) ? "0" + d : d;

	var o = new Object();
	o.y = y;
	o.m = m;
	o.d = d;
	o.yyyy = y;
	o.mm = mm;
	o.dd = dd;
	o.yyyymmdd = o.yyyy + o.mm + o.dd;
	o.yyyy_mm_dd = o.yyyy + "-" + o.mm + "-" + o.dd;


	var h = dt.getHours();
	if (h > 12)
		h = h - 12;

	if (h == 0)
		h = 12;

	//앞에서 h가 변경되므로 다시 가져옴.
	var hh = dt.getHours();
	hh = (hh < 10) ? ("0" + hh) : hh;

	var n = dt.getMinutes();
	var nn = (n < 10) ? ("0" + n) : n;

	var s = dt.getSeconds();
	var ss = (s < 10) ? ("0" + s) : s;


	var i = dt.getMilliseconds();

	var iii = "";
	if (i < 10)
		iii = "00" + i;
	else if (i < 100)
		iii = "0" + i;
	else
		iii = i;


	o.h = h;
	o.n = n;
	o.s = s;
	o.i = i;
	o.hh = hh;
	o.nn = nn;
	o.ss = ss;
	o.iii = iii;
	o.hhnnss = hh + ":" + nn + ":" + ss;
	o.hhnnssiii = hh + ":" + nn + ":" + ss + ":" + iii;


	return o;
}

/*
--설명
날짜 형식인 oldDate 개체에 number 개월(년)수 만큼 더한
날짜 개체를 리턴함.
interval은 다음의 문자열을 가짐.
yyyy: 년
m: 월
d: 일
h: 시
n: 분
s: 초

getFullYear(): 실제년도
getMonth(): 0-11
getDate(): 1-31
getHours(): 0-23
getMinutes(): 0-59
getSeconds(): 0-59
getMilliseconds(): 0-999

getDay(): 0-6

--예제
var d = new Date(2000, 0, 31);
var s = d.getFullYear() + "." + parseInt(d.getMonth() + 1, 10) + "." + d.getDate();
alert(s); //2000.1.31

var d = GetDateAdd("m", 1, d);
var s = d.getFullYear() + "." + parseInt(d.getMonth() + 1, 10) + "." + d.getDate();
alert(s); //2000.2.29
*/
CDateTime.GetDateAdd = function (Interval, Number, OldDate)
{
	with (OldDate)
	{
		var OldYear = getFullYear();
		var OldMonth = getMonth();
		var OldDay = getDate();
		var OldHours = getHours();
		var OldMinutes = getMinutes();
		var OldSeconds = getSeconds();
	}

	var NewDate = null;

	switch (Interval)
	{
		case "yyyy":
			NewDate = new Date(OldYear + Number, OldMonth, OldDay);
			break;
		case "m":
			NewDate = new Date(OldYear, OldMonth + Number, OldDay);
			break;
		case "d":
			NewDate = new Date(OldYear, OldMonth, OldDay + Number);
			break;
		case "h":
			NewDate = new Date(OldYear, OldMonth, OldDay, OldHours + Number, OldMinutes, OldSeconds);
			break;
		case "n":
			NewDate = new Date(OldYear, OldMonth, OldDay, OldHours, OldMinutes + Number, OldSeconds);
			break;
		case "s":
			NewDate = new Date(OldYear, OldMonth, OldDay, OldHours, OldMinutes, OldSeconds + Number);
			break;
	}

	//월을 가감했을 때 OldDate의 일수가 가감 후의 일수보다 더 큰 경우엔
	//해당 월 다음 월이 리턴되므로, 이런 경우엔 해당 월의 마지막 월로 결정함.
	//예: 2005-1-31의 월에 +1을 하면 2005-2-28일에 3을 더한 2005-3-3일이 되지만
	//2005-2-28일로 결정함.
	switch (Interval)
	{
		case "yyyy":
		case "m":
			if (NewDate.getDate() < OldDate.getDate())
			{
				var DatePrevM = new Date(NewDate.getFullYear(), NewDate.getMonth() - 1, 1);
				NewDate = new Date(DatePrevM.getFullYear(), DatePrevM.getMonth(), GetLastDay(DatePrevM.getFullYear(), DatePrevM.getMonth() + 1));
			}
			break;
	}

	return NewDate;
}

/*
--설명
VB의 DateDiff 함수와 동일.
interval은 다음의 문자열을 가짐.
yyyy: 년
m: 월
d: 일
h: 시
n: 분
s: 초

getFullYear(): 실제년도
getMonth(): 0-11
getDate(): 1-31
getHours(): 0-23
getMinutes(): 0-59
getSeconds(): 0-59
getMilliseconds(): 0-999

getDay(): 0-6
*/
CDateTime.GetDateDiff = function (interval, date1, date2)
{
	//	alert(interval);
	switch (interval)
	{
		case "yyyy":
			var yearFrom = date1.getFullYear();
			var yearTo = date2.getFullYear();
			var yearNew = yearTo - yearFrom;

			return yearNew;

			break;
		case "m":
			var cntMonth = 0;

			var yearFrom = date1.getFullYear();
			var yearTo = date2.getFullYear();

			var monthFrom = date1.getMonth();
			var monthTo = date2.getMonth();

			while (yearFrom < yearTo)
			{
				cntMonth += 11 - monthFrom;
				monthFrom = -1;
				yearFrom++;
			}
			cntMonth += monthTo - monthFrom;

			return cntMonth;

			break;
		case "d":
			//시, 분, 초, 밀리초가 없이 생성해야 일자 계산이 제대로 됨.
			var date1_ = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate());
			var date2_ = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate());

			var dateNew = (date2_ - date1_) / 1000 / 60 / 60 / 24;

			return dateNew;

			break;
		case "h":
			//분, 초, 밀리초가 없이 생성해야 시간 계산이 제대로 됨.
			var date1_ = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate(), date1.getHours());
			var date2_ = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate(), date2.getHours());

			var dateNew = (date2_ - date1_) / 1000 / 60 / 60;

			return dateNew;

			break;
		case "n":
			//초, 밀리초가 없이 생성해야 시간 계산이 제대로 됨.
			var date1_ = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate(), date1.getHours(), date1.getMinutes());
			var date2_ = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate(), date2.getHours(), date2.getMinutes());

			var dateNew = (date2_ - date1_) / 1000 / 60;

			return dateNew;

			break;
		case "s":
			//밀리초가 없이 생성해야 시간 계산이 제대로 됨.
			var date1_ = new Date(date1.getFullYear(), date1.getMonth(), date1.getDate(), date1.getHours(), date1.getMinutes(), date1.getSeconds());
			var date2_ = new Date(date2.getFullYear(), date2.getMonth(), date2.getDate(), date2.getHours(), date2.getMinutes(), date2.getSeconds());

			var dateNew = (date2_ - date1_) / 1000;

			return dateNew;

			break;
	}
}

/*
--설명
해당년, 월의 마지막 일을 리턴함.
--예제
var year = 2000, month = 2;
alert(GetLastDay(year, month); //29
*/
CDateTime.GetLastDay = function (year, month)
{
	if (month == 4 || month == 6 || month == 9 || month == 11)
	{
		return 30;
	}
	else if (month == 2)
	{
		if ((year % 4) == 0)
		{
			if ((year % 100) == 0)
			{
				if ((year % 400) == 0)
				{
					return 29;
				}
				else
				{
					return 28;
				}
			}
			else
			{
				return 29;
			}
		}
		else
		{
			return 28;
		}

	}
	else
	{
		return 31;
	}
}

CDateTime.GetDateFromYYYYMMDD = function (YYYYMMDD)
{
	var YYYY = YYYYMMDD.substr(0, 4);
	var MM = YYYYMMDD.substr(4, 2);
	var DD = YYYYMMDD.substr(6, 2);

	var Y = parseInt(YYYY);
	var M = (MM.substr(0, 1) == "0") ? parseInt(MM.substr(1, 1)) : parseInt(MM);
	var D = (DD.substr(0, 1) == "0") ? parseInt(DD.substr(1, 1)) : parseInt(DD);

	var d = new Date(Y, M - 1, D);
	return d;
}

CDateTime.GetDateTimeFormat = function (DateTimeIn14Char)
{
	return DateTimeIn14Char.substr(0, 4) + "-" +
		DateTimeIn14Char.substr(4, 2) + "-" +
		DateTimeIn14Char.substr(6, 2) + " " +
		DateTimeIn14Char.substr(8, 2) + ":" +
		DateTimeIn14Char.substr(10, 2) + ":" +
		DateTimeIn14Char.substr(12, 2);
}

/*
--설명
날짜 형식이면 Date 개체를 리턴하고 아니면 null을 리턴함.
--예제
d = GetDateValue("2002-2-30"); //null
d = GetDateValue("2002-1-30"); //Date 형식
*/
CDateTime.GetDateValue = function (p) {
	var year;
	var month;
	var day;

	var a = p.split("-");
	if (a.length != 3) {
		a = p.split("/");
	}
	if (a.length != 3) {
		a = p.split(".");
	}
	if (a.length != 3) {
		if ((p.length == 8) && (!isNaN(p))) {
			year = p.substr(0, 4);
			month = p.substr(4, 2);
			day = p.substr(6, 2);
		}
		else {
			return null;
		}
	}
	else {
		year = a[0];
		month = a[1];
		day = a[2];
	}

	if ((isNaN(year)) || (year == "")) {
		return null;
	}
	year = parseInt(year,10);
	if ((year < 1900) || (year > 2999)) {
		return null;
	}
	
	if ((isNaN(month)) || (month == "")) {
		return null;
	}
	month = parseInt(month,10);
	if(month < 1 || month > 12) {
		return null;
	}
	
	if ((isNaN(day)) || (day == "")) {
		return null;
	}
	day = parseInt(day,10);

	var lastDay = CDateTime.GetLastDay(year, month)
	if(day < 1 || day > lastDay) {
		return null;
	}

	return new Date(year, month - 1, day);
}

//=========================

/*
--설명
경과시간을 가져오기 위함.
--예제
var tm = new CTimeMeasure();
var ms = tm.GetElapsedText();
alert(ms);
*/
function CTimeMeasure()
{
	this.mStartTime = new Date();

	this.GetElapsedText = function ()
	{
		return this.GetText(this.GetElapsedMilliseconds());
	}

	this.GetElapsedMilliseconds = function ()
	{
		return ((new Date()) - this.mStartTime);
	}

	this.GetText = function (Milliseconds)
	{
		return CDateTime.GetHHNNSSIIIByMilliSeconds(Milliseconds).hhnnssiii;
	}
}
//=========================	
/*
--설명
OK 단추를 클릭했을 때 커서를 모래시계로 바꾸고 단추를 못 클릭하게 하고,
작업이 끝났을 때 커서를 기본으로 바꾸고 단추를 클릭할 수 있게 함.
--예제
var hg = new CHourGlass(document.getElementById("btnTest"));
alert(1);
hg.Dispose();
*/
function CHourGlass(Ctl)
{
	this.Ctl = Ctl;
	//alert(this.Ctl.value);
	if (this.Ctl) this.Ctl.disabled = true;

	window.status = "처리 중...";
	document.body.style.cursor = "wait";

	this.Dispose = function CHourGlass_Dispose()
	{
		if (this.Ctl) this.Ctl.disabled = false;

		window.status = "";
		document.body.style.cursor = "default";
	};
}

//=========================
var CTwoByte = new Object();

/*
--설명
2바이트 문자열의 길이를 2로 감안한 길이를 리턴함.
--예제
var s = "하a";
alert(LenH(s)); //3을 리턴함.
*/
CTwoByte.LenH = function (Value)
{
	var nChar = 0;
	
	for (var i = 0, i2 = Value.length; i < i2; i++)
	{
		nChar += (escape(Value.charCodeAt(i)).length > 4) ? 2 : 1;
	}

	return nChar;
}

/*
--설명
2바이트 문자열의 실제 길이를 2로 계산해서 왼쪽에서 Length만큼의 문자열을 리턴함.
--예제
LeftH("한a글", 3).Result -> "한a"
LeftH("한a글", 4).Result -> "한a", 이때 '글'의 왼쪽 부분이 남으므로 LeftH("한a글", 4).Mod는 1이 됨.
*/
CTwoByte.LeftH = function (Value, Length)
{
	var ModIs = 0;
	
	var LenH = 0;
	for (var i = 0, i2 = Value.length; i < i2; i++)
	{
		LenH += (escape(Value.charCodeAt(i)).length > 4) ? 2 : 1;

		if (LenH == Length)
		{
			this.Mod = 0;
			this.Result = Value.substr(0, i + 1);
			return this;
		}
		else if (LenH == (Length + 1))
		{
			this.Mod = 1;
			this.Result = ((Length == 1) ? "" : Value.substr(0, i));
			return this;
		}
	}

	//Length가 문자열보다 긴 경우엔 문자열 자체를 리턴함.
	this.Mod = 0;
	this.Result = Value;
	return this;
}

CTwoByte.IsHangul = function (Value)
{
	var CharCodeFrom = "가".charCodeAt(0);
	var CharCodeTo = "힣".charCodeAt(0);
	
	for (var i = 0, i2 = Value.length; i < i2; i++)
	{
		var CharCodeCur = Value.charCodeAt(0);
		if ((CharCodeCur < CharCodeFrom) || (CharCodeCur > CharCodeTo))
		{
			return false;
		}
	}
	
	return true;
}

CTwoByte.IsTwoByte = function (Value)
{
	return ((escape(Value) + "%u").match(/%u/g).length - 1) > 0;
}


//=========================
var CWindow = new Object();

CWindow.GetScreenCenterXY = function (Width, Height)
{
	this.X = (screen.availWidth - Width) / 2;
	this.Y = (screen.availHeight - Height) / 2;

	return this;
}

CWindow.CenterWindow = function (Width, Height)
{
	var Pos = CWindow.GetScreenCenterXY(Width, Height);
	window.resizeTo(Width, Height);
	window.moveTo(Pos.X, Pos.Y);
}

CWindow.GetRootOpener = function ()
{
	var Win = window;
	if (Win.parent.frames.length > 0)
		Win = Win.parent;

	if (Win.opener && (typeof Win.opener.document != "undefined"))
		return Win.opener;
	else
		return null;
	
	//	try
	//	{
	//		if (window.opener.opener) return window.opener.opener;
	//	}
	//	catch (e)
	//	{
	//	}

	//	try
	//	{
	//		if (window.opener) return window.opener;
	//	}
	//	catch (e)
	//	{
	//	}

	//	return window;
}

CWindow.AlertAndBack = function (Msg)
{
	alert(Msg);
	history.back();
}

//=========================
var CImage = new Object();

CImage.IsImageByFileName = function (FileName)
{
	var Ext = CFile.GetExtension(FileName);

	switch (Ext.toLowerCase())
	{
		case "bmp":
		case "emf":
		case "gif":
		case "ico":
		case "jpg":
		case "jpeg":
		case "png":
		case "tif":
		case "tiff":
		case "wmf":
			return true;
			break;
	}

	return false;
}

//=========================
var CArray = new Object();

CArray.IndexOf = function (aArray, Match, UseCase)
{
	var TypeOfMatch = typeof (Match);

	switch (TypeOfMatch)
	{
		case "object":
		case "number":
			for (var i = 0; i < aArray.length; i++)
			{
				if (aArray[i] == Match)
				{
					return i;
				}
			}
			break;
		default:
			if (UseCase)
			{
				for (var i = 0; i < aArray.length; i++)
				{
					if (aArray[i] == Match)
					{
						return i;
					}
				}
			}
			else
			{
				for (var i = 0; i < aArray.length; i++)
				{
					if (aArray[i].toLowerCase() == Match.toLowerCase())
					{
						return i;
					}
				}
			}

			break;
	}

	return -1;
}

//==========================
var CMath = new Object();

CMath.Round = function (d, digits)
{
	//round 함수는 정수부분만 되므로 정수부분으로 만들어 반올림한 후,
	//원래 값으로 되돌림.
	var d2 = Math.round(d * Math.pow(10, digits));
	return d2 / Math.pow(10, digits);
}

CMath.GetRandomizedNum = function (From, To)
{
	var Number = Math.floor(Math.random() * (From - To + 1)) + From;
	return Num;
}

CMath.GetPageCount = function (RowCount, PageSize)
{
	if (RowCount < 1) return 0;

	//총 페이지수는  총 행수에서 1페이지당 행수를 나눈 몫.
	//이때 나머지 값이 있다면 총 쪽수에 1을 더함.
	var RowCountOfLastPage = RowCount % PageSize;
	var PageCount = parseInt((RowCount / PageSize), 10);
	return PageCount + (RowCountOfLastPage > 0 ? 1 : 0);
}

// 현재 행 번호로 계산된 현재 페이지 번호를 리턴함.
// var Page1 = CMath.GetCurrentPage(10, 10); // 1
// var Page2 = CMath.GetCurrentPage(10, 11); // 2
CMath.GetCurrentPage = function (PageSize, CurrentRow)
{
	return parseInt(Math.ceil((CurrentRow + 0.0) / PageSize), 10);
}

/*
--설명
10진수를 16진수로 바꿔 리턴함.
--예제
CMath.Dec2Hex(10); //"A"
*/
CMath.Dec2Hex = function (Value)
{
	return parseInt(Value, 10).toString(16).toUpperCase();
}

/*
--설명
16진수를 10진수로 바꿔 리턴함.
--예제
CMath.Hex2Dec("A"); //10
*/
CMath.Hex2Dec = function (Value)
{
	var s = "";

	Value = Value.replace(/^\s+/, "");
	if (Value.length == 0)
		return "";

	Value = Value.replace(/\s+/g, " ");

	var aValue = Value.split(" ");
	for (var i = 0; i < aValue.length; i++)
	{
		if (i > 0)
			s += " ";

		var n = parseInt(aValue[i], 16);
		s += n;
	}

	return s;
}

/*
--설명
Script의 charCodeAt 함수는 유니코드 문자열에 대해서는 잘못된 결과를 표시하므로
유니코드 문자열에도 적용되는 아스키 코드 값을 16진수로 리턴함.
--예제
CMath.ConvertCharToAsciiHex("鎵"); //"93B5"
*/
CMath.ConvertCharToAsciiHex = function (Value)
{
	var Code2 = 0;

	var HexList = "";
	for (var i = 0; i < Value.length; i++)
	{
		var CodeCur = Value.charCodeAt(i);
		if (CodeCur < 0 || CodeCur > 0xFFFF)
		{
			throw ("Error in " + CMath.Dec2Hex(CodeCur) + "!");
		}

		if (Code2 != 0)
		{
			if (0xDC00 <= CodeCur && CodeCur <= 0xDFFF)
			{
				HexList += CMath.Dec2Hex(0x10000 + ((Code2 - 0xD800) << 10) + (CodeCur - 0xDC00)) + " ";
				Code2 = 0;
				continue;
			}
			else
			{
				throw ("Error in " + CMath.Dec2Hex(Code2) + "!");
				Code2 = 0;
			}
		}

		if (0xD800 <= CodeCur && CodeCur <= 0xDBFF)
		{
			Code2 = CodeCur;
		}
		else
		{
			HexList += CMath.Dec2Hex(CodeCur) + " ";
		}
	}

	HexList = HexList.substring(0, HexList.length - 1);

	return HexList;
}

CMath.ConvertCharToAscii = function (Value)
{
	return CMath.Hex2Dec(CMath.ConvertCharToAsciiHex(Value));
}

/*!
Math.uuid.js (v1.4)
http://www.broofa.com
mailto:robert@broofa.com

Copyright (c) 2009 Robert Kieffer
Dual licensed under the MIT and GPL licenses.
*/
CMath.NewGuid = function ()
{
	var aChars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
	var aGuid = new Array();

	// rfc4122, version 4 form
	var r;

	// rfc4122 requires these characters
	aGuid[8] = aGuid[13] = aGuid[18] = aGuid[23] = '-';
	aGuid[14] = '4';

	// Fill in random data.  At i==19 set the high bits of clock sequence as
	// per rfc4122, sec. 4.1.5
	for (var i = 0; i < 36; i++)
	{
		if (!aGuid[i])
		{
			r = (0 | (Math.random() * 16));
			aGuid[i] = aChars[(i == 19) ? ((r & 0x3) | 0x8) : r];
		}
	}

	return aGuid.join('');
}

//==========================
var CType = new Object();

CType.ConvertPercentToFloat = function (Value)
{
	if (CFindRep.EndsWith(Value, "%"))
	{
		//바로 100을 나누면 소수 자리 마지막에 1이 붙어 주석.
		//예: parseFloat(12.3)/100 -> 0.12300000000000001
		//return parseFloat(Value.substring(0, (Value.length - 1))) / 100;
		return parseFloat(Value.substring(0, (Value.length - 1)) * 100) / 10000;
	}
	else
	{
		return parseFloat(Value);
	}
}

//==========================
var CLang = new Object();

CLang.In = function (Value)
{
	for (var i = 1; i < arguments.length; i++)
	{
		if (arguments[i] == Value)
			return true;
	}

	return false;
}

//==========================
var CQueryString = function (Url)
{
	this.PathOnly = "";
	this.Items = {};
	this.Query = "";
	this.Count = 0;

	if (!Url)
		return null;

	var qPos = Url.indexOf("?");

	if (qPos >= 0)
	{
		this.PathOnly = Url.substr(0, qPos - 0);
		this.Query = Url.substr(qPos + 1);
	}
	else
	{
		if (Url.indexOf("=") == -1)
			this.PathOnly = Url;
		else
			this.Query = Url;
	}

	if ((this.Query.length > 0) && (this.Query.substr(0, 1) == "?"))
	{
		this.Query = this.Query.substr(1);
	}

	//파라미터가 없는 경우엔 빠져나감.
	if (this.Query.indexOf('=') == -1)
	{
		return null;
	}

	var aQuery = this.Query.split('&');
	for (var i = 0; i < aQuery.length; i++)
	{
		var NameValue = aQuery[i];

		var aNameValue = NameValue.split('=');
		this.Items[aNameValue[0]] = aNameValue[1];
	}

	this.Count = aQuery.length;

	return this;
}
CQueryString.prototype.GetQueryOnly = function ()
{
	var aQuery = this.Query ? this.Query.split('&') : [];
	
	var aName = [];
	//this.Items는 Name 순으로 자동 정렬 되므로 aQuery의 순서대로 해야 함.
	for (var i = 0; i < aQuery.length; i++)
	{
		var aNameValue = aQuery[i].split('=');
		var NameCur = aNameValue[0];
		var ValueCur = aNameValue[1];

		aName.push(NameCur);

		if (this.Items[NameCur])
			ValueCur = this.Items[NameCur];

		aQuery[i] = NameCur + "=" + ValueCur;
	}

	//값을 추가한 경우.
	for (var Name in this.Items)
	{
		if (CArray.IndexOf(aName, Name) == -1)
			aQuery.push(Name + "=" + this.Items[Name]);
	}

	this.Query = aQuery.join("&");

	return this.Query;
}
CQueryString.prototype.GetNames = function ()
{
	var aQuery = this.Query.split('&');

	var aName = [];
	//this.Items는 Name 순으로 자동 정렬 되므로 aQuery의 순서대로 해야 함.
	for (var i = 0; i < aQuery.length; i++)
	{
		aName.push(aQuery[i].split('=')[0]);
	}

	return aName;
}
CQueryString.prototype.GetValues = function ()
{
	var aQuery = this.Query.split('&');

	var aValue = [];
	//this.Items는 Name 순으로 자동 정렬 되므로 aQuery의 순서대로 해야 함.
	for (var i = 0; i < aQuery.length; i++)
	{
		aValue.push(aQuery[i].split('=')[1]);
	}

	return aValue;
}
CQueryString.prototype.GetPathAndQuery = function ()
{
	var Query = this.GetQueryOnly();
	return this.PathOnly + (!Query ? "" : "?" + Query);
}

CQueryString.AppendQueryString = function (Url, QueryString)
{
	Url = CFindRep.TrimEnd(Url, '?', '&');

	if (QueryString)
	{
		if (Url.indexOf("?") >= 0)
		{
			return Url + "&" + QueryString;
		}
		else
		{
			return Url + "?" + QueryString;
		}
	}
	else
	{
		return Url;
	}
}

//==========================
var CReflection = new Object();

CReflection.GetPropertyByName = function (Obj, Name)
{
	for (var NameCur in Obj)
	{
		if (NameCur == Name)
			return Obj[NameCur];
	}

	return null;
}

//==========================
var CXml = new Object();

CXml.GetXMLHttpRequest = function ()
{
	if (window.XMLHttpRequest)
	{
		return new XMLHttpRequest();
	}
	else if (window.ActiveXObject)
	{
		return new ActiveXObject("Microsoft.XMLHTTP");
		//return new ActiveXObject("MSXML2.XMLHTTP.3.0");
	}
	else
	{
		throw ("XMLHttpRequest 개체를 생성할 수 없습니다.");
	}
}


//==========================
var CHtml = new Object();

CHtml.ConvertHtmlToText = function (Html)
{
	var div = document.createElement("div");
	div.innerHTML = Html;
	return div.innerText || div.textContent;
}
// innerText에 넣고 innerHTML을 읽는 방식은 &mdash;와 같은 문자열엔 적용 안됨.
// http://stackoverflow.com/questions/1354064/how-to-convert-characters-to-html-entities-using-plain-javascript
// all HTML4 entities as defined here: http://www.w3.org/TR/html4/sgml/entities.html
// added: amp, lt, gt, quot and apos
// 39: 'apos', 는 제외(CKEditor에서 자동변환되지 않으므로)
CHtml.ConvertTextToHtml = function (Text)
{
	entityTable = { 34: 'quot', 38: 'amp', 60: 'lt', 62: 'gt', 160: 'nbsp', 161: 'iexcl', 162: 'cent', 163: 'pound', 164: 'curren', 165: 'yen', 166: 'brvbar', 167: 'sect', 168: 'uml', 169: 'copy', 170: 'ordf', 171: 'laquo', 172: 'not', 173: 'shy', 174: 'reg', 175: 'macr', 176: 'deg', 177: 'plusmn', 178: 'sup2', 179: 'sup3', 180: 'acute', 181: 'micro', 182: 'para', 183: 'middot', 184: 'cedil', 185: 'sup1', 186: 'ordm', 187: 'raquo', 188: 'frac14', 189: 'frac12', 190: 'frac34', 191: 'iquest', 192: 'Agrave', 193: 'Aacute', 194: 'Acirc', 195: 'Atilde', 196: 'Auml', 197: 'Aring', 198: 'AElig', 199: 'Ccedil', 200: 'Egrave', 201: 'Eacute', 202: 'Ecirc', 203: 'Euml', 204: 'Igrave', 205: 'Iacute', 206: 'Icirc', 207: 'Iuml', 208: 'ETH', 209: 'Ntilde', 210: 'Ograve', 211: 'Oacute', 212: 'Ocirc', 213: 'Otilde', 214: 'Ouml', 215: 'times', 216: 'Oslash', 217: 'Ugrave', 218: 'Uacute', 219: 'Ucirc', 220: 'Uuml', 221: 'Yacute', 222: 'THORN', 223: 'szlig', 224: 'agrave', 225: 'aacute', 226: 'acirc', 227: 'atilde', 228: 'auml', 229: 'aring', 230: 'aelig', 231: 'ccedil', 232: 'egrave', 233: 'eacute', 234: 'ecirc', 235: 'euml', 236: 'igrave', 237: 'iacute', 238: 'icirc', 239: 'iuml', 240: 'eth', 241: 'ntilde', 242: 'ograve', 243: 'oacute', 244: 'ocirc', 245: 'otilde', 246: 'ouml', 247: 'divide', 248: 'oslash', 249: 'ugrave', 250: 'uacute', 251: 'ucirc', 252: 'uuml', 253: 'yacute', 254: 'thorn', 255: 'yuml', 402: 'fnof', 913: 'Alpha', 914: 'Beta', 915: 'Gamma', 916: 'Delta', 917: 'Epsilon', 918: 'Zeta', 919: 'Eta', 920: 'Theta', 921: 'Iota', 922: 'Kappa', 923: 'Lambda', 924: 'Mu', 925: 'Nu', 926: 'Xi', 927: 'Omicron', 928: 'Pi', 929: 'Rho', 931: 'Sigma', 932: 'Tau', 933: 'Upsilon', 934: 'Phi', 935: 'Chi', 936: 'Psi', 937: 'Omega', 945: 'alpha', 946: 'beta', 947: 'gamma', 948: 'delta', 949: 'epsilon', 950: 'zeta', 951: 'eta', 952: 'theta', 953: 'iota', 954: 'kappa', 955: 'lambda', 956: 'mu', 957: 'nu', 958: 'xi', 959: 'omicron', 960: 'pi', 961: 'rho', 962: 'sigmaf', 963: 'sigma', 964: 'tau', 965: 'upsilon', 966: 'phi', 967: 'chi', 968: 'psi', 969: 'omega', 977: 'thetasym', 978: 'upsih', 982: 'piv', 8226: 'bull', 8230: 'hellip', 8242: 'prime', 8243: 'Prime', 8254: 'oline', 8260: 'frasl', 8472: 'weierp', 8465: 'image', 8476: 'real', 8482: 'trade', 8501: 'alefsym', 8592: 'larr', 8593: 'uarr', 8594: 'rarr', 8595: 'darr', 8596: 'harr', 8629: 'crarr', 8656: 'lArr', 8657: 'uArr', 8658: 'rArr', 8659: 'dArr', 8660: 'hArr', 8704: 'forall', 8706: 'part', 8707: 'exist', 8709: 'empty', 8711: 'nabla', 8712: 'isin', 8713: 'notin', 8715: 'ni', 8719: 'prod', 8721: 'sum', 8722: 'minus', 8727: 'lowast', 8730: 'radic', 8733: 'prop', 8734: 'infin', 8736: 'ang', 8743: 'and', 8744: 'or', 8745: 'cap', 8746: 'cup', 8747: 'int', 8756: 'there4', 8764: 'sim', 8773: 'cong', 8776: 'asymp', 8800: 'ne', 8801: 'equiv', 8804: 'le', 8805: 'ge', 8834: 'sub', 8835: 'sup', 8836: 'nsub', 8838: 'sube', 8839: 'supe', 8853: 'oplus', 8855: 'otimes', 8869: 'perp', 8901: 'sdot', 8968: 'lceil', 8969: 'rceil', 8970: 'lfloor', 8971: 'rfloor', 9001: 'lang', 9002: 'rang', 9674: 'loz', 9824: 'spades', 9827: 'clubs', 9829: 'hearts', 9830: 'diams', 34: 'quot', 38: 'amp', 60: 'lt', 62: 'gt', 338: 'OElig', 339: 'oelig', 352: 'Scaron', 353: 'scaron', 376: 'Yuml', 710: 'circ', 732: 'tilde', 8194: 'ensp', 8195: 'emsp', 8201: 'thinsp', 8204: 'zwnj', 8205: 'zwj', 8206: 'lrm', 8207: 'rlm', 8211: 'ndash', 8212: 'mdash', 8216: 'lsquo', 8217: 'rsquo', 8218: 'sbquo', 8220: 'ldquo', 8221: 'rdquo', 8222: 'bdquo', 8224: 'dagger', 8225: 'Dagger', 8240: 'permil', 8249: 'lsaquo', 8250: 'rsaquo', 8364: 'euro' };

	return Text.replace(/[\u00A0-\u2666<>\&]/g,
					function (c)
					{
						return '&' + (entityTable[c.charCodeAt(0)] || '#' + c.charCodeAt(0)) + ';';
					});
};

