상세 컨텐츠

본문 제목

시베리안 허숙희의 자바스크립트 비기닝 27 ( 스크립트 게시판!)

자바스크립트

by e7e 2023. 6. 22. 20:52

본문

이제 이쯤에서 쪼메 이상한 게시판을 맹글어 보도록 하장!(예전 모델1방식으로..)

데이타 저장공간으로는 연습을 위해 얼마 전에 배운 LocalStorage를 사용해 보장

 

[만들어 가는  과정에서 서버의 동적액션은 없으니 끊임없이 의심하고 의심해야 한당.

 제대로만 이해한다면, 웹 프로그램의 흐름 이해는 완벽하다고 단언할 수 있겠당! ]

 

먼저 글을 작성하는 페이지를 맹글장.(아래 코드를 카.복 하장)

write.html  [checkbox 갯수 체크와 submit부분은 유심히 보장!]

<!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);
    }
    #line {
        width:65%;
        height:10px;
        background-color: orange;
    } 
</style>
</head>
<body>
<div id="wrapper">
    <h1>어리둥절 JS 께시판</h1>
    <div id="line"></div><br>
    <form action="write_action.html" method="get">
        <table>
            <tr><td>제목</td><td><input type="text" name="n_title" value="aaa" autofocus required></td></tr>
            <tr><td>글쓰니</td><td><input type="text" name="n_writer" value="bbb" required></td></tr>
            <tr><td colspan="2">내용</td></tr>
            <tr><td colspan="2"><textarea name="n_cont" cols="40" rows="10">ccc</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>쩐쏭</button>&nbsp;&nbsp;
                    <button type="reset">따시</button>
                </td>
            </tr>
        </table>        
    </form>        
</div>
<script>
    // Global variables
    const maxCnt = 3;
    let totalCnt = 0;
    const myForm = document.forms[0];

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

    myForm.onsubmit = function(){
        event.preventDefault();
        ckboxs = document.querySelectorAll("[name=n_cate]:checked");
        if(ckboxs.length < 2){
            alert("최소 2개는 선택하셔야 해용");
        }else {
            myForm.submit();
        }
    }
</script>    
</body>
</html>

 

action에 써진 파일명이 확장자가 .html임에 주목하자! (의심의 시작)

쩐송 버튼을 누르면  주소표시줄(location)이 GET 방식으로  아래와 유사하게 서버에 요청할 것이다.

http://localhost/jsstudy/CRUD/write_action.html?n_title=aaa&n_writer=bbb&n_cont=ccc&n_cate=HTML&n_cate=CSS&n_cate=JS

 

아직 write_action.html이 없으닝, 커다란 글씨로 아래와 같은 메세지가 보일거시당. 

Not Found
The requested URL was not found on this server.

그렇다면 같은 폴더에 write_action.html을 맹글장. 브라우져 새로고침 버튼을 누르장!

(코드의 split에 주목하면서, 값을 찾아오는 process를 이해해보장)

write.html에서 입력한 값들이 queryString으로 넘어오는데  이것을 ?,&,= 기준 분리하여

값만 뽑아내는 코드와 한글 안깨지게 디코딩 적용한 것이 핵심이당.

<!DOCTYPE html>
<meta charset="UTF-8">
<script>
    /* 위 아래 짝을 맞추어 써야함, 마지막 꺼이 제일 최신꺼
      인코딩함수   escape         encodeURI       encodeURIComponent   
      디코딩함수   unescape       decodeURI       decodeURIComponent
     */
    alert("주소줄값: " + location.href);
    // queryString만 
    let queryString = location.href.split("?")[1];
    alert("queryString: " + queryString);

    let title = queryString.split("&")[0].split("=")[1];
    let writer = queryString.split("&")[1].split("=")[1];
    let cont = queryString.split("&")[2].split("=")[1];
    
    //관련언어는 여러갱
    let cate = [];     // 빈 배열(여러 값 담껭..)
    let items = queryString.split("&");
    for(let i=0; i<items.length; i++){
        if( (items[i].split("=")[0]) == "n_cate"){
            cate.push(items[i].split("=")[1]);
        }
    }

    // 테스통 decodeURIComponent는 한글 안 깨지겡 디코딩
    alert(`title: ${decodeURIComponent(title)}`);
    alert(`writer:  ${decodeURIComponent(writer)}`);
    alert(`cont:  ${decodeURIComponent(cont)}`);
    alert(`cate:  ${decodeURIComponent(cate)}`);
</script>

 

눈치 챗GPT 했겠지만, 저런식으로 짠다면 개발자가 요청URL 오는 것마다 Case By Case로 직접

처리해야 하므로 쓸 수 없는 코드당. 일반화(Generalization) 자동화가 필요하당.

아래코드로  write_action.html의 소스를 덮어쓰고 다시 테스트 해보장!(잘 될 거시당!)

만약 안된다면 주소표시줄에 ?가 있고 값들이 있는지 확인한당!

길지 않은 소스이니 빠른 눈놀림으로 으음.... 오켕!, 이상하면 잘하는 사람과 가치 이해

[왜 이렇게 하는 거예요?, 내 맘이당. jsp시뮬레이션으로 이해를 높이려 시도 중]

<!DOCTYPE html>
<meta charset="UTF-8">
<script>
    //사전처리 및 요청내용 추출 일반화 자동화
    const jusojul = location.href;
   
    const out = {};  // JSP out객체 흉네
    out.print = document.write.bind(document);

    const request = {}; // JSP request객체 흉네 
    request.getParameter = function(pName){
        return request[pName].split(",")[0];
    }
    request.getParameterValues = function(pName){
        return request[pName].split(",");
    } 

    request.url = jusojul.split("?")[0]; //? 왼쪽 값
    request.queryString = "";            // 초기값

    if(jusojul.includes("?")){           // 요청값이 있다면(?가 있다면)
        request.queryString = decodeURIComponent(jusojul.split("?")[1]);
        let items = request.queryString.split("&");
        for(let i=0; i<items.length; i++){
            let nameValue = items[i].split("=");
            if(request[nameValue[0]]){    // 이미 같은 name값이 있는 경우
                    request[nameValue[0]] += `,${decodeURIComponent(nameValue[1])}`;
            }else {
                request[nameValue[0]] = decodeURIComponent(nameValue[1]);
            }
        }
    }

    // 테스통!
    console.log(request);
    out.print(request.getParameter("n_title")+"<br>");
    out.print(request.getParameter("n_writer")+"<br>");
    out.print(request.getParameter("n_cont")+"<br>");
    out.print(request.getParameterValues("n_cate"));
</script>

 

요 타이밍에 소스를 조금 정리하장.

위 소스를 계속 html에 넣고 다니는 건 좋지 않당.(공부용? 좋을수동?)

일반화 자동화 해서 테스통까지 마쳤으니, jsp.js 파일명으로 아래 코드를 저장하장!

    //사전처리
    const jusojul = location.href;
   
    const out = {};
    out.print = document.write.bind(document);

    const request = {};
    request.getParameter = function(pName){
        if(!request[pName]) return null;
        return request[pName].split(",")[0];
    }
    request.getParameterValues = function(pName){
        if(!request[pName]) return null;
        return request[pName].split(",");
    } 

    request.url = jusojul.split("?")[0];
    request.queryString = "";

    if(jusojul.includes("?")){
        request.queryString = decodeURIComponent(jusojul.split("?")[1]);
        let items = request.queryString.split("&");
        for(let i=0; i<items.length; i++){
            let nameValue = items[i].replaceAll("+"," ").split("="); // 공백 처링
            if(request[nameValue[0]]){    // 이미 같은 name값이 있는 경우
                request[nameValue[0]] += `,${decodeURIComponent(nameValue[1])}`;
            }else {
                request[nameValue[0]] = decodeURIComponent(nameValue[1]);
            }
        }
    }

    // 날짜 포맷함수, 괘니 필요할 것 같아서, 미리
    function dateForm(pDate,pSep){
        let ranAddDay = Math.round(Math.random()*10);
        pDate.setDate(ranAddDay);
        let sYear = pDate.getFullYear();
        let sMonth = pDate.getMonth()+1;
        if(sMonth < 10) sMonth = "0"+sMonth; 
        let sDate = pDate.getDate();
        if(sDate < 10) sDate = "0"+sDate;
        
        return `${sYear}${pSep}${sMonth}${pSep}${sDate}`;
    }

    /*
    console.log(request);
    out.print(request.getParameter("n_title")+"<br>");
    out.print(request.getParameter("n_writer")+"<br>");
    out.print(request.getParameter("n_cont")+"<br>");
    out.print(request.getParameterValues("n_cate"));
    */

 이제 write_action.html의 소스도 아래 처럼 다시 쓰장!

<!DOCTYPE html>
<meta charset="UTF-8">
<!--jsp 시뮬레이레 jsp.js 추강 -->
<script src="jsp.js"></script>
<script>
    let title = request.getParameter("n_title");
    let writer = request.getParameter("n_writer");
    let cont = request.getParameter("n_cont");
    let cate = request.getParameterValues("n_cate"); 

    // LocalStorage에 저장하장,이전에 만든 localStorage 편하게
    // 다루는 거 있으면 좋은뎅.., 그냥 하장
    const tblName ="E7eBoard";
    let num = 1; 
    let gulDatas = localStorage.getItem(tblName); //로컬스토리지 읽기(없으면 null)
    if(!gulDatas){ 
        gulDatas = []; 
    }else {           // 이미 글이 있을 경우
       gulDatas = JSON.parse(gulDatas); // 문자열 객체화
       num = gulDatas[gulDatas.length-1].num+1;   
    }

    // 개별 데이타 하나의 글 정보로 모으깅
    let gulInfo = {
        num,
        title,
        writer,
        cont,
        cate,
        date: dateForm(new Date(),"-") 
    }
    // 배열에 추가
    gulDatas.push(gulInfo);

    //배열을 문자열화 저장!
    localStorage.setItem(tblName,JSON.stringify(gulDatas));

    alert("글이 잘 저장 되었습니당");
    // 아래는 일단 주석처리 해 놓장!
    //location.replace("list.html");
</script>

이제 브라우져에서 새로 고침을 누를 때 마다 localStorage에 아래처럼 글이 추가된당

확인이 되었다면, 위 소스에서 맨 아래 location.replace("list.html") 앞의 주석을 풀장

새로 고침하면 list.html이 없으니Not Found 화면이 나올 거시당.

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;
    }
    table,th,td {
        border:1px solid black;
    }
    table {
        width: 100%;
    }
</style>
</head>
<body>
<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 myHeader = document.querySelector("#header");
const myContent = document.querySelector("#content");
const myFooter = document.querySelector("#footer");
const tblName ="E7eBoard";
//괘니 백틱으로 써보는 템플릿
const writeLink = `
    <div id="links" style="text-align:right">
        <a href="write.html"><button>새글 쓰깅</button></a>
    </div>
`;
//모달 띠울 함수 이름만 미리 준비
const fmodal = function(pNum){
    event.preventDefault();  // a 태그 링크 이동 막깅
    alert(`클릭하신 글번호는 ${pNum}임당`);
}

//글 리스트 출력함수    
function gulList(){
    let loDatas =  JSON.parse(localStorage.getItem(tblName));
    let tblStr = "<table><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="fmodal('${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();
});
</script>  
</body>
</html>

list.html 소스는 그동안 욜씨미 했다면, css 스타일로 라인수의 기럭지만 길징

특별히 어려운 코드 부분은 없을 거시당.  그래도 규모도 어려움이라고 양이 많아지면

아무래도 누니 피곤해지니, 힘내서 차분히 화긴하도록 하장!

 


 

떠억 벌어진 2개의 입이 다물어질 줄 모른당. 난 아무렇지 않은뎅

고지혈증 수치가 900이 넘었다고 난리 부르스당.

다음날 연세지긋하신 할머니 의사께서 직접 오셨당.

내 손을 잡고 주무르면서 말없이 딴 곳을 바라본당.

 

초 고수당!!! 먼저 질문할 순 없당. 나도 딴 곳을 본당

생각과 의도를 읽어내야 한당!, 뭐징?  기가 빨린당.

오랫만이당. 손바닥 땀이 얼어가는 이 몹쓸파동!, 뭐라도 해야만 한당!

 

https://www.youtube.com/watch?v=c6rP-YP4c5I 

 

 

 

 

 

 

관련글 더보기