/**
 * BrowseXmlUtils JS 클래스 리스트
 * BrowseLib
 * CookieLib
 * XmlLib
 * XmlDocument
 * Node
 * Element
 * PQAjax
 * Utils
 */

// The Ultimate JavaScript Client Sniffer, Version 3.03:
// Determining Browser Vendor, Version, and Operating System With JavaScript
// 참조 : http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html

// Everything you always wanted to know about your JavaScript client
// but were afraid to ask. Creates "is_" variables indicating:
// (1) browser vendor:
//	 is_nav, is_ie, is_opera, is_hotjava, is_webtv, is_TVNavigator, is_AOLTV
// (2) browser version number:
//	 is_major (integer indicating major version number: 2, 3, 4 ...)
//	 is_minor (float   indicating full  version number: 2.02, 3.01, 4.04 ...)
// (3) browser vendor AND major version number
//	 is_nav2, is_nav3, is_nav4, is_nav4up, is_nav6, is_nav6up, is_gecko, is_ie3,
//	 is_ie4, is_ie4up, is_ie5, is_ie5up, is_ie5_5, is_ie5_5up, is_ie6, is_ie6up, is_hotjava3, is_hotjava3up,
//	 is_opera2, is_opera3, is_opera4, is_opera5, is_opera5up
// (4) JavaScript version number:
//	 is_js (float indicating full JavaScript version number: 1, 1.1, 1.2 ...)
// (5) OS platform and version:
//	 is_win, is_win16, is_win32, is_win31, is_win95, is_winnt, is_win98, is_winme, is_win2k
//
// See http://www.it97.de/JavaScript/JS_tutorial/bstat/navobj.html and
// http://www.it97.de/JavaScript/JS_tutorial/bstat/Browseraol.html

	// convert all characters to lowercase to simplify testing
	var agt=navigator.userAgent.toLowerCase();

	// *** BROWSER VERSION ***
	// Note: On IE5, these return 4, so use is_ie5up to detect IE5.
	var is_major = parseInt(navigator.appVersion);
	var is_minor = parseFloat(navigator.appVersion);

	// Note: Opera and WebTV spoof Navigator.  We do strict client detection.
	// If you want to allow spoofing, take out the tests for opera and webtv.
	var is_nav  = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
				&& (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
				&& (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1));
	var is_nav2 = (is_nav && (is_major == 2));
	var is_nav3 = (is_nav && (is_major == 3));
	var is_nav4 = (is_nav && (is_major == 4));
	var is_nav4up = (is_nav && (is_major >= 4));
	var is_navonly	= (is_nav && ((agt.indexOf(";nav") != -1) ||
					  (agt.indexOf("; nav") != -1)) );
	var is_nav6 = (is_nav && (is_major == 5));
	var is_nav6up = (is_nav && (is_major >= 5));

	var is_iev = (navigator.appVersion.indexOf("MSIE")!=-1) ? true:false;
	var is_firefox = (agt.indexOf('firefox')!=-1) ? true:false;
	var is_safari = (agt.indexOf("safari")!=-1) ? true:false;
	var is_chrome = (agt.indexOf("chrome")!=-1) ? true:false;

	var is_ie	= ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
	var is_ie3	= (is_ie && (is_major < 4));
	var is_ie4	= (is_ie && (is_major == 4) && (agt.indexOf("msie 4")!=-1) );
	var is_ie4up  = (is_ie && (is_major >= 4));
	var is_ie5	= (is_ie && (is_major == 4) && (agt.indexOf("msie 5.0")!=-1) );
	var is_ie5_5  = (is_ie && (is_major == 4) && (agt.indexOf("msie 5.5") !=-1));
	var is_ie5up  = (is_ie && !is_ie3 && !is_ie4);
	var is_ie5_5up =(is_ie && !is_ie3 && !is_ie4 && !is_ie5);
	var is_ie6	= (is_ie && (is_major == 4) && (agt.indexOf("msie 6.")!=-1) );
	var is_ie7	  = (is_ie && (agt.indexOf("msie 7.")!=-1));
	var is_ie8	  = (is_ie && (agt.indexOf("msie 8")!=-1));

	// *** JAVASCRIPT VERSION CHECK ***
	var is_js;
	if (is_nav2 || is_ie3) is_js = 1.0;
	else if (is_nav3) is_js = 1.1;
	else if ((is_nav4 && (is_minor <= 4.05)) || is_ie4) is_js = 1.2;
	else if ((is_nav4 && (is_minor > 4.05)) || is_ie5) is_js = 1.3;
	else if (is_nav6) is_js = 1.5;
	// NOTE: In the future, update this code when newer versions of JS
	// are released. For now, we try to provide some upward compatibility
	// so that future versions of Nav and IE will show they are at
	// *least* JS 1.x capable. Always check for JS version compatibility
	// with > or >=.
	else if (is_nav6up) is_js = 1.5;
	// NOTE: ie5up on mac is 1.4
	else if (is_ie5up) is_js = 1.3

	// HACK: no idea for other browsers; always check for JS version with > or >=
	else is_js = 0.0;

	// *** PLATFORM ***
	var is_win   = ( (agt.indexOf("win")!=-1) || (agt.indexOf("16bit")!=-1) );
	// NOTE: On Opera 3.0, the userAgent string includes "Windows 95/NT4" on all
	//		Win32, so you can't distinguish between Win95 and WinNT.
	var is_win95 = ((agt.indexOf("win95")!=-1) || (agt.indexOf("windows 95")!=-1));

	// is this a 16 bit compiled version?
	var is_win16 = ((agt.indexOf("win16")!=-1) || 
			   (agt.indexOf("16bit")!=-1) || (agt.indexOf("windows 3.1")!=-1) || 
			   (agt.indexOf("windows 16-bit")!=-1) );  

	var is_win31 = ((agt.indexOf("windows 3.1")!=-1) || (agt.indexOf("win16")!=-1) ||
					(agt.indexOf("windows 16-bit")!=-1));

	var is_winme = ((agt.indexOf("win 9x 4.90")!=-1));
	var is_win2k = ((agt.indexOf("windows nt 5.0")!=-1));

	// NOTE: Reliable detection of Win98 may not be possible. It appears that:
	//	   - On Nav 4.x and before you'll get plain "Windows" in userAgent.
	//	   - On Mercury client, the 32-bit version will return "Win98", but
	//		 the 16-bit version running on Win98 will still return "Win95".
	var is_win98 = ((agt.indexOf("win98")!=-1) || (agt.indexOf("windows 98")!=-1));
	var is_winnt = ((agt.indexOf("winnt")!=-1) || (agt.indexOf("windows nt")!=-1));
	var is_win32 = (is_win95 || is_winnt || is_win98 || 
					((is_major >= 4) && (navigator.platform == "Win32")) ||
					(agt.indexOf("win32")!=-1) || (agt.indexOf("32bit")!=-1));

/**
 * XML DOM에 Property 추가
 *
 * selectNodes()
 * selectSingleNode()
 */
if (document.implementation.hasFeature("XPath", "3.0")) 
{
	// prototying the XMLDocument 
	XMLDocument.prototype.selectNodes = function (strXPath, xnDoc) 
	{
		if (!xnDoc)
		{
			xnDoc = this;
		}
		
		var objNSResolver = this.createNSResolver(this.documentElement);
		var arItemList = this.evaluate(strXPath, xnDoc, objNSResolver,
									XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
		var arResultList = [];
		for (var i = 0; i < arItemList.snapshotLength; i++) 
		{
			arResultList[i] = arItemList.snapshotItem(i);
		}
		
		return arResultList;
	}
	
	// prototying the Element 
	Element.prototype.selectNodes = function (strXPath) 
	{
		if (this.ownerDocument.selectNodes)
		{
			return this.ownerDocument.selectNodes(strXPath, this);
		}
		else
		{
			throw "For XML Elements Only";
		}
	}
	
	// prototying the XMLDocument 
	XMLDocument.prototype.selectSingleNode = function (strXPath, xnDoc) 
	{
		if (!xnDoc)
		{
			xnDoc = this;
		}
		var xnItemList = this.selectNodes(strXPath, xnDoc);
		
		if (xnItemList.length > 0)
		{
			return xnItemList[0];
		}
		else
		{
			return null;
		}
	}
	
	// prototying the Element 
	Element.prototype.selectSingleNode = function (strXPath)
	{
		if (this.ownerDocument.selectSingleNode)
		{
			return this.ownerDocument.selectSingleNode(strXPath, this);
		}
		else
		{
			throw "For XML Elements Only";
		}
	}
}


/**
 * XmlLib.js
 *
 * XML 처리 라이브러리
 * 각 함수를 static으로 구현했다.
 * 브라우저에서 기본적으로 제공하는 것들은 구현 안함
 */

function XmlLib ()
{
}

////////////////////
// static method

XmlLib.loadXMLFromString = function (strXml)
{
	var xmlDoc = null;
	
	// Mozilla
	if(is_nav)
	{
		var parser = new DOMParser();
		xmlDoc = parser.parseFromString(strXml, "text/xml");
	}
	// IE
	else if(is_ie)
	{
		xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.async = false;
		xmlDoc.resolveExternals = true;
		xmlDoc.validateOnParse = false;
		xmlDoc.preserveWhiteSpace = true; 
		xmlDoc.loadXML(strXml);
	}

	return xmlDoc;
}

XmlLib.loadXMLFromFile = function (strXmlFilePath)
{
	var xmlDoc = null;
	
	// Mozilla
	if(is_nav)
	{
		//TODO
	}
	// IE
	else if(is_ie)
	{
		xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.async = false;
		xmlDoc.resolveExternals = true;
		xmlDoc.validateOnParse = false;
		xmlDoc.preserveWhiteSpace = true; 
		xmlDoc.load(strXmlFilePath);
	}
	
	return xmlDoc;
}

XmlLib.createXML = function (strRoot)
{
	var xmlDoc = null;
	
	// Mozilla
	if(is_nav)
	{
		xmlDoc = document.implementation.createDocument("", strRoot, null);
	}
	// IE
	else if(is_ie)
	{
		xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.async = false;
		xmlDoc.resolveExternals = true;
		xmlDoc.validateOnParse = false;
		xmlDoc.documentElement = xmlDoc.createElement(strRoot);
	}
		
	return xmlDoc;
}

XmlLib.serializeToString = function (node)
{
	var strXml = null;
	
	// Mozilla
	if (is_nav)
	{
		var serializer = new XMLSerializer();
		strXml = serializer.serializeToString(node);
	}
	// IE
	else if (is_ie)
	{
		strXml = node.xml
	}
	
	return strXml;
}

/**
 * Xml Node attribute 값을 얻어 온다.
 *
 * Node.getAttribute("속성이름") 함수로 얻어온 결과 값이 null일때, null로 제대로 인식하지 않는다... 왜 그럴까?
 */
XmlLib.getAttribute = function (xmlNode, strAttName)
{
	if (null != xmlNode)
	{
		var nAttrSize = xmlNode.attributes.length;
		
		for (var i = 0; i < nAttrSize; i++)
		{
			if (xmlNode.attributes[i].nodeName == strAttName)
			{
				return xmlNode.attributes[i].value;
			}
		}
	}
	return null;
}

/**
 * Xml Node attribute 를 설정한다
 *
 * Node.setAttribute(Node, "속성이름", "값")
 */
XmlLib.setAttribute = function (xmlNode, strAttName, strAttValue)
{
	xmlNode.setAttribute(strAttName, strAttValue);
}

XmlLib.createChild = function (xnParent, strNodeName)
{
	var xnDoc = xnParent.ownerDocument;
	var xnChild = xnDoc.createElement(strNodeName);
	xnParent.appendChild(xnChild);
	
	return xnChild;
}

/**
 * 값을 가진 자식 노드를 생성한다. 
 * @param nxParent (부모 노드) 
 * @param strNodeName (생성할 자식노드 이름)
 * @param strValue (자식노드에 부여할 값)
 * @return xnNode (생성한 자식 노드)
 */
XmlLib.createChildWithValue = function (xnParent, strNodeName, strValue)
{
	if (null == strValue)
	{
		strValue = "";
	}
	
	var xnChild = XmlLib.createChild(xnParent, strNodeName);
	XmlLib.setTextValue(xnChild, strValue);
	
	return xnChild;
}

XmlLib.getTextValue = function (xmlNode)
{
	var strValue = "";
	
	try
	{
		// Node.TEXT_NODE = 3 , CDATA section = 4
		if (Node.TEXT_NODE == xmlNode.firstChild.nodeType
			|| Node.CDATA_SECTION_NODE == xmlNode.firstChild.nodeType)
		{
			strValue = xmlNode.firstChild.nodeValue;
		}
	}
	catch (e)
	{
	}
	
	return strValue;
}

/**
 * @param xmlDoc 새로운 XML Node, impor된 Node가 child로 append 됩니다.
 * @param oldNode import 할 Node
 * @param deep 하위 노드 import 여부
 * @return 새롭게 import 된 Node
 */
XmlLib.importChildNode = function (xnParent, xnChild, deep)
{
	var xnNewChild = XmlLib.importNode(xnParent.ownerDocument, xnChild, deep);
	xnParent.appendChild(xnNewChild);
	
	return xnNewChild;
}

/**
 * @param xmlDoc 새로운 XML Document
 * @param oldNode import 할 Node
 * @param deep 하위 노드 import 여부
 * @return 새롭게 import 된 Node
 */
XmlLib.importNode = function (xmlDoc, oldNode, deep)
{
	if (xmlDoc.importNode)
	{
		return xmlDoc.importNode(oldNode, deep);
	}
	else
	{
		return XmlLib.importNodeOld(xmlDoc, oldNode, deep);
	}
}

// importNode를 지원하지 않는 브라우저를 위해...직접 구현
XmlLib.importNodeOld  = function (xmlDoc, oldNode, deep)
{
	deep = (deep == null) ? true : deep;
	
	var importChildren = function(doc, srcNode, parent)
	{
		if (deep)
		{
			for (var i = 0; i < srcNode.childNodes.length; i++)
			{
				var node = XmlLib.importNode(doc, srcNode.childNodes.item(i), true);
				parent.appendChild(node);
			}
		}
	};
	
	var newNode = null;
	
	switch(oldNode.nodeType)
	{
		case Node.ATTRIBUTE_NODE:
			if (null != xmlDoc.createAttributeNS)
				newNode = xmlDoc.createAttributeNS(oldNode.namespaceURI, oldNode.nodeName);
			else
				newNode = xmlDoc.createAttribute(oldNode.nodeName);
			newNode.value = oldNode.value;
			break;
		case Node.DOCUMENT_FRAGMENT_NODE:
			newNode = xmlDoc.createDocumentFragment();
			importChildren(xmlDoc, oldNode, newNode);
			break;
		case Node.ELEMENT_NODE:
			if (null != xmlDoc.createElementNS)
				newNode = xmlDoc.createElementNS(oldNode.namespaceURI, oldNode.tagName);
			else
				newNode = xmlDoc.createElement(oldNode.tagName);
			for (var i = 0; i < oldNode.attributes.length; i++)
			{
				var attr = XmlLib.importNode(xmlDoc, oldNode.attributes.item(i), deep);
				if (null != newNode.setAttributeNodeNS)
			   		newNode.setAttributeNodeNS(attr);
			   	else
			   		newNode.setAttributeNode(attr);
			}
			importChildren(xmlDoc, oldNode, newNode);
			break;
		case Node.ENTITY_REFERENCE_NODE:
			newNode = oldNode;
			break;
		case Node.PROCESSING_INSTRUCTION_NODE:
			newNode = xmlDoc.createProcessingInstruction(oldNode.target, oldNode.data);
			break;
		case Node.TEXT_NODE:
		case Node.CDATA_SECTION_NODE:
		case Node.COMMENT_NODE:
			newNode = xmlDoc.createTextNode(oldNode.nodeValue);
			break;
		case Node.DOCUMENT_NODE:
			//Document nodes cannot be imported.
		case Node.DOCUMENT_TYPE_NODE:
			//DocumentType nodes cannot be imported.
		case Node.NOTATION_NODE:
			//readonly in DOM2
		case Node.ENTITY_NODE:
			//readonly in DOM2
			throw "not supported in XmlLib";
			break;
	}
	
	return newNode;
}

XmlLib.setTextValue = function (xmlNode, strValue)
{
	if (xmlNode.hasChildNodes() && Node.TEXT_NODE == xmlNode.firstChild.nodeType) // Node.TEXT_NODE = 3
	{
		xmlNode.firstChild.nodeValue = strValue;
	}
	else
	{
		var xmlText = xmlNode.ownerDocument.createTextNode(strValue);
		xmlNode.appendChild(xmlText);
	}
}

XmlLib.createCDATASection = function (xmlNode, strValue)
{
	var xmlDocument = xmlNode.ownerDocument;
	
	var xmlCDATA = xmlDocument.createCDATASection(strValue);
	
	xmlNode.appendChild(xmlCDATA);
}

XmlLib.transformToHTMLElement = function (heElement, xnNode, xnXSL)
{
	try
	{
		if (is_nav)
		{
			var objXslt = new XSLTProcessor();
			objXslt.importStylesheet(xnXSL);
			
			var resultFragment = objXslt.transformToFragment(xnNode, document);		
			heElement.appendChild(resultFragment.firstChild);
			
			objXslt.reset();
			return;
		}
		else if (is_ie)
		{
			heElement.innerHTML = xnNode.transformNode(xnXSL);
		}
	}
	catch (e)
	{
		window.alert(e);
		// todo
	}
}

/*XmlLib.transformToDocument = function (doc, xml, xsl)
{
	try
	{
		var objBody = doc.getElementsByTagName("body")[0];
		
		if (is_nav)
		{
			var xslt = new XSLTProcessor();
			xslt.importStylesheet(xsl);
			
			var newDoc = xslt.transformToDocument(xml);
			
			objBody.appendChild(newDoc);
		}
		else if (is_ie)
		{
			objBody.innerHTML = xml.transformNode(xsl);
		}
	
	}
	catch (e)
	{
	}
}*/

/*XmlLib.transformNode = function (xnXML, xnXSL)
{
	var strResult = "";
	
	if (is_nav)
	{
		var xslt = new XSLTProcessor();
		xslt.importStylesheet(xnXSL);
		
		var newDoc = xslt.transformToDocument(xml);
		
		var serializer = new XMLSerializer();
		strResult = serializer.serializeToString(newDoc);
		
	}
	else if (is_ie)
	{
		strResult = xnXML.transformNode(xnXSL);
	}
	
	return strResult;
}*/

XmlLib.selectSingleNode = function (xmlNode, strPath)
{
	if (null == xmlNode)
	{
		return null;
	}
	
	var xmlSelectNode = null;
	
	xmlSelectNode = xmlNode.selectSingleNode(strPath);
	
	return xmlSelectNode;
}

XmlLib.selectNodeList = function (xmlNode, strPath)
{
	if (null == xmlNode)
	{
		return null;
	}
	
	var xmlSelectNodeList = null;
	
	xmlSelectNodeList = xmlNode.selectNodes(strPath);
	
	return xmlSelectNodeList;
}

XmlLib.removeNode = function (xnParentNode, xnRemoveNode)
{
	if (null == xnParentNode || null == xnRemoveNode)
	{
		return;
	}
	
	xnParentNode.removeChild(xnRemoveNode);
}

/**
 * NodeType Constants
 * Document Object Model (DOM) Level 1 Specification 에는
 * Node 인터페이스에 NodeType 이 상수로 선언되어 있는데,
 * ie는 이를 지원하고 있지 않다. (기타 표준을 준수하는 브라우저는 정의되어 있음.)
 * @see - http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-1950641247
 * 사용예 : if (Node.ELEMENT_NODE == Element.nodeType) // 노드타입이 엘리먼트 일 때
 */
if (!window.Node)
{
	var Node =
	{
		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
	};
}

/**
 * Ajax post 요청을 보냅니다.
 * @param strURL 요청을 받을 URL. 질의는 여기에 붙이세요.
 * @param strData 전송할 데이터. 
 */
PQAjax.post = function (strURL, strData)
{
	return g_objPQAjax.post(strURL, strData);
}

PQAjax.get = function (strURL)
{
	return g_objPQAjax.get(strURL);
}

PQAjax.getSessionID = function ()
{
	return g_objPQAjax.getSessionID();
}

PQAjax._factories =
[
	function () { return new XMLHttpRequest(); },
	function () { return new ActiveXObject("Msxml2.XMLHTTP"); },
	function () { return new ActiveXObject("Microsoft.XMLHTTP"); }
]

function PQAjax()
{
	this.m_objFactory = null;
	this.m_objXMLHttpRequest = null;
	this.m_bAsync = false;
	this.m_strContentType = "text/xml; charset=UTF-8";
	
	//현재 연결된 세션 ID
	this.m_strSessionID = "";
}

PQAjax.prototype.post = function (strURL, strData)
{
	strURL = encodeURI(strURL);

	this._sendRequest("POST", strURL, strData);
	
	return this._handleResult();
}

PQAjax.prototype.get = function (strURL)
{
	strURL = encodeURI(strURL);
	
	this._sendRequest("GET", strURL, null);
	
	return this._handleResult();
}

PQAjax.prototype.getSessionID = function ()
{
	return this.m_strSessionID;
}

PQAjax.prototype._newRequest = function ()
{
	if (null != this.m_objFactory)
	{
		return this.m_objFactory();
	}
	
	for (var i = 0; i < PQAjax._factories.length; i += 1)
	{
		try
		{
			var objfactory = PQAjax._factories[i];
			var objRequest = objfactory();
			
			if (null != objRequest)
			{
				this.m_objFactory = objfactory;
				
				return objRequest;
			}
		}
		catch (e)
		{
			continue;
		}
	}

	alert("not support");
}
	
PQAjax.prototype._sendRequest = function (strMethod, strURL, strData)
{
	this.m_objXMLHttpRequest = this._newRequest();
	
	this.m_objXMLHttpRequest.open(strMethod, strURL, this.m_bAsync);
	this.m_objXMLHttpRequest.setRequestHeader("Content-Type", this.m_strContentType);
	this.m_objXMLHttpRequest.send(strData);
}

PQAjax.prototype._handleResult = function ()
{
	if (4 == this.m_objXMLHttpRequest.readyState)
	{
		if (200 == this.m_objXMLHttpRequest.status)
		{
			this.m_strSessionID = this.m_objXMLHttpRequest.getResponseHeader("JSESSIONID");
			return this.m_objXMLHttpRequest.responseText;
		}
		else
		{
			this._handleError();
		}
	}
}

PQAjax.prototype._handleError = function ()
{
	throw new FailExecuteAjaxAction(this.m_objXMLHttpRequest.status);
}

PQAjax.prototype._parseHeaders = function ()
{
	var strHeaderText = this.m_objXMLHttpRequest.getAllResponseHeaders();
	var objHeaders = new Object();
	var objWhiteSpaceAtBeginning = /^\s*/;
	var objWhiteSpaceAtEnd = /\s*$/;
	
	var arLines = strHeaderText.split("\n");
	
	for (var i = 0; i < arLines.length; i += 1)
	{
		var strLine = arLines[i];
		
		if (0 == strLine.length)
		{
			continue;
		}
		
		var nPos = strLine.indexOf(":");
		var strName = strLine.substring(0, nPos).replace(objWhiteSpaceAtBeginning, "").replace(objWhiteSpaceAtEnd, "");
		var strValue = strLine.substring(nPos + 1).replace(objWhiteSpaceAtBeginning, "").replace(objWhiteSpaceAtEnd, "");
		
		objHeaders[strName] = strValue;
	}
	
	return objHeaders;
}

var g_objPQAjax = new PQAjax();


/**
 * 자바스크립트에서 사용자 객체는 Object를 상속받습니다.
 * Object는 Property를 Hash 알고리즘으로 구현했습니다.
 * 자바스크립트에서 HashTable을 명시적으로 사용하기 위해 빈 클래스를 만들었습니다.
 */
function Hashtable ()
{
}
 
/*
Utils.js
공통으로 쓰일 수 있는 유용한 함수 모음...
*/
function Utils ()
{
}

Utils.makeDDay = function (preDate, nextDate)
{
	return Math.ceil((preDate - nextDate) / (1000 * 60 * 60 * 24));
}

Utils.strPixelToint = function (strPixel)
{
	return parseInt(Utils.replace(strPixel, "px", ""));
}

Utils.parseInt = function (strValue)
{
	var nReturn = 0;
	
	if (null == strValue || "" == strValue)
	{
		nReturn = 0;
	}
	else
	{
		try
		{
			nReturn = Number(strValue);
			//nReturn = parseInt(strValue);
		}
		catch (e)
		{
			nReturn = 0;
		}
	}
	
	return nReturn;
}

Utils.getCSSRule = function (strLinkID, strSelectorText)
{
	var objRules = document.getElementById(strLinkID).styleSheet.rules;

	for (var i = 0, nLen = objRules.length; i < nLen; i++)
	{
		if (strSelectorText == objRules[i].selectorText)
		{
			return objRules[i];
		}
	}

	return null;
}

Utils.getPonitToPixel = function (nPoint)
{
	if (6 <= nPoint && 7 >= nPoint)
	{
		nPoint += 2;
	}
	else if (8 <= nPoint && 10 >= nPoint)
	{
		nPoint += 3;
	}
	else if (11 <= nPoint && 13 >= nPoint)
	{
		nPoint += 4;
	}
	else if (14 == nPoint)
	{
		nPoint += 5;
	}
	else if (15 <= nPoint && 22 >= nPoint)
	{
		nPoint += 6;
	}
	else if (24 == nPoint)
	{
		nPoint += 8;
	}
	else if (26 <= nPoint && 29 >= nPoint)
	{
		nPoint += 9;
	}
	else if (30 <= nPoint && 32 >= nPoint)
	{
		nPoint += 10;
	}
	else if (34 == nPoint)
	{
		nPoint += 11;
	}
	else if (36 == nPoint)
	{
		nPoint += 12;
	}
	
	return nPoint;
}
/**
 * 윤년 인가??
 * @param nYear
 * @return boolean
 * 배준배 2006. 09. 21
 */
Utils.isLeapyear = function (nYear)
{
	if (nYear % 400 == 0 || (nYear % 4 == 0 && nYear % 100 != 0))
	{
		return true;
	}

	return false;
}

Utils.isEmpty = function (strValue)
{
	if (null == strValue || 0 == strValue.length)
	{
		return true;
	}
	return false;
}

/**
 * 입력된 값의 자릿수를 유효한 자릿수로 바꿘준다. 
 * 만약 '월' 에 4를 입력 하고 nValidCount를 2로 하면, 04로 바꿔다. 
 * @param nValidCount(유효한 자릿수), strValue
 * @strValidValue (유효한값)
 * 배준배 2006. 09. 21 
 */
Utils.makeValidCiphers = function (nValidCount, strValue)
{
	var insertCount = 0;

	if ("string" != typeof(strValue))
	{
		strValue = strValue.toString();
	}

	var strValidValue = strValue;

	if (nValidCount > strValue.length)
	{
		insertCount = nValidCount - strValue.length;

		for (var i = 0; i < insertCount; i++)
		{
			strValidValue = "0" + strValidValue;
		}
	}

	return strValidValue;
}

Utils.isDigit = function (chValue)
{
	if ("0" <= chValue && "9" >= chValue)
	{
		return true;
	}
	
	return false;
}

Utils.isNumber = function (nValue)
{
	if (isNaN(nValue))
	{
		return false;
	}
	
	return true;
}

Utils.isAlphabet = function (ch)
{
	return ('A' <= ch && 'Z' >= ch || 'a' <= ch && 'z' >= ch) ? true : false;
}

Utils.trim = function (strValue)
{
	var strResult = "";
	
	// 예외 값의 경우 ""을 반환한다. 
	if (strValue == null || typeof(strValue) == "undefined") 
	{
		strResult = ""; 
	}
	else
	{
		strResult = strValue.replace( /^\s*/, "" ).replace( /\s*$/, "" ); 	
	}
	return strResult;
}

/**
 * '^', '$', '+', '*', '?', '{', '}', '|', '\\\\', '(', ')', '[', ']'
 * 위의 문자들의 경우 정규표현식의 특수 문자에 해당하므로
 * ("aaaa$aaaa", "\\$", " ") <== 왼쪽과 같이 문자 앞에 \\ 를 붙여 명확히 해 줍시다
 * 그러지 않을 경우 정상적인 replace 동작이 일어 나지 않을수도 있습니다
 */
Utils.replace = function (strValue, strOld, strNew)
{
	if (null == strValue || null == strOld || null == strNew)
	{
		return strValue;
	}

	var objRegExp = new RegExp(strOld, "g");
	
	return strValue.replace(objRegExp, strNew);
}

Utils.replaceAll = function (strValue, strOld, strNew)
{
	var nIndex = 0;
	while (0 <= nIndex)
	{
		nIndex = strValue.indexOf(strOld, nIndex);
		if (0 <= nIndex)
		{
			strValue = strValue.substring(0, nIndex) + strNew + strValue.substring(nIndex + strOld.length);
			nIndex += strNew.length;
		}
	}
	return strValue;
}

Utils.replaceFirst = function (strValue, strOld, strNew)
{
	var nIndex = strValue.indexOf(strOld);
	
	if (-1 < nIndex)
	{
		strValue = strValue.substring(0, nIndex) + strNew + strValue.substring(nIndex + strOld.length);
	}
	
	return strValue;
}

/**
 * 콤마를 삽입합니다.
 *
 * @param strValue 값
 * @return 콤마가 삽입된 값
 */
Utils.insertComma = function (strValue)
{
	var strResultValue = "";
	
	var bIsMinus = false;
	if (0 == strValue.indexOf("-"))	// 음수일 경우
	{
		bIsMinus = true;
		strValue = strValue.substring(1, strValue.length);
	}
	
	if (-1 < strValue.indexOf(".")) // 소숫점이 있을 경우
	{
		var arValue = strValue.split(".");
			
		strPrefix = arValue[0].toString();
		strSuffix = arValue[1].toString();
		
		strPrefix = Utils.insertCommaString(strPrefix);
			
		strResultValue = strPrefix + "." + strSuffix;
	}
	else
	{
		strResultValue = Utils.insertCommaString(strValue);
	}
	
	if (bIsMinus)
	{
		strResultValue = "-" + strResultValue;
	}
	
	return strResultValue;
}

/**
  * 콤마를 삽입합니다.
  *
  * @param strValue 값
  * @return 콤마가 삽입된 값
  */
Utils.insertCommaString = function (strValue)
{
	var strResult = ""; 		
	var nLen = strValue.length;
	
	if (3 >= nLen)		// 콤마를 삽입 하지 않아도 됨
	{
		return strValue;
	}
	
	var nFirstLen = nLen % 3;	// 첫번째 콤마의 왼쪽 부분
	
	if (0 == nFirstLen)
	{
		nFirstLen = 3;
	}
	
	strResult = strValue.substring(0, nFirstLen);

	for (var i = nFirstLen; i < nLen; i += 3)
	{
		strResult = strResult + "," + strValue.substr(i, 3);
	}
	
	return strResult;
}

Utils.removeComma = function (strValue)
{
	// TODO 조영운 StringLib를 만들어서 replaceAll을 구현해서 StringLib 사용하도록 수정해야 합니다.
	return strValue.replace(new RegExp(",", "g"), ""); 
}

/**
 * 소수점 자릿수에 숫자가 아니면, 전역정보에서 소수점 자릿수를 가져와야 합니다.
 *
 * 참고 : 전역정보에 소수점 자리수가 들어가는 경우
 *  1. 환경설정 - 운영환경 - 처리기준 - 소수점유형 : DB -> 전역정보
 *  2. 스크립트에서 전역정보 설정
 * @param strPeriod 속성창에서 입력된 소숫점 자리수
 */
Utils.initPeriod = function (strPeriod)
{	
	if (null == strPeriod || "" == strPeriod || "\"0\"" == strPeriod)
	{
		strPeriod = "0";
	}
	
	if (!Utils.isNumber(strPeriod))
	{
		var strTempPeriod = PQService.getGlobalInfo(strPeriod);
		if (strTempPeriod)
		{
			nPeriod = parseInt(strTempPeriod);
		}
		else
		{
			if ('\"' == strPeriod.charAt(0))
			{
				var nIndex = strPeriod.indexOf('\"', 1);
				if (1 < nIndex)
				{
					strTempPeriod = strPeriod.substring(1, nIndex);
					nPeriod = parseInt(strTempPeriod);
				}
			}
		}
	}
	else
	{
		nPeriod = parseInt(strPeriod);
	}
	return nPeriod;
}

Utils.getPrefix = function (strPrefix)
{
	if (0 == strPrefix.indexOf('\"'))
	{
		var nLen = strPrefix.length
		if (strPrefix.lastIndexOf('\"') == nLen - 1)
		{
			strPrefix = strPrefix.substring(1, nLen - 1);
		}
	}
	
	return strPrefix;
}

/**
 * 현재 시각을 YYYYMMDDHHMM으로 리턴한다.
 */
Utils.getCurrentDate = function ()
{
	var objDate = new Date()
	
	var strYear = objDate.getYear().toString();
	var strMonth = (objDate.getMonth() + 1).toString();
	var strDate = objDate.getDate().toString();
	var strHours = objDate.getHours().toString();
	var strMinutes = objDate.getMinutes().toString();
	if (1 == strMonth.length)
	{
		strMonth = "0" + strMonth;
	}
	if (1 == strDate.length)
	{
		strDate = "0" + strDate;
	}
	if (1 == strMinutes.length)
	{
		strMinutes = "0" + strMinutes;
	}
	
	return strYear + strMonth + strDate + strHours + strMinutes;
}

Utils.getTodayYear = function ()
{
	return new Date().getYear().toString();
}

Utils.getTodayMonth  = function()
{
	var strMonth = (new Date().getMonth() + 1).toString();
	if (1 == strMonth.length)
	{
		strMonth = "0" + strMonth;
	}
	
	return strMonth;
}

Utils.getTodayDate = function ()
{
	var strDate = new Date().getDate().toString();
	if (1 == strDate.length)
	{
		strDate = "0" + strDate;
	}

	return strDate;
}
Utils.getHours = function ()
{
	return new Date().getHours().toString();
}

Utils.getMinutes = function ()
{
	return new Date().getMinutes().toString();
}

/**
 * 달의 마지막 날짜 구하기 
 * @param nYear (해당 년도)
 * @param nMonth (해당 월)
 * @return nLastDate (마지막 날짜)
 */
Utils.getLastDateInMonth = function (nYear, nMonth)
{
	if (2 == nMonth && Utils.isLeapyear(nYear))
	{
		return 29; // 유년의 2월인 경우 29일
	}
	
	var alMonth = new Array (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
	
	return alMonth[nMonth - 1];
}

Utils.makeArray = function (strValue, nArrayLength)
{
	var listResult = new Array();

	if (nArrayLength > strValue.length)
	{
		return listResult;
	}

	for (var i = 0, nLen = strValue.length; i < nLen; i = i + nArrayLength)
	{
		listResult.push(strValue.substr(i, nArrayLength));
	}

	return listResult;
}


/**
 * 문자열을 "'"로 감쌉니다 
 * @param strValue
 */
Utils.changeFormatToChar = function (strValue)
{
	return "'" + strValue + "'";
}

/**
* 윈도우 창을 여는 공통 함수
* @param strURL
* @param nLinkType 0: 기존창으로 열기. 그외: 새창으로 열기
*/
Utils.openWindow = function (strURL, nLinkType, bToolbar, nHieght, nWidth)
{
	var strOption = "";
	
	// 일반모델, 결재모델
	if (-1 < strURL.indexOf("/ups/Model.html?ModelName="))
	{
		var nTop = 250;
		// 모델이 뜨는 화면상의 위치를 수정합니다.
		// 기업용 폼이니까 로고나 메뉴를 가려서는 안 된다는 의견이 반영된 것입니다. 임시.
		var nLeft = 230;
		
		if (-1 == strURL.indexOf(".", 26))
		{
			// 결재 모델일 경우
			nTop = 0;
			nLeft = 130;
		}
		
		
		if (bToolbar)
		{
			strOption = "top=" + nTop + ", left=" + nLeft + ", width=100, height=100, ";
			strOption += "scrollbars=yes, titlebar=yes, toolbar=yes, menubar=yes, location=yes, status=yes, directories=yes, resizable=yes, copyhistory=yes";
		}
		else
		{
			strOption = "top=" + nTop + ", left=" + nLeft + ", width=100, height=100, ";
			strOption += "scrollbars=no, titlebar=yes, menubar=no, toolbar=no, location=no, status=no, directories=no, resizable=no, copyhistory=no";
		}
	}
	// 출력물.
	else if (-1 < strURL.indexOf("/ups/Report.html?ModelName="))
	{
		// 출력물은 리사이즈 가능하도록 함.
		strOption += "scrollbars=no, titlebar=yes, menubar=no, toolbar=no, location=no, status=no, directories=no, resizable=yes, copyhistory=no";
	}
	else //웹페이지 모델 등.
	{
		strOption = "scrollbars=yes, titlebar=yes, toolbar=yes, menubar=yes, location=yes, status=yes, directories=yes, resizable=yes, copyhistory=yes";
		
		if (!bToolbar)
		{
			strOption = "scrollbars=no, titlebar=yes, menubar=no, toolbar=no, location=no, status=no, directories=no, resizable=no, copyhistory=no";
		}
		
		if (nHieght)
		{
			strOption += ", height=" + nHieght;
		}
		
		if (nWidth)
		{
			strOption += ", width=" + nWidth;
		}
	}
	
	var strType = "_self";
	if (nLinkType)
	{
		strType = "_blank";
	}
	
	var objChildWindow = window.open(strURL, strType, strOption);
	GlobalField.setChildWindow(objChildWindow);
	
	return objChildWindow;
}

/**
 * 툴바 등이 없는 모달 다이얼로그를 연다.
 */
Utils.showModalDialog = function (strUrl, objArgument, nLeft, nTop, nWidth, nHeight)
{
	var strOption = "";
	strOption += "titlebar:yes;menubar:no;toolbar:no;location:no;scroll:no;status:no;";
	strOption += "directories:no;resizable:no;copyhistory:no";
		
	return Utils.showModalDialogWithOption(strUrl, objArgument, nLeft, nTop, nWidth, nHeight, strOption);
}

/**
 * 모달 다이얼로그를 연다. 옵션을 사용할 수 있다.
 */
Utils.showModalDialogWithOption = function (strUrl, objArgument, nLeft, nTop, nWidth, nHeight, strOption)
{
	if (is_ie7 || is_ie8)
	{
		if (undefined != nWidth)
		{
			nWidth -= 4;
		}
		
		if (undefined != nHeight)
		{
			nHeight -= 35;
		}
	}

	var strPosition = "";
	if (undefined != nLeft && 0 <= nLeft)
	{
		strPosition += ";dialogLeft:" + nLeft + "px";
	}
	
	if (undefined != nTop && 0 <= nTop)
	{
		strPosition += ";dialogTop:" + nTop + "px";
	}
	
	if (undefined != nWidth && 0 <= nWidth)
	{
		strPosition += ";dialogWidth:" + nWidth + "px";
	}
	
	if (undefined != nHeight && 0 <= nHeight)
	{
		strPosition += ";dialogHeight:" + nHeight + "px";
	}
	
	strOption += strPosition;
	
	return window.showModalDialog(strUrl, objArgument, strOption);
}

/**
 * 모달리스 다이얼로그를 연다.
 */
Utils.showModelessDialog = function (strUrl, objArgument, nLeft, nTop, nWidth, nHeight)
{
	var strOption = "";
	strOption += "titlebar:yes;menubar:no;toolbar:no;location:no;scroll:no;status:no;";
	strOption += "directories:no;resizable:no;copyhistory:no";
		
	return Utils.showModelessDialogWithOption(strUrl, objArgument, nLeft, nTop, nWidth, nHeight, strOption);
}

/**
 * 모달리스 다이얼로그를 연다. 옵션을 사용할 수 있다.
 */
Utils.showModelessDialogWithOption = function (strUrl, objArgument, nLeft, nTop, nWidth, nHeight, strOption)
{
	if (is_ie7 || is_ie8)
	{
		if (undefined != nWidth)
		{
			nWidth -= 4;
		}
		
		if (undefined != nHeight)
		{
			nHeight -= 35;
		}
	}

	var strPosition = "";
	if (undefined != nLeft && 0 <= nLeft)
	{
		strPosition += ";dialogLeft:" + nLeft + "px";
	}
	
	if (undefined != nTop && 0 <= nTop)
	{
		strPosition += ";dialogTop:" + nTop + "px";
	}
	
	if (undefined != nWidth && 0 <= nWidth)
	{
		strPosition += ";dialogWidth:" + nWidth + "px";
	}
	
	if (undefined != nHeight && 0 <= nHeight)
	{
		strPosition += ";dialogHeight:" + nHeight + "px";
	}
	
	strOption += strPosition;
	
	return window.showModelessDialog(strUrl, objArgument, strOption);
}

Utils.getEvent = function ()
{
	var objEvent = null;

	if (window.event)
	{
		objEvent = window.event;
	}

	return objEvent;
}

/**
 * 이름에 따른 프레임을 찾아 반환한다
 * @param strName (프레임 이름)
 */
Utils.findFrame = function (strName, objframe)
{
	var objResult = null;

	if (null == objframe)
	{
		objframe = top;
	}
	
	var objResult = objframe.frames[strName];

	if (null == objResult && 0 < objframe.frames.length)
	{
		for (var i = 0, len = objframe.frames.length; i < len; i++)
		{
			var objChildframe = objframe.frames[i];

			if (null != objChildframe)
			{
				objResult = Utils.findFrame(strName, objChildframe);
							
				if (null != objResult)
				{
					break;
				}
			}
		}
	}
	
	return objResult;
}

/**
 * 일반 모델에서 자신의 applet 프레임을 가져온다.
 */
Utils.findClientFrame = function ()
{
	var objFrame = window.parent.frames["__PQClient_Frame"];
	
	return objFrame;
}

/**
 * 해당 모델 윈도우에서 자신의 모델(QPG 등등) 프레임을 반환한다.
 */
Utils.findModelFrame = function ()
{
	// 일반적 모델상황 (모델, 임베디드)
	var objFrame = window.parent.frames["__PQModel_Frame"];
	
	// 다이어리 아톰에서 자신이 포함된 웹페이지 모델을 필요로 할 때
	if (null == objFrame)
	{
		objFrame = window.parent;
	}
	
	return objFrame;
}

Utils.findElement = function (strID, objframe)
{
	var heResult = null;

	if (null == objframe)
	{
		objframe = top;
	}
	
	var heResult = objframe.document.getElementById(strID)

	if (null == heResult && 0 < objframe.frames.length)
	{
		for (var i = 0, len = objframe.frames.length; i < len; i++)
		{
			var objChildframe = objframe.frames[i];

			if (null != objChildframe)
			{
				heResult = Utils.findElement(strID, objChildframe);
							
				if (null != heResult)
				{
					break;
				}
			}
		}
	}
	
	return heResult;
}

/**
 * 임베드된 모델인 경우 모델을 감싸고 있는 frame을 반환한다
 * 단, 모델 내에서 호출한 경우 입니다 
 * @return objModelBaseframe
 */
Utils.getModelBaseOnEmbed = function ()
{
	if (true == Utils.isFloatingModel())
	{
		return;
	}
	
	return window.parent;
}

/**
 * 임베드된 모델인 경우 메인 페이지의 frame을 반환한다
 * 단, 모델 내에서 호출한 경우 입니다 
 * @return objMainpageBaseframe
 */
Utils.getMainpageBaseOnEmbed = function ()
{
	if (true == Utils.isFloatingModel())
	{
		return;
	}
	
	return window.parent.parent;
}

/**
 * 현재 모델이 플로팅인지 아닌지의 여부를 반환합니다
 * 단, 모델 내에서 호출한 경우 입니다 
 * @return objMainpageBaseframe
 */
Utils.isFloatingModel = function ()
{
	return (null != window.top.opener);
}

/**
 * 프로세스를 일시중지 시키고자 할 때 사용한다.
 * @param nMilliseconds 중지할 시간(밀리세컨드 단위) 
 */
Utils.pause = function (nMilliseconds)
{
	if (null == nMilliseconds || 0 > nMilliseconds)
	{
		nMilliseconds = 50;
	}

	if (is_ie7 || is_ie8)
	{
		var strPrefix = "";
		if (IsWPQModel)
		{
			strPrefix = IsWPQModel() ? "." : "";			
		}
		
		var strFeatures = "dialogWidth=400px;dialogHeight=100px;";	
		window.showModalDialog(strPrefix + '/ups/sys/html/support/Close.html?ms=' + nMilliseconds, '', strFeatures);
	}
	else
	{
		var strDialogScript = "window.setTimeout(function () { window.close(); }, " + nMilliseconds + ");";	
		window.showModalDialog("javascript:document.writeln(\"<script>" + strDialogScript + "<\/script>\")");
	}
}

/**
 * 웹브라우져 닫기.
 */
Utils.close = function ()
{
	if (IsWebModel())
	{
		var objModelWindow = window.top;
			
		if (null != objModelWindow)
		{
			objModelWindow.close();
		}
	}
	else
	{
		if (false == Utils.isFloatingModel())
		{
			var objModelBase = Utils.getModelBaseOnEmbed();
			var objMainpageBase = Utils.getMainpageBaseOnEmbed();
			
			if (null != objMainpageBase.MainpageManager)
			{
				objMainpageBase.MainpageManager.modelClosed(objModelBase.frameElement.id);
			}
			else
			{
				var objModelWindow = window.top;
				if (null != objModelWindow)
				{
					objModelWindow.close();
				}
			}
		}
		else
		{
			var objModelWindow = window.top;
			if (null != objModelWindow)
			{
				objModelWindow.close();
			}
		}
	}
}

/**
 * IE7 이상버전에서 창이 닫일때 경고창 발생을 막아준다. 
 *
 */
Utils.closeWithoutQuestion = function ()
{
	window.open('','_parent','');

	var objModelWindow = window.top;
			
	if (null != objModelWindow)
	{
		objModelWindow.close();
	}
}

/**
 * 경로 키워드('@path:/', '@http:/')를 제거한다. 키워드가 없을 경우에는 인자를 다시 리턴한다.
 *
 * @param strPath 경로 키워드를 제거할 경로 문자열.
 * @return 경로 키워드가 제거된 경로 문자열. 
 */
Utils.removePQPath = function (strPath)
{
	if (null != strPath)
	{
		var strPathTemp = strPath.toUpperCase();
		
		var nIndex = strPathTemp.indexOf("@PATH:\\");
		if (0 == strPathTemp.indexOf("@PATH:\\") || 0 == strPathTemp.indexOf("@PATH:/") ||
			0 == strPathTemp.indexOf("@HTTP:\\") || 0 == strPathTemp.indexOf("@HTTP:/"))
		{
			strPath = strPath.substring(7);
		}
	}
	
	return strPath;
}

/**
 *	각 OS의 separator를 자바에서 사용하는 separator(/)로 변환합니다.
 */
Utils.getPathString = function (strPath)
{
	if (null != strPath)
	{
		strPath =  strPath.replace(/\\\\\\\\/gi, "/");
		strPath =  strPath.replace(/\\\\/gi, "/");
		strPath =  strPath.replace(/\\/gi, "/");
		strPath =  strPath.replace(/\/\//gi, "/");
	}
	return strPath;
}

/**
 * 생성조건과 연결모델명을 분리하여 모델명을 구한다.
 * @param strConnectionModel
 * @return 모델명.
 */
Utils.getModelName = function (strModelName)
{
	var nlastSlash = strModelName.lastIndexOf("/");
	if (-1 != nlastSlash)
	{
		var strCreateCondition = strModelName.substring(nlastSlash + 1);
		
		if (-1 == strCreateCondition.indexOf("."))
		{
			return Utils.trim(strModelName.substring(0, nlastSlash));
		}
	}
	return Utils.trim(strModelName);
}

/**
 * 생성조건과 연결모델명을 분리하여 생성조건을 구한다.
 * @param strConnectionModel
 * @return
 */
Utils.getCreateCondition = function (strModelName)
{
	var nlastSlash = strModelName.lastIndexOf("/");
	if (-1 != nlastSlash)
	{
		var strCreateCondition = strModelName.substring(nlastSlash + 1);
		
		if (-1 == strCreateCondition.indexOf("."))
		{
			return Utils.trim(strCreateCondition); 
		}
	}
	return "";
}

/**
 * 현재 날짜 및 시간을 조합하여 랜덤한 파일 이름을 생성하여 반환한다
 *
 * @param strFileName (원본 파일 이름) 파일의 확장자를 추출하기 위해 쓰인다
 *
 * @return strNewFileName
 */
Utils.getRandomFileNameFromDate = function (strFileName, strSubPath)
{
	var objDate = new Date();
	
	
	var strNewFileName = Date.parse(objDate);
	
	return strSubPath + "/" + strNewFileName;
}

/**
 * 파일의 확장자를 뽑아 반환한다
 * @param strFileName
 * @return
 */
Utils.extractExtension = function (strFileName)
{
	if (null == strFileName || "" == strFileName)
	{
		return "";
	}
	
	var strExeension = strFileName.substring(strFileName.lastIndexOf("."));
	
	return strExeension;
}

/**
 * 입력값을 base64기반 문자열로 암호화합니다.
 * @param strToEncrypt 
 * @param nXorKey
 * @return
 */
Utils.encrypt = function (strToEncrypt, nKey)
{
	// Key XOR Value -> EncryptedValue 
	// Key XOR EncryptedValue -> Value
	var strResult = "";
	
	for (i = 0; i < strToEncrypt.length; i++)
	{
		strResult += String.fromCharCode(nKey ^ strToEncrypt.charCodeAt(i));
	}
	
	// 암호화된 값 중에 URI에 포함될 수 없는 문자가 생길 수 있으므로 base64로 변환합니다.
	return Utils.encodeBase64(strResult);
}

/**
 * 입력값을 Base64로 변환한다.
 * @param strInput
 * @return
 */
Utils.encodeBase64 = function (strInput)
{
	if (null == strInput)
	{
		return strInput;
	}
	strInput = strInput.toString();
	
	var strKeyString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
	var strResult = "";
	var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
	var i = 0;

	strInput = Utils.encodeUTF8(strInput);
	while (i < strInput.length) 
	{
		chr1 = strInput.charCodeAt(i++);
		chr2 = strInput.charCodeAt(i++);
		chr3 = strInput.charCodeAt(i++);

		enc1 = chr1 >> 2;
		enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
		enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
		enc4 = chr3 & 63;

		if (isNaN(chr2)) 
		{
			enc3 = enc4 = 64;
		} 
		else if (isNaN(chr3)) 
		{
			enc4 = 64;
		}

		strResult = strResult + 
			strKeyString.charAt(enc1) + strKeyString.charAt(enc2) +
			strKeyString.charAt(enc3) + strKeyString.charAt(enc4);
	}

	return strResult;
}

/**
 * 입력값을 UTF-8로 변환한다.
 * @param strInput
 * @return
 */
Utils.encodeUTF8 = function (strInput)
{
	strInput = strInput.replace(/\r\n/g,"\n");
	var strResult = "";

	for (var i = 0, nLen = strInput.length; i != nLen; i++) 
	{
		var c = strInput.charCodeAt(i);

		if (c < 128) 
		{
			strResult += String.fromCharCode(c);
		}
		else if((c > 127) && (c < 2048)) 
		{
			strResult += String.fromCharCode((c >> 6) | 192);
			strResult += String.fromCharCode((c & 63) | 128);
		}
		else 
		{
			strResult += String.fromCharCode((c >> 12) | 224);
			strResult += String.fromCharCode(((c >> 6) & 63) | 128);
			strResult += String.fromCharCode((c & 63) | 128);
		}
	}

	return strResult;
}

Utils.decodeBase64 = function (strInput)
{
	var strKeyString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
	var strResult = "";
	var chr1, chr2, chr3;
	var enc1, enc2, enc3, enc4;
	var i = 0;

	strInput = strInput.replace(/[^A-Za-z0-9\+\/\=]/g, "");

	while (i < strInput.length)
	{
		enc1 = strKeyString.indexOf(strInput.charAt(i++));
		enc2 = strKeyString.indexOf(strInput.charAt(i++));
		enc3 = strKeyString.indexOf(strInput.charAt(i++));
		enc4 = strKeyString.indexOf(strInput.charAt(i++));

		chr1 = (enc1 << 2) | (enc2 >> 4);
		chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
		chr3 = ((enc3 & 3) << 6) | enc4;

		strResult = strResult + String.fromCharCode(chr1);

		if (enc3 != 64) {
			strResult = strResult + String.fromCharCode(chr2);
		}
		if (enc4 != 64) {
			strResult = strResult + String.fromCharCode(chr3);
		}
	}

	strResult = Utils.decodeUTF8(strResult);

	return strResult;
}

Utils.decodeUTF8 = function (strInput)
{
	var strResult = "";
	var i = 0;
	var c = c1 = c2 = 0;

	while ( i < strInput.length )
	{
		c = strInput.charCodeAt(i);

		if (c < 128)
		{
			strResult += String.fromCharCode(c);
			i++;
		}
		else if((c > 191) && (c < 224))
		{
			c2 = strInput.charCodeAt(i+1);
			strResult += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
			i += 2;
		}
		else
		{
			c2 = strInput.charCodeAt(i+1);
			c3 = strInput.charCodeAt(i+2);
			strResult += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
			i += 3;
		}
	}

	return strResult;
}

/*
 * 업로드될 파일의 크기를 검사합니다.
 * objAtom : 해당 아톰
 * *strFilePath : 전체 파일명 (전체 경로포함)
 */
Utils.checkFileSize = function (objAtom, strResult)
{
	var nUploadFileSize = 0;	// 파일 크기
	var nFileSize = objAtom.getFileSize();		// 한번에 올릴 수 있는 파일의 최대 크기 
	var nTotalSize = null;
	
	if ("WebPicture" != objAtom.getAtomType())
	{
		nTotalSize = objAtom.getTotalSize();	// 한 게시물에 올를 수 있는 최대 파일 용량
	}
	
	if ("filesizeover" == strResult)
	{
		alert ('업로드할 파일의 크기는 ' + nFileSize + ' KB를 초과할 수 없습니다.');
		return false;
	}
	
	else if ("failed" == strResult)
	{
		alert ('파일을 저장할 수 없습니다.\n잠시 후 다시 시도해주시기 바랍니다.');
		return false;
	}
	else if ("totalsizeover" == strResult)
	{
		alert ('파일 첨부는 최대 '+ nTotalSize + ' KB까지 가능합니다.\n');
		return false;
	}
	else
	{
		if ("WebPicture" != objAtom.getAtomType())
		{
			nUploadFileSize = parseInt(strResult);
			if (null != nUploadFileSize)
			{
				objAtom.setUploadedFileSize(nUploadFileSize);
			}
		}
		
		return true;
	}
}

/**
 * 웹페이지 모델의 사진게시, 파일첨부, 웹편집기 아톰 등에서 첨부한 파일이 서버로 전송이 어떻게 되었는지,
 * 그 상태를 가져옵니다.
 */
Utils.getUploadState = function (xnUploadRequestDoc)
{
	var strResult = "succeed";	
	
	while (true)
	{
		Utils.pause(1000);
		
		var strURL = "/ups/Upload.do?ServiceName=uploadState";
		strResult = PQAjax.post(strURL, xnUploadRequestDoc);
					
		if (null != strResult)
		{
			if ("uploading" != strResult)
			{
				break;
			}
		}
	}
	
	return strResult;
}

/*
 * HTML 상에서 길이값을 가져올 때 px가 포함되어있는 경우에 제거한 정수값을 반환한다.
 */
Utils.removePx = function (nValue)
{
	var strValue = nValue.toString();
	if (-1 < strValue.toLowerCase().indexOf("px"))
	{
		strValue = strValue.substring(0, strValue.length-2);
	}
	
	return parseInt(strValue);
}

/**
 * 시간 측정 값 초기화
 */
Utils.initTimeCheck = function ()
{
	g_CheckTime = g_PageStartTime = Number(new Date());
	g_strTimeCheckResult = "";
}

/**
 * 시간 측정 메세지를 추가함
 */
Utils.addTimeCheck = function (strMessage)
{
	var nTimeNow = Number(new Date());
	g_strTimeCheckResult += strMessage + " :\t" + (nTimeNow - g_PageStartTime) + "\t" + (nTimeNow - g_CheckTime) + "\n";
	
	g_CheckTime = nTimeNow;
}

/**
 * 시간측정 결과를 화면에 표시함
 */
Utils.printTimeCheckResult = function ()
{
	g_strTimeCheckResult += "PageLoading:\t" + (Number(new Date()) - g_PageStartTime);
	
	window.prompt('print result', g_strTimeCheckResult);
}


/**
 * 웹 접근성을 높이기 위한 방법중 크로스브라우징의 수단으로 쓰이는 함수 모음.
 */
function CrossBrowsing ()
{
	//이하 함수 모음에서 기술되지 않은 브라우저는 필요에 따라 추가해 주세요.
}

/**
 * heElement.innerText 우변
 */
CrossBrowsing.getInnerText = function (heElement)
{
	if (is_ie)
	{
		return heElement.innerText;
	}
	else if (is_firefox || is_chrome)
	{
		return heElement.textContent;
	}
}

/**
 * heElement.innerText 좌변
 */
CrossBrowsing.setInnerText = function (heElement, strText)
{
	if (is_ie)
	{
		heElement.innerText = strText;
	}
	else if (is_firefox || is_chrome)
	{
		heElement.textContent = strText;
	}
}

/**
 * Date 객체에서 Year를 가지고 옴.
 */
CrossBrowsing.getYear = function (objDate)
{
	if (is_ie)
	{
		return objDate.getYear();
	}
	else if (is_firefox || is_chrome)
	{
		return objDate.getYear() + 1900;
	}
}



/**
 * 자바스크립트로 쿠키를 핸들하는 도구
 */
function CookieLib ()
{
}

/**
 * 쿠키를 저장한다
 */
CookieLib.setCookie = function (strName, strValue, nExpiredays) 
{ 
	var objExpireDate = new Date();
	
	objExpireDate.setDate(objExpireDate.getDate() + nExpiredays);
	
	document.cookie = escape(Utils.trim(strName)) + "=" + escape(strValue) + ";path=/;expires=" + objExpireDate.toGMTString() + ";";
}

/**
 * 이름에 해당하는 쿠키를 삭제 한다
 */
CookieLib.deleteCookie = function (strName)
{
	var objExpireDate = new Date(2000, 1, 1);
	
	strName = escape(Utils.trim(strName));
	
	document.cookie = strName + "=;path=/;expires=" + objExpireDate.toGMTString();
}

/**
 * 쿠키에서 값을 가지고 온다.
 */
CookieLib.getCookie = function (strName)
{
	var strCookieValue = "";
	var strCookieName = escape(strName) + "=";
	var objCookie = document.cookie;
	
	if (objCookie.length > 0) 
	{
		var nBegin = objCookie.indexOf(strCookieName);
		
		if (nBegin != -1) 
		{
			nBegin += strCookieName.length;
			
			var nEnd = objCookie.indexOf(";", nBegin);
			
			if (nEnd == -1) 
			{
				nEnd = objCookie.length;
			}
			strCookieValue = unescape(objCookie.substring(nBegin, nEnd));
		}
	}
	return strCookieValue;
}

/**
 * 모든 쿠키 값을 리스트 형식으로 반환한다
 */
CookieLib.getAllCookie = function ()
{
	var alCookie = document.cookie.split(";")
	
	var alResult = new Array();
	
	for (i=0; i < alCookie.length; i++)
	{
		if (null == alCookie[i] || "" == alCookie[i])
		{
			continue;
		}
		
		cookieName = alCookie[i].split("=")[0];
		
		alResult.push(CookieLib.getCookie(cookieName));
	}
	
	return alResult;
}

/**
 * 모든 쿠키 값을 리스트 형식으로 반환한다
 */
CookieLib.getAllCookieWithName = function ()
{
	var alCookie = document.cookie.split(";")
	
	var alResult = new Array();
	
	for (i=0; i < alCookie.length; i++)
	{
		if (null == alCookie[i] || "" == alCookie[i])
		{
			continue;
		}
		
		var strCookieName = alCookie[i].split("=")[0];
		
		// cookie에 "key=값; key=값" 형식으로.. 중간에 공백이 들어가는 경우가 있어 공백제거함  
		strCookieName = Utils.trim(strCookieName);
		
		var strValue = CookieLib.getCookie(strCookieName);

		strCookieName = strCookieName.replace( /^\s*/, "" ).replace( /\s*$/, "" );
		strValue = strValue.replace( /^\s*/, "" ).replace( /\s*$/, "" );
		
		// 쿠키 이름 , 값 의 묶으로 반환한다
		objCookieInfo = 
		{
			Name : strCookieName,
			Value : strValue
		};
		
		alResult.push(objCookieInfo);
	}
	
	return alResult;
}
