자바스크립트로 모달창 만들기
자바스크립트로 모달창을 만들려고 한다.
모달창은 보통 배경은 어둡고, 팝업 레이어가 뜨는 형태로 많이 사용한다. 모달창을 만들기 위해서 모달창에 어떤 기능을 넣을지 정의 해야 한다.
- 보여주기
- 감추기
- 배경 어둡게 하는 레이어 생성
- 가운데 보여주기
간단하게 기능 정의를 했다. 이 정도 기능을 가진 모달창을 어떻게 만드는지 알아본다.
먼저 HTML과 CSS를 정의한다.
HTML
<!-- 모달창을 여는 버튼 -->
<button id="button">Open Modal</button>
<!-- 모달창 -->
<div id="modal">
<h3>Test Modal</h3>
<p>이 창은 모달창입니다.</p>
<button id="confirm_button">확인</button>
<button class="js_close">닫기</button>
</div>
CSS
#modal {display:none;background-color:#FFFFFF;position:absolute;top:300px;left:200px;padding:10px;border:2px solid #E2E2E2;z-Index:9999}
버튼이 하나가 있고, 감춰진 레이어(모달창)가 있다. 버튼을 누르면 감춰진 레이어가 모달창으로 나타나고, 확인 버튼이나 닫기 버튼을 누른다는 것이 예상되는 HTML이다.
Javascript
<!-- 스크립트 영역 -->
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
<script type="text/javascript" src="/Example.Modal.js"></script>
<script type="text/javascript">
// 모달창 인스턴트 생성
var myModal = new Example.Modal({
id: "modal" // 모달창 아이디 지정
});
// 모달창 여는 버튼에 이벤트 걸기
$("#button").click(function() {
myModal.show(); // 모달창 보여주기
});
// 모달창 안에 있는 확인 버튼에 이벤트 걸기
$("#confirm_button").click(function() {
alert("나는 모달창이다.");
myModal.hide(); // 모달창 감추기
});
</script>
자바스크립트를 살펴보면, 3가지 액션을 한다.
- 모달창 인스턴트 생성
- 모달창 여는 버튼에 이벤트 걸기
- 모달창 안에 있는 확인 버튼에 이벤트 걸기
Example.Modal.js
if(typeof(Example) == "undefined") var Example = {};
(function($){
Example.Modal = function() {
this.initialize.apply(this,arguments);
}
Example.Modal.prototype = {
initialize : function(hash) {
var obj = this;
// 멤버변수 정의
this.hash = this.getHashData(hash);
this.width = 0; // 콘텐츠 레이어 너비
this.height = 0; // 콘텐츠 레이어 높이
this.c_width = 0; // body 화면 너비
this.c_height = 0; // body 화면 높이
this.s_width = 0; // body 전체 너비
this.s_height = 0; // body 전체 높이
// 콘텐츠 레이어 크기 구하기(멤버변수에 저장)
this.getLayerSize();
// body 크기 구하기(멤버변수에 저장)
this.getBodySize();
// 추가 요소 생성
this.addElement();
// 마우스, 키 이벤트 정의
this.addEvent();
},
// Hash 변수정의
getHashData : function(hash) {
if(typeof(hash.id) == "undefined") hash.id = "modal"; // 개체 아이디
if(typeof(hash.is_slide) == "undefined") hash.is_slide = 0; // 슬라이딩 여부
return hash;
},
// 추가 요소 생성 - JS에서 추가해 주어야 할 HTML 작성합니다.
addElement : function() {
// 배경 레이어 HTML 받아오기
var html = this.addOverlay();
// 배경 레이어 HTML을 콘텐츠레이어 앞에 추가
$("#"+this.hash.id).before(html);
},
// 마우스, 키 이벤트 정의
addEvent : function() {
var obj = this;
// 닫기 버튼 클릭 이벤트 정의
$("#"+this.hash.id+" .js_close").click(function() {
// 모달창 감추기(여기서 obj는 Example.Modal 인스턴트 자체를 의미)
obj.hide();
});
},
/* 주요기능 */
// 모달창 보여주기
show : function() {
// 가운데로 이동
this.moveCenter();
// 배경 레이어 적용
this.applyOverlay();
// 콘텐츠 레이어 보여주기
$("#"+this.hash.id).show();
// 배경 레이어 보여주기
$("#"+this.hash.id+"_overlay").show();
},
// 모달창 감추기
hide : function() {
$("#"+this.hash.id).hide(); // 콘텐츠 레이어 감추기
$("#"+this.hash.id+"_overlay").hide(); // 배경 레이어 감추기
},
/* 부가 기능 */
// 콘텐츠 레이어의 너비와 높이를 구해서 멤버변수에 정의
getLayerSize : function() {
this.width = $("#"+this.hash.id).outerWidth();
this.height = $("#"+this.hash.id).outerHeight();
},
// body 크기 구해서 멤버변수에 정의
getBodySize : function() {
this.c_width = document.documentElement.clientWidth;
this.c_height = document.documentElement.clientHeight;
this.s_width = document.documentElement.scrollWidth;
this.s_height = document.documentElement.scrollHeight;
},
// 배경 레이어 HTML 생성
addOverlay : function() {
var html = "";
html += "<div id='"+this.hash.id+"_overlay' style='display:none;width:100%;position:absolute;top:0px;left:0px;opacity:0.5;background-color:#000000;z-Index:999'></div>";
return html;
},
// 콘텐츠 레이어를 가운데로 이동(top, left 조절해 줌)
moveCenter : function() {
// left 좌표 구하기
var left = Math.floor((this.c_width-this.width)/2);
// top 좌표 구하기
var res_height; // 콘텐츠를 화면상의 가운데로 두었을 때의 높이
if(this.c_height < this.height) { // 화면 높이 < 콘텐츠 레이어 높이
res_height = 0;
} else { // 화면 높기 >= 콘텐츠 레이어 높이
res_height = Math.floor((this.c_height-this.height)/2); // 차이를 빼서 2로 나눔. 그리고 내림.
}
var top = res_height+$(document).scrollTop(); // 화면상의 높이에 스크롤높이를 더한 절대좌표를 top에 저장
// css의 top,left 조정
$("#"+this.hash.id).css("top",top);
$("#"+this.hash.id).css("left",left);
},
// 배경 레이어 적용
applyOverlay : function() {
// body 크기 구하기(멤버변수에 저장)
this.getBodySize();
// 배경 레이어에 width, height css 값 조정
$("#"+this.hash.id+"_overlay").css("width",this.s_width);
$("#"+this.hash.id+"_overlay").css("height",this.s_height);
}
}
})(jQuery);
이 메소드가 어떤 일을 하는지 알아봤다.
Initialize
인스턴트를 생성했을 때 초기화를 시켜주는 생성자다. 인스턴트 생성되었을 때 하는 모든 일은 여기서 정의한다. getLayerSize(), getBodySize(), addElement(), addEvent() 메소드를 실행한다.
getHashData
다음과 같은 부분이 있는데, getHashData 메소드를 실행시키고 그 반환 값을 멤버 변수인 this.hash에 집어넣는다는 의미다. 이 메소드는 자바스크립트 인스턴트의 기본(default)값을 정의하는 역할을 한다.
this.hash = this.getHashData(hash);
addElement
추가 요소를 생성한다. 모달창 div 나 버튼 같은 요소들은 Javascript로 처리되기 전에 있어도 상관없지만, 백그라운드 레이어 같은 경우는 모달창이 뜰 때만 필요한 부분일 수도 있기 때문에 동적으로 생성되는 게 더 효율적이라고 생각한다.
addEvent
모듈에 관련된 요소들에 이벤트를 걸어준다. 여기서는 모달창 모듈의 닫기 버튼에 클릭 이벤트를 걸었다.
show
가장 중요한 보여주기 기능이다. 콘텐츠 레이어를 가운데로 옮기고, 배경 레이어 크기 조정 후 콘텐츠와 배경 레이어를 보여준다.
hide
감추는 기능이다. 모달창과 배경 레이어를 감추는 내용이다.
getLayerSize
콘텐츠 레이어의 너비와 높이를 구하는 메소드다. 가운데 정렬하기 위해서 필요한 수치이기 때문에 이 메소드를 따로 두게 되었다.
getBodySize
body의 너비와 높이를 구하는 메소드다. 이 메소드 역시 가운데 정렬을 하기 위해 필요하다.
addOverlay
단순히 배경 레이어를 생성하고, CSS를 in-line으로 정의되어서 독립적으로 쓸 수 있다.
moveCenter
위 메소드를 실행시켜 구한 수치들을 이용해서 계산하는 메소드다. 마지막에는 CSS의 top, left의 수치를 변화시켜서 가운데 정렬을 하게 된다.
applyOverlay
배경 레이어의 크기를 body의 크기에 따라서 변화한다. 이 메소드는 resize를 할 때 body의 크기가 달라졌을 경우 실행하도록 하면 항상 body를 덮는 배경 레이어를 만들 수 있다.