Timeline

JS Yoon·2022년 1월 4일
0

스파르타

목록 보기
4/4
  1. HTML
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@500&display=swap" rel="stylesheet">
    <script src="js/main.js"></script>
    <link rel="stylesheet" href="css/main.css">
</head>
<body>

  <!-- <<<<<<<<<<<<<<<<<< 배경 부분 >>>>>>>>>>>>>>>>>>> -->
<!--배경 머리-->
<div class="background-header"></div> 
<!-- position: fixed; top: 0;  height: 428px; width: 100%; z-index: -1;-->

<!--배경 바디-->
<div class="background-body"></div> 
  <!--position:fixed; top: 428px; height: 100%; width: 100%; z-index: -1-->
  <!-- fixed 는 위치를 잡아 주지 않으면 형체가 안 보인다-->
  
  
  <!-- <<<<<<<<<<<<<<<<<<<< 바디 시작 >>>>>>>>>>>>>>>>>>>>>-->
  <!--  Body= 1.header+ 2.area-write+ 3.area-read(#cards-box) -->  
  <div class="wrap"> 
    
    <!-------- 헤더 부분 --------->
    <div class="header">
        <h2>Timeline Service</h2>
        <p>
            공유하고 싶은 소식을 입력해주세요.<br>
            24시간이 지난 뒤에는 사라집니다.d
        </p>
    </div>
    
    
    <!------- 타임라인 작성 하는 부분 ------------->
    <!-- area-write = textarea + btn image -->
    <div class="area-write">
        <textarea class="field" name="contents" id="contents" cols="30" rows="10" placeholder="공유하고 싶은 소식을 공유해 주세요"></textarea>
        <img src="images/send.png" alt="" onclick="writePost()">
    </div>

    
    <!----- 저장한 글 목록이 보여지는 부분------->
    <!--  
	######### 가장 중요한 부분 ########!
      데이터베이스(DB) 부분 -> id="${id}-name"        
   데이터베이스의 column 부분:  username, contents(text) 가 들어가는 부분
   RUD 부분(C는 제외): read, update, delete btn 

	#cards-box( = .card + .card ...
	.card = .metadata + .contents

	.matadata = date + ${id}-username
	.contents = ${id}-contents 혹은 ${id}-editarea(> ${id}-textarea)
    -->
    <div id="cards-box" class="area-read">
        <div class="card">
            <div class="meta-data">
                <div class="date">
                    October 10, 2020
                </div>
                <div class="username">
                    anonymous
                </div>
            </div>
            <div class="contents">
                <div id="1-contents" class="text">
                    dsafnkalfklewakflekelafkleajfkleafkldsankflenwaklfnekwlafneklwanfkelawnfkelanfkleanfklew
                </div>
                <div id="1-editarea" class="edit">
                    <textarea name="" id="1-textarea" class="te-edit" cols="30" rows="10"></textarea>
                </div>
            </div>
            <div class="footer">
                <img src="images/edit.png" id="1-edit" class="icon-start-edit" alt="" onclick="editPost('1')">
                <img src="images/delete.png" id="1-delete" class="icon-delete" alt="" onclick="deleteOne('1')">
                <img src="images/done.png" id="1-submit" class="icon-end-edit" alt="" onclick="submitEdit('1')">
            </div>
        </div>
    </div>
</div>
</body>
</html>
  1. Javascript
// 부수적인 동사들: 1.유효성테스트 2.임의의 이름 생성

// 1. 유효성 테스트: 상황에 따라 내용은 다를 수 있다.
function isValidContents(contents) {
    if (contents === "") {
        alert("내용을 입력해주세요");
        return false;
    }

    if (contents.trim().length > 140) {
        alert("내용은 140자 이내(공백 포함)이어야 합니다.")
        return false;
    }
    return true;
}

// 2. 임의의 문자열 생성: copy and paste
function genRandomName(length) {
    let result = '';
    let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let charactersLength = characters.length;
    for (let i = 0; i < length; i++) {
        let number = Math.random() * charactersLength;
        let index = Math.floor(number);
        result += characters.charAt(index);
    }
    return result;
}

/**
 *  ######### CRUD ##########
 *  1. create: writePost()
 *  2. read: getMessages()
 *  2.5 update 준비 editPost(id)
 *  3. update: submitEdit(id)
 *  4. delete: deleteOne(id)
 */

$(document).ready(function (){
    getMessages();
});

// 1. Create
function writePost() {
    let contents = $('#contents').val();

    if (isValidContents(contents)=== false) {
        return ;
    }

    let username = genRandomName(10);

    let data = {'username': username, 'contents': contents}

    $.ajax({
        type: 'POST',
        url: '/api/memos',
        contentType: 'application/json',
        data: JSON.stringify(data),
        success:function(response){
            alert('당신의 소식을 저장하였습니다')
            window.location.reload();
        }
    });

}

// 2. Read
function getMessages() {
    $('#cards-box').empty();

    $.ajax({
        type: 'GET',
        url: '/api/memos',
        success:function(response) {
            for (let responseElement of response) {
                let id = responseElement.id;
                let username = responseElement.username;
                let contents = responseElement.contents;
                let modifiedAt = responseElement.modifiedAt;
                addHTML(id, username, contents, modifiedAt)
            }
        }
    });
}

// 2-1. Read 한 데이터의 웹 구현
function addHTML(id, username, contents, modifiedAt) {
    let tempHTML = `<div class="card">
                        <div class="meta-data">
                            <div class="date">${modifiedAt}</div>
                            <div class="username" id="${id}-username">
                                ${username}
                            </div>
                        </div>
                        <!-- 그냥 보이는 Text or textarea  -->
                        <div class="contents">
                            <div id="${id}-contents" class="text">
                                ${contents}
                            </div>
                            <div id="${id}-editarea" class="edit">
                                <textarea name="" id="${id}-textarea" class="te-edit" cols="30" rows="5"></textarea>
                            </div>
                            <div class="footer">
                                <img id="${id}-edit" src="images/edit.png" class="icon-start-edit"token interpolation">${id}')" alt="">
                                <img id="${id}-delete" src="images/delete.png" class="icon-delete"token interpolation">${id}')" alt="">
                                <img id="${id}-submit" src="images/done.png" class="icon-end-edit"token interpolation">${id}')" alt="">
                            </div>
                        </div>
                    </div>`

    $('#cards-box').append(tempHTML);
}

// 2.5 editPost()
function editPost(id) {
    showEdits(id);
    let contents = $(`#${id}-contents`).text().trim();
    $(`#${id}-textarea`).val(contents);
}

function showEdits(id) {
    $(`#${id}-submit`).show();
    $(`#${id}-editarea`).show();
    $(`#${id}-delete`).show();

    $(`#${id}-edit`).hide();
    $(`#${id}-contents`).hide();
}

function hideEdits(id) {
    $(`#${id}-edit`).show();
    $(`#${id}-contents`).show();

    $(`#${id}-delete`).hide();
    $(`#${id}-submit`).hide();
    $(`#${id}-editarea`).hide();
}

// 3. Update
function submitEdit(id) {
    let username = $(`#${id}-username`).text().trim();
    let contents = $(`#${id}-textarea`).val().trim();

    if (isValidContents(contents) === false) {
        return;
    }

    let data = {'username': username, 'contents': contents};

    console.log(data);
    $.ajax({
        type: 'PUT',
        url: `/api/memos/${id}`,
        contentType: 'application/json',
        data: JSON.stringify(data),
        success: function (response){
            alert('고객님의 소식을 수정하였습니다');
            window.location.reload();
        }
    })
}

// 4. Delete
function deleteOne(id){
    $.ajax({
        type: 'DELETE',
        url: `/api/memos/${id}`,
        success: function (response) {
            let deletedId = response.id;
            alert('당신의 글이 삭제되었습니다');
            window.location.reload();
        }
    });
}
  1. CSS
body {
    margin: 0;
}


/*.background-header 완료*/
.background-header {
    position: fixed;
    top: 0;
    width: 100%;
    height: 428px;
    background-color: #339af0;
    z-index: -1;
}

/*background-body 완료*/
.background-body {
    position: fixed;
    background-color: #dee2e6;
    top: 428px;
    width: 100%;
    height: 100%;
    z-index: -1;
}

.wrap {
    width: 538px;
    margin: 10px auto;
}

.header {
    margin-top: 50px;
}
.header h2 {
    /* h2 크기 */
    height: 33px;
    /* 폰트 */
    color: #ffffff;
    font-size: 42px;
    font-weight: 500;
    font-stretch: normal;
    font-style: normal;
    line-height: 0.79;
    letter-spacing: -0.5px;
    text-align: center;
}

.header p {
    /* p 크기 */
    width: 220px;
    height: 48px;
    margin: 40px auto;
    /* font 관련*/
    font-family: 'Noto Sans KR', sans-serif;
    font-size: 16px;
    font-weight: 500;
    font-stretch: normal;
    font-style: normal;
    line-height: 1.5;
    letter-spacing: -1.12px;
    text-align: center;
    color: #ffffff;

}

textarea.field {
    /* textarea 크기 */
    width: 502px;
    height: 146px;
    /* textarea 모양 */
    border: none;
    border-radius: 5px;
    /*textarea 위치*/
    padding: 18px;
    background-color: #fff;
}

textarea.field::placeholder {
    width: 300px;
    height: 16px;
    font-family: 'Noto Sans KR', sans-serif;
    font-size: 16px;
    font-weight: normal;
    font-stretch: normal;
    font-style: normal;
    line-height: 1;
    letter-spacing: -0.96px;
    color: #868e96;
    text-align: left;
}

.area-write {
    /* send btn 의 위치를 잡기 위해 */
    position: relative;
    width: 538px;
}
.area-write img {
    cursor: pointer;
    /*크기를 줄이고*/
    width: 22.2px;
    height: 18.7px;
    /*위치잡기*/
    position: absolute;
    bottom: 15px;
    right: 17px;
}


#cards-box {
    margin-top: 12px;
}

.card {
    width: 538px;
    background-color: #fff;
    border-radius: 5px;
    margin-bottom: 12px;
}

.card .meta-data {
    position: relative;
    display: flex;
    font-family: 'Spoqa Han Sans';
    font-size: 11px;
    font-weight: normal;
    font-stretch: normal;
    font-style: normal;
    line-height: 1;
    letter-spacing: -0.77px;
    text-align: left;
    color: #adb5bd;
    height: 14px;
    padding: 10px 23px;
}
.card .meta-data .username {
    margin-left: 20px;
}

.contents {
    padding: 0 23px;
    word-wrap: break-word;
    word-break: break-all;
}

.contents div.edit {
    display: none;
}

.contents textarea.te-edit {
    border-top: none;
    border-right: none;
    border-left: none;
    resize: none;
    border-bottom: 1px solid #212529;
    width: 100%;
    font-family: 'Spoqa Han Sans';
}

.footer {
    height: 40px;
    position: relative;
}

.footer .icon-start-edit {
    cursor: pointer;
    position: absolute;
    bottom: 14px;
    right: 55px;
    width: 18px;
    height: 18px;
}
.footer .icon-delete {
    cursor: pointer;
    position: absolute;
    bottom: 12px;
    right: 19px;
    width: 14px;
    height: 18px;
}
.footer .icon-end-edit {
    cursor: pointer;
    position: absolute;
    display: none;
    bottom: 14px;
    right: 55px;
    width: 20px;
    height: 15px;
}
profile
기냥^^

0개의 댓글