빵 입니다.

dom api를 사용하여 Todo 만들기 본문

프론트엔드/TODO 만들기

dom api를 사용하여 Todo 만들기

bread-gee 2019. 2. 20. 15:16

기능 정의

  • Todo 입력
  • Todo 수정
  • Todo 삭제
  • Todo Total 갯수 체크
  • Todo 완료 갯수 체크
  • Todo 미완료 갯수 체크


어떻게 해야하는지 감이 잡히지 않아서 dom api만 가지고 개발을 했다.

우선, 코드가 매우 비효율적이다.

재사용할 수 있는 코드가 매우 적고, ES5, ES6 섞어 쓴 부분도 많다.

자바스크립트보단 html, css 단에 더 집중을 많이 한 느낌이 든다.



HTML

        

Todo

    완료 0 미완료 0 0

    CSS

    .todo_wrap{width:300px; margin:0 auto;}
    .todo_wrap h1{text-align:center;}
    .input_wrap{background:red;}
    .input_wrap:after{content:""; display:block; clear:both;}
    .input_wrap input{box-sizing:border-box; float:left; width:231px; height:40px; outline:0 none; border:1px solid #999; text-indent:5px;}
    .input_wrap input:focus{border-color:#03cf5d;}
    .input_wrap button{box-sizing:border-box; float:left; width:70px; height:40px; margin-left:-1px; outline:0 none; border:1px solid #03cf5d; background:#03cf5d; color:#fff;}
    .input_wrap button:hover{cursor:pointer;}
    
    .todo_list{list-style-type:none; margin:0; padding:30px 0;}
    .todo_list li{line-height:30px; font-family:'Noto Sans KR', sans-serif; font-size:13px;}
    .todo_list li input{vertical-align:middle;}
    .todo_list li label{vertical-align:middle; cursor:pointer;}
    .todo_list li button{box-sizing:border-box; width:20px; height:20px; outline:0 none; border:0 none; background:#ffffff; line-height:20px; color:red; vertical-align:middle; cursor:pointer; transition:background-color 0.5s ease;}
    .todo_list li button:hover{background:#03cf5d;}
    .todo_list .complete{text-decoration:line-through;}
    
    .todo_count{}
    .todo_count>span{position:relative; display:inline-block; width:30%; font-size:12px; text-align:center;}
    .todo_count>span>strong{position:relative; top:1px; display:inline-block; color:#1aaf5c;}
    

    JAVASCRIPT

    // 초기화
    var todoList = document.getElementById('todoList');
    var btnAdd = document.getElementById('btnAdd');
    var inputText = document.getElementById('txtInput');
    inputText.focus();
    
    var totalItems = 0;
    var todoCount = document.getElementById('todoCount');
    
    // todo 추가
    function addNewItem(list, string){
        if( inputText.value === '' || inputText.value === ' ' || !inputText ){
            alert('할 일을 입력해주세요.');
            return false;
        }
        var todoWrap = document.createElement('li');
        var todoTimestamp = new Date().getTime();
        todoWrap.innerHTML = `
            
            
            `;
        list.appendChild(todoWrap);
    
        var chkbox = todoWrap.children[0];
        chkbox.onclick = chkClassToggle;
    
        var todoTxt = todoWrap.children[1];
        todoTxt.addEventListener("dblclick", renameItem);
    
        var btnDelete = todoWrap.children[2];
        btnDelete.addEventListener("click", deleteItem);
    
        inputText.value = '';
        inputText.focus();
        updateState();
    }
    // todo 삭제
    function deleteItem(){
        var todo = this.parentNode;
        todoList.removeChild(todo);
        updateState();
    }
    // 건수 계산
    function updateState(){
        totalItems = todoList.querySelectorAll('li').length;
        var cntItem = todoList.querySelectorAll('.complete').length;
        todoCount.querySelector('#cntTotal').innerHTML = totalItems;
        todoCount.querySelector('#cntComplete').innerHTML = cntItem;
        todoCount.querySelector('#cntIncomplete').innerHTML = totalItems - cntItem;
    }
    // todo 텍스트 변경 이벤트
    function changeTxt(){
        var todo = this.parentNode;
        var todoId = this.previousElementSibling.id;
        var todoValue = this.value;
        if( this.getElementsByTagName('input') ){
            todo.innerHTML = `
                
                
                `;
            var todoTxt = todo.children[1];
            todoTxt.focus();
        }    
        var chkbox = todo.children[0];
        chkbox.onclick = chkClassToggle;
    
        var todoTxt = todo.children[1];
        todoTxt.addEventListener("dblclick", renameItem);
    
        var btnDelete = todo.children[2];
        btnDelete.addEventListener("click", deleteItem);
    
        updateState();
    }
    // todo 내용 변경
    function renameItem(){
        var todo = this.parentNode;
        var todoId = this.previousElementSibling.id;
        var todoValue = this.innerText;
    
        if( this.getElementsByTagName('label') ){
            todo.innerHTML = `
                
                
                `;
            var todoTxt = todo.children[1];
            todoTxt.focus();
        }
        todoTxt.addEventListener("focusout", changeTxt);
    
        updateState();
    }
    // 체크박스 체크 시(= todo 완료 시) 클래스 추가
    function chkClassToggle(){
        var todoWrap = this.parentElement;
        if(this.checked){
            todoWrap.className = 'complete';
        }else{
            todoWrap.className = '';
        }
        updateState();
    }
    // 추가 버튼 이벤트
    btnAdd.onclick = function(){
        var todoString = inputText.value;
        addNewItem(todoList, todoString);
    };
    // 입력 필드 키보드 이벤트
    inputText.onkeyup = function(e){
        if(e.which == 13){
            var todoString = inputText.value;
            addNewItem(todoList, todoString);
        }
    };
    

    CODEPEN 확인
    https://codepen.io/bread_gee/pen/pYNGZr


    반응형
    Comments