ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 학원 day63. HTML DOM(2), AJAX
    기록 2022. 12. 2. 12:26

    엘리먼트 추가 / 삭제

    * 추가기능
    $(selector).append()  엘리먼트의 맨마지막 자식요소로 추가된다.
    $(selector).prepend()  엘리먼트의 첫번째 자식요소로 추가된다.
    $(selector).after()  엘리먼트의 동생으로(뒤에) 추가된다.
    $(selector).before()  엘리먼트의 형으로(앞에) 추가된다.
      * 추가기능도 메소드 체이닝을 이어갈 수 있다.

    * append, prepend, after, before는 text 또는 html처럼 박스 안의 전체를 변경하는게 아니라 추가하는 것이기 때문에 엘리먼트들(태그)을 작성해야 한다.

    * 삭제기능
    $(selector).remove()  엘리먼트를 삭제한다.(자식요소도 같이 삭제된다.)
    $(selector).empty()  엘리먼트는 남아있고 자식요소들만 삭제된다.
      * 삭제기능도 메소드 체이닝을 이어갈 수 있다.

    <div class="container">
       <h1>jQuery DOM</h1>
       
       <div id="box" class="border p-3 mb-3">
          <p>내용</p>
          <p>내용</p>
          <p>내용</p>
       </div>
       
       <div class="border p-2 mb-3">
          <button class="btn btn-outline-primary" id="btn-append">append</button>
          <button class="btn btn-outline-primary" id="btn-prepend">prepend</button>
          <button class="btn btn-outline-primary" id="btn-after">after</button>
          <button class="btn btn-outline-primary" id="btn-before">before</button>
          <button class="btn btn-outline-primary" id="btn-empty">empty</button>
          <button class="btn btn-outline-primary" id="btn-remove">remove</button>
       </div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() {
    	$("#btn-append").click(function() {
    		$("#box").append("<p class='text-danger'>append</p>")
    	});
    	$("#btn-prepend").click(function() {
    		$("#box").prepend("<p class='text-warning'>prepend</p>")
    	});
    	$("#btn-after").click(function() {
    		$("#box").after("<p class='text-primary'>after</p>")
    	});
    	$("#btn-before").click(function() {
    		$("#box").before("<p class='text-success'>before</p>")
    	});
    	$("#btn-empty").click(function() {
    		$("#box").empty();
    	});
    	$("#btn-remove").click(function() {
    		$("#box").remove();
    	});
    })
    
    </script>
    </body>
    </html>


    <style>
    	.btn-xs {
    		--bs-btn-padding-y: .25rem; 
    		--bs-btn-padding-x: .5rem; 
    		--bs-btn-font-size: .75rem;
    	}
    </style>
    </head>
    <body>
    <div class="container">
    	<h1>jQuery DOM</h1>
    	
    	<form class="border bg-light p-3">
    		<div class="mb-3">
    			<label class="form-label">이름</label>
    			<input type="text" class="form-control" name="name">
    		</div>
    		<div class="mb-3" id="box-career">
    			<label class="form-label">
    				경력사항 
    				<button type="button" class="btn btn-outline-primary btn-sm" id="btn-add-career-field">추가</button>
    			</label>
    			<input type="text" class="form-control mb-2" name="career">
    		</div>
    		<div class="text-end">
    			<button type="submit" class="btn btn-primary">등록</button>
    		</div>
    	</form>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
    <script>
    $(function() {
    	$("#btn-add-career-field").click(function() {
    		
    		var careerFieldLength = $("#box-career :input[name=career]").length;
    		if (careerFieldLength >= 5) {
    			alert("경력사항 입력필드는 최대 4개까지만 추가 가능합니다.");
    			return;
    		}
    		
    		var htmlContent = `
    			<div class="row ">
    				<div class="col-10">
    					<input type="text" class="form-control mb-2" name="career">
    				</div>
    				<div class="col-2 text-end pt-1">
    					<button type="button" class="btn btn-danger btn-xs">삭제</button>
    				</div>
    			</div>
    		`;
    		$("#box-career").append(htmlContent);
    	});
    	
    	// <div id="box-career"> 내부에 미래에 추가되는 삭제버튼을 클릭했을 때 실행 될 이벤트핸들러 등록하기
    	$("#box-career").on("click", '.btn-danger', function() {
    		alert("삭제하기");
    	})
    })
    </script>
    </body>
    </html>

    * 백틱(`)이란?

    키보드 탭 위, 1의 왼쪽, '~'(물결표)와 같이 있는 '와 비슷하게 생긴 문자

    백틱을 사용하면 html적듯이 사용할 수 있다.


    HTML DOM 돌아다니기

    * 현재 선택된 엘리먼트를 기준으로 다른 엘리먼트와의 관계를 활용해서 특정 엘리먼트를 검색하는 것이다.

    * 부모, 조상 검색 메소드  
    $(selector).parent()  selector로 검색된 엘리먼트의 부모 엘리먼트를 선택
    $(selector).parents()  selector로 검색된 엘리먼트의 모든 조상 엘리먼트를 선택
    $(selector1).parents(selector2)  selector1으로 검색된 엘리먼트 조상중에서 selector2에 해당하는 모든 조상 엘리먼트들 선택
    $(selector1).closest(selector2)  selector1으로 검색된 엘리먼의 조상중에서 selector2에 해당되는 가장 가까운 조상 엘리먼트 선택

    	// <div id="box-career"> 내부에 미래에 추가되는 삭제버튼을 클릭했을 때 실행 될 이벤트핸들러 등록하기
    	$("#box-career").on("click", '.btn-danger', function() {
    		// this는 클릭이벤트가 발생할 엘리먼트다.
    		// $(this) 함수의 실행결과는 this를 포함하는 jQuery객체다.
    		
    		// .closest('선택자')는 조상 엘리먼트 중에서 지정한 선택자에 해당하는 가장 가까운 조상엘리먼트가 포함된 jQuery객체를 반환한다.
    		$(this).closest('.row').remove();
    	})

    append로 추가하고, closest로 가까운 엘리먼트를 찾고, remove로 삭제한다.


    * 클래스 조작(스타일 조작)  
    $(selector).addClass(classname)  엘리먼트에 지정된 클래스를 추가한다.
    $(selector).removeClass(classname)  엘리먼트에서 지정된 클래스를 삭제한다.
    $(selector).toggleClass(classname)  엘리먼트에서 지정된 클래스를 토글시킨다.
    $(selector).hasClass(classname)  엘리먼트가 지정된 클래스를 가지고 있는지 여부를 반환한다.(true/false)

    * hasClass()기능을 제외하고 나머지는 메소드 체이닝을 이어갈 수 있다.

    * addClass(), removeClass(), toggleClass()는 클래스를 조작함으로써 그 클래스명으로 정의된 스타일이 해당 엘리먼트에 적용되게하거나, 적용된 것을 취소시키기 위해서 사용한다.

     

    체크박스의 체크 선택/해제하기

    <style>
    	.btn-xs {
    		--bs-btn-padding-y: .25rem; 
    		--bs-btn-padding-x: .5rem; 
    		--bs-btn-font-size: .75rem;
    	}
    </style>
    </head>
    <body>
    <div class="container">
    	<h1>jQuery DOM</h1>
    	
    	<div class="mb-3">
    		<table class="table">
    			<thead>
    				<tr>
    					<th><input type="checkbox" id="checkbox-all" checked/></th>
    					<th>제목</th>
    					<th>수량</th>
    					<th>가격</th>
    					<th>구매가겨</th>
    				</tr>
    			</thead>
    			<tbody>
    				<tr>
    					<td><input type="checkbox" name="bookNo" value="10" checked /></td>
    					<td>이것이 자바다</td>
    					<td>1 권</td>
    					<td>35,000 원</td>
    					<td>35,000 원</td>
    				</tr>
    				<tr>
    					<td><input type="checkbox" name="bookNo" value="12" checked /></td>
    					<td>자바의 정석</td>
    					<td>1 권</td>
    					<td>30,000 원</td>
    					<td>30,000 원</td>
    				</tr>
    				<tr>
    					<td><input type="checkbox" name="bookNo" value="14" checked /></td>
    					<td>혼자서 공부하는 자바</td>
    					<td>1 권</td>
    					<td>32,000 원</td>
    					<td>32,000 원</td>
    				</tr>
    			</tbody>
    		</table>
    		<div class="mb-3 d-flex justify-content-between">
    			<span>
    				<a href="" class="btn btn-secondary btn-xs" id="btn-delete-all">전체삭제</a>
    				<a href="" class="btn btn-secondary btn-xs" id="btn-delete-selected">선택삭제</a>
    			</span>
    			<span>
    				<a href="" class="btn btn-outline-primary btn-xs" id="btn-order-all">전체주문</a>
    				<a href="" class="btn btn-outline-primary btn-xs" id="btn-order-selected">선택주문</a>
    			</span>
    		</div>
    	</div>
    </div>
    
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() {
    	$("#checkbox-all").change(function(){
    		// 전체선택 체크박스의 체크여부를 조회한다.
    		var checkboxAllChecked = $(this).prop("checked");
    		// 각 도서들의 체크박스의 체크여부를 전체선택 체크박스의 체크여부와 같은 상태로 변경한다.
    		$(":checkbox[name=bookNo]").prop('checked', checkboxAllChecked);
    		
    		toggleSelectedButton();
    	});
    	
    	$(":checkbox[name=bookNo]").change(function(){
    		toggleCheckboxAll();
    		toggleSelectedButton();
    	});
    	
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////	
    	
    	function toggleCheckboxAll() {
    		// 도서 체크박스 갯수 조회하기
    		var checkboxLength = $(":checkbox[name=bookNo]").length;
    		// 도서 체크박스 중에서 체크된 갯수 조회하기
    		var checkedCheckboxLength = $(":checkbox[name=bookNo]:checked").length;
    		
    		// 도서 체크박스의 갯수와 체크된 갯수가 일치하면 전체 선택 체크박스를 체크상태로 변경한다.
    		/*
    		if (checkboxLength == checkedCheckboxLength) {
    			$("#checkbox-all").prop("checked", true);
    		} else {
    			$("#checkbox-all").prop("checked", false);
    		}
    		*/
    		
    		$("#checkbox-all").prop("checked", checkboxLength == checkedCheckboxLength);
    	}
    	
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
    	
    	function toggleSelectedButton(){
    		// 도서 체크박스 중에서 체크된 갯수 조회하기
    		var checkedCheckboxLength = $(":checkbox[name=bookNo]:checked").length;
    		
    		// 선택삭제버튼과 선택주문버튼을 포함하는 jQuery객체를 조회한다.		
    		var btnDeleteSelected = $("#btn-delete-selected");
    		var btnOrderSelected = $("#btn-order-selected");
    		
    		// 체크된 체크박스 0개일 때 선택삭제버튼과 선택주문버튼에 disabled 클래스를 추가한다.
    		//
    		
    		if (checkedCheckboxLength == 0) {
    			btnDeleteSelected.addClass("disabled");
    			btnOrderSelected.addClass("disabled");
    		} else {
    			btnDeleteSelected.removeClass("disabled");
    			btnOrderSelected.removeClass("disabled");
    		}
    		
    	}
    })
    </script>
    </body>
    </html>

    var $btnDeleteSelected = $("#btn-delete-selected");

     

    이제부터 var btnDeleteSelected가 제이쿼리 객체임을 나타내기 위해서 변수이름 앞에 $를 적는다.

    jQuery 객체가 들어있는 변수라고 생각하면 된다.


    자바스크립트와 제이쿼리의 차이 

    패러다임이 달라짐. 비침투적 코딩을 제이쿼리는 원함. html코드에 자바스크립트 코드가 없도록 함.


    $ 함수 안에 적지 않으면 화면이 출력 완료된 이후에야 실행이 되고,

    $ 함수 안에 적으면 화면에 출력되기 전에 실행이 된다.


    <div class="container">
    	<h1>jQuery DOM</h1>
    	
    	<div class="mb-3">
    		<button class="btn btn-primary" id="btn-target">버튼</button>
    	</div>
    	
    	<div class="mb-3">
    		<button class="btn btn-outline-primary" id="btn-add">클래스 추가</button>
    		<button class="btn btn-outline-primary" id="btn-remove">클래스 삭제</button>
    		<button class="btn btn-outline-primary" id="btn-toggle">클래스 토글</button>
    		<button class="btn btn-outline-primary" id="btn-has">클래스 포함여부 확인</button>
    	</div>
    	
    	<div class="mb-3">
    		<a href="" class="text-decoration-none text-dark" id="btn-toggle-display">[보기]</a>
    	</div>
    	
    	<div class="mb-3 d-none" id="target-collapse">
    		<h3>메뉴</h3>
    		<ul>
    			<li>커피</li>
    			<li>커피</li>
    			<li>커피</li>
    			<li>커피</li>
    		</ul>
    	</div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() {
    	var $targetButton = $("#btn-target");
    	var $targetCollapse = $("#target-collapse");
    	
    	$("#btn-toggle-display").click(function(event) {
    		event.preventDefault();
    		$targetCollapse.toggleClass("d-none");
    
    		if ($targetCollapse.hasClass("d-none")) {
    			$(this).text("[보기]");
    		} else {
    			$(this).text("[감추기]")
    		}
    	});
    	
    	$("#btn-add").click(function() {
    		$targetButton.addClass("btn-lg");
    	});
    	
    	$("#btn-remove").click(function() {
    		$targetButton.removeClass("btn-lg");
    	});
    	
    	$("#btn-toggle").click(function() {
    		$targetButton.toggleClass("disabled");
    	});
    	
    	$("#btn-has").click(function() {
    		// boolean 값을 반환한다. 지정된 클래스를 포함하고 있으면 true를 반환한다.
    		var isDisabled = $targetButton.hasClass('disabled');
    		alert(isDisabled);
    	});
    })
    </script>
    </body>
    </html>


    * 자식, 자손 검색 메소드
    $(selector).children()  selector의 검색된 엘리먼트의 모든 자식 엘리먼트를 선택
    $(selector1).find(selector2)  selector1으로 검색된 엘리먼트의 후손 엘리먼트 중에서 selector2에 해당하는 모든 후손 엘리먼트 선택
    * 형제 검색 메소드
    $(selector).prev()  selector로 검색된 엘리먼트의 바로 윗 형 엘리먼트 선택
    $(selector).prevAll()  selector로 검색된 엘리먼트의 모든 형 엘리먼트들 선택
    $(selector).next()  selector로 검색된 엘리먼트의 바로 아래 동생 엘리먼트 선택
    $(selector).nextAll()  selector로 검색된 엘리먼트의 모든 동생 엘리먼트들 선택
    $(selector).siblings()  selector로 검색된 엘리먼트의 모든 형제 엘리먼트들 선택

     

    * 응용 : 만약, Select에서 Link를 찾고 싶다면 ? 

       $("select").parent().parent().find("link"); 

     

    open API 사용해서 데이터를 파싱할 때 find를 많이 사용한다.

     

    <div class="container">
    	<h1>jQuery DOM</h1>
    	
    	<div class="mb-3 border p-3">
    		<h3>연습</h3>
    		<p>첫번째</p>
    		<p id="selected-p">두번째</p>
    		<p>세번째</p>
    		<p>네번째</p>
    	</div>
    	
    	<div class="mb-3 p-3">
    		<div class="row border mb-3 p-3">
    			<div class="col border">1-1</div>
    			<div class="col border">1-2</div>
    			<div class="col border">1-3</div>
    		</div>
    		<div class="row border mb-3 p-3">
    			<div class="col border">2-1</div>
    			<div class="col border">2-2</div>
    			<div class="col border">2-3</div>
    		</div>
    		<div class="row border mb-3 p-3">
    			<div class="col border">3-1</div>
    			<div class="col border">3-2</div>
    			<div class="col border">3-3</div>
    		</div>
    	</div>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() { 
    	
    	// 선택된 엘리먼트의 바로 앞에 있는 엘리먼트가 포함된 jQuery객체를 반환한다.
    	$("#selected-p").prev().addClass("fw-bold text-danger");
    	// 선택된 엘리먼트의 앞에 있는 모든 엘리먼트가 포함된 jQuery객체를 반환한다.
    	$("#selected-p").prevAll().addClass("border border-danger");
    	// 선택된 엘리먼트의 바로 다음에 있는 엘리먼트가 포함된 jQuery객체를 반환한다.
    	$("#selected-p").next().addClass("fw-bold text-primary");
    	// 선택된 엘리먼트의 다음에 있는 모든 엘리먼트가 포함된 jQuery객체를 반환한다.
    	$("#selected-p").nextAll().addClass("border border-primary");
    	// 선택된 엘리먼트의 모든 형제 엘리먼트가 포함된 jQuery객체를 반환한다.
    	$("#selected-p").siblings().addClass("bg-secondary");
    	
    	//".row"로 선택된 엘리먼트 중에서 ":first"에 해당하는 엘리먼트를 선택한다.
    	// 따라서, <div class="row"></div> 중에서 첫번째 엘리먼트가 선택됨
    	$(".row").filter(":first").addClass('bg-warning');
    	
    	// ".row"로 선택된 엘리먼트의 자손 엘리먼트 중에서 ":first"에 해당하는 엘리먼트를 선택한다.
    	// 따라서, <div class="col">1-1</div>, <div class="col">2-1</div>, <div class="col">3-1</div> 이 선택됨 
    	//
    	$(".row").find(":first").addClass('bg-danger')
    })
    </script>
    </body>
    </html>

     

    * 주의해야 할 점은 형제검색 메소드를 사용할 때 형제는 같은 부모 아래에 있는 것들이라는 점이다. 4촌관계는 형제 x


     

    일반적인 HTTP 동작 방식 - 브라우저가 서버에 요청

     

     

    AJAX 기술을 활용한 XHR과 서버의 통신 방식

    지도는 브라우저가 아닌 active x가 서버에 요청하는 방식을 사용했다.

     

    자바스크립트는 화면이 가만히 있는 상태에서 화면을 조작할 수 있다. 

    자바스크립트 안에 XHR이라는 객체가 있다. 

    XHR이라는 객체는 이벤트가 발생할 때마다 만들어진다.

     

    XHR은 서버한테 http요청을 보낼 수 있다. 요청에 대한 응답 또한 XHR이 받을 수 있다.

    그런데 HTML문서가 아닌 데이터가 온다. 

    응답데이터로 html tag를 생성한다. 그리고 화면에 반영한다. 

    브라우저가 요청한 것이 아니기 때문에 화면이 갱신되지 않는다.

    XHR이라는 객체의 도움을 받아서 화면의 갱신없이 서버랑 통신할 수 있게 되었다. => Ajax 기술

     

    화면이 사라지지 않기 때문에 응답이 오기전에 이벤트를 발생시킬 수 있다.

    추천 검색어 기능, 아이디 작성할 때 사용가능한 아이디인지 사용불가능한 아이디인지 알려주는 기능, 카테고리 선택 기능 등에 쓰인다.

     

    Ajax(Asynchronous JavaScript and XML)

    - 자바스크립트와 XML(JSON)을 활용한 서버와의 비동기 데이터 통신

    - XMLHttpRequest 객체를 활용해서 서버와 데이터 통신을 한다. (다양한 라이브러리가 있어서 XMLHttpRequest를 직접적으로 사용하지는 않는다.)

     

    특징

    - 자바스크립트로 서버와 데이터통신이 가능해졌다. 

    - 페이지의 리로딩없이 화면의 일부분을 갱신하는게 가능해졌다. (서버로부터 데이터를 가져와서)

     

    대표적인 기능

    - 구글 맵

    - 포털사이트 검색기능

    - 대분류의 하위분류를 조회하는 기능

     

    sample19-ajax.jsp

    <div class="container">
    	<h1>jQuery ajax</h1>
    	
    	<form method="post" action="register.jsp" class="border bg-light p-3">
    		<div class="mb-3">
    			<label class="form-label">아이디</label>
    			<input type="text" class="form-control" name="id" /> 
    			<div class="form-text" id="id-help-block">아이디는 3글자 이상 입력하세요.</div>
    		</div>
    		<div class="mb-3">
    			<label class="form-label">비밀번호</label>
    			<input type="password" class="form-control" name="pwd" /> 
    		</div>
    		<div class="mb-3">
    			<label class="form-label">이름</label>
    			<input type="text" class="form-control" name="name" /> 
    		</div>
    		<div class="text-end">
    			<button type="submit" class="btn btn-primary btn-sm">등록</button>
    		</div>
    	</form>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() {
    	var $idHelpBlock = $("#id-help-block");
    	
    	$(":input[name=id]").keyup(function() {
    		var inputedUserId = $(this).val();
    		// 입력한 아이디가 3글자 이하면 에러메세지를 표시한다.
    		if (inputedUserId.length <= 3) {
    			$idHelpBlock.addClass('text-danger').text("아이디를 3글자이상 입력하세요.");
    			return;
    		}
    		
    		// 입력한 아이디가 4글자 이상이면 서버로 보내서 아이디 존재여부를 확인하는 요청을 보낸다.
    		$.get("sample19-response.jsp", {userId: inputedUserId}, function(responseData) {
    			$idHelpBlock.removeClass('text-success text-danger');	
    			
    			if (responseData === 'exist') {
    				$idHelpBlock.addClass('text-danger').text("이미 사용중인 아이디입니다.");
    			} else if (responseData === 'notExist'){
    				$idHelpBlock.addClass('text-success').text("사용가능한 아이디입니다.");
    			}
    		});
    	});
    })
    </script>
    </body>
    </html>

    $.get(url, {name:value, name:value}, 콜백함수);
         - url : 요청URL, ajax 요청을 처리하는 jsp의 경로
         - data : jsp로 보내는 요청파라미터 정보
                쿼리스트링 형식
                        "name=value&name=value"
                 자바스크립트 객체 형식
                        {name:value, name:value, name:value}
    - 콜백함수 : 성공적인 응답이 오면 실행되는 함수다. 
        function(responseData) { ... }
                 *responseData는 서버에 응답으로 보내는 데이터다.
                 *responseData는 Text, JSON, XML, HTML 등 다양한 형식이 가능하다.

     

    sample19-response.jsp

    <%@page import="java.util.Set"%>
    <%@ page language="java" contentType="text/plain; charset=UTF-8"
        pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
    <%
    	Set<String> userIds = Set.of("hong", "hong1", "hong12", "hong123", "kim", "kim1", "kim12", "kim123",
    		"kang", "kang1", "kang12", "kang123", "lee", "lee1", "lee12", "lee2", "lee123", "hong2", "kim2",
    		"hong3", "kim3", "king2", "kang3");
    
    	String userId = request.getParameter("userId");
    	
    	if (userIds.contains(userId)) {
    		out.write("exist");	
    	} else {
    		out.write("notExist");
    	}	
    %>

    댓글

Designed by Tistory.