상세 컨텐츠

본문 제목

시베리안 허숙희의 자바스크립트 비기닝 28 (모달 modal)

자바스크립트

by e7e 2023. 6. 23. 17:00

본문

이전 글

2023.06.22 - [자바스크립트] - 시베리안 허숙희의 자바스크립트 비기닝 27

의 list.htm에는 글의 제목을 클릭하면  상세내용을 모달창으로 보여주기 위해

함수 fmodal이 일부러 껍데기만 들어있당!.(모든 게 알고보면 다 안배당~~) 

 

실제 모달창은 CSS 몇개만 알면 아주 쉽고도 쉽게 만들 수 있는 데도 불구하고,

원리  이해 없이 bootstrap의 모달 창과 씨름 하는 모습이 아쉽기만 하당. 이번 기회에 

자기만의 모달창을 잘 만들어 두고, 계속 기능 확장해서 사용할 수 있길 기대본당.

 

먼저 모달창이 뭔지?, 왜 이걸  많이 쓰게 되었는지 생각해 보장!

예전엔 window.open을 이용하여 새창을 여는 거슬 많이  사용하였지만, 못된 사이트들이

새창 열기 지옥(도박,성인사이트등 불법사이트들이 줄줄이 계단식으로 새창에 열림 -

당시 웹개발자는 공부 초기에 이것을 구현하고,재밌어 했었당, 추억이 되었당)을

광고로 악용함으로써, 브라우져에는 새창을 열 때 사용자의 허락을 얻어야 하는 거스로 

당연 바뀌었당. 그리하여 새창 열기를  이용하면 사용자가 거부해 놓았을 경우, 멧돼지를

전달할 수 없어, 그 뒤로는 대안으로 모달이 많이 사용될 수 밖에 없게 되었당.

 

요즘 모달은 정형화 되어서 DIV 태그를 이용해서 만드는 데, 전체화면에 꽉차는 DIV

영역을 하나의 레이어로 맹글어서 현재 보는 화면을 막아버리는 거시다.(3D 기술이당)

모달을 만들려면 CSS의 필수 기본인 position, display, z-index와 background-color 정도는

어떤 기능을 하는 지 알고 있어야 한당.( 모른다면 지금 당장 구글 껌쌕하장)

 

모달기본이해.html (카.복 해서 만들장)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
<style>
    #modalWin{
        position: fixed;
        width:100vw;
        height:100vh;
        left:0px;
        top:0px;
        z-index: 1000;
      /*  background-color: blueviolet; */
        background-color: rgba(138, 43, 226, 0.5);
        display: none;
    }
</style>
</head>
<body>
    <div id="modalWin"></div>
    <button onclick="fmodal()">모달창열기</button>
<script>
const myModalWin = document.querySelector("#modalWin"); 
const fmodal = function(){
    myModalWin.style.display = "block";
}
</script>
</body>
</html>

 posiion:fixed와 width,height,left,top을 이용하여 전체화면 크기로 화면 왼쪽 모서리에 고정했다.

z-index(숫자가 클수록 레이어가 앞으로 나온다)를 이용하여 대략 앞쪽에 나오게 했당.

display:none(아주 많이 사용)을 이용하여, 처음에는 자리차지 없이 안 보이게 했당.

버튼을 누르면 보인당.(modalWin div가 모든 걸 덮는당! 오켕?)

background-color부분을 기존 건 주석 처리하고, 주석 된 건 풀어보장(투명도 느낌온당!)

 

모달기본완성.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
<style>
    #modalWin{
        position: fixed;
        width:100vw;
        height:100vh;
        left:0px;
        top:0px;
        z-index: 1000;
      /*  background-color: blueviolet; */
        background-color: rgba(138, 43, 226, 0.5);
        display: none;
    }
    #modalCont {
        width:60%;
        height:70%;
        margin:10% auto;
        border:3px solid black; /* 낸중에 필요없음 주석 */
        background-color: brown;
    }
    #menu {
        width:100%;
        height:10%;
        text-align: right;
    }
    #close {
        font-size: 2em;
    }
    h1 {
        text-align: center;
    }
</style>
</head>
<body>
    <div id="modalWin">
        <div id="modalCont">
            <div id="menu">
                <button id="close" onclick="fmodalClose()">X</button>
            </div>
            <h1>이거슨 모달 내용이디용</h1>
        </div>
    </div>
    <button onclick="fmodalOpen()">모달창열기</button>
<script>
const myModalWin = document.querySelector("#modalWin"); 
//모달 열기
const fmodalOpen = function(){
    myModalWin.style.display = "block";
}

//모달 닫기
const fmodalClose = function(){
    myModalWin.style.display = "none";
}
</script>
</body>
</html>

모달을 공부했으니, 이것을 list.html에 적용시켜 보장!

list.html에서 제목을 클릭하면, 이전 작성했던 내용이 모달에 보이기만 하믄 되므로,

write.html을 재활용하면 좋을 것이다. 대략 합치면 아래처럼 된당!

맘에 안 든다면 마음껏 고쳐 쓰도록 하장. (나의 디자인 감각은 셀프 디스 수준!)

list.html (모달 적용버젼)

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>E7E JS 께시판</title>
    <link rel="shortcut icon" 
          href="https://img.icons8.com/?size=512&id=42814&format=png" 
          type="image/x-icon">
<style>
    #wrapper {
        width:520px;
        margin: 20px auto;
        color: rgb(83, 0, 161);
    }

    #header {
        border-bottom: 2px solid orange;
        text-align: center;
    }
    #content {
        height:70vh;
        overflow: auto;
    }
    #footer {
        height:10vh;
        line-height: 200%;
        text-align: center;
    }
    #list,#list th,#list td {
        border:1px solid black;
        text-align: center;
    }
    th {
        background-color: orange;
    }
    table {
        width: 100%;
    }
    #modalWin{
        position: fixed;
        width:100vw;
        height:100vh;
        left:0px;
        top:0px;
        z-index: 1000;
      /*  background-color: blueviolet; */
        background-color: rgba(138, 43, 226, 0.9);
        display: none;
    }
    #modalCont {
        width:400px;
        height:70%;
        margin:10% auto;
        border:3px solid black; /* 낸중에 필요없음 주석 */
        background-color: gray;
        color:yellow;
        text-align: center;
    }
    #menu {
        width:100%;
        height:10%;
        text-align: right;
    }
    #close {
        font-size: 2em;
    }
</style>
</head>
<body>
<!-- 모달 모달  -->
<div id="modalWin">
    <div id="modalCont">
        <div id="menu">
            <button id="close" onclick="fmodalClose()">X</button>
        </div>
        <div id="detail">
            <form action="" method="get">
                <table>
                    <tr><td>제목</td><td><input type="text" name="n_title" value="" required></td></tr>
                    <tr><td>글쓰니</td><td><input type="text" name="n_writer" value="" disabled></td></tr>
                    <tr><td colspan="2">내용</td></tr>
                    <tr><td colspan="2">
                            <textarea name="n_cont" cols="40" rows="10" required></textarea>
                        </td>
                    </tr>
                    <tr><td colspan="2">관련언어(최소1개 MAX 3개까지 선택)</td></tr>
                    <tr><td colspan="2">
                        HTML<input type="checkbox" name="n_cate" value="HTML" onclick="ckCnt(this)">
                        CSS<input type="checkbox" name="n_cate" value="CSS" onclick="ckCnt(this)">
                        JS<input type="checkbox" name="n_cate" value="JS" onclick="ckCnt(this)">
                        JAVA<input type="checkbox" name="n_cate" value="JAVA" onclick="ckCnt(this)">
                        ORACLE<input type="checkbox" name="n_cate" value="ORACLE" onclick="ckCnt(this)">
                        </td>
                    </tr>
                    <tr><td colspan="2"><br>
                            <button onclick="fPreSub('modify')">수정</button>&nbsp;&nbsp;
                            <button onclick="fPreSub('delete')">삭제</button>
                        </td>
                    </tr>
                </table>        
            </form> 
            <div>
                <img src="https://cdn.pixabay.com/photo/2019/11/28/21/31/lynx-4660096_1280.jpg" 
                     style="width:100%;height:150px">
            </div>       
        </div>
    </div>
</div>
<!-- 화면 레이아웃-->    
<div id="wrapper">
    <div id="header">
        <h1>어리둥절 JS 께시판</h1>
    </div>
    <div id="content"></div>
    <div id="footer">
        <h1>&copy;E7E Compony Since 1969</h1>
    </div>        
</div>
<script>
//전역 변수
const myModalWin = document.querySelector("#modalWin"); 
const myHeader = document.querySelector("#header");
const myContent = document.querySelector("#content");
const myFooter = document.querySelector("#footer");
const myTitle = document.querySelector("[name=n_title]");
const myWriter = document.querySelector("[name=n_writer]");
const myCont = document.querySelector("[name=n_cont]");
const myCate = document.querySelectorAll("[name=n_cate]");
const tblName ="E7eBoard";
//괘니 백틱으로 써보는 템플릿
const writeLink = `
    <div id="links" style="text-align:right">
        <a href="write.html"><button>새글 쓰깅</button></a>
    </div>
`;
let loDatas;

// Global variables
const maxCnt = 3;
let totalCnt = 0;
const myForm = document.forms[0];
let modOrDel ="";


function fPreSub(pSet){
    modOrDel = pSet;
}

// Global functions
const ckCnt = function(pThis){
    if(pThis.checked){
        totalCnt++;
    }else {
        totalCnt--;
    }
    if(totalCnt > maxCnt){
        alert("3개 까지망");
        pThis.checked = !1;
        totalCnt--;
    }
}

myForm.onsubmit = function(){
    alert(`${modOrDel}을 누르셨군용`);
    event.preventDefault(); 
    ckboxs = document.querySelectorAll("[name=n_cate]:checked");
    if(ckboxs.length < 2){
        alert("최소 2개는 선택하셔야 해용");
    }else {
        myForm.action=`${modOrDel}_action.html`; 
        myForm.submit();
    }
}

//글 리스트 출력함수    
function gulList(){
    loDatas =  JSON.parse(localStorage.getItem(tblName));
    let tblStr = `<table id="list"><tbody>`;
    tblStr += `<tr><th>글번</th><th>제목</th><th>지으니</th><th>관련</th><th>날짜</th></tr>`;
    for(let i=0; i<loDatas.length; i++){
        let gul = loDatas[i];
        tblStr += `<tr>`;
        tblStr += `<td>${gul.num}</td>`;    
        tblStr += `<td><a href="#" onclick="fmodalOpen('${gul.num}')">${gul.title}</a></td>`;    
        tblStr += `<td>${gul.writer}</td>`;    
        tblStr += `<td>${gul.cate}</td>`;    
        tblStr += `<td>${gul.date}</td>`;      
        tblStr += `<tr>`;
    }
    tblStr += `</tbody></table>`;
    tblStr += writeLink;
    myContent.innerHTML = tblStr;
}
//모든 태그해석이 끝나면(DOMContentLoaded 이벤트) 자동실행    
window.addEventListener("DOMContentLoaded",function(){
    gulList();
});

//모달 열기
const fmodalOpen = function(pNum){
    event.preventDefault();  // a 태그 링크 이동 막깅
    for(let i=0; i<loDatas.length; i++){
        if(loDatas[i].num == pNum){
            myTitle.value = loDatas[i].title;
            myWriter.value = loDatas[i].writer;
            myCont.value = loDatas[i].cont;
            let cates = loDatas[i].cate;
            totalCnt = cates.length;
            for(let j=0; j < cates.length; j++){
                document.querySelector(`[type=checkbox][value=${cates[j]}]`).checked = true;
            }
            break;
        }
    }
    myModalWin.style.display = "block";
}

//모달 닫기
const fmodalClose = function(){
    myModalWin.style.display = "none";
}
</script>  
</body>
</html>

CSS 기럭지가 기러지고, write.html에 있던 스크립트도 재활용하였당.

(따로 빼면 좋은데, 보통 개발시에는 흩어져 있는 것보다 찾기 쉬운 게 좋당)

눈 뜨고 볼만한 부분은 관련언어 체크박스를 읽어온 값에 맞춰 다시 체크하는 정도!(화이팅!)

다음 글을 위해 수정/삭제 버튼  이벤트에 action을 넣어 놓았당

 

 

살다 보면  눈 과 눈 의 차이를 알아야 할 때가 있다.

눈 속에 담긴 눈에 비친 눈을 찾는 건 그런 건 일도 아니었다.

 

당신은 사랑 과 사랑의 차이를 아는가?

술 과 술 , 삶 과 삶의 차이, 사람 과 사람의 차이는?

 

아무것도 모른다면  껍데기가 아직 두껍다.

더욱 열씨미 자신을 불태우는 달리는 삶을 살아라!

껍데기가 다 타고 남은 재속에 답이 기다린당

구지 빨리 가려하진 마라, 답은 거기에 머무르니..

 

 

https://www.youtube.com/watch?v=nwnUDdvmCy8 

관련글 더보기