자바스크립트로 모달창 만들기

Aug 5, 2013

자바스크립트로 모달창을 만들려고 한다.

모달창은 보통 배경은 어둡고, 팝업 레이어가 뜨는 형태로 많이 사용한다. 모달창을 만들기 위해서 모달창에 어떤 기능을 넣을지 정의 해야 한다.

  • 보여주기
  • 감추기
  • 배경 어둡게 하는 레이어 생성
  • 가운데 보여주기

간단하게 기능 정의를 했다. 이 정도 기능을 가진 모달창을 어떻게 만드는지 알아본다.

먼저 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를 덮는 배경 레이어를 만들 수 있다.

See Also