5장 에서는 정적인 페이지에서 벗어나 리치 인터넷 애플리케이션 에 필요한 여러 부가 기능을 살펴 본다.내용은 드롭다운 메뉴, 탭, 슬라이딩 패널, 툴팁, 아코디언을 이용해 사용자가 쉽게 접근할 수 있도록 한다.
메뉴
확장하고 접을수 있는 메뉴
특정한 주제에 대한 사이트는 일반적으로 다단계 메뉴로 구성된다. 다단계 메뉴는 유사한 분류로 나뉘어 있으며 이러한 방법을 사용하면 사용자는 손쉽게 관련 정보를 찾을 수 있으며 상대적으로 작은 영역에 많은 양의 정보를 넣을 수 있다.
index.html(일부)
<ul class="active">
<li><a href="#">Weekly specials</a></li>
<li><a href="#">Last night's pics!</a></li>
<li><a href="#">Users' comments</a></li>
</ul>
</li>
<li><a href="#">Member extras</a>
<ul>
<li><a href="#">Premium Celebrities</a></li>
<li><a href="#">24-hour Surveillance</a></li>
</ul>
</li>
menu.css(일부)
float: right;
width:200px;
}
list-style-type: none;
padding: 0;
margin: 0;
}
cursor:pointer;
background:#94C5EB;
border-bottom:1px solid #444;
}
text-decoration: none;
}
padding: 2px 10px; font-weight:bold;
}
cursor:auto;
border:0;
padding:0 14px;
background-color:#fff;
}
#menu > li > a css를 보면 자식 선택자를 사용해 최상위 링크에 다른 링크와는 다른 스타일을 적용한다.
Script(일부)
.hide()
.click(function( e ){
e.stopPropagation(); //#menu > li > ul 의 목록을 클릭 했을때 움직이지 않게 하기 위한것
});
자식 선택자를 사용하므로 메뉴 구조에서 더 하위에 있는 엘리멘트를 우연히 숨기게 되는 일을 피할 수 있다.
$(this).find('ul').slideDown();
}, function(){
$( this ).find('ul').slideUp();
});
메뉴 id의 자식 li를 토글했을때 this값의 ul 엘리먼트를 찾아 slideDown을 해준다. 그리고 같은 this가 왔을때 ul 엘리멘트를 slideUp 시켜준다.
이벤트 전달
이벤트 전달은 DOM 구조 안에서 발생하는 이벤트의 흐름에 대한 이야기다.
어떤 엘리멘트에서 이벤트가 발생하면 해당 엘리멘트에 있는 핸들러에서 이벤트를 잡을 수 있고 이런 처리가 일어난 후 이벤트는 DOM 트리의 상위로 이동해 부모 엘리먼트에서 이벤트를 처리할 수 있는 기회를 갔는다.
index.html (일부)
Click Outer!
<div id="inner">
Click Inner!
</div>
</div>
script.js(일부)
alert('Hello from ' + $(this).attr('id'));
});
두 개의 클릭 이벤트가 아니라 실제로는 하나의 클릭 이벤트가 두개의 다른 곳에서 일어난다. 이벤트는 안쪽의 div에서 시작해 안쪽의 div에 연결된 이벤트 핸들러가 존재하는지 확인 한다. 그리고 이벤트는 div의 부모 엘리먼트 여기서는 바깥쪽 div로 전달된다.
(버블링) 엘리먼트에 연결된 이벤트 핸들러가 더이상 존재 하지 않을 때까지 이벤트는 계속해서 DOM 구조를 따라 부모 엘리먼트로 전달된다.
버블링이 필요할 때도 있지만 그렇지 않을 때도 많을 것이다. 버블링을 막기 위해 자바 스크립트를 사용하는 가장 일반적인 방법은 이벤트 핸들러에서 false를 반환 하는것이다
제이쿼리로 이벤트 전달을 멈추려면 stopPropagation을 사용하면 된다. 함수에 e 파라미터를 전달하고 이 이벤트에 대해 e.stopPropagation을 호출하면 더이상 DOM을 타고 이벤트가 전달 되지 않는다.
이벤트 기본 동작
이벤트의 흐름을 제어 하는 일반적인 방법은 preventDefault를 사용하는 것이다.
e.preventDefault
});
이 코드는 페이지의 모든 링크를 동작하지 않게 만든다.
false 를 사용하는것과 preventDefault 와 stopPropagation을 동시에 호출하는 것과 같다.
isDefaultPrevented와 is PropagationStopped 명령어를 사용해 이벤트의 흐름이 수정됐는지 확인 가능함.
기본동작이 중지됐거나 이벤트 전달이 중지되면 true를 반환하고 나머지 경우는 모두 false를 반환한다.
열림 / 닫힘 표시
메뉴의 숨겨진 정보가 있다는 사실을 표현하기 위해 열림/닫힘 표시를 붙인다.
cursor:pointer;
background:#94C5EB url(arrows.png) no-repeat right top;
border-bottom:1px solid #444;
}
#menu li li{
cursor:auto;
border:0;
padding:0 14px;
background-color:#fff;
background-image: none;
}
기본적으로 모든 메뉴는 닫혀 있으므로 아래 방향 화살표를 설정해야 한다.
아래 방향의 화살표는 위쪽에 있고 위 방향의 화살표는 위에서 부터 20픽셀 아래에 있다.
$(this)
.css('background-position', 'right -20px')
.find('ul').slideDown();
}, function(){
$( this )
.css('background-position', 'right top')
.find('ul').slideUp();
});
메뉴를 토글할 때마다 CSS 스프라이트 위치를 조절해야한다.
호버 이벤트일 때 메뉴 확장
메뉴가 클릭 이벤트뿐 아니라 호버 이벤트에도 응답하게 만들고자 한다.
사용자가 상위 메뉴 중 하나에 마우스를 올리면 잠시 기다린 후 메뉴를 확장한다.
$('#menu > li').hover(function() {
$(this).addClass('waiting');
setTimeout(function() {
$('#menu .waiting')
.click()
.removeClass('waiting');
}, 600);
}, function() {
$('#menu .waiting').removeClass('waiting');
});
마우스를 올리자 마자 실행되는 현상을 막기 위해 사용자가 일정 시간 동안 마우스를 올릴 때만 실행되게 만든다.
메뉴 엘리먼트로 마우스를 가져가면 wating 클래스를 메뉴 항목에 추가한다.
크로스 브라우저를 지원하는 서커피시 메뉴
첫 번째로 기초가 될 서커피시 드롭다운을 설정한다.
#container {
position: relative;
}
#menu {
position: absolute;
top: 0;
right: 0;
}
#menu, #menu ul {
padding: 0;
margin: 0;
list-style: none;
}
#menu li {
float: left;
background: #FFF;
}
#menu a {
display: block;
padding: 5px;
width: 130px;
}
#menu li ul {
position: absolute;
left: -999em;
width: 140px;
}
#menu li:hover ul, #menu li ul:hover { //상태에 따른 선택자
left:auto;
}
자바 스크립트를 사용하지 않고도 정상적으로 대부분의 브라우저에서 잘 동작하는지 확인할 수 있다.
그렇다면 이 기능을 JQUERY로 구현하자면 hover 액션에 슬라이드 다운효과를 적용하면 된다.
하지만 CSS 와 제이쿼리의 hover 가 싸우면 누가 이길까? 두 기능이 같기 때문에 둘중 하나는 쓰지 못한다.
제이 쿼리에서 유연하게 만들고 CSS와의 충돌을 피하기 위해 마우스가 올라가 있든 아니든 자식 메뉴 항목의 CSS 프로퍼티값을 대체한다.
$('#menu li ul').css({
display: "none",
left: "auto"
});
$('#menu li').hover(function() {
$(this)
.find('ul')
.stop(true, true)
.slideDown('fast');
}, function() {
$(this)
.find('ul')
.stop(true,true)
.fadeOut('fast');
});
이와 같이 설정한 CSS 값을 무시해버린다.
앞 장에서 본것과 같이 마우스를 빠르게 움직일 때 stop(true, true)를 사용하여 애니메이션이 큐에 누적돼 쌓이는 일을 막아준다.
아코디언 메뉴
간단한 아코디언
제이쿼리를 사용하여 간단하게 아코디언 메뉴를 만들 수 있지만 반드시 알고 지켜야할 몇가지 복잡한 조건이 있다.
<ul id="accordion">
<li class="active">
A-List Celebrities
<ul>
<li><a href="#">Computadors</a> New!</li>
<li><a href="#">Johny Stardust</a></li>
<li><a href="#">Beau Dandy</a></li>
</ul>
</li>
헤더 엘리먼트는 각 영역의 제목이 된다.
$('#celebs ul > li ul')
.click(function(e){
e.stopPropagation();
})
.filter(':not(:first)') //필터 선택자 위치기반 선택자 // 처음 요소는 hide되는것을 filter
.hide();
첫번째 영역을 제외하고 남아있는 영역을 숨기기 위해 filter를 사용했다. :not은 활용도가 높은 선택자이다.
이 선택자는 괄호 안에 있는 조건과 반대되는 것을 선택한다.
$('#celebs ul > li').click(function(){
var selfClick = $(this).find('ul:first').is(':visible');
if(!selfClick) {
$(this)
.parent()
.find('> li ul:visible') :visible 보이는 엘리멘트만 선택
.slideToggle();
}
$(this)
.find('ul:first')
.slideToggle();
});
아코디언 효과의 코드는 열려 있는 항목은 닫고 클릭한 항목은 열어야 한다. 동시에 하나의 항목만 열려야 한다.
.is('visible')을 사용해 중첩된 ul이 보이는 상황인지 확인한다. 그리고 결과를 selfClick이라는 변수에 저장한다. 사용자가 이미 열려 있는 곳을 클릭 했다면 값은 true 다.
이미 클릭된 것이 아니라면 if 구문에서 자바스크립트의 ! 연산자를 사용해 보이는 영역을 감춘다.
마지막으로 클릭한 항목의 상태를 토글한다. 항목이 이미 열려 있다면 닫힐 것이고 닫혀있다면 열릴것이다.
다단계 아코디언
다단계 아코디언을 적용하려면 같은 코드를 중첩된 엘리먼트에 적용하기만 하면 된다.
('#celebs ul > li, #celebs ul > li > ul > li').click
아코디언에 단계를 더 추가하고 싶다면 이과정을 반복하면 된다.
제이쿼리 UI 아코디언
앞에서 본것과 같이 아코디언 메뉴를 만드는 방법도 있고 그것보다 더 복잡하게 해서 만드는 방법도 있다. 그러나 제이쿼리 UI라이브러리에는 상당히 많은 옵션을 지원하는 아코디언이 들어 있다.
$('#accordion').accordion({header: 'h3'});
H3의 다음 엘리먼트가 보여주거나 감추고자 하는 본문이 담긴 영역이라면 작성한 내용을 완전한 기능이 갖춰진 아코디언으로 바꾸는 데 필요한 코드는 위의 코드가 전부다.
$('#accordion').accordion('activate', 2);
또한 아코디언은 프로그램을 이용해 아코디언을 동작시킬 수 있는 기능을 제공해준다.
제이쿼리 UI를 사용하면 직접 만들어 사용할 때보다 파일의 크기나 네트워크 사용량에서 불리하다.
그러나 복잡한 기능이 필요하고 직접 만드는 일에 시간을 보내고 싶지 않다면 제이쿼리 UI를 사용하는게 좋다.
탭
기본 탭
기본 탭에는 페이지의 모든 내용이 미리 로드된다. 해야 할 작업은 필요에 따라 감추고 보여 주는것이다.
우선 본문을 만들어 본다.
<div id="info">
<p id="intro">
Welcome to <strong>StarTrackr!</strong> the....
</p>
<p id="about">
StarTrackr! was ...
</p>
<p id="disclaimer">
Disclaimer! This service is not intended...
</p>
</div>
다음으로 탭 내비에기션 바를 만든다.
<div id="navigation">
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Buy Now!</a></li>
<li><a href="#">About Us</a></li>
<li><a href="#">Gift Ideas</a></li>
</ul>
</div>
문서 준비가 완료되면 첫 번째로 해야 할 작업은 탭을 감추는 작업이다.
$( '#info p:not(:first)' ).hide();
위의 코드처럼 다른탭은 숨기고 첫 번째 탭을 보여준다.
$('#info-nav li').click(function(e) {
$('#info p').hide();
$('#info-nav .current').removeClass("current");
$(this).addClass('current');
var clicked = $(this).find('a:first').attr('href');
$('#info ' + clicked).fadeIn('fast');
e.preventDefault();
}).eq(0).addClass('current');
info-nav를 클릭하면 info id의 p 태그를 가리고 .current 클래스를 삭제하고 현재 클릭된 태그에 current 클래스를 추가한다(본문).
해당 값의 첫번째 a태그의 href값을 담고 fadin 함수를 써서 본문을 교체한다.
제이쿼리 UI탭
다음으로는 제이쿼리에서 제공하는 UI탭을 살펴 보겠다.
UI 라이브러리와 CSS를 적절한 곳에 위치시키면 내용을 추가하기는 쉽다. Ajax를 사용해 로드한 내용이 표시될 곳을 따로 지정할 필요도 없다. 플러그인에서 자동으로 DOM 엘리먼트를 생성한다.
<div id="info">
<ul>
<li><a href="#intro">Intro</a></li>
<li><a href="about.html">About StarTrackr!</a></li>
<li><a href="disclaimer.html">Disclaimer</a></li>
</ul>
<div id="intro">
<p>
Welcome to <strong>StarTrackr!</strong>
</p>
</div>
여기서 주의깊게 봐야하는것이 위 예제에서는 정적인 HTML 파일을 가지고 실행하였지만 두개의 탭은Ajax를 사용하여 동적인 내용을 생성하는 서버 스크립트를 생성할 수 도 있다.
$('#info').tabs();
위의 마크업을 Ajax가 적용된 탭으로 만들려면 다음과 같이 코드를 작성해야 한다.
탭 옵션
제이쿼리 UI 탭에 대해 몇가지 유용한 내용에 대해 알아보자.
$('#info').tabs({
event: 'mouseover',
fx: {
opacity: 'toggle',
duration: 'fast'
},
spinner: 'Loading...',
cache: true
});
여기서 event 옵션은 탭을 전환하는 이벤트를 선택 할 수 있게 한다.
탭 사이를 이동할 때 빠른 페이드 전환을 지정하는 애니메이션을 추가 한다. fx는 animate 명령어와 동일하게 동작하며 원하는 방식으로 전환 효과를 설정 할 수 있다.
그리고 마지막 두개는 Ajax를 사용하기 위한 것이다. spinner는 내용을 로드하는 동안 표시할 HTML을 지정한다.
cache는 탭에 표시되는 내용을 로드한 후 복사본을 브라우저에서 유지해야 하는지 설정한다. 이방법을 사용하면 사용자가 탭을 앞, 뒤로 반복해서 여러번 클릭하더라도 브라우저는 매번 데이터를 다운로드하지 않는다.
위에서 내려오는 로그인 폼
시각적인 어수선함을 줄이는 방법으로 널리 사용되는 방법 중 하나는 화면의 최상단에 숨겨진 메뉴이다.
위에서 내려오는 패널을 가장 많이 쓰는 경우는 사이트의 로그인 영역을 표시 할 대이다.
$('#login form').hide();
$('#login a').toggle(function() {
$(this)
.addClass('active')
.next('form')
.animate({'height':'show'}, {
duration:'slow',
easing: 'easeOutBounce'
});
}, function() {
$(this)
.removeClass('active')
.next('form')
.slideUp();
});
위 코드는 최초에 로그인 폼을 숨기고 로그인 버튼을 클릭하면 animate를 사용해 로그인 폼을 보여주고 있다.
슬라이드 오버레이
반투명한 슬라이드 오버레이는 메시지 다이얼로그, 쇼핑카트 요약, 내비게이션 컨트롤까지 많은 곳에서 사용된다. 많이 사용되는 이유는 간단하다. 아주 멋져보이기 때문이다.
#content {
position: relative;
}
.cart a {
position: absolute;
width: 32px;
height: 32px;
right: 15px;
top: -10px;
background: transparent url(shoppingcart.png) no-repeat 0 0;
text-indent: -9999px;
}
.cart a:hover, .cart-hover {
background-position: 0 -32px;
}
#overlay {
position: absolute;
width: 100%;
height: 100px;
top: 0;
left: 0;
color: #fff;
background-color: #000;
display: none;
text-align: center;
}
#overlay a {
font-size: 130%;
font-weight: bold;
}
오버레이 너비는 페이지 너비의 100%로 설정하며, 높이는 100픽셀로 설정한다. 오버레이가 위에서부터 아래로 내려와야 하므로 상단의 위치를 0으로 설정한다.
$('<div></div>')
.attr('id', 'overlay')
.css('opacity', 0.65)
.hover(function(){
$(this).addClass('active');
}, function() {
$(this).removeClass('active');
setTimeout(function(){
$('#overlay:not(.active)').slideUp(function(){
$('a.cart-hover').removeClass('cart-hover');
});
}, 800);
첫 번째 단계는 오버레이를 마크업에 추가하는것이다.
오버레이에는 호버 핸들러를 붙인다. 오버레이가 열려있는동안 active 클래스를 지정하고 해당 클래스를 이용해 닫을 때를 결정한다.
사용자가 마우스를 다른 곳으로 이동시키면 active를 제거하고 타이머를 설정한다.
1초 정도 난 후 오버레이를 닫는다. 이런방법을 사용하면 타이머가 실행되는 동안 사용자가 오버레이를 다시 열었을때 타이머의 동작이 무효화 된다.
opacity 프로퍼티를 사용해 오버레이를 반투명 하게 만든다.
$('.cart a').mouseover(function(){
$(this).addClass('cart-hover');
$('#overlay:not(:animated)')
.addClass('active')
.html('<h1>You have 5 items in your cart.</h1><a href="#">View Cart</a> <a href="#">Checkout</a>')
.slideDown();
});
여기서는 :animated라는 새로운 필터를 사용한다. 이 코드에서는 :not 필터와 함께 사용해 애니메이션 중이 아닌 엘리먼트를 선택한다.
툴팁
일반적으로 툴팁은 사용자가 하이퍼링크 위로 마우스를 올리면 나타난다.
<a href="#" title="뉴욕의 모든 유명인을 확인..."> 뉴욕</a>
title 속성을 사용하므로 몇 가지 한계가 있다. 툴팁 내에 HTML을 사용할 수 없다. 또한 특수 문자로 인해 태그가 이상해질 수 있다.
.tooltip {
display: none;
position: absolute;
border: 1px solid #333;
background-color: #ffed8a;
padding: 2px 6px;
}
툴팁의 위치는 절대 위치다. 그러므로 어떤 곳이라도 툴팁을 배치할 수 있다.
$(document).ready(function(){
$('.location').hover(function(e){
// Hover over code
}, function() {
// Hover out code
}).mousemove(function(e){
// Mouse move code
});
기본 툴팁의 코드는 크게 3가지로 나뉜다. 마우스가 올라갔을 경우와 마우스가 밖으로 이동했을 경우 마우스가 이동하는 경우 이다.
var titleText = $(this).attr('title');
$(this)
.data('tipText', titleText)
.removeAttr('title');
$('<p class="tooltip"></p>')
.text(titleText)
.appendTo('body')
.css('top', (e.pageY - 10) + 'px')
.css('left', (e.pageX + 20) + 'px')
.fadeIn('slow');
먼저 링크의 title을 찾는다. title 값은 툴팁에서 보여줄 메시지가 된다.
data 메소드를 사용해 툴팁의 메시지를 저장한다. 직젖 만든 툴팁과 브라우저의 기본 툴팁이 함께 표시되는 것을 방지하기 위해 링크의 title을 제거할 것이므로 이런 작업이 필요하다.
pageX와 pageY는 페이지에서 이벤트가 발생한 좌표를 알 수 있는 이벤트 객체 프로퍼티다.
function() {
// Hover out code
$(this).attr('title', $(this).data('tipText'));
$('.tooltip').remove();
마우스가 이동 했을 때는 마우스가 올라갔을 때 한 작업을 거꾸로 하면 된다.
title 속성의 값을 복원하고 툴팁을 제거하면 된다.
$('.tooltip')
.css('top', (e.pageY - 10) + 'px')
.css('left', (e.pageX + 20) + 'px');
});
마지막으로 마우스의 움직임에 따라 툴팁의 위치를 변경해야한다.
고급 툴팁
첫 번재 작업은 코드를 담게 될 TT 객체를 만드는 것이다.
var TT = {
delay: 600,
그리고 setTips 함수를 추가 한다. 이 함수는 페이지가 로드되거나 크기가 변경될 때 실행 된다.
이 함수는 모든 툴팁을 찾아 부모 엘리먼트를 살펴보고 툴팁의 위치를 결정한다.
또한 부모 엘리먼트의 hover 이벤트를 설정해 마우스가 위로 올라가면 툴팁이 출력되게 된다.
$('.tooltip').parent().hover(function(){ //툴팁 spa의 부모 엘리먼트에 hover이벤트
// store the tooltip being hovered
TT.current = $(this); //변수에 부모 엘리먼트 참조 저장
TT.timer = setTimeout(function(){ //타이머를 변수에 저장 타이머를 멈출 수 있음.
// find the tooltip,
TT.current.find(".tooltip").fadeIn('fast');
}, TT.delay);
}, function(){
// on mouseout, clear timer and hide tooltip
clearTimeout(TT.timer); //대기 시간이 지나도 툴팁이 보이지 않게 타이머 중지
$(this).find(".tooltip").fadeOut('fast');
}).attr("title", ""); // clear the title to stop browser tooltips
hover 핸들러는 완성되었다.
이제 툴팁의 위치를 결정할 차례다.
var screenWidth = $(window).width();
var screenBottom = $(window).scrollTop() + $(window).height();
$(".tooltip").each(function(){
// grab the containing element
$container = $(this).parent();
// give it relative position if required
if ($container.css("position") != 'absolute' //부모 엘리먼트가 postion absolute인지 확인
&& $container.css("position") != "fixed") { //
$container.css({position: 'relative'});
}
var totalHeight = $container.height() + $(this).outerHeight(); //툴팁과 부모 엘리먼트의 높이 합
var width = $(this).outerWidth();
var offset = $container.offset();
// now we get the position the tip
var top = $container.height(); // default placement
// 기본적으로 툴팁의 top 위치를 부모 엘리
var left = 0; //먼트의 높이와 같게 설정
//부모 엘리먼트 바로 아래 표시하기 위해
//부모 엘리먼트의 상단으로 떨어진 거리가
/// 부모 엘리먼트의 높이와 같음
이제 툴팁이 화면의 아래쪽이나 오른쪽과 충돌하는 지 알아내는 코드를 작성해야 한다.
// 화면의 오른쪽으로 사라지는 경우 위치를 다시 결정
if (offset.left + width > screenWidth) {
left = 0 - width + 42;
$(this).addClass('left');
} else {
$(this).removeClass('left');
}
// re-position if it's off the bottom of the screen
// 화면의 아래쪽으로 사라지는 경우 위치를 다시 결정
if (offset.top + totalHeight > screenBottom) {
top = 0 - $(this).outerHeight();
$(this).addClass('above');
} else {
$(this).removeClass('above');
}
화면의 왼쪽이나 상단에서부터 툴팁까지의 거리를 확인하고 여기에 툴팁의 너비 또는 높이를 더해 이 값을 화면의 너비나 또는 높이를 더해 이 값을 화면의 너비나 높이보다 큰지 확인한다.
만약 화면의 너비나 높이보다 크면 top이나 left 프로퍼티를 수정한다.
$(this).css({
"top": top,
"left": left
});
css 액션을 사용해 계산을 완료한 top과 left 프로퍼티를 툴팁에 지정한다.
$(document).ready(function() {
TT.setTips();
});
$(window).resize(function(){
TT.setTips();
});
툴팁이 항상 적절한 위치에 노출되도록 문서의 준비가 완료됐거나, 창의 크기가 변경됐을 때 setTips 메소드를 호출한다.
용어정리
*리치 인터넷 애플리케이션(Rich Internet Application; RIA)은 웹 애플리케이션의 장점은 유지하면서 기존 웹 브라우저 기반 인터페이스의 단점인 늦은 응답 속도, 데스크톱 애플리케이션에 비해 떨어지는 조작성 등을 개선하기 위한 기술의 통칭이다. 즉, 별도의 설치가 필요 없는 웹 브라우저 기반의 애플리케이션 배포 장점과 서버 측 웹 서비스와의 연동, 마크업 언어 기반의 선언적 애플리케이션 구성 등은 유지하면서 데스크톱 애플리케이션과 대등한 사용자 경험을 주는 것을 목표로 하는 기술이다.
'jquery' 카테고리의 다른 글
1.5 DOM 요소의 래퍼 집합 필터링하기 (0) | 2017.11.15 |
---|---|
1.4 특정 컨텍스트 안에서 DOM 요소 선택하기 (0) | 2017.11.15 |
1.2 Dom은 로드되었지만 페이자가 로드되기 전에 jQuery/자바스크립트 실행하기 (0) | 2017.11.15 |
7. 효과 (0) | 2017.11.15 |