728x90

$('h1,h3').next().hide();

h1태그와 h3 태그 다음 형제 노드인 div 태그를 숨긴다.

$('h1,h3').click(function(e){
      //$(e.target).next().toggle(500);
      $(e.target).next().fadeToggle(1000);
    });

클릭하면 div가 fadeToggle 천천히 생성된다. 

h1을 클릭했기 때문에 h1의 div의 자식인 h3가 생성되고 h3를 다시 클릭하면 h3의 div가 생성된다.

$('#logo').click(function(){
      $('#logo').animate({width:'50%',heigth:'50%'},2000);
      $('#logo').animate({width:'10%',heigth:'10%'},1900);
      $('#logo').animate({width:'300%',heigth:'300%'},400);
      $('#logo').animate({width:'100%',heigth:'100%'},400);
    });

.animate()

animate는 properties를 받는데 properties는 object이다. 

>> 

.animate({

property:value,

property:value

},duration, complete(){...})

 

 

 $(function () {
            // animate() 메서드를 사용합니다.
            $('div').animate({ left: '+=60' }, 2000);
            $('div').animate({ width: '+=60' }, 2000);
            $('div').animate({ height: '+=60' }, 2000);

            // 3초 후에 함수를 실행합니다.
           
            setTimeout(function () {
                // 애니메이션 큐를 제거합니다.
                $('div').clearQueue();
                // 효과 메서드를 사용합니다.
                $('div').hide();
            }, 3000);
        });

 

 

setTimeout(실행할 함수, 시간 설정)

 

clearQueue() 애니메이션 큐를 제거 (진행중인 애니메이션이 있다면 정지되고 큐도 제거된다.)

 

delay(ms).animate() ms초 후 실행 

 

$('.circle').approach({
                opacity: 0.2
            }, 200);

 접근할때 투명도 변경

 

 

$(document).ready(function () {
            $('div').hover(function () {
                $(this).addClass('reverse', 1000);
            }, function () {
                $(this).removeClass('reverse', 1000);
            });
        });

마우스가 위에 올라오면 .addClass('reverse',1000); 'reverse'클래스를 생성해주고 

'reverse'클래스가 생성되면 style에 설정된 코드에 따라 색상이 바뀌고 removeClass 함수가 실행되면 사라지면서 원래색상으로 돌아온다.

.reverse {
            color:White;
            background-color:gray;
        }

여기서 hover(function, function) 두개 함수가 인자로 들어갔는데

첫번째 함수는 hover 되었을때 실행되고 두번째함수는 hover out 되었을때 실행되는 함수이다.

 

'Javascript' 카테고리의 다른 글

JQuery event  (0) 2023.09.23
Javascript this  (0) 2023.09.23
JQuery 입문  (1) 2023.09.22
JQuery 이해하기  (0) 2023.09.22
Javascript defer  (0) 2023.09.21
728x90

JQuery 사용하기 

https://developers.google.com/speed/libraries#jquery

 

호스팅된 라이브러리  |  Hosted Libraries  |  Google for Developers

인기 있는 오픈소스 자바스크립트 라이브러리에 대해 Google에서 호스팅하는 콘텐츠 배포 네트워크에 포함된 라이브러리 목록을 가져옵니다.

developers.google.com

JQuery 사이트의 다운로드에서 Google CDN 링크 

JQuery의 3.x snippet의 

<script>태그를 복사해서 html의 head에 붙여준다.

jQuery()       [$()]

jQuery()는 팩토리 함수로 작업할 객체를 Wrapper객체로 만들어주는 공장의 역할을 한다. 

jQueryWrapper객체가 되면 다양한 프로퍼티를 다룰 수 있게 된다. 

jQuery() 대신 $() 를 사용할 수도 있다. 

$('h1').css('color','blue').text('바꿈');

$('h1')으로 h1태그 객체들을 Wrapper객체로 반환해주고 

css()함수로 Wrapper객체들의 css를 변경해주고 다시 반환해준다. 

반환받은 객체는 다시 text() 함수로 text가 변경되고 wrapper객체가 반환된다. 

jQuery는 기본적으로 factory 함수로 대부분 wrapper객체를 반환해주기 때문에 체이닝 코딩이 가능하다.

 

jQuery는 string(css selector, <tag>), object(DOM node), function을 인자로 받을 수 있다. 

 

대부분의 작업은 돔트리가 생성되어야 시작할 수 있는 작업이므로 

$(function(){

onload 이후 실행할 코드 

});

onload에 등록된 함수안에서 기술한다. 

$(function(){...});

 

let h2Text = $('h2').text();//get은 모든 텍스트, 자손의 텍스트를 누적해서 반환해줌

$('h2').text();

text() 함수에 인자가 없으면 get, 인자가 있으면 set을 해주는 함수 

 

$('.contents1').html("<u>jQuery는 오픈소스 </u>");//tag 파싱 함

.html()함수는 innerHTML 과 같은 역할을 하는 함수로 인자로 받은 내용을 html로 올려주어 만약, 태그가 있다면 parsing된다.

 

반면, .text()함수는  text로 받기 때문에 <>태그가 있어도 text 그대로 출력해준다. 

 

$('h2').text(function(elementIndex,previousText){//엘레먼트 인덱스와 변경전 기존 값을 인자로 줌, function실행 결과를 text에

if(index%2==0){

return `하하하하하[${index}]`;

}else{

return `glglglgl[${index}]`;

}

});

 

text()함수에 함수를 인자로 넣으면 요소의 인덱스와 그 텍스트를 사용할 수 있다. 

 

jQuery에 string을 인자로 넣을 때는 <tag>나 css Selector인데 css Selector라면 당연히 > . # 도 사용할 수 있다.

$('body > *').css('font-wegith','bold');

 

 

jQuery 함수 이용

 

each(array,function(arrayIndex,name){...}}

array를 받았을 경우 각 원소들을 순회하고 

객체를 받았을 경우 객체의 프로퍼티를 순회한다. 

$.each(memeberNameArray,function(index,name){//컬렉션일 경우 원소를 , 객체일 경우 객체의 프로퍼티를 순회

$('#memberNameList').append(`<li>${name}</li>`);

});

 

grep(array,function(name,index){...}) 

let filterNameArray=$.grep(memberNameArray,(name,index)=>name.startsWith('k'));//한줄이면 {}바디 필요 없고 return 한줄뿐이면 return 생략

function에서는 name의 원소를 받아서 true, false를 반환하고 true인 원소들만 새로운 배열로 모아서 반환해준다. 

이때, 기존의 배열은 변하지 않는다. 

each 함수는 함수에서 index, name의 순서로 인자로 받지만 

grep 함수는 함수에서 name, index의 순서로 인자를 받는다. 

 

sort([function(){...}])

sort()함수는 배열을 오름차순 정렬해준다. 

내림차순 정렬하려면 function을 정의해주거나 reverse()함수를 사용해서 오름차순된 배열을 뒤집어준다. 

 

내림차순 정렬 함수 정의하기 

memberScoreArray.sort((a,b)=>b-a);

연속한 원소를 인자로 받아서 두 원소를 뺏을때 양수이면 두 원소의 순서를 바꿔준다. 

뒤에 있는 원소인 b가 a보다 크면 바꿔줘야 내림차순으로 정렬되므로 b-a를 반환해주면 된다. 

memberArray.sort(function(member1,member2){

if(member1.id>member2.id)

return 1 ;

else return -1;

});

만약 객체를 정렬한다면 객체의 어떤 프로퍼티를 기준으로 정렬할지 정하고 그 프로퍼티의 대소를 비교하는 식을 세워주면 된다. 

string 프로퍼티로 대소를 비교하면 큰 값이 앞에 있으면 오름차순 정렬일 때는 1(양수)을,

내림차순 정렬일때는 -1(음수)을 반환해준다. 

 

join()함수 

배열의 원소를 join의 인자로 연결하여 하나의 문자열로 반환해준다. 

memberNameArray.join(' -> ')

 

 

++css selector 

 

 

속성 선택자 [attribute]

$('a[target]').css('border','3px solid green');

[target] 

target 속성이 존재하는 모든 객체

 

a[target] 

a태그의 target 속성이 존재하는 모든 객체  

 

a[target != '_blank']{

a[target!='_blank']

a태그의 target 속성이 _blank가 아닌 모든 객체 

 

[attribute ^= 'value']

attribute의 값이 'value'로 시작하는 모든 객체

 

[attribute $= 'value']

attribute의 값이 'value'로 끝나는 모든 객체

 

[attribute = 'value']

attribute의 값이 'value'와 일치하는 모든 객체

 

[attribute *= 'value']

attribute의 값이 'value'을 포함하는 모든 객체

 

[attribute ~= 'value']

attribute의 값이 'value'단어를 포함하는 모든 객체 (단어라 함은 value를 공백으로 구분해 줄 수 있어야 한다.)

 

 

: pseudo class 가상클래스(의사클래스)

선택한 요소가 특정 조건을 만족하여야 적용되게 할 수 있다. 

 

LVHA(Link - Visited - Hover - Active) 여러개의 슈도클래스를 같이 작성할 때는 순서를 지켜 작성해야 정상 작동한다.

:link 방문전 

a:link{

color:grey;

}

:visited 방문후

:hover 마우스가 위에 올라와있을때

:active 누르고 있을때

:first(last)-child 첫번째(마지막) 자식인 경우

 

:: pseudo element 가상 엘레먼트

::before(after) 요소의 앞(뒤)에 요소 삽

::first-letter 요소의 첫 글자

h2::first-letter{ }

::selection 사용자가 선택한 요소

::placeholder placeholder의 텍스트 

 

jQuery에서 제공하는 슈도클래스 

$('tr:eq(0) > td:gt(2)').css('background','orange');

:eq(),gt(),lt() 요소의 값이 일치(크거나 작으면)하면

:odd() 요소의 값이 홀수이면

$('tr:eq(2)>td:even').css('background','purple');

:even() 요소의 값이 짝수이면

:first() 요소의 첫번째 값

$('tr:eq(3)>td:first').css('background','purple');

:last() 요소의 마지막 

:nth-child(n) n번째 자식

:not() ~가 아니면 

td.notSelect{

border: 0.5px dashed blue;

}

td태그 중 notSelect클래스 

td:not(.notSelect)

notSelect 클래스가 아니면 

 

 

'Javascript' 카테고리의 다른 글

Javascript this  (0) 2023.09.23
JQuery effect  (0) 2023.09.22
JQuery 이해하기  (0) 2023.09.22
Javascript defer  (0) 2023.09.21
CSS 선택자를 이용한 HTML DOM 객체 Handling  (0) 2023.09.18
728x90

JQuery를 이해하기 위해 직접 만들어보는 Query 

 

window.kQuery=function(arg){//arg = selector, function, dom Node

if(typeof arg == 'string'){

//css selector

let elementNodeList =document.querySelectorAll(arg);

if(!elementNodeList)elementNodeList=[];//list가 없으면 []초기화

 

let jqueryWrapperObject = {

'elementNodeList':elementNodeList,

'css':function(propertyName,propertyValue){

for(let i=0; i<this.elementNodeList.length;i++){

this.elementNodeList[i].style.cssText=`${propertyName}:${propertyValue}`;

}

return this;

},

'text':function(textArg){

if(!textArg){//falsy, getter

let returnText="";

for(let i=0; i<this.elementNodeList.length;i++){

returnText+=this.elementNodeList[i].innerHTML;

}

return returnText;

}else{//setter

for(let i =0; i<this.elementNodeList.length;i++){

this.elementNodeList[i].innerHTML=textArg;

}

return this;

}

}

};

return jqueryWrapperObject;

}

if(typeof arg == 'function'){

/*

인자로 대입된 함수를 DOM 트리 생성직후에 호출되도록

window.onload 이벤트 프로퍼티에 등록

*/

window.addEventListener('load',arg);

}

if(typeof arg == 'object'){

//dom node

}

if(typeof arg == 'undefined'){

//arg가 없을때

}

}

/****Jquery[$] global function */

kQuery.each=function(array, functionArg){

for(let i=0;i<array.length;i++){

functionArg(i,array[i]);

}

};

window.$=window.kQuery;

window에 kQuery 라는 펑션 프로퍼티를 등록한다. 

이 kQuery 펑션은 파라메터를 받을 수 있다. 

window.kQuery=function(arg){

}

파라메터를 받은 후 파라메터의 타입을 구분해 타입에 따라 처리하는게 달라진다.

if(typeof arg == 'string'){

//css selector

let elementNodeList =document.querySelectorAll(arg);

if(!elementNodeList)elementNodeList=[];//list가 없으면 []초기화

 

let jqueryWrapperObject = {

'elementNodeList':elementNodeList,

'css':function(propertyName,propertyValue){

for(let i=0; i<this.elementNodeList.length;i++){

this.elementNodeList[i].style.cssText=`${propertyName}:${propertyValue}`;

}

return this;

},

'text':function(textArg){

if(!textArg){//falsy, getter

let returnText="";

for(let i=0; i<this.elementNodeList.length;i++){

returnText+=this.elementNodeList[i].innerHTML;

}

return returnText;

}else{//setter

for(let i =0; i<this.elementNodeList.length;i++){

this.elementNodeList[i].innerHTML=textArg;

}

return this;

}

}

};

return jqueryWrapperObject;

}

css selector에 들어갈 선택자 String이 입력되면 

선택된 노드들을 WrapperNode로 만들고 

다양한 함수를 사용할 수 있게 WrapperNode에 함수들을 붙여준다. 

위 예제에서는 text()를 get하거나 set하는 text()함수와 css를 변경해주는 css()함수를 만들었고

css()함수는 wrapper 객체의 css를 변경해준뒤 다시 반환해준다.

text()함수는 인자가 없는 경우 객체의 text를 반환하고 인자가 있는 경우 객체의 text를 인자의 string으로 바꾼뒤 반환해준다. 

 

if(typeof arg == 'function'){

/*

인자로 대입된 함수를 DOM 트리 생성직후에 호출되도록

window.onload 이벤트 프로퍼티에 등록

*/

window.addEventListener('load',arg);

}

만약 함수가 kQuery에 인자로 들어온다면 인자로 대입된 함수를 onload 이벤트 프로퍼티에 등록한다.

 

kQuery.each=function(array, functionArg){

for(let i=0;i<array.length;i++){

functionArg(i,array[i]);

}

};

kQuery가 가지는 함수를 정의해준다. 위 예제는 반복문을 정의하였다. 

kQuery.each(array,function(){});

사용할 때는 kQuery에 바로 each 함수를 호출하여 반복할 array와 함수를 인자로 대입해준다. 

 

window.$=window.kQuery;

JQuery는 $로도 사용하는데 

window.$에 kQuery를 등록하면 kQuery도 $로 사용할 수 있다. 

'Javascript' 카테고리의 다른 글

JQuery effect  (0) 2023.09.22
JQuery 입문  (1) 2023.09.22
Javascript defer  (0) 2023.09.21
CSS 선택자를 이용한 HTML DOM 객체 Handling  (0) 2023.09.18
Javascript intermediate  (0) 2023.09.18
728x90

Handlebars 다운로드 

https://handlebarsjs.com/installation/#downloading-handlebars

 

Installation | Handlebars

Installation There are a variety of ways to install Handlebars, depending on the programming language and environment you are using. npm or yarn (recommended) The reference implementation of Handlebars is written in JavaScript. It is most commonly installe

handlebarsjs.com

cdnjs click

최신버전 또는 원하는 특정 버전의 scritp tag를 copy해온다. 

<script defer type="text/JAVASCRIPT"

src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.8/handlebars.min.js"></script>

 

SPA(Single Page Application)  

서버로부터 완전히 새로운 페이지를 받아로딩하지 않고 

하나의 페이지에서 갱신이 필요한 부분만 동적으로 다시 작성하여 사용자와 상호작용하는 방식

 

1. 하나의 페이지에 여러 페이지에 들어갈 컨텐츠를 모두 만들고 

그 컨텐츠들을 숨겨놓았다가

<div id="guest-view-template" style="display: none;">

요청과 응답에 따라 보여줄 템플릿을 보여준다. 

 

2. Handlebars에서 지원하는 <script> 태그를 이용

 

<script id="guest-modify-form-template" type="text/x-handlebars-template">

<script> 태그내에 데이터를 모두 텍스트로 가지고 있다가 요청에 따라 

<script> 태그의 내용을 html로 파싱하여 콘텐츠를 출력해준다. 

 

 

 

Handlebars expressions

{{...}}

 

반복문

{{#each 반복할컬렉션}}

        컬렉션.guest_no를 출력하려면{{guest_no}}

{{/each}}

 

{{#each data}}

<tr class="guest_item">

<td width="50" align="center" bgcolor="ffffff" height="20" >{{guest_no}}</td>

<a href="#{{guest_no}}" class="guest_item_a" guest_no="124">{{guest_title}}

</a>

{{/each}}

<a href="#1">

href 속성에 #를 붙이면 페이지기반요청을 하지 않는다. 

여기서 #guest_no를 붙여준 이유는 

a 클릭이벤트 발생시 href 속성의 값에서  guest_no를 문자열 처리를 하여 얻어내고 

페이지 기반 요청 없이 /guests/{guest_no} URI 맵핑하는데 이용하기 위해서 사용했다.

 

{{#with 객체}}

        {{property}}

{{/with}}

#with는 프로퍼티에 접근할 객체를 지정하여 

프로퍼티를 기술할 때 객체를 생략할 수 있게 해준다. 

{{#with data.[0]}}

<form name="f" id="guest_view_form" method="post">

<input type="hidden" name="guest_no" value="3">

<table border="0" cellpadding="0" cellspacing="1" width="590"

bgcolor="BBBBBB">

<tbody>

<tr>

<td width="100" align="center" bgcolor="E6ECDE" height="22">번호</td>

<td width="490" bgcolor="ffffff" align="left"

style="padding-left: 10px">{{guest_no}}</td>

</tr>

<tr>

<td width="100" align="center" bgcolor="E6ECDE" height="22">이름</td>

<td width="490" bgcolor="ffffff" align="left"

style="padding-left: 10px">{{guest_name}}</td>

</tr>

</tbody>

</table>

{{/with}}

여기선 data 배열에 있는 원소들 중 0번 인덱스에 접근하여 guest_no, guest_name에 접근한다. 

{{내에서 배열의 인덱스에 접근할 땐 }}

array[index]가 아니라 array.[index] 으로 기술한다. 

 

 

++<태그 내에 정의된 속성 이외에 커스텀으로 속성을 추가할 수 있다. >

<input type="button" value="수정"

id="btn_guest_modify_form" guest_no="{{data.[0].guest_no}}">

modify action을 위한 guest_no 

 

 

 

 

handlebars에 함수 등록하기 

function addCustomFunctionHandlebars(){

//Handlebars 함수 등록

Handlebars.registerHelper('substring',function(str,start,end){

return str.substring(start,end);

});

Handlebars.registerHelper('toUpperCase',function(str){

return str.toUpperCase();

});

}

Handlebars.registerHelper('funcName',funcArg); 

<td width="120" align="center" bgcolor="ffffff">{{toUpperCase guest_name}}</td>

<td width="120" align="center" bgcolor="ffffff">{{substring guest_date 0 10}}</td>

{{...}} 표현식에서 함수와 인자를 사용할 땐

funcName param1 param2 param2 

공백으로 구분해준다.

 

 

페이지 내 컨텐츠 영역을 갱신해주는 메소드

function render(templateId="#guest-main-template",jsonResult={},contentId="#content")

{//templateId="", contentId="" >>default값 설정

addCustomFunctionHandlebars();

let templateHtml = document.querySelector(templateId).innerHTML;

let bindTemplate =Handlebars.compile(templateHtml);

let resultTemplate =bindTemplate(jsonResult);

document.querySelector(contentId).innerHTML = resultTemplate;

}

<script> 태그 내에 작성한 템플릿의 HTML (컨텐츠 영역에 표시할 템플릿)

Handlebars.compile(템플릿HTML) 을 사용하면 

Handlebars 엔진이 expressions에 맞춰 데이터를 바꿔 출력할 수 있도록 함수로 만들어 반환해주면  

json 데이터를 그 함수에 넣어주면 HTML을 완성해준다. 

완성된 HTML을 content 영역에 innerHTML 해준다. 

 

++함수를 정의할 때 파라메터에 값을 지정해주면 default 값으로 지정해준다. 

 

버튼 또는 돔 객체에 addEventListener('click', funcArg) 으로 템플릿을 바꿔주는 render 메소드를 실행하는 익명함수를 작성해준다. 

menuGuestWriteForm.addEventListener('click', function(e) {

View.render('#guest-write-form-template');

e.preventDefault();

});

이때 버튼이 페이지기반 요청을 Default로 한다면 event.preventDefault() 함수로 페이지 기반 요청을 막아줘야 한다. 

 

document.addEventListener('click', function(e) {

if (e.target.id == 'btn_guest_write_action') {

 }

if (e.target.classList.contains('guest_item_a')) {

}

 

만약 click 이벤트를 등록해야할 객체가 <script> 태그에 속한다면 

그 템플릿이 HTML로 올라오기 전엔 접근할 수 없다. 

 

event가 발생할 땐 window에서부터 타겟까지 타고 내려와 window로 bubble되며 이벤트가 발생하는 점을 이용하면

document.에 이벤트 등록을 하면 document 내의 모든 객체에서 들어오는 click 이벤트를 받아 처리할 수 있다. 

 

document에서 이벤트를 받아 이벤트의 타겟에 접근해서 <script> 태그 내의 객체의 이벤트가 발생하는 경우도 

이벤트 등록을 할 수 있다. 

 

if (e.target.classList.contains('guest_item_a')) {

if(e.target.href.indexOf('#')>=0){

let guest_no = e.target.href.substring(e.target.href.indexOf("#")+1);

//e.preventDefault(); #요청은 페이지기반 요청 아니라 필요없다.

let sendJsonObject = {};

/**********ajax 요청 **********/

Request.ajaxRequest(RequestURL.GUEST_DETAIL.method,

RequestURL.GUEST_DETAIL.url.replace('@guest_no',guest_no),

function(responseJsonObject) {

if (responseJsonObject.status == 1) {

//쓰기 성공시 리스트 클릭 이벤트 발생

View.render('#guest-view-template',responseJsonObject);

} else {

alert(responseJsonObject.msg);

}

},

sendJsonObject);

}

}

이전에 href="#{{guest_no}}"에서 받은 #1 에서 #를 제외한 나머지 {{guest_no}}를 구하여 URL에 붙여준다.

const GUEST_DETAIL = { method: 'GET', url: 'guests/@guest_no' };

 

export function ajaxRequest(method,url,callbackFunction,sendJsonObject={}) {

let xhr = new XMLHttpRequest();

xhr.open(method, url);

xhr.setRequestHeader('Content-type', 'application/json;charset=UTF-8');

xhr.onload = function() {

callbackFunction(JSON.parse(xhr.responseText));

}

xhr.send(JSON.stringify(sendJsonObject));//js에서는 키값에 ""필요없고 ''도 허용하지만 server측에선 ""필수기 때문에

}

ajaxRequest는 ajax 요청하는 과정을 함수로 추출하였다. 

이 과정은 추후 라이브러리를 사용하여 처리 가능하다. 

 

 

 

html 파일에서 module 사용하기 

<script src="js/app.js" type="module"></script>

type="javascript"대신 "module" 사용 

module을 사용하면 돔트리가 다 생성되고 난 후에 실행된다.

++type= "module"과 "javascript"

 

module 은 import, export 사용 가능 

module 은 독립적인 scope을 가져 프로퍼티는 module의 scope에 등록된다.

 

 

모듈은 모듈만 import 할 수 있다.

import * as View from "./view.js";

모듈에서 다른 모듈 import 하기 

as View : "./view.js"로부터 import 모든 프로퍼티를 View라는 이름으로 사용하겠다

import {render} from "./view.js";    하면 render만 임포트

다른 모듈의 특정 메소드나 변수만 import 하고 싶은 경우 {..} 로 지정해줄 수 있다. 

export 하는 파일에서는 export 프로퍼티를 지정해줄 수 있다. 

프로퍼티 앞에 export를 붙이거나 

export{property1, property2...} 으로 지정한다.

 

 

 

 

'Web' 카테고리의 다른 글

YAML Converter  (0) 2023.10.11
HTML5 Basic  (0) 2023.09.19
Mybatis Mapper  (0) 2023.09.19
MyBatis Config  (0) 2023.09.19
AJAX Asynchronous Javascript And XML  (0) 2023.09.18
728x90

브라우저가 HTML을 읽다가 <script> 태그를 만나면 HTML 파싱을 멈추고 <script>를 먼저 실행합니다. 

이때문에 DOM 객체 생성이 중단되고 사용자는 HTML 이 다 파싱될 때까지 UI를 사용하지 못하는데 

 

<script src> src 속성을 가져 파일을 다운받아오는 script태그는 다운로드가 오래 걸리면 다운로드가 완료될때까지 

파싱이 지연되게 됩니다.

 

이를 해결하기 위해 <script> 태그를 body 끝부분에 위치시키거나

defer 속성을 사용합니다. 

 

script src 는 태그 순서대로 실행되기로 되어있고 

다운로드가 먼저끝나더라도 실행은 태그의 위치 순서에 따른다.

 

defer 속성을 사용하면 script를 백그라운드에서 병렬적으로 다운로드 받고 HTML을 멈추지 않고 계속 파싱합니다.

 

<script defer src="small.js">

 

'Javascript' 카테고리의 다른 글

JQuery 입문  (1) 2023.09.22
JQuery 이해하기  (0) 2023.09.22
CSS 선택자를 이용한 HTML DOM 객체 Handling  (0) 2023.09.18
Javascript intermediate  (0) 2023.09.18
Javascript Event  (0) 2023.09.17
728x90

RestApi method

 

GET 서버의 리소스에 접근
POST 서버에 데이터 전송
PUT 서버의 리소스를 갱신
DELETE 서버의 리소스 삭제

 

URI 맵핑 

site/items/sub-items/pk

 기존에 uri를 설계할 때는 'site/items_service' 처럼 자원과 그 행위를 표현하는 방식을 많이 사용했는데 

RestApi는 행위는 RequestMethod로 충분하고

- URI는 자원을 표현한다. 

- /은 자원의 계층관계를 나타내고 URI 마지막에 붙이지 않는다. 

- _은 사용하지 않는다. -은 가독성을 위해 사용할 수 있다.

-  소문자를 사용한다. 

- 파일 확장자.xx는 사용하지 않는다. 

- 컬렉션(집합)자원은 s(복수형)을 붙이고, 다큐먼트(객체) 자원은 단수형을 사용하면 직관적인 설계가 될 수 있다.

 

 

HTTP 응답상태 코드 

- 2xx : 정상적 응답

- 301 : redirect 된 경우 

- 4xx : 클라이언트의 부적절한 요청에 대한 응답 

- 500 : 서버측에 문제 발생

 

RestController

@GetMapping(value = "/guests",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

public Map<String,Object> guest_list()throws Exception{

Map<String, Object> resultMap=new HashMap<String, Object>();

int status=1;

String msg="성공";

List<Guest> data=new ArrayList<Guest>();

data=guestService.selectAll();

resultMap.put("status", status);

resultMap.put("msg", msg);

resultMap.put("data", data);

 

return resultMap;

}

@GetMapping(value = "/guests/{guest_no}",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

public Map<String,Object> guest_detail(@PathVariable(value = "guest_no") int guest_no )throws Exception{

Map<String, Object> resultMap=new HashMap<String, Object>();

int status=1;

String msg="성공";

List<Guest> data=new ArrayList<Guest>();

Guest guest=guestService.selectByNo(guest_no);

if(guest!=null) {

data.add(guest);

}else {

status=2;

msg="게시물이 존재하지않습니다.";

}

 

resultMap.put("status", status);

resultMap.put("msg", msg);

resultMap.put("data", data);

 

return resultMap;

}

guests URI 에 파라메터를 받아서 queryString으로 맵핑하지 않고 

guests/{guest_no}로 guest_no를 URI PathVariable로 받아서 맵핑한다. 

@PostMapping(value = "/guests",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)

public Map<String,Object> guest_write_action(@RequestBody Guest guest){

Map<String, Object> resultMap=new HashMap<String, Object>();

int status=1;

String msg="성공";

List<Guest> data=new ArrayList<Guest>();

try {

int insert_guest_no=guestService.insertGuest(guest);

status=1;

msg="성공";

Guest newGuest=guestService.selectByNo(insert_guest_no);

data.add(newGuest);

} catch (Exception e) {

status=2;

msg="방명록쓰기실패";

e.printStackTrace();

}

 

resultMap.put("status", status);

resultMap.put("msg", msg);

resultMap.put("data", data);

return resultMap;

}

동일한 guests URI에 POST 방식으로 요청을 보내는 컨트롤러 

Model이나 Request Param이 아닌 

RequestBody 어노테이션을 사용

@Operation(summary = "방명록수정",description = "전송되는아이디에해당하는 게시물수정")

@Parameter(name = "guest_no",description = "방명록의번호")

@PutMapping(value = "/guests/{guest_no}")

public Map<String,Object> guest_modify_action( @PathVariable("guest_no") int guest_no,

@RequestBody Guest guest)throws Exception{

Map<String, Object> resultMap=new HashMap<String, Object>();

int status=1;

String msg="성공";

List<Guest> data=new ArrayList<Guest>();

guest.setGuest_no(guest_no);

guestService.updateGuest(guest);

data.add(guest);

 

resultMap.put("status", status);

resultMap.put("msg", msg);

resultMap.put("data", data);

 

return resultMap;

}

Put 방식으로 맵핑

//@ExceptionHandler(Exception.class)

public Map<String,Object> exceptionHandler(Exception e){

Map<String, Object> resultMap=new HashMap<String, Object>();

int status=3;

String msg="알수없는예외";

List data=new ArrayList();

data.add(e.getMessage());

 

resultMap.put("status", status);

resultMap.put("msg", msg);

resultMap.put("data", data);

return resultMap;

}

Exception이 발생할 때 처리할 Controller도 다른 RestController와 같은 형식을 갖는다. 

 

 

 

HTTP 요청시 Content-Type 

 - text타입 : text/css, text/plain, text/javascript, text/html

 - file : multipart/form-data

 - application : application/json, application/x-www-urlencoded

 

application/json 

{key : value}

 

application/x-www-urlencoded

key=value&key=value

html의 form의 기본 content-type 

'Java > Spring Boot' 카테고리의 다른 글

JPA 계층형 게시판  (0) 2023.10.10
Spring Data JPA begins  (0) 2023.10.06
Spring addViewControllers  (0) 2023.09.14
Thymeleaf in Spring  (0) 2023.09.14
Spring Interceptor  (0) 2023.09.14
728x90

기본 HTML 구조

<html>

<head>

<!-- 문서 정보 -->

<meta charset="UTF-8">

<title>html문서구조</title>

<style>

/*스타일 정의*/

</style>

<script>

<!-- 스크립트 정의 -->

</script>

</head>

<body>

<!-- 문서의 내용 -->

</body>

</html>

<html> 태그로 시작

<head>문서정보</head>

<body>컨텐츠</body>

</html> 태그로 문서 끝 

 

Block Element VS Inline Element

블록태그는 위에서 아래로 배치되는 태그이다. 

블록 태그의 다음 태그는 블록태그의 아래 위치한다. 

ex) div, p, h1~6, ul, li, table, form

 

인라인태그는 옆으로 배치되는 태그이다.

인라인태그는 같은 줄의 옆으로 배치된다.

ex) img, span, a

 

 

<div> 태그 

영역을 표시하는 마크업 

 

float:left >>블록 태그라 옆으로 배치되지 않지만 스타일에서 float 속성을 left로 주어 좌측 영역 차지 

<div style="border:solid 1px;width:250px;height:350px;float:left">

 

<p> 태그

문단을 표시하는 마크업

<div>영역</div>

<p>문단</p>

 

<ul>, <ol>, <li> 태그

<ul> : 순서가 없는 태그, 리스트의 머리말에 모양을 정할 수 있다.

<ol> : 순서가 있는 태그, 순서의 표시 형식을 정할 수 있다. 

<li> : 리스트의 요소 태그 

<ol type="A">

<li>로보캅</li>

<li>300</li>

<li>수상한 그녀</li>

<li>수상한 그남</li>

</ol>

<ul type="circle">

<li>한화-기아</li>

<li>NC-삼성</li>

<li>두산-롯데</li>

</ul>

 

<li style="display: inline;"><a href = "#">회원</a>

<li style="display: inline;"><a href = "#">주문</a>

style="display: inline"으로 인라인으로 출력할 수 있다. 

 

<table>태그

<tr> 태그 : 행

<td> 태그 : 열

colspan = " column (열) 을 합친다."

rowspan = " row () 을 합친다."

<table border="1">

<tr>

<td>번호</td>

<td>이름</td>

<td colspan="2">전화번호</td>

<td>비고</td>

</tr>

<tr>

<td>1</td>

<td>KIM</td>

<td>010-899-5656</td>

<td>011-899-5656</td>

<td rowspan='3'>X</td>

</tr>

<tr>

<td>2</td>

<td>LEE</td>

<td>018-959-8989</td>

<td>017-959-8989</td>

 

</tr>

<tr>

<td>3</td>

<td>SIM</td>

<td>012-959-8989</td>

<td>019-959-8989</td>

 

</tr>

</table>

 

 

<span>태그

컨텐츠를 표시하는 액자 역할, 컨텐츠이 표시 방법 제어하는 인라인 태그

<span style="color: red;font-size: large;font-weight: bold;border: 1px solid;">

테스트 문자열

</span>

<span style="font-style: italic;border: 1px solid;">span태그</span>를 이용해서 표시합니다.

 

 

 

<iframe>태그

윈도우 안에 frame을 생성하는 태그

<iframe src="http://www.daum.net"

width="800px" height="200px"></iframe>

 

<form> 태그

form 에서 데이터를 입력받아 url로 데이터를 보낼 수 있다. 

action = "url"

method= "requestMethod"

<input> 태그 

<form action="#" method="post">

<!-- 한 줄 짜리 키보드 입력 요소 -->

<input type="text" style="width:400px" />

<!-- 비밀번호 입력 요소 : 입력하는 동안 입력 문자가 표시되지 X -->

<input type="password" style="width:400px" />

 

<!-- 배타적 단일 선택 입력 요소 (radio button) -->

<!-- 배타적 단일 선택이 되려면 각 radio가 같은 name을 가져야 합니다. -->

<input type="radio" name="gender" />

<input type="radio" name="gender" checked="checked" />

 

<!-- 다중 선택 입력 요소 (checkbox) -->

<input type="checkbox" />IT

&nbsp;&nbsp;&nbsp;

<input type="checkbox" />경제

&nbsp;&nbsp;&nbsp;

<input type="checkbox" />정치

&nbsp;&nbsp;&nbsp;

<input type="checkbox" />문화

&nbsp;&nbsp;&nbsp;

<input type="checkbox" />연예

 

<!-- button : 버튼 모양, 자바스크립트와 연결을 위해 사용 -->

<input type="button" value="눌러주세요" />

<!-- reset : 초기화, 최초 페이지 로딩할 때 상태로 전환 -->

<input type="reset" value="초기화" />

<!-- image : 이미지 입힌 버튼 모양, 서버로 데이터 전송 -->

<input type="image" src="../image/btn.jpg" />

<!-- submit : 버튼 모양, 서버로 데이터 전송 -->

<input type="submit" value="서버로 전송" />

 

</form>

 

type : text, password, radio, checkbox, button, reset, image, submit

radio = > name 이 같은 radio 끼리는 1개만 선택할 수 있다.

checkbox = > 다중 선택

button = > 자바스크립트로 action 처리 가능한 버튼 

reset = > input의 모든 데이터를 reset하는 버튼

submit = > input의 모든 데이터를 서버로 전송하는 버튼, 클릭시 submit 이벤트 발생

image = > 이미지를 입힌 submit 버튼 

 

<textarea> 태그 

여러줄의 텍스트 input 

<!-- 여러 줄 키보드 자유 입력 요소 -->

<!-- 반드시 시작 태그와 종료 태그 쌍으로 작성 -->

<textarea rows="10" cols="55"></textarea>

<select> 태그 

select 태그 내 <option> 태그에 선택사항을 입

<select style="width:170px">

<option>도메인을 선택하세요</option>

<option>naver.com</option>

<option>daum.net</option>

<option>gmail.com</option>

<option>nate.com</option>

<option>dreamwiz.com</option>

<option>직접입력</option>

</select>

 

 

 

<a> 태그 

다른 페이지로 이동하는 태그 

href = "url"

target = "페이지를 이동할 타겟 윈도우"

 - _blank : 새창

 - _self : 현재창

 

절대경로 http://*

<a href="http://www.google.com" target="_blank">

 

상대경로 

기준경로==> 현재 리소스 url 중 리소스 이름을 제외한 주

>> 다른 위치의 리소스

<a href="../images/penguin1.gif">

>> 동일한 위치의 리소스 ./생략가능

<a href="./02.head.html">

 

페이지 내 지정 위치

<a href="http://www.naver.com#top">

naver의 #top 위치

<a href="#top">

현재 페이지의 #top 위치

<a href="#">

현재 페이지의 최상단으로 이동

 

<img> 태그

src = "url" 

<img src="../tomcat.gif" width="50" height="50">

 

 

 

 

html 문서 내에서 여러개의 공백, 탭, 줄바꿈 실제론 하나의 공백으로 출력된다. 

 

<br> 내려쓰기 

내려쓰기로 출력하려면 <br> 태그를 사용해야한다.

문장<br>

&nbsp; 띄어쓰기

명시적으로 띄어쓰기 출력하려면 &nbsp; 사용

&nbsp;&nbsp;&nbsp;&nbsp;

<, > == &lt; &rt;

&lt;, &rt;

 

<pre>태그 

공백, 탭, 줄바꿈 등 태그 내의 내용을 모두 그대로 출력한다. 

 

 

<h1~6>태그 

제목 마크업,  h1이 가장 크다. h6이 가장 작고 그 이상 존재하지 않는다. 

<h1>제목 표시 마크업</h1>

<h2>제목 표시 마크업</h2>

<h3>제목 표시 마크업</h3>

<h4>제목 표시 마크업</h4>

<h5>제목 표시 마크업</h5>

<h6>제목 표시 마크업</h6>

<hr> 태그 

수평가로선 

보통 제목 밑에 혹은 컨텐츠가 바뀌는 부분을 구분하기 위해 사용

 

'Web' 카테고리의 다른 글

YAML Converter  (0) 2023.10.11
SPA(single page application) Handlebars 활용하기  (1) 2023.09.21
Mybatis Mapper  (0) 2023.09.19
MyBatis Config  (0) 2023.09.19
AJAX Asynchronous Javascript And XML  (0) 2023.09.18
728x90

xml에서 설정

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.mybatis3.dao.mapper.StudentMapper">

         <resultMap id="studentResultMap" type="com.mybatis3.domain.Student">    

         <select id="findStudentByIdMap">

</mapper>

mapper의 namespace = "mapper의 위치"

 

<resultMap>

type: DB로 부터 받은 데이터 result를 바인딩할 java의 클래스 

<resultMap id="studentResultMap" type="com.mybatis3.domain.Student">

<id column="STUD_ID" property="studId"/>

<result column="NAME" property="name"/>

<result column="EMAIL" property="email"/>

<result column="DOB" property="dob"/>

</resultMap>

id = primaryKey

result = 나머지

column="데이터베이스의 컬럼명"

property="자바 클래스의 변수명" 

 

<resultMap id="studentWithAddressResultMap" type="com.mybatis3.domain.Student" autoMapping="true">

autoMapping = id, result를 직접 바인딩하지 않아도 column과 property를 비교하여 알아서 바인딩 해준다. 

다만, 하나의 클래스가 다른 클래스를 포함하고 있거나 컬렉션으로 갖는 경우 

id는 직접 기술해주어야하며, 

포함하고 있는 다른 클래스에 동일한 변수명을 가진 property가 있다면 또한 명시해주어야 한다. 

 

하나의 클래스가 다른 클래스를 포함하고 있는 경우 

<resultMap id="studentWithAddressResultMap" type="com.mybatis3.domain.Student" autoMapping="true">

<id column="STUD_ID" property="studId"/>

<association property="address" javaType="com.mybatis3.domain.Address" autoMapping="true">

<id column="ADDR_ID" property="addrId"/>

</association>

</resultMap>

<association> javaType="포함되는 클래스"

 

하나의 클래스가 다른 컬렉션을 포함하고 있는 경우

<resultMap id="studentWithCoursesResultMap" type="com.mybatis3.domain.Student" autoMapping="true">

<id column="STUD_ID" property="studId"/>

<result column="STUDENT_NAME" property="name"/>

<collection property="courseList" ofType="com.mybatis3.domain.Course" autoMapping="true">

<id column="COURSE_ID" property="courseId"/>

<result column="COURSE_NAME" property="name"/>

</collection>

</resultMap>

 

<collection> ofType="포함되는 컬렉션의 클래스"

동일한 프로퍼티를 가진 경우, <result>로 따로 맵핑해준다.

 

sql문도 작성 가능

<insert id="insertStudentBySequenceReturnPrimaryKey" parameterType="com.mybatis3.domain.Student">

<selectKey keyProperty="studId" order="BEFORE" resultType="int">select students_stud_id_seq.nextval from dual</selectKey>

insert into students(stud_id,name,email,dob) values(#{studId},#{name},#{email},#{dob})

</insert>

parameterType="insert시 필요한 파라메터의 타입"

<selectKey> insert시 sequence를 사용하여 pk를 초기화한다면 

insert후 insert한 데이터의 pk를 바로 반환 받기 위해 사용 

select students_stud_id_seq.nextval from dual

seq.nextval로 다음 seq 값을 미리 알아낸 후 

insert 할때는 seq.currval 값으로 insert 한다. 

파라메터를 넣을 땐 #{...property...} 표현식을 사용한다.

 

mybatis 사용

* 0. mybatis-config.xml --> InputStream

InputStream myBatisConfigInputStream = Resources.getResourceAsStream("mybatis-config.xml");

* 1. SqlSessionFactoryBuilder

SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();

* 2. SqlSessionFactory

SqlSessionFactory sqlSessionFactory=sqlSessionFactoryBuilder.build(myBatisConfigInputStream);

* 3. SqlSession open (Connection) autocommit true

SqlSession sqlSession=sqlSessionFactory.openSession(true);

* 4. SqlSession사용(CRUD)

//List<Student> studentList=sqlSession.selectList("com.mybatis3.dao.mapper.StudentBasicMapper.findAllStudents");

Student student=sqlSession.selectOne(

"com.mybatis3.dao.mapper.StudentBasicMapper.findStudentById",1);

* 5. SqlSession close

sqlSession.close();

sqlSessionFactory.open(autocommit true?)

 

sqlSession 메소드

selectOne()  객체 한개 반환 받을 때 

selectList() 객체 컬렉션을 반환 받을 때

insert(), update(), delete()

 

sqlSession.method(namespace+sql태그 id, 파라메터)

 

 

 

 

 

interface 에서 설정

-인터페이스의 풀네임은 Mapper.xml의 namespace와 일치

-메소드 이름은 Mapper.xml의 id와 일치

-메소드 인자타입은 Mapper.xml의 parameterType과 일치

-메소드 리턴타입은 Mapper.xml의 resultType과 일치 

 

@Select("select stud_id as studid,name,email,dob from students where stud_id = #{studId}")

public Student findStudentById(@Param("studId")Integer studId);

어노테이션으로 sql문을 .xml 파일 대신 Mapper인터페이스에서 작성할 수 있다. 

 

 

Mapper interface 사용

* 0.mybatis-config-mapper-interface.xml --> InputStream

InputStream myBatisConfigInputStream = Resources.getResourceAsStream("mybatis-config-mapper-interface.xml");

* 1. SqlSessionFactoryBuilder

SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();

* 2. SqlSessionFactory

SqlSessionFactory sqlSessionFactory=

sqlSessionFactoryBuilder.build(myBatisConfigInputStream);

* 3. SqlSession open (Connection ) autocommit true

SqlSession sqlSession=sqlSessionFactory.openSession(true);

* 4. StudentMapper[MapperInterface]생성

* org.apache.ibatis.binding.MapperProxy

StudentBasicMapper studentBasicMapper

=sqlSession.getMapper(StudentBasicMapper.class);

* 4. StudentMapper[MapperInterface]사용(CRUD)

Student student = studentBasicMapper.findStudentByNo(1);

* 5. SqlSession close

sqlSession.close();

sqlSession을 얻는것까진 동일 

 

인터페이스는 직접 사용하지 못하고 인터페이스를 상속받아 구현한 클래스를 사용해야 한다. 

Mapper는 인터페이스이므로 Mapper를 구현한 클래스를 가져와야하는데 

sqlSession의 getMapper가 이러한 일을 대신해준다. 

이를 Proxy라고 한다. 

Mapper mapper = sqlSession.getMapper(Mapper.class);

mapper.메소드를 이용해 인터페이스에서 만든 메소드를 사용할 수 있다. 

 

 

Dao에서 Mapper 사용하기 예제

public class AddressDao {

private SqlSessionFactory sqlSessionFactory;

private static final String NAMESPACE ="com.mybatis3.dao.mapper.AddressMapper.";

public AddressDao() {

try {

InputStream myBatisConfigInputStream = Resources.getResourceAsStream("mybatis-config.xml");

SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

this.sqlSessionFactory = sqlSessionFactoryBuilder.build(myBatisConfigInputStream);

} catch (Exception e) {

e.printStackTrace();

}

}

sqlSession이 아닌 factory를 필드로 갖고 매번 factory에서 sqlSession을 가져다 쓰고 반납한다. 

Dao 생성자에서 sqlSessionFactory를 생성해준다.

 

public Address findAddressByIdWithStudents(Integer addrId) {

SqlSession sqlSession= sqlSessionFactory.openSession(true);

Address address=sqlSession.selectOne(NAMESPACE+"findAddressByIdWithStudents",addrId);

sqlSession.close();

return address;

}

'Web' 카테고리의 다른 글

YAML Converter  (0) 2023.10.11
SPA(single page application) Handlebars 활용하기  (1) 2023.09.21
HTML5 Basic  (0) 2023.09.19
MyBatis Config  (0) 2023.09.19
AJAX Asynchronous Javascript And XML  (0) 2023.09.18

+ Recent posts