<%@ page language="java" contentType="text/html; charset=utf-8"%>
<%@ page import="java.io.*"%>
<%@ page import="com.eactive.eai.rms.common.login.SessionManager"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ include file="/jsp/common/include/localemessage.jsp" %>
<%
	response.setHeader("Pragma", "No-cache");
	response.setHeader("Cache-Control", "no-cache");
	response.setHeader("Expires", "0");
%>
<html>
<head>
	<title></title>
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
	<jsp:include page="/jsp/common/include/css.jsp"/>
	<style>
		.jtk-connector { z-index:4; }
		.jtk-endpoint { z-index:5; }
		.ui-dialog { z-index:11; }
		path, .jtk-endpoint {
			cursor: pointer;
		}

		.mouseover-endpoint path {
			stroke : #4D54B6;
			stroke-width : 6;
			z-index : 10;
		}

		.mouseover-endpoint circle {
			fill: #4D54B6;
			z-index : 1000;
		}

		.click-endpoint path {
			stroke : #4D54B6;
			stroke-width : 6
		}

		.click-endpoint circle {
			fill: #4D54B6;
		}

		.div-hover {
			background-color: #EDD5DD
		}

	</style>
	<jsp:include page="/jsp/common/include/script.jsp"/>
	<script language="javascript" src="<c:url value="/js/jsplumb.js"/>"></script>
	<script language="javascript">
		const isPop = "${param.pop}";

		const LAYOUT_ITEM_TYPE_GROUP = "Group";
		const LAYOUT_ITEM_TYPE_GRID = "Grid";
		const LAYOUT_ITEM_TYPE_FIELD = "Field";
		const LAYOUT_ITEM_TYPE_ARRAY = "Array";

		var isDetail = false;

		var srcGroup;
		var tgtGroup;
		var sourceGrid ;
		var targetGrid ;
		var url 	 = '<c:url value="/onl/admin/rule/transform2/transform2Man.json" />';
		var url_view = '<c:url value="/onl/admin/rule/transform2/transform2Man.view" />';

		var isAdmin = "";

		var returnUrl = getReturnUrlForReturn();
		var roleString	= "<%=SessionManager.getRoleIdString(request)%>";

		var selectName = "functionCombo"; // selectBox Name

		var isContextMenuShow = false;

		var srcMappingDatas;
		var tgtMappingDatas;

		var mappingDialog;
		var mappingDialogParent;

		var LIST_TRANSFORM_ITEM;
		var LIST_LAYOUT_ITEM;

		var isValidMapping = true;

		var transformGrid = {
			ENDPOINT_PREFIX_SRC : 'div_src_',
			ENDPOINT_PREFIX_TGT : 'div_tgt_',
			POSITION_PREFIX_SRC : 'div_srcgroup_',
			POSITION_PREFIX_TGT : 'div_tgtgroup_',
			GRID_ID_SRC : 'sourceGrid',
			GRID_ID_TGT : 'targetGrid',
			getId : function () {
				return this.attr('id');
			},
			getRowId : function (endpointElementId) {
				return endpointElementId.substring(this.ENDPOINT_PREFIX_SRC.length);
			},
			getOtherGrid : function () {
				if (this.isSource()) {
					return targetGrid;
				} else {
					return sourceGrid;
				}
			},
			getEndpointElementId : function (rowId) {
				if (this.isSource()) {
					return this.ENDPOINT_PREFIX_SRC + rowId;
				} else {
					return this.ENDPOINT_PREFIX_TGT + rowId;
				}
			},
			getContextMenuPositionElementId : function (rowId) {
				// field, group
				const rowData = this.getRowData(rowId);
				const loutItemType = rowData["loutItemType"];

				if (loutItemType == LAYOUT_ITEM_TYPE_GRID || loutItemType == LAYOUT_ITEM_TYPE_GROUP) {
					// group 인 경우
					if (this.isSource()) {
						return this.POSITION_PREFIX_SRC + rowId;
					} else {
						return this.POSITION_PREFIX_TGT + rowId;
					}
				} else {
					// field 인 경우
					return this.getEndpointElementId(rowId);
				}


			},
			getEndpointElement : function (rowId) {
				return $('#' + this.getEndpointElementId(rowId));
			},
			getContextMenuPositionElement : function (rowId) {
				return $('#' + this.getContextMenuPositionElementId(rowId));
			},
			getGrid : function (endpointElementId) {
				if (endpointElementId.indexOf(this.ENDPOINT_PREFIX_SRC) > -1) {
					return sourceGrid;
				} else if (endpointElementId.indexOf(this.ENDPOINT_PREFIX_TGT) > -1) {
					return targetGrid;
				}
			},
			isSource : function () {
				return this.getId() == this.GRID_ID_SRC;
			},
			isTarget : function () {
				return this.getId() == this.GRID_ID_TGT;
			},
			findRowDatasByLayoutItemName : function (layoutItemName) {
				return this.findRowDatasByLayoutItemNameWithoutNamespace(layoutItemName);
			},
			findRowDatasByLayoutItemNameWithoutNamespace : function (layoutItemName) {
				layoutItemName = removeNamespace(layoutItemName.toUpperCase());
				const rowDatas = this.getRowData();
				const returnRowDatas = [];
				for (var i = 0; i < rowDatas.length; i++) {
					if (removeNamespace(rowDatas[i]['loutItemName'].toUpperCase()) == layoutItemName) {
						returnRowDatas.push(rowDatas[i]);
					}
				}
				return returnRowDatas;
			},
			findEndpointConnections : function (rowId) {
				// 해당 row의 endpoint를 검색
				const endpointElementId = this.getEndpointElementId(rowId);
				let filter;
				if (this.isSource()) {
					// endpointElementId가 source로 사용된 모든 EndpointConnection을 검색
					filter = {source:endpointElementId, target:''};
				} else if (this.isTarget()) {
					// endpointElementId가 target으로 사용된 모든 EndpointConnection을 검색
					filter = {source:'', target:endpointElementId};
				}
				return jsPlumbInstance.getConnections(filter);
			}
		};

		$.jgrid.extend(transformGrid);

		$(document).mousemove(function (e) {
			$('html, body').scrollTop(function(i, v) {
				var h = $(window).height();
				if (e.clientY > 0 && h - e.clientY > 0) {
					return;
				}

				var y = e.clientY - h/2;
				var percent = v + y * 0.03;
				return percent;
			});
		});

		function doneAction(){
			if(isPop == "true"){
				window.close();
			} else {
				goNav(returnUrl);
			}
		}

		function getSourceResult(cnvsnName){

			console.debug("start getSourceResult : " + cnvsnName);

			// 기존 Connection을 모두 삭제
			jsPlumbInstance.deleteEveryConnection();
			jsPlumbInstance.deleteEveryEndpoint();

			var LIST_TRANSFORM_SOURCE_RESULT = $.ajax({
				type : "POST",
				url:url,
				dataType:"json",
				data:{cmd : 'LIST_TRANSFORM_SOURCE_RESULT', cnvsnName : cnvsnName},
			});

			LIST_TRANSFORM_SOURCE_RESULT.done(function (json) {
				var data = json.rows;
				var src = null;
				var tgt = null;;
				var srcDesc = null;
				var tgtDesc = null;
				var srcLoutIoId = null;
				var tgtLoutIoId = null;
				var srcLoutType = null;
				var tgtLoutType = null;
				for ( var i = 0; i < data.length; i++) {
					if (data[i]['SOURCRSULTDSTCD'] == 'SRC_LAYOUT' ){
						src = data[i]['LOUTNAME'];
						srcDesc = data[i]['LOUTDESC'];
						$("input[name=srcLayout]").val(src);
						$("input[name=srcLayoutDesc]").val(srcDesc);
						srcLoutIoId = data[i]['LOUTIOID'];
						$("input[name=srcLoutIoId]").val(srcLoutIoId);
						srcLoutType = data[i]['LOUTTYPE'];
					}else if (data[i]['SOURCRSULTDSTCD'] == 'TGT_LAYOUT' ){
						tgt = data[i]['LOUTNAME'];
						tgtDesc = data[i]['LOUTDESC'];
						$("input[name=tgtLayout]").val(tgt);
						$("input[name=tgtLayoutDesc]").val(tgtDesc);
						tgtLoutIoId = data[i]['LOUTIOID'];
						$("input[name=tgtLoutIoId]").val(tgtLoutIoId);
						tgtLoutType = data[i]['LOUTTYPE'];
					}
				}

				confirmLastAmnDhms();

				LIST_TRANSFORM_ITEM = listTransformItem(tgt, cnvsnName, tgtLoutIoId, tgtLoutType, src);
				LIST_LAYOUT_ITEM = listLayoutItem(src, srcLoutIoId, srcLoutType);

				$.when(LIST_TRANSFORM_ITEM, LIST_LAYOUT_ITEM).then(function (json) {
					if (json) {
						initialConnections(json[0].rows);
					}
				});

				console.debug('LIST_TRANSFORM_SOURCE_RESULT done');
			}).fail(function (e) {
				alert(e.responseText);
			});

			console.debug("end getSourceResult : " + cnvsnName);
		}

		function formatDate(cellvalue){
			if (!cellvalue || cellvalue.length < 14) {
				return "";
			}
			const year = cellvalue.substr(0, 4);
			const month = cellvalue.substr(4, 2);
			const day = cellvalue.substr(6, 2);
			const hour = cellvalue.substr(8, 2);
			const minute = cellvalue.substr(10, 2);
			const second = cellvalue.substr(12, 2);

			return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
		}

		function confirmLastAmnDhms () {
			var reqCnvsnLastAmnDhms = parseLastAmnDhms($('#REQ').attr('lastAmnDhms'));
			var resCnvsnLastAmnDhms = parseLastAmnDhms($('#RES').attr('lastAmnDhms'));

			var tgtLastAmnDhms = parseLastAmnDhms($("#tgtLastAmnDhms").val());
			var srcLastAmnDhms = parseLastAmnDhms($("#srcLastAmnDhms").val());

			var message = "";
			if (reqCnvsnLastAmnDhms > 0 && (reqCnvsnLastAmnDhms < tgtLastAmnDhms || reqCnvsnLastAmnDhms < srcLastAmnDhms)) {
				message = "<%=localeMessage.getString("transformManDetail.request")%>"
			}

			if (resCnvsnLastAmnDhms > 0 && (resCnvsnLastAmnDhms < tgtLastAmnDhms || resCnvsnLastAmnDhms < srcLastAmnDhms)) {
				if (message.length > 0) {
					message = message + ", <%=localeMessage.getString("transformManDetail.response")%>"
				} else {
					message = "<%=localeMessage.getString("transformManDetail.response")%>"
				}
			}

			if (message.length > 0) {
				if (isValidMapping) {
					isValidMapping = false;
					// alert은 1회
					alert("<%=localeMessage.getString("transformManDetail.alert6")%> "+ message +" <%=localeMessage.getString("transformManDetail.alert7")%>");
				}
				return false;
			}

			return true;
		}

		function parseLastAmnDhms(lastAmnDhms) {
			try {
				return parseInt(lastAmnDhms);
			} catch (e) {
				return 0;
			}
		}

		function listLayoutItem(srcLayoutName, srcLoutIoId, srcLoutType) {
			// console.error("start LIST_LAYOUT_ITEM : " + srcLayoutName);
			if (srcLayoutName == null) {
				return;
			}

			var LIST_LAYOUT_ITEM = $.ajax({
				type : "POST",
				url:url,
				dataType:"json",
				data:{ cmd : 'LIST_LAYOUT_ITEM', loutName: srcLayoutName, loutIoId:srcLoutIoId, loutType:srcLoutType },
			});
			LIST_LAYOUT_ITEM = LIST_LAYOUT_ITEM.done(function (json) {
				jsPlumbInstance.deleteEveryConnection();
				var data = json.rows;
				sourceGrid.get(0).addJSONData(data);

				srcGroup = new Object();
				srcMappingDatas = new Object();
				for ( var i = 0; i < data.length; i++) {
					var rowData = data[i];
					if (rowData["LOUTITEMPATH"].length > 0
							&& (rowData["loutItemType"] == LAYOUT_ITEM_TYPE_GRID)
					)  {
						srcGroup[data[i]["LOUTITEMPATH"]]= data[i]["LOUTITEMPATH"];
					}
					srcMappingDatas[getLoutItemPath(data[i]["LOUTITEMPATH"])] = data[i]['id'];
				}

				sourceGrid.find("div[name^=src_]").each(function(){
					var source = $(this);
					var sourceObject = jsPlumbInstance.makeSource($(this),{
						anchor:'Right'
					});
				});

				sourceGrid.find('.jqgrow').mouseover(function (e) {
					var rowId = $(this).attr('id');
					var endpointElement = sourceGrid.getEndpointElement(rowId);
					var endpoints = jsPlumbInstance.selectEndpoints({element:endpointElement});

					if (endpoints.length > 0) {
						mouseoverEndpoint(endpoints.get(0), 'mouseover-endpoint');
					}

					const loutItemName =  sourceGrid.getRowData(rowId)['loutItemName']
					mouseoverJqgrid(loutItemName, targetGrid);
				}).mouseout(function (e) {
					var rowId = $(this).attr('id');
					var endpointElement = sourceGrid.getEndpointElement(rowId);
					var endpoints = jsPlumbInstance.selectEndpoints({element:endpointElement});

					if (endpoints.length > 0) {
						mouseoutEndpoint(endpoints.get(0), 'mouseover-endpoint');
					}
					const loutItemName =  sourceGrid.getRowData(rowId)['loutItemName']
					mouseoutJqgrid(loutItemName, targetGrid);
				}).contextmenu(function (e) {
					console.debug('contextmenu');
					e.preventDefault();
					const contextMenuDiv = $('#contextMenuDiv');
					contextMenuDiv.attr('rowId', $(this).attr('id'));
					contextMenuDiv.attr('gridId', 'sourceGrid');
					contextMenuDiv.contextMenu();
				});
			});
			return LIST_LAYOUT_ITEM;
		}

		function listLayoutItemForTarget(tgtLayoutName, tgtLoutIoId, tgtLoutType) {
			if (tgtLayoutName == null) {
				return;
			}

			var LIST_LAYOUT_ITEM = $.ajax({
				type : "POST",
				url:url,
				dataType:"json",
				data:{ cmd : 'LIST_LAYOUT_ITEM', loutName: tgtLayoutName, loutIoId:tgtLoutIoId, loutType:tgtLoutType },
			});
			LIST_LAYOUT_ITEM = LIST_LAYOUT_ITEM.done(function (json) {
				jsPlumbInstance.deleteEveryConnection();
				var data = json.rows;
				targetGrid.get(0).addJSONData(data);

				tgtGroup = new Object();
				tgtMappingDatas = new Object();
				for ( var i = 0; i < data.length; i++) {
					var rowData = data[i];
					if (rowData["LOUTITEMPATH"].length > 0
							&& (rowData["loutItemType"] == LAYOUT_ITEM_TYPE_GRID)
					)  {
						tgtGroup[rowData["LOUTITEMPATH"]]= rowData["LOUTITEMPATH"];
					}
					tgtMappingDatas[getLoutItemPath(data[i]["LOUTITEMPATH"])] = data[i]['id'];
				}

				targetGrid.find("div[name^=tgt_]").each(function(){
					var target = $(this);
					var targetObject = jsPlumbInstance.makeTarget($(this),{
						anchor:'Left'
					});
				});

				targetGrid.find('.jqgrow').mouseover(function (e) {
					var rowId = $(this).attr('id');
					var endpointElement = targetGrid.getEndpointElement(rowId);
					var endpoints = jsPlumbInstance.selectEndpoints({element:endpointElement});

					if (endpoints.length > 0) {
						mouseoverEndpoint(endpoints.get(0), 'mouseover-endpoint');
					}

					const loutItemName =  targetGrid.getRowData(rowId)['loutItemName']
					mouseoverJqgrid(loutItemName, targetGrid);
				}).mouseout(function (e) {
					var rowId = $(this).attr('id');
					var endpointElement = targetGrid.getEndpointElement(rowId);
					var endpoints = jsPlumbInstance.selectEndpoints({element:endpointElement});

					if (endpoints.length > 0) {
						mouseoutEndpoint(endpoints.get(0), 'mouseover-endpoint');
					}
					const loutItemName =  targetGrid.getRowData(rowId)['loutItemName']
					mouseoutJqgrid(loutItemName, targetGrid);
				}).contextmenu(function (e) {
					console.debug('contextmenu');
					e.preventDefault();
					const contextMenuDiv = $('#contextMenuDiv');
					contextMenuDiv.attr('rowId', $(this).attr('id'));
					contextMenuDiv.attr('gridId', 'targetGrid');
					contextMenuDiv.contextMenu();
				});
			});
			return LIST_LAYOUT_ITEM;
		}

		function listTransformItem (tgtLayoutName, cnvsnName, tgtLoutIoId, tgtLoutType, srcLayoutName) {
			//console.error("start LIST_TRANSFORM_ITEM : " + cnvsnName);
			if (tgtLayoutName == null) {
				return;
			}

			var LIST_TRANSFORM_ITEM = $.ajax({
				type : "POST",
				url:url,
				dataType:"json",
				data:{ cmd : 'LIST_TRANSFORM_ITEM', loutName: tgtLayoutName, cnvsnName : cnvsnName, loutIoId:tgtLoutIoId, loutType:tgtLoutType, srcLayoutName:srcLayoutName },
			});

			LIST_TRANSFORM_ITEM = LIST_TRANSFORM_ITEM.done(function (json) {
				var data = json.rows;
				targetGrid.get(0).addJSONData(data);

				tgtGroup = new Object();
				for ( var i = 0; i < data.length; i++) {
					var rowData = data[i];
					if (rowData["LOUTITEMPATH"].length > 0
							&& (rowData["loutItemType"] == LAYOUT_ITEM_TYPE_GRID)
					)  {
						tgtGroup[rowData["LOUTITEMPATH"]]= rowData["LOUTITEMPATH"];
					}
				}

				targetGrid.find("div[name^=tgt_]").each(function(){
					jsPlumbInstance.makeTarget($(this),{anchor:'Left'
					});
				});

				mappingDialog.dialog('close');

				targetGrid.find('.jqgrow').mouseover(function (e) {
					var rowId = $(this).attr('id');
					var endpointElement = targetGrid.getEndpointElement(rowId);
					var endpoints = jsPlumbInstance.selectEndpoints({element:endpointElement});

					const loutItemName =  targetGrid.getRowData(rowId)['loutItemName']
					mouseoverJqgrid(loutItemName, sourceGrid);
					if (endpoints.length > 0) {
						mouseoverEndpoint(endpoints.get(0), 'mouseover-endpoint');
						// target grid일 경우 mappingDialog를 클릭 할 수 있도록 cursor 모양을 변경 해 준다.
						endpointElement.css('cursor', 'pointer');
					}
				}).mouseout(function (e) {
					var rowId = $(this).attr('id');
					var endpointElement = targetGrid.getEndpointElement(rowId);
					var endpoints = jsPlumbInstance.selectEndpoints({element:endpointElement});

					const loutItemName =  targetGrid.getRowData(rowId)['loutItemName']
					mouseoutJqgrid(loutItemName, sourceGrid);
					if (endpoints.length > 0) {
						mouseoutEndpoint(endpoints.get(0), 'mouseover-endpoint');
					}
					// target grid일 경우 mappingDialog를 클릭 할 수 있도록 cursor 모양을 변경 해 준다.
					endpointElement.css('cursor', '');
				}).contextmenu(function (e) {
					console.debug('contextmenu');
					e.preventDefault();
					const contextMenuDiv = $('#contextMenuDiv');
					contextMenuDiv.attr('rowId', $(this).attr('id'));
					contextMenuDiv.attr('gridId', 'targetGrid');
					contextMenuDiv.contextMenu();
				});

				if (json.isRemappingRequired != undefined && json.isRemappingRequired == true) {
					if (isValidMapping) {
						isValidMapping = false;
						// alert은 1회
						alert('<%=localeMessage.getString("transformManDetail.alert8")%>');
					}
				}

				console.debug('isRemappingRequired : ' + json.isRemappingRequired);
				//console.error("end LIST_TRANSFORM_ITEM : " + cnvsnName);

			});
			return LIST_TRANSFORM_ITEM;
		}


		function addGroupTag(group, data) {
			Object.keys(group)
					.sort((a, b) => b.length - a.length)
					.forEach(key => {
						if (data.includes(key+".")) {
							data = data.replace(key, key + "[*]");
						}
					});
			return data;
		}

		// 항목 자신이 Array인 경우, 경로/변환명령 끝에 반복 표시 [*]를 추가
		function addArrayTag(loutItemType, data) {
			if (loutItemType == LAYOUT_ITEM_TYPE_ARRAY && !data.endsWith("[*]")) {
				data = data + "[*]";
			}
			return data;
		}

		//변환명에 있는 서비스코드와 if서비스 코드 매칭
		function validation(){
			if ($('input[name=cnvsnName]').val() == '') {
				$('#dialog').dialog('open');
				return false;
			}
			return true;
		}

		async function initialConnection(rowData) {
			var cnvsnSrcItems = $.trim(rowData['CNVSNSRCITEMS']);
			console.debug("CNVSNSRCITEMS");
			console.debug(cnvsnSrcItems);

			if (cnvsnSrcItems != "") {
				var cnvsnSrcItems = cnvsnSrcItems.split(',');
				$.each(cnvsnSrcItems, function (k, srcItem) {
					var loutItemPath = getLoutItemPath(srcItem);
					console.debug('initialConnection loutItemPath : ' + loutItemPath);

					const sourceEndpointElementId = sourceGrid.getEndpointElementId(srcMappingDatas[loutItemPath]);
					const targetEndpointElementId = targetGrid.getEndpointElementId(rowData['id']);

					if ($('#' + sourceEndpointElementId).length == 0 || $('#' + targetEndpointElementId).length == 0 ) {


						if (isValidMapping) {
							isValidMapping = false;
							// alert은 1회
							alert('<%=localeMessage.getString("transformManDetail.alert8")%>');
						}

						jqGridOnConnectionDetached('', rowData['id'], '');

						// ConnectionDetached 후 매핑 정보를 설정 한다.
						targetGrid.jqGrid('setCell', rowData['id'], 'ISVALIDMAPPING', false);
						targetGrid.jqGrid('setCell', rowData['id'], 'loutItemName', '', {color:'red'});
						isValidMapping = false;
						return;
					}
					targetGrid.jqGrid('setCell', rowData['id'], 'ISVALIDMAPPING', true);
					jsPlumbConnect(sourceEndpointElementId, targetEndpointElementId);
				});
			}
		}

		function asyncConnection(data) {
			// 100 개씩 잘라서 넣어 준다.
			// 이렇게 넣으면 100개씩 화면에 그려주기 때문에 좀더 빠르게 뜬 것처럼 느껴진다.
			setTimeout(function () {
				for ( var j = 0; j < data.length; j++) {
					// target row loop
					var rowData = data[j];
					console.debug("start call connect target : " + rowData['id'])
					initialConnection(rowData);
					console.debug("end call connect target : " + rowData['id']);
				}
			}, 1000);
		}

		function initialConnections(data) {
			console.debug(data);
			if (data.length <= 100) {
				for ( var j = 0; j < data.length; j++) {
					// target row loop
					var rowData = data[j];
					console.debug("start call connect target : " + rowData['id'])
					initialConnection(rowData);
					console.debug("end call connect target : " + rowData['id']);
				}
			} else {
				do {
					var spliceData = data.splice(0, 99);
					asyncConnection(spliceData);
				} while (data.length > 0);
			}
		}

		function getLoutItemPath(loutitempath){
			loutitempath = loutitempath.replace(/[\[\*\]]/g,"");
			return loutitempath;
		}

		function clearThisPage() {
			$("select[name=transformForEaiSvcNameCombo]").val('');
			$("input[name=cnvsnDesc]").val('');
			$("input[name=cnvsnTypeCombo]").val('');
			sourceGrid.jqGrid('clearGridData');
			targetGrid.jqGrid('clearGridData');
			$('input[name=srcLayout]').val('');
			$('input[name=srcLayoutDesc]').val('');
			$('input[name=tgtLayout]').val('');
			$('input[name=tgtLayoutDesc]').val('');
		}

		var jsPlumbInstance;
		var transformRows;
		jsPlumb.ready(function() {

			jsPlumbInstance = jsPlumb.getInstance({
				DragOptions: { cursor: 'pointer', zIndex: 2000 },
				PaintStyle : { stroke : "#A6A8CE", strokeWidth :4},
				HoverPaintStyle : { stroke:"#4D54B6", strokeWidth:6},
				EndpointStyle : { radius:8, fill:"#7579BB",  },
				EndpointHoverStyle : { radius:12, fill:"#4D54B6" },
				Connector : [ "Bezier", { curviness:50 } ],
				Container : "right_box",
			});

			jsPlumbInstance.batch(batchJsPlumbInstance);

			mappingDialog = $('#mappingDialog').dialog({
				autoOpen : false,
				modal : false,
				buttons : {
					"<%=localeMessage.getString("transformManDetail.save")%>" : mappingDialogSave,
					"<%=localeMessage.getString("transformManDetail.close")%>" : function () {
						mappingDialog.dialog('close');
					},
				},
				beforeClose : mappingDialogBeforeClose
			});
			mappingDialogParent = mappingDialog.parent('.ui-dialog');

			var verInfo = "${param.verInfo}";
			if (verInfo == "" || verInfo == "null") {
				verInfo = "0";
			}

			$("input[name=verInfo]").val(verInfo);

			var key = '${param.eaiSvcName}';
			if (key != "" && key != "null") {
				isDetail = true;
			}

			let cnvsnName = '${param.cnvsnName}';
			if (cnvsnName != "" && cnvsnName != "null") {
				isDetail = true;
			}

			//combo
			$.ajax({
				type : "POST",
				url:url,
				dataType:"json",
				data:{cmd : 'LIST_INIT_COMBO', eaiSvcName: '${param.eaiSvcName}', cnvsnName: '${param.cnvsnName}' },
				success:function(json){
					isAdmin = json.isAdmin;
					var interfaceMap = json.interfaceMap;
					transformRows = json.transformRows;
					//eaiSvcName combo
					$("input[name=eaiSvcName]").val('${param.eaiSvcName }');

					var rawDesc = '${param.eaiSvcDesc}';
					
					// XSS filter 값 복구
					function decodeHTMLEntities(text) {
				        if (!text) return "";
				        var textArea = document.createElement('textarea');
				        textArea.innerHTML = text;
				        return textArea.value;
				    }
				    
					var cleanDesc = decodeURIComponent(rawDesc); 
				    cleanDesc = decodeHTMLEntities(cleanDesc); 

				    if (cleanDesc) {
				        $("input[name=eaiSvcDesc]").val(cleanDesc);
				    } else {
				        $("input[name=eaiSvcDesc]").val("");
				    }

					//$("input[name=cnvsnDesc]").val('${param.cnvsnDesc }');

					new makeOptions("CODE","NAME").setObj($("#functionCombo")).setData(json.functionRows).setNoValueInclude(true).setNoValue("", "<%=localeMessage.getString("transformManDetail.none")%>").setFormat(codeName3OptionFormat).rendering();
					new makeOptions("CODE","NAME").setObj($("#functionComboDialog")).setData(json.functionRows).setNoValueInclude(true).setNoValue("", "<%=localeMessage.getString("transformManDetail.none")%>").setFormat(codeName3OptionFormat).rendering();
					new makeOptions("CODE","NAME").setObj($("#transformForEaiSvcNameCombo")).setData(transformRows).setFormat(codeOptionFormat).rendering();
					new makeOptions("CODE","NAME").setObj($("#eaiSevrDStcd")).setData(json.svrDstcd).setFormat(codeName3OptionFormat).rendering();
					new makeOptions("CODE","NAME").setObj($("#useYn")).setData(json.useYnRows).setFormat(codeName3OptionFormat).rendering();

					$("select[name=useYn]").val('${param.useYn }');
					$("select[name=eaiSevrDStcd]").val('${param.eaiSevrDStcd }').attr("disabled",true);

					reloadSourceTargetGrid('${param.cnvsnName}');
					reloadCnvsnDesc();

					setSearchable("functionCombo");
				},
				error:function(e){
					alert(e.responseText);
				}
			});

			sourceGrid = $("#sourceGrid");
			sourceGrid.jqGrid({
				datatype:'json',
				loadui: "disable",
				mtype: 'POST',
				colNames: [
					"id",
					'<%=localeMessage.getString("tran2ManDt.engNm")%>',
					'<%=localeMessage.getString("tran2ManDt.korNm")%>',
					'<%=localeMessage.getString("transformManDetail.num")%>',
					'<%=localeMessage.getString("tran2ManDt.itTp")%>',
					'<%=localeMessage.getString("tran2ManDt.dtTp")%>',
					"->",
					"LOUTITEMNODEPTRNIDDESC",
					"LOUTITEMPTRNIDNAME",
					"LOUTITEMPATH",
					"loutName",
					"LOUTITEMMAXOCCURNOITM",
					"LOUTITEMREFINFO2",
				],
				colModel: [
					{name: "id"                     , hidden:true,key:true},
					{name: "loutItemName"           , width:"150"},
					{name: "loutItemDesc"                      },
					{name: "loutItemSerno"          , width:"20", align : 'center' },
					{name: "loutItemType" , width:"35"},
					{name: "loutItemDataType"     , width:"40"},
					{name: "CONNECT"                , width:"17", align : 'center', unformat : srcunformatterFunction, formatter: srcformatterFunction},
					{name: "loutItemType" , hidden:true},
					{name: "loutItemDataType"     , hidden:true},
					{name: "LOUTITEMPATH"           , hidden:true},
					{name: "loutName"               , hidden:true},
					{name: "loutItemOccCnt"  , hidden:true},
					{name: "loutItemOccRef"       , hidden:true}
				],
				treeGrid: true,
				treeGridModel: "adjacency",
				ExpandColumn: "loutItemName",
				height:"100%",
				width: "660",
				rowNum: 10000,
				treeIcons: {leaf:'ui-icon-document-b'},
				jsonReader: {
					repeatitems: false
				},
				loadError: function (jqXHR, textStatus, errorThrown) {
					if(jqXHR.status == 401) {
						alert('HTTP status code: ' + jqXHR.status + '\n' +
								'<%=localeMessage.getString("transformManDetail.alert9")%>');
						parent.location.href='<%=request.getContextPath()%>/';
					}
				}
			});

			targetGrid = $("#targetGrid");
			targetGrid.jqGrid({
				//url: '<c:url value="/iim/transform/transformMan.json" />',
				//postData : { cmd : 'LAYOUT_ITEM', loutName: 'LAC_BBSA311_ORGS'},
				datatype:'json',
				loadui: "disable",
				mtype: 'POST',
				colNames: [
					"id",
					"<-",
					'<%=localeMessage.getString("tran2ManDt.tgetItem")%>',
					'<%=localeMessage.getString("tran2ManDt.tgetItemDesc")%>',
					'<%=localeMessage.getString("transformManDetail.num")%>',
					'<%=localeMessage.getString("tran2ManDt.itTp")%>',
					'<%=localeMessage.getString("tran2ManDt.dtTp")%>',
					"loutItemType",
					"LOUTITEMPTRNIDNAME",
					"LOUTITEMPATH",
					"loutName",
					"CNVSNNAME",
					'<%=localeMessage.getString("transformManDetail.tgtItemName")%>',
					'<%=localeMessage.getString("transformManDetail.transCmdName")%>',
					"CNVSNITEMBASCVAL",
					"CNVSNITEMSERNO",
					"CNVSNSRCITEMS",
					"ISVALIDMAPPING"
				],
				colModel: [
					{name: "id"                     , hidden:true,key:true},
					{name: "CONNECT"                , width:"20", align : 'center' , unformat : tgtunformatterFunction, formatter: tgtformatterFunction},
					{name: "loutItemName"           , width:"100" },
					{name: "loutItemDesc"           , width:"100"},
					{name: "loutItemSerno"          , width:"20", align : 'center' },
					{name: "loutItemType" , width:"35" },
					{name: "loutItemDataType"     , width:"40" },

					{name: "loutItemType" , hidden:true},
					{name: "loutItemDataType"     , hidden:true},
					{name: "LOUTITEMPATH"           , hidden:true},
					{name: "loutName"               , hidden:true},

					{name: "CNVSNNAME"              , hidden:true}, //변환 명
					{name: "CNVSNRSULTITEMPATHNAME" , hidden:false}, //타겟 항목명
					{name: "CNVSNCMDNAME"           }, //변환 명령
					{name: "CNVSNITEMBASCVAL"       , hidden:true}, //기본값
					{name: "CNVSNITEMSERNO"         , hidden:true},  //매핑순서
					{name: "CNVSNSRCITEMS"          , hidden:true},
					{name: "ISVALIDMAPPING"         , hidden:true}
				],
				treeGrid: true,
				treeIcons : {
					plus: "ui-icon-circlesmall-plus",
					minus: "ui-icon-circlesmall-minus",
					leaf : "ui-icon-document"
				},
				treeGridModel: "adjacency",
				ExpandColumn: "loutItemName",
				height:"100%",
				width: "860",
				rowNum: 10000,
				//ExpandColClick: true,
				treeIcons: {leaf:'ui-icon-document-b'},
				jsonReader: {
					repeatitems: false
				},
				loadError: function (jqXHR, textStatus, errorThrown) {
					if(jqXHR.status == 401) {
						alert('HTTP status code: ' + jqXHR.status + '\n' +
								'<%=localeMessage.getString("transformManDetail.alert9")%>');
						parent.location.href='<%=request.getContextPath()%>/';
					}
				}
			});

			$("#sourceGrid").jqGrid('gridDnD', {
				connectWith: '#targetGrid',
				ondrop: function (ev, ui, data, rowid, iRow, iCol, e) {
					alert("Dropped!");
				}
			});

			$("input[name=auto]").click(function(){
				//debugger;
				jsPlumbInstance.deleteEveryConnection();

				const sourceData = sourceGrid.getRowData();
				const targetData = targetGrid.getRowData();

				let selectValue = "";
				let targetValue = "";
				for ( var i = 0; i < sourceData.length; i++) {
					if (sourceData[i]['loutItemType'] != "Field" && sourceData[i]['loutItemType'] != "Attr" && sourceData[i]['loutItemType'] != "Array") continue;
					selectValue = (sourceData[i]['LOUTITEMPATH']).substr(sourceData[i]['loutName'].length+1);
					for (var j = 0; j <targetData.length; j++) {
						if (targetData[j]['loutItemType'] != "Field" && targetData[j]['loutItemType'] != "Attr" && targetData[j]['loutItemType'] != "Array") continue;
						targetValue = (targetData[j]['LOUTITEMPATH']).substr(targetData[j]['loutName'].length+1);
						if (targetValue == selectValue ) {
							var data = sourceData[i]['LOUTITEMPATH'];
							var tgtRowId = targetData[j]['id'];
							try {
								jsPlumbConnect(sourceData[i]['id'], tgtRowId);
							} catch (e) {console.error(e);}
							break;
						}
					}
				}
			});

			$("input[name=addAll]").click(function() {
				console.debug('addAll');
				var srcRowId = sourceGrid.getGridParam( "selrow" );
				var tgtRowId = targetGrid.getGridParam( "selrow" );
				if (srcRowId == null) {alert('<%=localeMessage.getString("transformManDetail.alert1")%>');return;}
				if (tgtRowId == null) {alert('<%=localeMessage.getString("transformManDetail.alert2")%>');return;}

				//field, ATTR 여부 판단
				var sourceRow = sourceGrid.getRowData( srcRowId );
				var targetRow = targetGrid.getRowData( tgtRowId );
				if ( (sourceRow["loutItemType"] == 'Field' || sourceRow["loutItemType"] == 'Attr' || sourceRow["loutItemType"] == 'Array') &&
						(targetRow["loutItemType"] == 'Field' || targetRow["loutItemType"] == 'Attr' || targetRow["loutItemType"] == 'Array')  ){
					;
				}else{
					alert('<%=localeMessage.getString("transformManDetail.alert3")%>');
					return ;
				}
				//grid data
				var sourceData = sourceGrid.getRowData();
				var targetData = targetGrid.getRowData();

				//grid index
				var srcIndex = sourceGrid.jqGrid('getInd',srcRowId);
				var tgtIndex = targetGrid.jqGrid('getInd',tgtRowId);


				var selectValue = "";
				var targetValue = "";
				var j=tgtIndex-1-1;
				for ( var i = srcIndex-1; i < sourceData.length; i++) {
					if (sourceData[i]['loutItemType'] != LAYOUT_ITEM_TYPE_FIELD && sourceData[i]['loutItemType'] != LAYOUT_ITEM_TYPE_ARRAY) continue;
					j++;
					while (targetData.length -1 >= j && targetData[j]["loutItemType"] != LAYOUT_ITEM_TYPE_FIELD && targetData[j]["loutItemType"] != LAYOUT_ITEM_TYPE_ARRAY){
						j++;
					}
					if (targetData.length -1 < j) break;
					var targetRowId = targetData[j]['id'];
					targetGrid.jqGrid('setCell',targetRowId,'CNVSNCMDNAME',addArrayTag(sourceData[i]['loutItemType'], addGroupTag(srcGroup,sourceData[i]['LOUTITEMPATH'])));
					targetGrid.jqGrid('setCell',targetRowId,'CNVSNRSULTITEMPATHNAME',addArrayTag(targetData[j]['loutItemType'], addGroupTag(tgtGroup,targetData[j]['LOUTITEMPATH'])));
					targetGrid.jqGrid('setCell',targetRowId,'CNVSNITEMSERNO',targetData[j]['loutItemSerno']);

					const sourceEndpointElementId = sourceGrid.getEndpointElementId(sourceData[i]['id']);
					const targetEndpointElementId = targetGrid.getEndpointElementId(targetRowId);

					jsPlumbInstance.deleteConnectionsForElement(document.getElementById(sourceEndpointElementId));
					jsPlumbInstance.deleteConnectionsForElement(document.getElementById(targetEndpointElementId));

					jsPlumbConnect(sourceEndpointElementId, targetEndpointElementId);
				}
			});

			$("input[name=removeAll]").click(function(){
				var tgtRowId = targetGrid.getGridParam( "selrow" );
				if (tgtRowId == null) {alert("타겟레이아웃을 선택하여 주십시요.");return;}
				//grid data
				var targetData = targetGrid.getRowData();
				//grid index
				var tgtIndex = targetGrid.jqGrid('getInd',tgtRowId);

				for ( var i = tgtIndex-1; i < targetData.length; i++) {
					var rowId = targetData[i]['id'];
					targetGrid.jqGrid('setCell', rowId, 'CNVSNCMDNAME', null);
					targetGrid.jqGrid('setCell', rowId, 'CNVSNRSULTITEMPATHNAME', null);
					targetGrid.jqGrid('setCell', rowId, 'CNVSNITEMSERNO', null);
					targetGrid.jqGrid('setCell', rowId, 'CNVSNITEMBASCVAL', null);

					const targetEndpointElementId = targetGrid.getEndpointElementId(rowId);
					jsPlumbInstance.deleteConnectionsForElement(document.getElementById(targetEndpointElementId));
				}
			});

			$("textarea[name=CNVSNRSULTITEMPATHNAME],textarea[name=CNVSNCMDNAME],input[name=CNVSNITEMBASCVAL],input[name=CNVSNITEMSERNO]").blur(function(){
				var rowId = targetGrid.getGridParam( "selrow" );
				if (isNull(rowId)) return;
			});

			$("#btn_close").click(function() {
				isValidMapping = true;
				if (confirmLastAmnDhms()) {
					window.close();
				}
			});

			$("#btn_previous").click(function(){
				doneAction();
			});

			$("#btn_modify").click(function(){

				var cmd;
				if (isDetail) {
					cmd = "UPDATE";
				} else {
					cmd = "INSERT";
				}

				let useYn = $("select[name=useYn]").val();
				if (useYn === null || useYn.trim() === "") {
					useYn = "1";
				}

				//disabled 해제
				$("select[name=eaiSevrDStcd]").attr("disabled",false);

				if(!validation()) return;

				var targetData = targetGrid.getRowData();
				var gridData                = new Array();
				for (var i = 0; i <targetData.length; i++) {
					if ((targetData[i]['loutItemType'] != "Field") && (targetData[i]['loutItemType'] != "Attr") && (targetData[i]['loutItemType'] != "Array")) {
						continue;
					}
					if (targetData[i]['CNVSNCMDNAME']==null
							|| targetData[i]['CNVSNCMDNAME']== undefined
							|| targetData[i]['CNVSNCMDNAME'].trim() ==""
					) continue;

					gridData.push(targetGrid.jqGrid('getRowData', targetData[i]['id']));

				}
				var postData = [];
				postData.push({ name: "cmd"           , value:cmd});
				postData.push({ name: "cnvsnName"     , value:$("#transformForEaiSvcNameCombo").val()});
				postData.push({ name: "cnvsnDesc"     , value:$("input[name=cnvsnDesc]").val()});
				postData.push({ name: "cnvsnType"     , value:$("#transformForEaiSvcNameCombo").val().substr(-3)});
				postData.push({ name: "eaiSevrDStcd"  , value:$("select[name=eaiSevrDStcd]").val()});
				postData.push({ name: "chkForce"      , value:$("input:checkbox[name=chk_eaiSvcName]").is(":checked")});
				postData.push({ name: "srcLayoutName" , value:$("input[name=srcLayout]").val()});
				postData.push({ name: "tgtLayoutName" , value:$("input[name=tgtLayout]").val()});
				postData.push({ name: "useYn" 		  , value: useYn});
				postData.push({ name: "verInfo" 	  , value:$("input[name=verInfo]").val()});
				postData.push({ name: "gridData"      , value:JSON.stringify(gridData)});
				postData.push({ name: "eaiSvcName"      	  , value:$("input[name=eaiSvcName]").val()});
				$("#ajax_wait_modal").show();
				$.ajax({
					type : "POST",
					url:url,
					data:postData,
					success:function(args){
						$("#ajax_wait_modal").hide();
						alert('<%=localeMessage.getString("common.saveMsg")%>');

						var transform = args;

						var lastAmnDhms = transform['LASTAMNDHMS'];
						$('#cnvsnlastAmnDhms').val(transform['LASTAMNDHMS']);
						$("#displayCnvsnlastAmnDhms").val(formatDate(transform['LASTAMNDHMS']));

						var cnvsnType = $("input[name=cnvsnTypeCombo]").val();
						$('#' + cnvsnType).attr('lastAmnDhms', lastAmnDhms);
						doneAction();
					},
					error:function(e){
						$("#ajax_wait_modal").hide();
						alert(e.responseText);
					}
				});
			});

			$("input[name=addCmd]").click(function(){
				var rowId = targetGrid.getGridParam( "selrow" );
				var targetRow = "";
				var cnvsnCmdName = "";

				if (isNull(rowId)){
					alert('<%=localeMessage.getString("transformManDetail.alert4")%>');
					return;
				}

				targetRow = targetGrid.getRowData( rowId );	// 타겟 그리드에서 선택된 ROW 값
				rowId = sourceGrid.getGridParam( "selrow" );
				if (isNull(rowId)){
					alert('<%=localeMessage.getString("transformManDetail.alert5")%>');
					return;
				}
			});

			$("#btn_delete").click(function(){
            	if(!confirm("삭제하시겠습니까?")){
   				 return;
               	}
				
				var postData = [];
				const cnvsnName = $("select[name=transformForEaiSvcNameCombo]").val();
				const cnvsnType = cnvsnName.slice(-3);

				postData.push({ name: "cmd"       , value:"DELETE"});
				postData.push({ name: "eaiSvcName", value:$("input[name=eaiSvcName]").val()});
				postData.push({ name: "cnvsnName" , value: cnvsnName});
				postData.push({ name: "cnvsnType" , value: cnvsnType});

				$.ajax({
					type : "POST",
					url:url,
					data:postData,
					success:function(args){
						alert("삭제 되었습니다.");
						if(isPop == "true"){
							window.close();
							const transformName ="${param.cnvsnName}";
							window.parent.postMessage({cmd:'DELETE', type: 'transform', transformName});
						}else{
							goNav(returnUrl);
						}
					},
					error:function(e){
						alert(e.responseText);
					}
				});
			});

			$("#btn_initialize").click(function(){
				$.ajax({
					type : "POST",
					url:url,
					dataType:"json",
					data:{cmd: 'INITIALIZE',cnvsnName:$("select[name=transformForEaiSvcNameCombo]").val()},
					success:function(json){
						alert(json.message);
					},
					error:function(e){
						alert(e.responseText);
					}
				});

			});

			if(isPop){
				$(".content_top").css('display', 'none');
				$(".content_middle").css('margin-top', '0px');
				$(".content_middle").css('padding', '20px');
				$("#btn_previous").html('<i class="material-icons">close</i> 닫기');
				// $("input[name=srcLayout]").attr("readonly",true);
				// $("input[name=tgtLayout]").attr("readonly",true);
				// $("input[name=cnvsnDesc]").attr("readonly",true);
				// $("input[name=eaiSvcName]").attr("readonly",true);
				// $("select[name=transformForEaiSvcNameCombo]").attr("disabled",true);
				// $("input:checkbox[name=chk_eaiSvcName]").attr("disabled",true);
				// $("#btn_search").css('pointer-events','none');
				// $("#btn_searchSrcLout").hide();
				// $("#btn_searchTgtLout").hide();
				$("input[name=srcLayout]").css('width','100%');
				$("input[name=tgtLayout]").css('width','100%');
			}

			buttonControl();
			// setBtnHide(roleString, "admin", "btn_initialize");
		});

		function srcformatterFunction(cellvalue,options,rowObject){
			var rowId = options["rowId"];
			var loutItemType = rowObject["loutItemType"];
			if (loutItemType == 'Field' || loutItemType == 'Attr' || loutItemType == 'Array'){
				return "<div id='div_src_"+rowId+"' name='src_"+rowId+"' style='width:28px;height:17px;background-color: #D12F35; border-color: #ab1717; border-style: solid; border-width: 1px; border-radius: 3px;' />";
			}else{
				return "<div id='div_srcgroup_"+rowId+"' name='srcgroup_"+rowId+"' style='width:28px;height:17px;' />";
			}
		}
		function srcunformatterFunction(cellvalue,options, rowObject){
			return cellvalue;
		}
		function tgtformatterFunction(cellvalue,options,rowObject){
			var rowId = options["rowId"];
			var loutItemType = rowObject["loutItemType"];
			if (loutItemType == 'Field' || loutItemType == 'Attr' || loutItemType == 'Array'){
				return "<div id='div_tgt_"+rowId+"_base' name='div_tgt_"+rowId+"_base' style='width:30px;height:20px; background-color:gray;' >"
						+ "<div id='div_tgt_"+rowId+"' name='tgt_"+rowId+"' style='width:28px;height:17px; background-color: #3E7E9C;  border-color: #217ca7; border-style: solid; border-width: 1px; border-radius: 3px;' onclick='jqGridOnTargetGridEndpointClick(this)'>"
						+ "</div></div>";
			}else{
				return "<div id='div_tgtgroup_"+rowId+"' name='tgtgroup_"+rowId+"' style='width:28px;height:17px;' />";
			}
		}
		function tgtunformatterFunction(cellvalue,options, rowObject){
			return cellvalue;
		}

		function batchJsPlumbInstance() {

			$(window).on('resize',function(){
				// window 크기가 변경 될 때
				// 모든 connection repaint
				jsPlumbInstance.repaintEverything();

				// 창에 맞춰서 mappingDialog position 변경
				if (mappingDialog.dialog('isOpen')) {
					moveDialogPosition(false);
				}
			});

			$(window).scroll(function(){
				// scroll 시 mappingDialog position 변경
				if (mappingDialog.dialog('isOpen')) {
					moveDialogPosition(true);
				}
			});

			jsPlumbInstance.bind("endpointClick", jsPlumbOnEndpointClick);
			jsPlumbInstance.bind("connection", jsPlumbOnConnection);
			jsPlumbInstance.bind("connectionDetached", jsPlumbOnConnectionDetached);
			jsPlumbInstance.bind("connectionMoved", jsPlumbOnConnectionMoved);
			jsPlumbInstance.bind("beforeDrop", jsPlumbOnBeforeDrop);
			jsPlumbInstance.bind("connectionDrag", jsPlumbOnConnectionDrag);
			jsPlumbInstance.bind("connectionDragStop", jsPlumbOnConnectionDragStop);

		}

		function jsPlumbOnConnectionDrag(conn) {
			console.debug('jsPlumbOnConnectionDrag');
			console.debug(conn);

			// drag 시 sourceRow와 같은 이름을 가진 targetRow를 검색
			const sourceRowId = sourceGrid.getRowId(conn.sourceId);
			const sourceRowData = sourceGrid.getRowData(sourceRowId);
			const layoutItemName = sourceRowData['loutItemName'];
			const targetRowDatas = targetGrid.findRowDatasByLayoutItemName(layoutItemName);

			console.debug("jsPlumbOnConnectionDrag sourceRowId: " + sourceRowId)
			console.debug("jsPlumbOnConnectionDrag targetRowDatas: " +targetRowDatas);

			var endpoints = conn.endpoints;
			if (endpoints.length > 0) {
				mouseoverEndpoint(endpoints[0], 'mouseover-endpoint');
			}

			sourceGrid.find("tr[id="+sourceRowId+"]").addClass('ui-state-hover');
			$(targetRowDatas).each(function (i, rowData) {
				targetGrid.find('#' + rowData['id']).addClass('div-hover');
			});
		}

		function jsPlumbOnConnectionDragStop(conn) {
			console.debug('jsPlumbOnConnectionDragStop');

			// drag 시 sourceRow와 같은 이름을 가진 targetRow를 검색
			const sourceRowId = sourceGrid.getRowId(conn.sourceId);
			const sourceRowData = sourceGrid.getRowData(sourceRowId);

			console.debug("jsPlumbOnConnectionDragStop sourceRowId: " + sourceRowId)

			var endpoints = conn.endpoints;
			if (endpoints != null && endpoints.length > 0) {
				mouseoutEndpoint(endpoints[0], 'mouseover-endpoint');
			}

			sourceGrid.find("tr[id="+sourceRowId+"]").removeClass('ui-state-hover');
			targetGrid.find('tr').removeClass('div-hover');
		}

		function jsPlumbOnBeforeDrop(info) {
			console.debug('jsPlumbOnBeforeDrop');
			var connections = jsPlumbInstance.getConnections({source:info.sourceId, target:info.targetId});

			console.debug(info);
			console.debug(connections)

			var isConnected = false;

			if (connections.length == 0) {
				return true;
			}

			$.each(connections, function (i, conn) {
				// connection id가 다른 connection이 존재 한다.
				if (conn.id != info.connection.id && !conn.isSuspendEvents()) {
					isConnected = true;
					return false;
				}
			});

			if (isConnected) {
				alert('<%=localeMessage.getString("transformManDetail.alert10")%>');
			}

			// 기존의 연결이 존재 할 경우 연결을
			return !isConnected;
		}

		function jsPlumbOnEndpointClick (endpoint, originalEvent) {
			console.debug('jsPlumbOnEndpointClick');
			openFunctionDialog(endpoint);
		}

		function jqGridOnTargetGridEndpointClick (endpointElement) {
			var endpoints = jsPlumbInstance.selectEndpoints({element:endpointElement});
			console.debug(endpoints);
			if (endpoints.length > 0) {
				openFunctionDialog(endpoints.get(0));
			}
		}

		function openFunctionDialog(endpoint) {
			if (!jsPlumbInstance.isTarget(endpoint.getElement())) {
				return;
			}

			if (!mappingDialog.dialog('isOpen')) {
				console.debug("id : " + endpoint.elementId);
				var targetRowId = targetGrid.getRowId(endpoint.elementId);
				setDialogValues(targetRowId);

				mappingDialog.dialog({
					width:$('#targetGridTd').width() * 0.9,
					open : function () {
						console.debug('dialog open');

						$('#functionComboDialog').val($('#functionCombo').val());

						setSearchable("functionComboDialog");

						mouseoverEndpoint(endpoint, 'click-endpoint');
						moveDialogPosition(false);
					},
					drag : function () {
						console.debug('dialog drag');
						moveDialogEndpointPosition();
					},
					close : function () {
						console.debug('dialog close');
						returnDialogEndpointPosition(endpoint);
						return;
					}
				}).dialog('open');
			}
		}

		function mappingDialogSave() {
			var targetRowId = $('#targetRowId').val();
			console.debug('targetRowId : ' + targetRowId);
			targetGrid.jqGrid('setCell',targetRowId,'CNVSNRSULTITEMPATHNAME',$('textarea[name=CNVSNRSULTITEMPATHNAME]').val());
			targetGrid.jqGrid('setCell',targetRowId,'CNVSNCMDNAME',$('textarea[name=CNVSNCMDNAME]').val());
			targetGrid.jqGrid('setCell',targetRowId,'CNVSNITEMBASCVAL',$('input[name=CNVSNITEMBASCVAL]').val() == "" ? null : $('input[name=CNVSNITEMBASCVAL]').val());
			targetGrid.jqGrid('setCell',targetRowId,'CNVSNITEMSERNO',$('input[name=CNVSNITEMSERNO]').val());

			mappingDialog.dialog('close');
		}

		function mappingDialogBeforeClose() {
			console.debug('mappingDialogBeforeClose')
			// 사용하지 않는 변환 전 항목 체크
			var targetRowId = $('#targetRowId').val();
			var targetRowData = targetGrid.getRowData(targetRowId);

			var cnvsnCmdName = targetRowData['CNVSNCMDNAME'];
			var cnvsnSrcItems = $.trim(targetRowData['CNVSNSRCITEMS']).split(',');

			console.debug('targetRowId : ' + targetRowId);
			console.debug('cnvsnCmdName : ' + cnvsnCmdName);
			console.debug('cnvsnSrcItems : ' + cnvsnSrcItems);

			for (var i = 0; i < cnvsnSrcItems.length; i++) {
				var srcItem = cnvsnSrcItems[i];
				if (cnvsnCmdName != undefined && cnvsnCmdName.indexOf(srcItem) == -1) {
					alert('<%=localeMessage.getString("transformManDetail.alert11")%>');
					return true;
				}
			}

			return true;
		}

		function mappingDialogCancle() {
			// dialog 열기 전 상태로 cancle
			var targetRowId = $('#targetRowId').val();
			var targetRowData = targetGrid.getRowData(targetRowId);

			targetGrid.jqGrid('setCell', targetRowId, 'CNVSNCMDNAME', $('#cancleCnvsnCmdName').val());
			targetGrid.jqGrid('setCell', targetRowId, 'CNVSNSRCITEMS', $('#cancleSrcItems').val());

			mappingDialog.dialog('close');
		}

		function mouseoverEndpoint(endpoint, cssClass) {
			console.debug('mouseoverEndpoint');
			var sourceElementId = jsPlumbInstance.isSource(endpoint.element) ? endpoint.elementId : '';
			var targetElementId = jsPlumbInstance.isTarget(endpoint.element) ? endpoint.elementId : '';

			var filter = {source:sourceElementId, target:targetElementId};

			var endpointConnection = jsPlumbInstance.getConnections(filter);

			$.each(endpointConnection, function(i, conn) {
				conn.addClass(cssClass);
				$.each(conn.endpoints, function (j, endpoint) {
					endpoint.addClass(cssClass)
				});
			});
		}

		function mouseoutEndpoint(endpoint, cssClass) {
			console.debug('mouseoutEndpoint');

			if (isContextMenuShow) {
				return;
			}

			var sourceElementId = jsPlumbInstance.isSource(endpoint.element) ? endpoint.elementId : '';
			var targetElementId = jsPlumbInstance.isTarget(endpoint.element) ? endpoint.elementId : '';

			var filter = {source:sourceElementId, target:targetElementId};

			var endpointConnection = jsPlumbInstance.getConnections(filter);

			$.each(endpointConnection, function(i, conn) {
				conn.removeClass(cssClass);
				$.each(conn.endpoints, function (j, endpoint) {
					endpoint.removeClass(cssClass)
				});
			});
		}

		function mouseoverJqgrid(loutItemName, grid) {
			// 해당 row의 이름을 조회 하여 해당 row의 배경색을 강조
			console.debug('mouseoverJqgrid loutItemName : ' + loutItemName);
			const rowDatas = grid.findRowDatasByLayoutItemName(loutItemName);
			// 기존의 row의 class를 모두 삭제
			grid.find('tr').removeClass('div-hover');
			// 신규 row의 class를 추가
			$(rowDatas).each(function(i, rowData) {
				grid.find('#' + rowData['id']).addClass('div-hover');
			});
		}

		function mouseoutJqgrid(loutItemName, grid) {
			if (!isContextMenuShow) {
				// context menu 가 열려 있을 경우
				console.debug('mouseoutJqgrid loutItemName : ' + loutItemName);
				grid.find('tr').removeClass('div-hover');
			}
		}


		function jsPlumbOnConnection (info, originalEvent) {
			console.debug("jsPlumbOnConnection start");

			$.each(info.connection.endpoints, function (index, endpoint) {
				// mouseover event bind
				endpoint.bind('mouseover', function () {
					mouseoverEndpoint(endpoint, 'mouseover-endpoint');
				});
				// mouseout event bind
				endpoint.bind('mouseout', function () {
					mouseoutEndpoint(endpoint, 'mouseover-endpoint');
				});

				// dialog 가 열려있을 때 connection 연결 connection style 적용 한다.
				if (mappingDialog.dialog('isOpen')
						&& jsPlumbInstance.isTarget(endpoint.element)
						&& targetGrid.getRowId(endpoint.elementId) == $('#targetRowId').val()) {

					mouseoverEndpoint(endpoint, 'click-endpoint');
				}
			});

			const sourceId = sourceGrid.getRowId(info.sourceId);
			const targetId = targetGrid.getRowId(info.targetId);
			const targetConnections = jsPlumbInstance.getConnections({target:info.targetId});

			const sourceIds = $.map(targetConnections, function(conn) {
				return sourceGrid.getRowId(conn.sourceId);
			});

			jqGridOnConnection(sourceId, targetId, sourceIds);
		}

		function jsPlumbOnConnectionDetached (info, originalEvent) {
			console.debug("jsPlumbOnConnectionDetached start");
			var targetConnections = jsPlumbInstance.getConnections({target:info.targetId})
			if (targetConnections != null) {
				const targetRowId = targetGrid.getRowId(info.targetId);
				const sourceRowId = sourceGrid.getRowId(info.sourceId);

				const sourceIds = $.map(targetConnections, function(conn) {
					if (conn.sourceId == info.sourceId) {
						return;
					} else {
						return sourceGrid.getRowId(conn.sourceId);
					}
				});

				jqGridOnConnectionDetached(sourceRowId, targetRowId, sourceIds);
			}
		}

		function jsPlumbOnConnectionMoved (info, originalEvent) {
			console.debug("connectionMoved start");
			const originalTargetConnections = jsPlumbInstance.getConnections({target:info.originalTargetId});

			const originalSourceId = sourceGrid.getRowId(info.originalSourceId);
			const originalTargetId = targetGrid.getRowId(info.originalTargetId);

			const originalSourceIds = $.map(originalTargetConnections, function(conn) {
				return sourceGrid.getRowId(conn.sourceId);
			});

			// 변경 전 타겟의 소스 정보 수정
			jqGridOnConnectionDetached(originalSourceId, originalTargetId, originalSourceIds);

		};

		function setDialogValues(targetRowId) {
			var rowData = targetGrid.getRowData(targetRowId);
			$('textarea[name=CNVSNRSULTITEMPATHNAME]').val(rowData['CNVSNRSULTITEMPATHNAME']);//
			$('textarea[name=CNVSNCMDNAME]').val(rowData['CNVSNCMDNAME']);
			$('input[name=CNVSNITEMBASCVAL]').val(rowData['CNVSNITEMBASCVAL']);
			$('input[name=CNVSNITEMSERNO]').val(rowData['CNVSNITEMSERNO']);

			// dialog open 시 cancle 정보 입력
			// var targetRowData = targetGrid.getRowData(targetRowId);

			if (!mappingDialog.dialog('isOpen')) {
				$('#targetRowId').val(targetRowId);
				$('#cancleCnvsnCmdName').val(rowData['CNVSNCMDNAME']);
				$('#cancleSrcItems').val(rowData['CNVSNSRCITEMS']);
			}

			updateSourceItem(targetRowId);
		}

		function updateSourceItem(targetRowId) {
			console.debug('updateSourceItem');

			var targetRowData = targetGrid.getRowData(targetRowId);
			var cnvsnSrcItems = $.trim(targetRowData['CNVSNSRCITEMS']).split(',');

			$('#mappingDialog table tr').each(function () {
				var thisTr = $(this);
				if (thisTr.attr('isSrcItem') == 'true') {
					console.debug('updateSourceItem remove : ' + this);
					thisTr.remove();
				}
			});

			// table row 추가
			$.each(cnvsnSrcItems, function (index, srcLoutItemPath) {
				if (srcLoutItemPath == '') {
					return;
				}

				var row = '<tr isSrcItem="true"><th style="width:130px;"><%=localeMessage.getString("transformManDetail.preConIt")%></th><td>'
						+ srcLoutItemPath
						+ ' <input type="button" onclick="addSrcLoutItemPath( \''
						+ srcLoutItemPath + '\', \''
						+ targetRowId + '\' )" class="btn_img btn_pop_add" /> '
						+'</td></tr>';
				console.debug('updateSourceItem addItemBeforeTr : ' + srcLoutItemPath);
				$('#addItemBeforeTr').before(row);
			});
		}

		function addSrcLoutItemPath (srcLoutItemPath, targetRowId) {
			console.debug('addSrcLoutItemPath');
			var cnvsnCmdName = srcLoutItemPath;
			var targetRowData = targetGrid.getRowData(targetRowId);    // 타겟 그리드에서 선택된 ROW 값

			if($('#functionComboDialog').val() != "") {
				cnvsnCmdName = $('#functionComboDialog').val() + "(" + cnvsnCmdName + ")";
			}

			$('textarea[name=CNVSNCMDNAME]').val($('textarea[name=CNVSNCMDNAME]').val() + ' ' +  cnvsnCmdName);
			$('textarea[name=CNVSNRSULTITEMPATHNAME]').val(addGroupTag(tgtGroup,targetRowData["LOUTITEMPATH"]));
			$('input[name=CNVSNITEMSERNO]').val(targetRowData['loutItemSerno']);

			// setTgtCell();
		}

		function moveDialogPosition(isScroll) {
			console.debug('moveDialogPosition : ' + isScroll);
			if (!mappingDialog.dialog('isOpen')) {
				console.debug('dialog closed');
				return;
			}

			var autoOffset = $('#auto').offset();
			// scroll 한 값
			var winY = window.pageYOffset;

			mappingDialogParent.css('position', "absolute");
			// scroll 한 만큼 추가로 내려 준다
			mappingDialogParent.css('top', autoOffset.top + 40 + winY);
			if (!isScroll) {
				// scroll 할 때는 좌우 포지션은 변경 하지 않는다.
				mappingDialogParent.css('left', autoOffset.left + 40);
			}

			moveDialogEndpointPosition();
		}

		function moveDialogEndpointPosition() {
			var targetEndpointElement = targetGrid.getEndpointElement($('#targetRowId').val());
			mappingDialogParent.before(targetEndpointElement);

			targetEndpointElement.css({width:'20px', height:'20px' });
			targetEndpointElement.position({
				my : 'right', at : 'left', of:mappingDialogParent
			});

			jsPlumbInstance.revalidate(targetEndpointElement.attr('id'));
		}

		function returnDialogEndpointPosition(endpoint) {
			var targetEndpointDiv = $('#' + endpoint.elementId);
			$('#' + endpoint.elementId + "_base").append(targetEndpointDiv);

			mouseoutEndpoint(endpoint, 'click-endpoint');
			mouseoutEndpoint(endpoint, 'mouseover-endpoint');

			targetEndpointDiv.css({position:'relative', top:'', left:'', width:'100%', height:'100%' });
			jsPlumbInstance.revalidate(endpoint.elementId);
		}

		function jsPlumbConnect(source, target) {

			var sourceEndpointElementId = source;
			var targetEndpointElementId = target;

			if (source.indexOf(transformGrid.ENDPOINT_PREFIX_SRC) == -1) {
				sourceEndpointElementId = transformGrid.ENDPOINT_PREFIX_SRC + source;
			}

			if (target.indexOf(transformGrid.ENDPOINT_PREFIX_TGT) == -1) {
				targetEndpointElementId = transformGrid.ENDPOINT_PREFIX_TGT + target;
			}

			// 연결이 존재 하는 지 확인
			if (jsPlumbInstance.getConnections({source:sourceEndpointElementId, target:targetEndpointElementId}).length > 0) {
<%-- 				alert('<%=localeMessage.getString("transformManDetail.alert10")%>'); --%>
				return;
			}

			var connection = jsPlumbInstance.connect({
				source:sourceEndpointElementId,
				target:targetEndpointElementId,
			});
		}

		function jqGridOnConnection(newSourceRowId, tgtRowId, srcRowIds) {
			console.debug('jqGridOnConnection');
			console.debug('newSourceRowId : ' + newSourceRowId);
			console.debug('tgtRowId : ' + tgtRowId);
			console.debug('srcRowIds : ' + srcRowIds);

			if (newSourceRowId == undefined || srcRowIds.length == 0) {
				// 연결 정보가 없음
				targetGrid.jqGrid('setCell', tgtRowId,'CNVSNCMDNAME',null);
				targetGrid.jqGrid('setCell', tgtRowId,'CNVSNRSULTITEMPATHNAME',null);
				targetGrid.jqGrid('setCell', tgtRowId,'CNVSNITEMSERNO',null);
				targetGrid.jqGrid('setCell', tgtRowId,'CNVSNITEMBASCVAL',null);
				targetGrid.jqGrid('setCell', tgtRowId,'CNVSNSRCITEMS', null);

				setDialogValues(tgtRowId);
				updateSourceItem(tgtRowId);
				return;
			}

			//field, ATTR 여부 판단
			var sourceRow = sourceGrid.getRowData( newSourceRowId );
			var targetRow = targetGrid.getRowData( tgtRowId );

			if (sourceRow["loutItemType"] == undefined) {
				// tab을 변경 했을 경우 source row가 존재 하지 않을 수 있다.
				return;
			}

			if ((sourceRow["loutItemType"] != 'Field' && sourceRow["loutItemType"] != 'Attr' && sourceRow["loutItemType"] != 'Array')
					|| (targetRow["loutItemType"] != 'Field' && targetRow["loutItemType"] != 'Attr' && targetRow["loutItemType"] != 'Array')) {
				alert('<%=localeMessage.getString("transformManDetail.alert3")%>');
				return ;
			}

			var cnvsnSrcItems = $.map(srcRowIds, function (rowId) {
				var rowData = sourceGrid.getRowData(rowId);
				return addGroupTag(srcGroup, rowData["LOUTITEMPATH"]);
			});

			console.debug(targetRow['CNVSNCMDNAME'] == '');

			if (targetRow['CNVSNCMDNAME'] == '') {
				// 변환 명령 값이 한번 설정 되면 변경 되지 않게 함.
				var cnvsnCmdName = addArrayTag(sourceRow["loutItemType"], addGroupTag(srcGroup,sourceRow["LOUTITEMPATH"]));
				// function까지 처리되도록 수정했으나, parameter가 하나인 경우에만 정상처리됨
				if($('#functionCombo').val() != "") {
					cnvsnCmdName = $('#functionCombo').val() + "(" + cnvsnCmdName + ")";
				}

				targetGrid.jqGrid('setCell',tgtRowId,'CNVSNCMDNAME', cnvsnCmdName);
			}

			targetGrid.jqGrid('setCell',tgtRowId,'CNVSNRSULTITEMPATHNAME',addArrayTag(targetRow["loutItemType"], addGroupTag(tgtGroup,targetRow["LOUTITEMPATH"])));
			targetGrid.jqGrid('setCell',tgtRowId,'CNVSNITEMSERNO',targetRow['loutItemSerno']);
			targetGrid.jqGrid('setCell',tgtRowId,'CNVSNSRCITEMS', cnvsnSrcItems);
			targetGrid.jqGrid('setCell',tgtRowId,'ISVALIDMAPPING', true);

			// dialog 가 열려있을 때 connection 연결
			if (mappingDialog.dialog('isOpen')) {
				setDialogValues(tgtRowId);
			}
		}

		function jqGridOnConnectionDetached(detachedSourceRowId, tgtRowId, srcRowIds) {
			console.debug('jqGridOnConnectionDetached');
			console.debug('srcRowIds : ' + srcRowIds);
			console.debug('detachedSourceRowId : ' + detachedSourceRowId);

			jqGridOnConnection(srcRowIds[0], tgtRowId, srcRowIds);
		}

		function reloadSourceTargetGrid(cnvsnName) {

			var conversionName = cnvsnName;

			if(conversionName == undefined) {
				conversionName = $("#transformForEaiSvcNameCombo").val();
			} else {
				$("#transformForEaiSvcNameCombo").val(cnvsnName).prop("selected", true);
			}

			getSourceResult(conversionName);
		}

		$('#contextMenuDiv').ready(function () {

			// context build 시에 사용되는 context menu create 함수
			var createFieldContextMenuItems = function (grid, endpointElementId) {

				var rowId = grid.getRowId(endpointElementId);
				var contextMenuItems = {
					connectByName : {
						name : "(+)<%=localeMessage.getString("transformManDetail.mapping.samename")%>",
						callback : function () {
							// 같은 이름의로 연결을 시도
							console.debug('connectByName : ' + endpointElementId);

							const rowData = grid.getRowData(rowId);
							const loutItemName = rowData['loutItemName'];

							var otherRowDatas = grid.getOtherGrid().findRowDatasByLayoutItemName(loutItemName);

							if (otherRowDatas.length < 1) {
								alert('<%=localeMessage.getString("transformManDetail.alert12")%>');
								return;
							}

							for (var i = 0; i < otherRowDatas.length; i++) {
								const otherRowId = otherRowDatas[i]['id'];
								console.debug('otherRowId : ' + otherRowId);

								// 이름이 완전히 같은 item만 매핑
								if (removeNamespace(otherRowDatas[i]['loutItemName']) != removeNamespace(loutItemName)) {
									continue;
								}

								if (grid.isSource()) {
									jsPlumbConnect(rowId, otherRowId);
								} else {
									jsPlumbConnect(otherRowId, rowId);
								}
							}
						}
					},
					sep1 : "----------------",
				};

				// ContextMenu 클릭한 row에 연결 되어 있는 모든 Connection
				var endpointConnections = grid.findEndpointConnections(rowId);
				// sort 하기 위해 따로 저장
				var sortedItems = [];

				// 매핑 제거용 context menu 생성
				$.each(endpointConnections, function(i, conn) {
					// ContextMenu 클릭한 row에 연결 되어 있는 상대 endpoint element id
					var otherEndpointId;
					if (grid.isSource()) {
						otherEndpointId = conn.targetId;
					} else {
						otherEndpointId = conn.sourceId;
					}
					// ContextMenu 클릭한 row에 연결 되어 있는 상대 row id
					var otherRowId = grid.getRowId(otherEndpointId);
					var rowData = grid.getOtherGrid().getRowData(otherRowId);

					// context menu의 삭제 항목 생성
					var item = {
						rowId : otherRowId,
						name : '(-)' + rowData['loutItemName'],
						order : rowData['loutItemSerno'],
						callback : function () {
							// 매핑을 삭제
							jsPlumbInstance.deleteConnection(conn);
						}
					};

					sortedItems.push(item);
				});

				// item을 loutItemSerno 순서대로 sort
				sortedItems = sortedItems.sort(function (itemA, itemB) {
					return itemA.order - itemB.order;
				});

				$.each(sortedItems, function(i, item) {
					// sort 된 각 item을 items에 추가 한다.
					contextMenuItems[item.rowId] = item;
					console.debug(item.rowId + '=' + item.order);
				});

				return contextMenuItems;
			}

			// grid group context build 시에 사용되는 context menu create 함수
			var createGridGroupContextMenuItems = function (grid, rowId) {
				var contextMenuItems = {
					connectByName : {
						name : "(+)<%=localeMessage.getString("transformManDetail.mapping.samegroupname")%>",
						callback : function () {
							const groupRowData = grid.getRowData(rowId);
							const groupLoutItemName = removeNamespace(groupRowData["loutItemName"]);

							const otherGrid = grid.getOtherGrid();

							const sourceGroupRowDatas = groupDatas(grid, rowId);
							const otherGrodRowData = otherGrid.findRowDatasByLayoutItemName(groupLoutItemName)[0];

							if (!otherGrodRowData) {
								return;
							}

							jsPlumbInstance.deleteEveryConnection();

							const otherGridRowId = otherGrodRowData["id"];
							const targetGroupRowDatas = groupDatas(otherGrid, removeNamespace(otherGridRowId));

							for (const groupLoutItemPath in sourceGroupRowDatas) {
								// 'pacs:'를 포함하여 그 앞의 모든 문자 제거
								const selectValue = removeNamespace(groupLoutItemPath);

								for (const otherGroupLoutItemPath in targetGroupRowDatas) {
									const targetValue = removeNamespace(otherGroupLoutItemPath);

									if (targetValue == selectValue ) {
										try {
											if (grid.isSource()) {
												jsPlumbConnect(sourceGroupRowDatas[groupLoutItemPath]['id'], targetGroupRowDatas[otherGroupLoutItemPath]['id']);
											} else {
												jsPlumbConnect(targetGroupRowDatas[otherGroupLoutItemPath]['id'], sourceGroupRowDatas[groupLoutItemPath]['id']);
											}
										} catch (e) {console.error(e);}

										break;
									}
								}
							}

							//////////////////////////
						}
					},
					sep1 : "----------------",
				};
				return contextMenuItems;
			}

			$.contextMenu({
				selector : '#contextMenuDiv',
				trigger : 'none',
				build: function ($trigger, e) {
					console.debug('build');

					const grid = $('#' + $trigger.attr('gridId'));
					const rowId = $trigger.attr('rowId');
					const rowData = grid.getRowData(rowId);
					const loutItemType = rowData["loutItemType"];
					const loutItemName = rowData['loutItemName'];
					const endpointElement = grid.getEndpointElement(rowId);
					const endpoints = jsPlumbInstance.selectEndpoints({element:endpointElement});
					const positionElement = grid.getContextMenuPositionElement(rowId);

					let items;
					if (loutItemType == LAYOUT_ITEM_TYPE_GRID || loutItemType == LAYOUT_ITEM_TYPE_GROUP) {
						// group 인 경우
						items = createGridGroupContextMenuItems(grid, rowId);
					} else if(loutItemType == LAYOUT_ITEM_TYPE_FIELD || loutItemType == LAYOUT_ITEM_TYPE_ARRAY) {
						// field, array 인 경우
						items = createFieldContextMenuItems(grid, positionElement.attr('id'));
					} else {
						return false;
					}

					var options = {
						callback : function (key, options) {
						},
					};

					options.items = items;
					options.determinePosition = function ($menu) {
						if (grid.isSource()) {
							$menu.position({my: 'right top', at: 'left bottom', of: positionElement});
						} else if (grid.isTarget()) {
							$menu.position({my: 'left top', at: 'right bottom', of: positionElement});
						}
					};
					options.events = {
						show : function () {
							console.debug('show');
							isContextMenuShow = true;
						},
						hide : function () {
							console.debug('hide');
							isContextMenuShow = false;

							if (endpoints.length > 0) {
								mouseoutJqgrid(loutItemName, grid);
								mouseoutEndpoint(endpoints.get(0), 'mouseover-endpoint');
							}
						}
					}
					return options;
				}
			});

			$("#transformForEaiSvcNameCombo").change(function() {
				reloadSourceTargetGrid();
			});
			$("#btn_searchSrcLout").click(function(){
				layoutListPop("srcLayout", "srcLayoutDesc", sourceGrid);
			});
			$("#btn_searchTgtLout").click(function(){
				layoutListPop("tgtLayout", "tgtLayoutDesc", targetGrid);
			});

			$("#btn_search").click(function(){
				var key = "";
				var args = new Object();
				args['eaiSvcName'] = $('input[name=eaiSvcName]').val();
				var url=url_view; //'<c:url value="/onl/transaction/extnl/interfaceMan.view"/>';
				url = url + "?cmd=API_POPUP";				
				var ret = showModal(url,args,1020,630, function(arg){
					var args = null;
					if(arg == null || arg == undefined ) {//chrome
						args = this.dialogArguments;
						args.returnValue = this.returnValue;
					} else {//ie
						args = arg;
					}

					if( !args || !args.returnValue ) return;

					var ret = args.returnValue;
					console.log("ret",ret);
					key = ret['apiId'];

					$("input[name=eaiSvcName]").val(key);
					$("input[name=eaiSvcDesc]").val(ret['apiDesc']);
					bzwkDstCd = ret['bizCode'];

					$("input[name=eaiSvcName]").change();
				});
			});

		});

		function groupDatas(grid, rowId) {
			const groupRowIndex = grid.jqGrid("getInd", rowId);
			const gridRowDatas = grid.getRowData();
			const groupRowData = grid.getRowData(rowId);
			const groupLoutItemName = groupRowData["loutItemName"];
			const groupLoutItemPath = groupRowData['LOUTITEMPATH'];
			const groupLoutItemType = groupRowData["loutItemType"];

			console.debug(grid.getId() + " : group root lout item path : " + groupLoutItemPath);

			const index = groupLoutItemPath.indexOf(groupLoutItemName);
			const prefix = groupLoutItemPath.substring(0, index);

			const groupRowDatas = {};

			for ( var i = groupRowIndex - 1; i < gridRowDatas.length; i++) {
				const rowData = gridRowDatas[i];
				const loutItemType = rowData["loutItemType"];
				let loutItemPath = rowData['LOUTITEMPATH'];

				if (!containsIgnoreCase(loutItemPath, groupLoutItemPath)) {
					break;
				}

				if (loutItemType == LAYOUT_ITEM_TYPE_FIELD || loutItemType == LAYOUT_ITEM_TYPE_ARRAY) {
					loutItemPath = loutItemPath.replace(new RegExp("^" + prefix), "");
					console.debug(grid.getId() + " : loutItemPath : " + loutItemPath);
					rowData['GROUP_LOUTITEMPATH'] = loutItemPath;
					groupRowDatas[loutItemPath] = rowData;
				}
			}
			return groupRowDatas;
		}

		function layoutListPop(loutName, loutDesc, gridObj) {

			var key = "";
			var args = new Object();
			args['loutName'] = $('input[name=' + loutName + ']').val();
			args['selLoutName'] = loutName;
			var urlLayout = url_view;
			urlLayout = urlLayout + "?cmd=LAYOUT";

			var result = showModal(urlLayout,args,800,708, function(arg){
				var args = null;
				if(arg == null || arg == undefined ) {//chrome
					args = this.dialogArguments;
					args.returnValue = this.returnValue;
				} else {//ie
					args = arg;
				}

				if( !args || !args.returnValue ) return;

				var result = args.returnValue;

				if( result ) {
					$("input[name=" + loutName + "]").val(result.key);
					$("input[name=" + loutDesc + "]").val(result.loutDesc);

					//gridObj.setGridParam( {url :url ,postData: { cmd : 'LIST_LAYOUT_ITEM', loutName: result.key } }).trigger("reloadGrid");
					if (loutName == "srcLayout") {
						listLayoutItem(result.key, "", "");
					} else {
						listLayoutItemForTarget(result.key, "", "");
					}
				}

			});
		}

		function reloadCnvsnDesc() {
			var selectedCnvsnCode = $("#transformForEaiSvcNameCombo option:selected").val();
			var cnvsnObj = transformRows.find(function (rows) {
				return rows.CODE == selectedCnvsnCode;
			});
			if (cnvsnObj) {
				console.debug(cnvsnObj);
				$("#cnvsnDesc").val(cnvsnObj.NAME);
			}
		}

		function containsIgnoreCase(str, substr) {
			return str.toLowerCase().includes(substr.toLowerCase());
		}

		function removeNamespace(element) {
			return element.replace(/\w+:/g, "");
		}

	</script>
</head>
<body>
<div class="right_box" id="right_box">
	<div class="content_top">
		<ul class="path">
			<li><a href="#">${rmsMenuPath}</a></li>
		</ul>
	</div><!-- end content_top -->
	<div class="content_middle" id="dropArea">
		<div class="search_wrap">
			<button type="button" class="cssbtn" id="btn_delete" level="W" status="DETAIL"><i class="material-icons">delete</i> <%= localeMessage.getString("button.delete") %></button>
			<button type="button" class="cssbtn" id="btn_modify" level="W" status="DETAIL,NEW"><i class="material-icons">save</i> <%= localeMessage.getString("button.modify") %></button>
			<button type="button" class="cssbtn" id="btn_previous" level="R" status="DETAIL,NEW"><i class="material-icons">arrow_back</i> <%= localeMessage.getString("button.previous") %></button>
			<%-- 					<img src="<c:url value="/img/btn_modify.png"/>" alt="" id="btn_modify" level="W" status="DETAIL,NEW" />				 --%>
			<%-- 					<img src="<c:url value="/img/btn_previous.png"/>" alt="" id="btn_previous" level="R" status="DETAIL,NEW" />	 --%>
		</div>
		<div class="title"><%=localeMessage.getString("tran2ManDt.title")%></div>
		<input type="hidden" name="cnvsnTypeCombo">
		<table class="search_condition" cellspacing="0">
			<tr>
				<th style="width:13%; min-width:130px;"><%=localeMessage.getString("tran2ManDt.intfId")%></th>
				<td style="width:*">
					<input type="text" name="eaiSvcName" style="width:calc(100% - 220px);" readonly>
					<button type="button" class="cssbtn smallBtn2" id="btn_search" style="vertical-align:middle; font-weight:bold;" level="R"><i class="material-icons">search</i><%= localeMessage.getString("button.search") %></button>
					<input type="checkbox" name="chk_eaiSvcName" id="sub2_4_3_modify_1"><label for="sub2_4_3_modify_1"><%=localeMessage.getString("transformManDetail.ifSvcCdChk")%></label>
				</td>
				<th style="width:13%; min-width:130px;"><%=localeMessage.getString("tran2ManDt.verInfo")%></th>
				<td style="width: 30%">
					<input type="text" name="verInfo" value="0" readonly>
				</td>
			</tr>
			<tr>
				<th><%=localeMessage.getString("tran2ManDt.intfNm")%></th>
				<td>
					<input type="text" name="eaiSvcDesc" readonly="readonly">
				</td>
				<th><%=localeMessage.getString("tran2ManDt.svrClaCd")%></th>
				<td>
					<div class="select-style">
						<select id="eaiSevrDStcd" name="eaiSevrDStcd"></select>
					</div>
				</td>
			</tr>
			<tr>
				<th><%=localeMessage.getString("tran2ManDt.conRlCd")%></th>
				<td>
					<div class="select-style">
						<select id="transformForEaiSvcNameCombo" name="transformForEaiSvcNameCombo" ></select>
					</div>
				</td>
				<th><%=localeMessage.getString("tran2ManDt.useYn")%></th>
				<td >
					<div class="select-style" >
						<select id="useYn" name="useYn"></select>
					</div>
				</td>
			</tr>
			<tr>
				<th><%=localeMessage.getString("tran2ManDt.conRlDesc")%></th>
				<td>
					<input type="text" id="cnvsnDesc" name="cnvsnDesc">
				</td>
				<th><%=localeMessage.getString("tran2ManDt.defConCom")%></th>
				<td>
					<div class="select-style" >
						<select id="functionCombo" name="functionCombo"></select>
					</div>
				</td>
			</tr>
		</table>
		<!-- tree -->
		<table style="width:100%; " >
			<tr>
				<td style="width:40%; vertical-align:top;">
					<table class="table_row" cellspacing="0">
						<tr>
							<th style="width:13%; min-width:130px;"><%=localeMessage.getString("tran2ManDt.ioMsgIdBfCon")%></th>
							<td>
								<input type="text" name="srcLayout" style="width:85%" readonly="readonly" />
								<button type="button" class="cssbtn smallBtn2" id="btn_searchSrcLout" style="vertical-align:middle; font-weight:bold;" level="R"><i class="material-icons">search</i><%= localeMessage.getString("button.search") %></button>
								<input type="hidden" name="srcLoutIoId" />
							</td>
						</tr>
						<tr>
							<th><%=localeMessage.getString("tran2ManDt.ioMsgIdNmBfCon")%></th>
							<td>
								<input type="text" name="srcLayoutDesc" readonly="readonly">
							</td>
						</tr>
					</table>

					<div id="sourceGridTd" style="margin-bottom:15px;">
						<table id="sourceGrid"></table>
						<div id="sourcePage"></div>
					</div>
				</td>
				<td style="width:30%; text-align:center; vertical-align: top;">

					<br /><!-- 이 br 이 없을 때 버튼이 제대로 동작 하지 않는다. -->
					<input type=button id="removeAll" name="removeAll" class="btn_img btn_removeAll"/><br />
					<input type=button id="addAll" name="addAll" class="btn_img btn_addAll"/><br />
					<input type=button id="auto" name="auto" class="btn_img btn_auto" />
				</td>
				<td style="vertical-align:top;">
					<table class="table_row" cellspacing="0">
						<tr>
							<th style="width:13%; min-width:130px;"><%=localeMessage.getString("tran2ManDt.ioMsgIdAtCon")%></th>
							<td>
								<input type="text" name="tgtLayout" style="width:85%" readonly="readonly" >
								<button type="button" class="cssbtn smallBtn2" id="btn_searchTgtLout" style="vertical-align:middle; font-weight:bold;" level="R"><i class="material-icons">search</i><%= localeMessage.getString("button.search") %></button>
								<input type="hidden" name="tgtLoutIoId" value=""/>
							</td>
						</tr>
						<tr>
							<th><%=localeMessage.getString("tran2ManDt.ioMsgIdNmAtCon")%></th>
							<td>
								<input type="text" name="tgtLayoutDesc" readonly="readonly">
							</td>
						</tr>
					</table>
					<div id="targetGridTd" style="margin-bottom:15px;">
						<table id="targetGrid"></table>
						<div id="targetPage"></div>
					</div>
				</td>
			</tr>
		</table>

		<div id="mappingDialog" title="<%=localeMessage.getString("transformManDetail.title2")%>" >
			<input type="hidden" id="targetRowId"  name="targetRowId" />
			<input type="hidden" id="cancleCnvsnCmdName"  name="cancleCnvsnCmdName" />
			<input type="hidden" id="cancleSrcItems"  name="cancleSrcItems" />
			<table class="table_row" cellspacing="0">
				<tr>
					<th style="width:130px;">
						<%=localeMessage.getString("transformManDetail.transCmdName")%></th>
					<td>
						<div class="select-style" style="display:inline-block; width:calc((100%)*0.7);">
							<select id="functionComboDialog" name="functionComboDialog" style="width:120%;"></select>
						</div>
					</td>
				</tr>
				<tr id="addItemBeforeTr" height="80px">
					<td colspan="2"><textarea  name="CNVSNCMDNAME" style="height: 100%" ></textarea></td>
				</tr>
				<tr>
					<th><%=localeMessage.getString("transformManDetail.default")%></th><td><input type="text" name="CNVSNITEMBASCVAL"/></td>
				</tr>
				<tr height="75px">
					<th style="width:130px;"><%=localeMessage.getString("transformManDetail.tgtItemName")%></th>
					<td><textarea  name="CNVSNRSULTITEMPATHNAME" readonly="readonly"></textarea></td>
				</tr>
				<tr>
					<th><%=localeMessage.getString("transformManDetail.mappSerNo")%></th>
					<td><input type="text"  name="CNVSNITEMSERNO" readonly="readonly"/></td>
				</tr>
			</table>
		</div>
		<div id="contextMenuDiv" style="position:relative;"></div>
	</div><!-- end right_box -->
</div>
<div id="ajax_wait_modal" class="ajax_wait_modal">
</div>
</body>
</html>