-
학원 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"); } %>
'기록' 카테고리의 다른 글
학원 day65. Git (0) 2022.12.06 학원 day64. ajax (0) 2022.12.05 학원 day62. jquery 이벤트처리(2), HTML DOM 조작, ER다이어그램 (0) 2022.12.01 학원 day61. jquery 선택자, 이벤트 처리 (0) 2022.11.30 학원 day60. 부트스트랩, Jquery (0) 2022.11.29