https://developer.mozilla.org/ko/docs/Web/API/Document/visibilityState#%EB%AA%85%EC%84%B8%EC%84%9C

 

Document.visibilityState - Web API | MDN

Document.visibilityState 읽기 전용 property로, 이 element가 현재 표시된 컨텍스트를 나타내는 document의 가시성을 반환합니다. document가 background 또는 보이지 않는 탭(다른 탭)에 있는지, 또는 pre-rendering을

developer.mozilla.org

document.addEventListener("visibilitychange", () => {
  console.log(document.visibilityState);
  // 기타 동작...
});

위 이벤트를 이용해서 브라우저가 "hidden" or "visible" 되었는지 확인 가능 (상태가 변경될때마다 감지된다)

 

포커스로 확인하는 코드는 아래와 같다.

window.addEventListener('focus', function() {
    console.log('사용자가 웹페이지에 돌아왔습니다.')
}, false);​

 

ajax 처리를 위해 코드를 작성하였는데 아래와 같은 에러 코드가 발생하였다.

$.ajax({
    url:"/login/login",
    type:"POST",
    data:JSON.stringify(params),
    contentType: "application/json",
    success: function(result) {
        if (result) {
            alert("저장되었습니다.");
        } else {
            alert("잠시 후에 시도해주세요.");
        }
    },
    error: function() {
        alert("에러 발생");
    }
})

 

 

원인: jquery 선언을 위에 안해주었기 때문에 발생

 

jquery cdn을 검색하여 코드에 추가해준다.

https://releases.jquery.com/

 

jQuery CDN

The integrity and crossorigin attributes are used for Subresource Integrity (SRI) checking. This allows browsers to ensure that resources hosted on third-party servers have not been tampered with. Use of SRI is recommended as a best-practice, whenever libr

releases.jquery.com

추가 후 에러가 발생하지 않는다.

입력란 생성

<td class="last">
<span class="td_type06"><input type="text" name="from_date" value="${baseMap.from_date }" class="date" onkeyup="enterkey()"/></span>
~
<span class="td_type06"><input type="text" name="to_date" value="${baseMap.to_date }" class="date" onkeyup="enterkey()"/></span>
</td>

 

초기화 버튼 및  한글 표시, 해당 input type 속성을 readonly로 설정하기 위해 브라우저를 실행하자 마자 아래 코드 동작

$(function() {

	window.onload = function cleanDatepicker(){
		//alert('aaaa');
        // clear 버튼 생성
	     var old_fn = $.datepicker._updateDatepicker;

		 $.datepicker._updateDatepicker = function(inst) {
		   old_fn.call(this, inst);

		   var buttonPane = $(this).datepicker("widget").find(".ui-datepicker-buttonpane");

		   $("<button type='button' class='ui-datepicker-clean ui-state-default ui-priority-primary ui-corner-all'>clear</button>").appendTo(buttonPane).click(function(ev) {
		    $.datepicker._clearDate(inst.input);
		   }) ;
		}
		
        // 한글 표시
		$.datepicker.setDefaults({
		        dateFormat: 'yymmdd',
		        prevText: '이전 달',
		        nextText: '다음 달',
		        monthNames: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
		        monthNamesShort: ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월'],
		        dayNames: ['일', '월', '화', '수', '목', '금', '토'],
		        dayNamesShort: ['일', '월', '화', '수', '목', '금', '토'],
		        dayNamesMin: ['일', '월', '화', '수', '목', '금', '토'],
		        showMonthAfterYear: true,
		        yearSuffix: '년'
		});
		
        // 읽기 전용으로 변환
		$(".date").attr("readonly",true);

	}
    
    // input에 datepicker 적용
    $(".date").datepicker({
		dateFormat: 'yy-mm-dd',
		showButtonPanel: true
	});
}

 

HTML의 각 태그 데이터를 선택자를 이용하여 변수에 담은 후 배열에 저장한다.

그 후 ajax를 통해 배열 데이터를 전송

function order(flag) {
		var isAdmin = <c:out value="${isMasterAdmin }" />;
		var url = "/dit/apps/array123.nr";
		var num_check=/^[0-9]*$/;
		var data = new Object();
		var rowData = new Array(); 
	    var tdArr = new Array();
	    var checkbox = $("input[name=select]:checked");
	    
	    // 인수확인버튼 클릭할때에만 메일번호 생성
	   /* if(flag == "a2"){
	    	var mailNum = get_MailNum();
	    }*/
	    
	    //alert('메일번호: ' + mailNum)
//	    alert('checkbox: ' + checkbox);
	 // 체크된 체크박스 값을 가져온다
	    checkbox.each(function(i) {
	    	//alert('aaa: ' + i);
		    // checkbox.parent() : checkbox의 부모는 <td>이다.
		    // checkbox.parent().parent() : <td>의 부모이므로 <tr>이다.
		    var tr = checkbox.parent().parent().eq(i);
		    var td = tr.children();
		                
		    // 체크된 row의 모든 값을 배열에 담는다.
		    rowData.push(tr.text());
		                
		    // td.eq(0)은 체크박스 이므로  td.eq(1)의 값부터 가져온다.
		    var req_id = td.eq(1).text();
		    var vendor_id = td.eq(2).text();
		    var company_reg_no = td.eq(3).text();		    
		    var req_num = td.eq(4).text();
		    var company_name = td.eq(5).text();
		    var item_id = td.eq(6).text();
		    var item_desc = td.eq(7).text();
		    var req_quantity = td.eq(8).text();
		    var ship_method = td.eq(9).find('input[type="text"]').val();
		    var ship_quantity = td.eq(10).find('input[type="number"]').val();
		    var take_quantity = td.eq(11).find('input[type="number"]').val();
		    var req_date = td.eq(12).text();
		    var take_check = td.eq(13).text();
		    var status_ori = td.eq(14).text();
		    var status = td.eq(14).text();
		    
		    if (status == '작성중'){
		    	status = "01";	
		    } else if (status == '주문'){
		    	status = "02";	
		    } else if (status == '발송'){
		    	status = "03";	
		    } else if (status == '인수확인'){
		    	status = "04";	
		    } else if (status == '취소'){
		    	status = "05";	
		    } else if (status == '최종확인'){
		    	status = "06";	
		    }
		    
		    if (flag == "a0"){
		    	status = "02";	
		    } else if(flag == "a1"){
		    	status = "03";	
		    } else if (flag == "a2") {
		    	take_check = "Y";	
		    	status = "04";	
		    } else if (flag == "a3") {
		    	take_check = "C";	
		    	status = "05";	
		    } else if (flag == "a4") {
		    	take_check = "Y";	
		    	status = "06";	
		    }
		    
		    
		                
		    // 가져온 값을 배열에 담는다.
		    var allData = {"req_num": req_num, "company_name" : company_name, "item_id" : item_id
		    		      ,"item_desc" : item_desc, "req_quantity" : req_quantity, "ship_method" : ship_method
		    		      ,"ship_quantity" : ship_quantity, "take_quantity" : take_quantity, "req_date" : req_date
		    		      ,"take_check" : take_check, "status" : status, "req_id": req_id, "vendor_id": vendor_id, "company_reg_no": company_reg_no
		    		      ,"attribute2": '11'};
		    

		    if(td.eq(1).text() != '요청번호'){
			    // 관리자일 경우 어떤상태에서든지 이벤트 가능
			    if(isAdmin){
			    	
					$.ajax({
						 type: 'post'
					    ,data: allData
					    ,url: url
					    ,dataType: "json"
						,async: false
						,success: function(data, status){
						   num = data;
						}
					});
			    // 관리자가 아니면 발송버튼은 주문상태에서만, 확인버튼은 발송상태에서만 가능
			    } else {
			    	// 주문버튼 -> 주문
			    	if(flag == "a0"){
					    if(status_ori == "작성중"){
					    		
						    $.ajax({
								type: 'post'
							   ,data: allData
							   ,url: url
							   ,dataType: "json"
							   ,async: false
							   ,success: function(data, status){
								   num = data;
							   }
							});
					    } else {
					    	alert("요청번호: " + req_num + "은 진행상태가 작성중상태가 아닙니다.");
					    }
					 // 발송버튼 -> 발송    
					}else if(flag == "a1"){
					    if(status_ori == "주문"){
					    		
						    $.ajax({
								type: 'post'
							   ,data: allData
							   ,url: url
							   ,dataType: "json"
							   ,async: false
							   ,success: function(data, status){
								   num = data;
							   }
							});
					    } else {
					    	alert("요청번호: " + req_num + "은 진행상태가 주문상태가 아닙니다.");
					    }
					 // 인수버튼 -> 인수확인    
					}else if(flag == "a2"){
					   	if(status_ori == "발송"){
					    		
							 $.ajax({
								type: 'post'
							   ,data: allData
							   ,url: url
							   ,dataType: "json"
							   ,async: false
							   ,success: function(data, status){
								   num = data;
							   }
							});
					    }else{
					    	alert("요청번호: " + req_num + "은 진행상태가 발송상태가 아닙니다.");
					    }
					 // 취소버튼 -> 취소
					}else if(flag == "a3"){
					   	
				    	// 취소상태는 언제든 취소가능	
						$.ajax({
							type: 'post'
						   ,data: allData
						   ,url: url
						   ,dataType: "json"
						   ,async: false
						   ,success: function(data, status){
						       num = data;
						   }
					    });
					// 발송버튼 -> 최종확인  
			       }else if(flag == "a4"){
					   	if(status_ori == "인수확인"){
				    		
							 $.ajax({
								type: 'post'
							   ,data: allData
							   ,url: url
							   ,dataType: "json"
							   ,async: false
							   ,success: function(data, status){
								   num = data;
							   }
							});
					    }else{
					    	alert("요청번호: " + req_num + "은 진행상태가 인수확인상태가 아닙니다.");
					    }
			       }

		    }
	    
		    }
		    
	    });
	 /*
	   if(flag == "a2") {
		   url = "/dit/apps/ReqMat/mail.nr";
		   var TakeMailData = {"key": mailNum, "flag": flag};
		   $.ajax({
				 type: 'post'
			    ,data: TakeMailData
			    ,url: url
			    ,dataType: "json"
				,async: false
				,success: function(data, status){
				   num = data;
				}
			});   
	   } 
	 */
	   movePage(); /* 재조회 */
	 
	}

 

controller에서 VO객체를 이용하여 배열로 전송된 데이터를 받는다.

@SuppressWarnings({ "rawtypes", "unchecked" })
		@RequestMapping(value = "/dit/apps/array123.nr")
		@ResponseBody
		public void ProductMail(HttpServletRequest request, Model model, ReqMaterialVO vo) throws Exception {
			logger.debug("## 체크리스트");
			LoginoutUserEntity userInfo = SessionManager.getLoginoutUser(request);
			logger.debug(userInfo.getUserLoginID());
			//QueryCondition qc = new QueryCondition(param);
			//logger.debug((String) param.get("allData"));
			//logger.debug("no: " + no);
			logger.debug(vo.getReq_id());
			logger.debug(vo.getReq_num());
			logger.debug(vo.getItem_desc());
			logger.debug(vo.getShip_method());
			logger.debug(vo.getShip_quantity());
			logger.debug(vo.getAttribute2()); // 메일 묶음 키 값
			logger.debug(vo.toString());
			vo.setCreated_by(userInfo.getUserLoginID());
			vo.setLast_updated_by(userInfo.getUserLoginID());
			logger.debug("최종: " + vo.toString());
			//vo.setStatus("03"); // 발송상태로 변경
			int result = 0;
			result = materialService.reqMaterialUpdate(vo);
			
			// 메일 전송을 위해 데이터 저장
			materialService.reqMaterialMail(vo);
			
			//logger.debug("arrayParams: " + arrayParams);
			//Object a = param.get("data");
			//System.out.println("aaa: " + a.toString());
			//List<Map<String, Object>> list = new ArrayList();
			//list.addAll("data",(String)param.get("data"));
			//logger.debug(list.get(0).toString());
			
		}

 

참고 사이트

https://itkjspo56.tistory.com/181

 

[Java] Array 배열 Controller VO로 받기 파싱

자바를 이용하면서 MVC패턴을 통해 Controller에서 데이터를 주고받는일이 있다. 기존 JSP에서는 제목 ${testVO.title} 내용 ${testVO.content} 이름 ${testVO.name} 번호 ${testVO.bno} 이러한 형태로 데이터를..

itkjspo56.tistory.com

 

VO방식 말고도 map으로 받는 방법도 있는것으로 보인다.

https://yulfsong.tistory.com/76

 

Ajax data를 Controller에서 받는 두 가지 방법 : Vo / Map

Ajax의 data를 Controller에서 받아야할 때가 자주 있는데 Vo를 만들어서 받는 방법이 있고 Map을 이용하는 방법이 있다. 1. Vo로 받는 방법 var memberId = $("#memberId").val(); var memberPass = $("#memberPa..

yulfsong.tistory.com

 

ajax를 사용할 함수 생성

async속성을 false로 주는것이 중요

function MAIL_NUM(){
		var num;
		
		$.ajax({
			type: 'post'
		   ,url: "/???/???/mailnum.nr"
		   ,dataType: "text"
		   ,async: false
		   ,success: function(data, status){
			   num = data;
		   }
		});
		return num;
	}

 

서버쪽 코드 작성

ResponseBody 어노테이션을 적용해주는것이 중요!!

	@RequestMapping(value = "/???/???/mailnum.nr")
	@ResponseBody
	public Integer ProductMail(HttpServletRequest request, @RequestParam Map param, Model model) throws Exception {
		Integer mail_num = 5;
		mail_num = productService.mail_num();
		logger.debug("## ts_num: " + mail_num);
		return mail_num;
	}

 

참고

 

https://webdevtechblog.com/reqeustbody%EC%99%80-responsebody-%EC%96%B8%EC%A0%9C-%EC%82%AC%EC%9A%A9%ED%95%A0%EA%B9%8C-2efcab364edb

 

@ReqeustBody와 @ResponseBody 언제 사용할까?

비동기 통신을 위한 어노테이션

webdevtechblog.com

 

<script>
$(function() {
	// 행추가
	$("#btnAddRow").on("click", function() {
		addRow();
		return false;
	});
	
	<%-- 행추가 --%>
	function addRow() {
		var html = "";
		html += '<tr>';
		html += '<td><input type="text" name="name1"  value="" maxlength="15" /></td>';
		html += '<td><input type="text" name="name2"  value="" maxlength="15" /></td>';
		html += '<td><input type="text" name="name3"  value="" maxlength="15" /></td>';
		html += '<td><input type="text" name="name4"  value="" maxlength="15" /></td>';
		html += '<td><input type="text" name="name5"  value="" maxlength="15" /></td>';
		html += '<td><input type="text" name="name6" value="" maxlength="6" /></td>';
		html += '<td class="last"><a id="btnRemoverow" href=""><img src="${pageContext.request.contextPath}/img/icon/minus_icon.gif" /></a></td>';
		html += '</tr/>';
		$("#row_table tbody").append(html);
		return false;
	}
    
    // 행 삭제
	$("#row_table").on("click", "a[id=btnRemoverow]", function() {
		$(this).closest("tr").remove();
		return false;
	});
 })
 </script>

 

<body style="padding:0; margin:0;">
<form id="form1" name="form1" method="post">

	<div class="popup_wrap_">
		<h2 class="pop_title">행추가</h2>
		<!--행추가 St-->
		<table cellpadding="0" cellspacing="0" border="0" width="100%" summary="행추가" class="pop_table" id = "row_table">
			<caption>행추가</caption>
			<colgroup>
				<col style="width:10%">
				<col style="width:10%">
				<col style="width:10%">
				<col style="width:10%">
				<col style="width:10%">
				<col style="width:10%">
				<col style="width:5%">
			</colgroup>
			<tbody>				
				<tr>
					<th>1</th>
					<th>2</th>
					<th>3</th>
					<th>4</th>
					<th>5</th>
					<th>6</th>
					<th>7</th>
				</tr>
				<tr>
					<c:forEach items="${listRow}" var="listRow" varStatus="status">
						<td><input type="text" name="AUTH_CODE"  value="" maxlength="15" /></td>
						<td><input type="text" name="AUTH_TEXT"  value="" maxlength="20" /></td>
						<td><input type="text" name="AUTH_TEXT"  value="" maxlength="20" /></td>
						<td><input type="text" name="AUTH_TEXT"  value="" maxlength="20" /></td>
						<td><input type="text" name="AUTH_TEXT"  value="" maxlength="20" /></td>
						<td><input type="text" name="AUTH_TEXT"  value="" maxlength="20" /></td>
						<td>
							
						</td>
					</c:forEach>
				</tr>				
			 </tbody>
		</table>
		<!--행추가 En-->
		
		<!--버튼 St-->
		<a href="#" id="btnAddRow"><img src="${pageContext.request.contextPath}/img/icon/plus_icon.gif" /></a>
		<div class="btn_wrap">
			<a href="#" id="btnAdd" class="" ><span class="save_btn">저장</span></a>
		</div>
		<!--버튼 En-->

	</div>

</form>
</body>

히든데이터를 함께 보내줘야할경우에는 td 안에 추가해주고

자바스크립트로 행추가하는 함수에도 td 안에 input type="hidden"으로 넣어주어야 한다.

그래야 배열로 컨트롤러에서 받아서 처리가 가능하다.

+ Recent posts