
연습문제 18
- 다음과 같은 HTML 문서와 JavaScript 프로그램을 작성하라.
- 각각 제목(h2)와 본문(p)을 포함하는 여러 섹션(section)이 있는 HTML 문서 작성
- 문서의 우측에 각 섹션으로 이동할 수 있는 고정된 목차 작성
- 목차의 항목을 클릭했을 때 해당 섹션으로 부드럽게 이동하는 JavaScript 프로그램 작성
풀이
1. 목차를 표현할 요소를 생성한다.
1.1. 새로운 ol 요소를 생성해서 body 요소에 추가한다.
1.2. 각 .section 요소를 대상으로
1.3. id 속성 값을 만들어서, .section 요소에 id 속성을 대입한다.
1.4. 새로운 a 요소를 생성하고, 이 요소의 내부 문자를 .section 요소의 자식 요소 중
h2 요소의 내부 문자를 읽어와 a 요소의 내부 문자로 설정한다.
1.5. 새로운 li 요소를 생성해서, 앞에서 생성했던 a 요소를 자식 요소로 추가한다.
1.6. 생성했던 li 요소를 위에서 생성했던 ol 요소에 자식 요소로 추가한다.
2. 목차의 a 요소를 클릭하면
2.1. href 속성 값, 즉 이동하고자 하는 요소의 선택자를 읽어온다.
2.2. 위에서 읽어온 선택자를 이용해, 이동하고자 하는 요소의 위치를 확인한다.
2.3. 위에서 확인한 위치로 부드럽게 스크롤 시킨다.
● HTML
<body>
<!-- TOC (Table Of Contents; 목차) -->
<!-- 문서 내의 특정 요소의 영역에 이동하려면 특정 요소의 아이디를
href 속성에 #을 덧붙여 값으로 대입하면 된다. -->
<!-- <ol id="toc">
<li><a href="#section-1">Lorem ipsum dolor sit amet</a></li>
<li><a href="#section-2">ultricies non arcu</a></li>
<li><a href="#section-3">Sed auctor pharetra nibh</a></li>
<li><a href="#section-4">Nulla eget luctus risus</a></li>
</ol> -->
<section class="section">
<h2>Lorem ipsum dolor sit amet</h2>
<p>
consectetur adipiscing elit.
Curabitur at bibendum risus, vitae finibus ex.
Fusce non augue in diam ultrices dapibus nec laoreet turpis.
Pellentesque pretium fringilla diam, a tincidunt ante fringilla ac.
Quisque justo lacus, posuere ut nulla non, sagittis euismod velit.
Mauris nec mollis massa. Nulla facilisi.
Etiam eget nulla at enim porta fringilla at eu massa.
Donec ac tincidunt ipsum. Nulla condimentum, ante sed consectetur congue,
purus turpis sodales leo, vitae rhoncus enim sem non metus.
Etiam mollis pulvinar libero et placerat.
In sed sapien semper, scelerisque sapien at, lobortis felis.
Fusce feugiat nisi nec sapien pellentesque, in fringilla neque efficitur.
Sed ex magna, mollis vel nulla a, porta lacinia felis.
Donec a nibh et nulla blandit venenatis.
Morbi ut enim efficitur, convallis leo eget, fermentum urna.
Orci varius natoque penatibus et magnis dis parturient montes,
nascetur ridiculus mus. Cras quis nulla pellentesque,
placerat nulla non, porta augue.
Nulla nisl libero, rutrum sodales ullamcorper suscipit,
Aenean nec odio ut diam tristique sollicitudin.
Cras a lacus ipsum. Mauris malesuada et urna in consectetur.
Morbi consectetur, tortor eu ultrices porta, nulla felis gravida justo,
eget molestie neque ante faucibus lorem. Nullam vel vestibulum urna, ac aliquam libero.
Nulla gravida velit ex, sodales posuere sapien faucibus eget.
Mauris feugiat imperdiet urna, vel convallis orci.
Sed finibus ullamcorper augue quis mollis.
In sollicitudin neque quis neque tincidunt tristique. Cras eu condimentum orci.
Vestibulum pretium felis in ligula dapibus rutrum.
</p>
</section>
<section class="section">
<h2>ultricies non arcu</h2>
<p>
Vivamus et aliquam dui.
Praesent vulputate lobortis magna, in placerat magna vestibulum eget.
Proin quis felis tellus.
Pellentesque vel massa ac magna consectetur lacinia quis quis nunc.
Mauris vestibulum nibh lectus, et tincidunt nunc auctor vel.
Aenean at pretium magna. Morbi congue lectus magna,
quis maximus nibh tincidunt vitae. Maecenas ac viverra diam, ut tempus nisi.
Aenean velit orci, pharetra quis gravida sed, porta ut leo.
Nam mattis mattis purus ut rutrum. Donec ac eleifend elit.
Vestibulum at ipsum in justo lobortis laoreet ac eget erat.
Morbi tortor augue, ullamcorper nec nulla sed, commodo eleifend libero.
Cras et fringilla diam. Nam vehicula semper nisi et consequat.
Sed pretium consequat augue a consectetur.
In bibendum est eu diam posuere sodales.
Pellentesque dapibus urna sit amet ante hendrerit fermentum.
Phasellus id odio efficitur, dignissim nunc ac, bibendum mauris.
Suspendisse ut scelerisque tellus, ac suscipit mauris.
Aenean mattis molestie odio non porttitor. Cras vel eros lectus.
Sed at nulla a sapien blandit bibendum nec varius elit.
Aenean mattis ut quam non cursus. Proin lobortis pulvinar tempus.
Sed ante est, commodo in consectetur vel, congue vitae ex.
Aenean consequat vel eros in mattis. Phasellus ut rutrum metus.
Aliquam pulvinar eget nibh in tempor.
Duis sagittis rutrum neque sed consectetur.
Donec vehicula augue id nulla faucibus tempus vel non tortor.
Class aptent taciti sociosqu ad litora torquent per conubia nostra,
per inceptos himenaeos. Maecenas ultrices turpis id sem tempus sagittis.
</p>
</section>
<section class="section">
<h2>Sed auctor pharetra nibh</h2>
<p>
vitae aliquet lectus porttitor eu.
Nullam accumsan et tellus quis consectetur.
Curabitur faucibus, metus vitae condimentum rhoncus,
urna lacus elementum lorem, nec imperdiet enim odio vitae justo.
Suspendisse cursus cursus augue sit amet varius.
Nam sagittis nunc vitae tristique feugiat.
Phasellus ornare aliquet felis, a suscipit felis laoreet non.
Nunc volutpat vitae augue at vehicula.
Maecenas venenatis sapien ut velit lacinia, non bibendum ante elementum.
Sed ullamcorper, quam vitae tristique blandit, nisi enim semper neque,
ut viverra arcu justo eu sapien. Proin malesuada diam sed magna imperdiet,
sed pellentesque nulla gravida. Pellentesque sed pulvinar felis.
In hac habitasse platea dictumst. Ut tortor magna, iaculis nec leo ut,
elementum facilisis lorem. Phasellus quis ante quis magna commodo consequat.
In ornare purus sapien, sed placerat lorem scelerisque nec.
Maecenas metus ligula, lacinia eu turpis id, congue facilisis nulla.
Sed vitae lectus nec mauris consequat gravida.
Phasellus tincidunt ex turpis, in vestibulum massa vestibulum dapibus.
Donec massa ipsum, posuere non nisi et, ultricies blandit risus.
Vestibulum vitae lacus vel diam tristique blandit.
Cras justo magna, placerat venenatis tellus sit amet, varius consequat dolor.
Nulla ornare sapien venenatis justo semper, eu hendrerit lectus mollis.
Nulla maximus quam nec odio eleifend, in egestas magna tristique.
Ut eleifend molestie elit et dapibus.
Sed arcu ipsum, mattis nec nulla eget, laoreet cursus velit.
Pellentesque feugiat lectus non laoreet tincidunt.
Maecenas vel velit lacinia, finibus felis sed, ullamcorper elit.
Suspendisse et mauris at eros eleifend lobortis. Vestibulum sed ultricies ex.
Vestibulum euismod nisi arcu, vehicula laoreet est mattis sed.
</p>
</section>
<section class="section">
<h2>Nulla eget luctus risus</h2>
<p>
Integer vitae leo hendrerit, interdum tortor egestas,
vehicula libero. Proin sed venenatis ex, et ornare lectus.
Aliquam feugiat odio sem, vel eleifend velit blandit a.
Mauris eu lacus nec sapien finibus interdum.
Nam non elementum magna, eget hendrerit orci.
Phasellus sed nisi sit amet sapien fringilla imperdiet.
Suspendisse ut nulla ornare, placerat leo sit amet, malesuada nulla.
Aliquam efficitur tempus nisl. Nunc volutpat tempor dictum.
Aenean vitae tortor at magna sodales ultrices.
Aenean molestie nulla ipsum, sit amet finibus sem scelerisque in.
Nam accumsan at metus et consectetur. Sed tincidunt ac est ac volutpat.
Nunc imperdiet facilisis molestie. Mauris id metus tortor.
Cras non dui ut nulla aliquet commodo. Donec vitae consectetur odio,
pellentesque volutpat eros. Maecenas ornare magna vitae leo sagittis efficitur.
Maecenas at ultricies diam. Maecenas facilisis nunc id pharetra maximus.
Vestibulum semper erat tempus, pellentesque purus ut, cursus dui. Nam felis mi,
feugiat ut velit sed, blandit suscipit quam. Nulla faucibus a urna non blandit.
Sed tortor neque, lacinia pharetra dui ut, hendrerit fermentum ex.
Mauris aliquet nisi id nisi convallis dictum.
Donec blandit justo ac gravida pharetra. Suspendisse sed nibh eros.
Mauris sit amet nulla at neque facilisis tempus.
Nulla non lectus nec diam volutpat dignissim sed vitae lectus.
Donec blandit ornare nulla, sed sollicitudin arcu lobortis eu.
Nulla sodales dolor sed tellus ornare facilisis.
Etiam vehicula posuere enim at feugiat. Praesent ornare,
risus faucibus varius volutpat, odio nisi placerat justo,
quis faucibus urna metus posuere massa.
</p>
</section>
</body>
● CSS
<style>
body {
/* padding-left: 1em; */
background-color: #111;
color: white;
font-size: 1.2em;
}
/* 목차 (Table Of Contents) */
#toc {
/* 브라우저 화면(viewport)을 기준으로 오른쪽 상단에 배치 */
position: fixed;
top: 3em; right: 2em;
width: 300px;
background-color: #444;
/* 마커를 표현하기 위해 왼쪽 여백을 다른 여백보다 충분히 설정 */
padding: 0.8em 1.5em 0.8em 3em;
box-sizing: border-box;
border-radius: 6px;
font-size: 0.9em;
line-height: 2;
/* 마커를 십진수 형태로 표현 */
list-style-type: decimal;
}
#toc > li > a {
display: block;
text-decoration: none;
color: white;
}
.section {
padding: 2em 2em 0.5em 3.5em;
/* margin: 2em 300px 2em 2em; */
margin-right: 316px;
line-height: 1.9;
}
.section > h2 {
font-size: 1.5em;
font-weight: 900;
letter-spacing: -2px;
padding-bottom: 0.5em;
border-bottom: 2px solid goldenrod;
}
.section > p {
margin-top: 0.5em;
}
</style>
● script
<script src="https://code.jquery.com/jquery.min.js"></script>
<script>
$(function () {
// 1. 목차를 표현할 요소를 생성한다.
// 1.1. 새로운 ol 요소를 생성해서 body 요소에 추가한다.
var $toc = $("<ol></ol>").attr("id", "toc").appendTo("body");
// 1.2. 각 .section 요소를 대상으로
$(".section").each(function (index, item) {
// 이 함수는 jQuery 객체에 담겨있는 Element 객체들을 대상으로 해서
// 순차적으로 그 객체의 메서드로 실행된다.
// 1.3. id 속성 값을 만들어서, .section 요소에 id 속성을 대입한다.
var id = "section" + (index + 1);
$(this).attr("id", id);
var innerText = $(this).children("h2").html();
// 1.4. 새로운 a 요소를 생성하고, 이 요소의 내부 문자를 .section 요소의 자식 요소 중
// h2 요소의 내부 문자를 읽어와 a 요소의 내부 문자로 설정한다.
var $link = $("<a></a>").attr("href", "#" + id).html(innerText).appendTo($toc);
// 1.5. 새로운 li 요소를 생성해서, 앞에서 생성했던 a 요소를 자식 요소로 추가한다.
// 1.6. 생성했던 li 요소를 위에서 생성했던 ol 요소에 자식 요소로 추가한다.
$("<li></li>").append($link).appendTo($toc);
});
//-----------------------------------------------------------------------------
// 2. 목차의 a 요소를 클릭하면
$toc.find("a").on("click", function (event) {
// 이벤트 핸들러: 목차의 a 요소에 click 이벤트가 발생하면 실행할 기능
// 기본 이벤트 제거
event.preventDefault();
// 2.1. href 속성 값, 즉 이동하고자 하는 요소의 선택자를 읽어온다.
var targetId = $(this).attr("href");
console.log("targetId = " + targetId);
// 2.2. 위에서 읽어온 선택자를 이용해, 이동하고자 하는 요소의 위치를 확인한다.
var posTop = $(targetId).offset().top;
// 2.3. 위에서 확인한 위치로 부드럽게 스크롤 시킨다.
$("html").animate({ scrollTop: posTop });
});
}); // document.onready
</script>
