자바스크립트를 vanilla js 를 통해 mvc 형식으로 구현한 예제이다. 만드신 분 멋짐.~
index.html
<div class="list-container">
<header>
<form id="list-form">
<div class="list-form__add-item">
<input type="text" id="add-item__input" required autofocus>
<input type="submit" value="✚">
</div>
<div class="list-form__search-item">
<input type="search" id="search-item__input">
<label for="search-item__input">
<i class="fa fa-search" aria-hidden="true"></i>
</label>
</div>
</form>
</header>
<section>
<ul class="to-do-list"></ul>
<hr>
<ul class="finished-list"></ul>
</section>
<div class="text-center">
<a href="https://github.com/EastSun5566" target="_blank">
<i class="fa fa-github" aria-hidden="true"></i>
</a>
</div>
</div>
index.css
@import url(//fonts.googleapis.com/earlyaccess/notosanstc.css);
* {
/* border: 1px solid #000; */
position: relative;
box-sizing: border-box;
}
:root {
--color-primary: #d3cce3;
--color-secondary: chocolate;
--color-font-dark: darkred;
--color-font-light: #eee;
}
body {
margin: 0;
min-height: 100vh;
background: radial-gradient(circle, #e9e4f0, var(--color-primary));
color: var(--color-font-dark);
letter-spacing: 2px;
font-family: 'Noto Sans TC', sans-serif;
display: flex;
justify-content: center;
align-items: center;
}
/* list container */
.list-container {
width: 60%;
padding: 16px 0;
}
@media (max-width: 500px) {
.list-container {
width: 100%;
}
}
/* form */
#list-form {
display: flex;
justify-content: space-around;
}
.list-form__add-item,
.list-form__search-item {
width: 45%;
}
input {
background-color: transparent;
border: 2px solid var(--color-secondary);
border-radius: 100px;
padding: 16px;
text-indent: 8px;
color: var(--color-font-dark);
letter-spacing: 2px;
transition: 0.5s;
}
input:focus {
outline: none;
}
/* add input */
input[type=text],
input[type=search] {
width: 100%;
}
#add-item__input:focus,
#search-item__input:focus {
background-color: var(--color-secondary);
color: var(--color-font-light);
}
input[type=text] {
padding-right: 40px;
}
input[type=submit] {
border: none;
font-size: 16px;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
transition: 0.5s;
cursor: pointer;
}
/* serch input */
input[type=search] {
text-indent: 24px;
}
label[for=search-item__input] {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
transition: 0.5s;
cursor: pointer;
}
#add-item__input:focus + input[type=submit],
#search-item__input:focus + label[for=search-item__input]{
color: var(--color-font-light);
}
/* list */
ul {
list-style: none;
padding: 0;
}
/* to do list */
.to-do-list:empty::before {
content: 'Nothing to do...';
display: block;
text-align: center;
font-size: 12px;
font-weight: lighter;
}
/* finished list */
.finished-list:empty::before {
content: 'Nothing finished...';
display: block;
text-align: center;
font-size: 12px;
font-weight: lighter;
}
li {
border: 1.5px solid transparent;
border-radius: 100px;
margin: 8px;
padding: 8px;
display: flex;
justify-content: space-between;
align-items: center;
font-weight: bold;
transition: 0.5s;
/* animation: fadeIn 0.5s both; */
}
@keyframes fadeIn {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
li:hover {
/* border-color: var(--color-secondary); */
}
.item__content {
max-width: 80%;
overflow: hidden;
text-overflow: ellipsis;
}
/* item action */
.item__action {
width: 20%;
display: flex;
justify-content: space-between;
align-items: center;
}
/* check input */
input[type="checkbox"] {
appearance: none;
padding: 8px;
transition: 0.3s;
cursor: pointer;
}
input[type=checkbox]:checked,
input[type=checkbox]:hover {
background-color: var(--color-secondary);
}
input[type=checkbox]:checked::after {
content: '✔';
position: absolute;
top: 50%;
left: 35%;
transform: translate(-50%, -50%);
color: #eee;
font-weight: bold;
}
.fa-trash {
display: block;
cursor: pointer;
transition: 0.3s 0.1s;
}
.fa-trash::after {
content: '';
position: absolute;
right: -10px;
width: 3px;
height: 100%;
background-color: var(--color-secondary);
z-index: -1;
transition: 0.3s;
}
.fa-trash:hover {
color: var(--color-font-light);
}
.fa-trash:hover::after {
width: 200%;
}
/* hr */
hr {
width: 80%;
border: 1px solid var(--color-secondary);
opacity: 0.5;
}
.text-center {
text-align: center;
}
mvc.js
// model
var Data =(function() {
var list = [];
var Item = function(content) {
this.content = content;
};
Item.prototype.finished = false;
var addItem = function(content) {
var item = new Item(content);
list.push(item);
}
var removeItem = function(item_index) {
list.splice(item_index, 1);
}
var checkItem = function(item_index) {
var current_item = list[item_index];
current_item.finished = !current_item.finished;
}
return {
list: list,
Item: Item,
addItem: addItem,
removeItem: removeItem,
checkItem: checkItem
};
})();
//controller
var Controller = (function(){
var addItem = function(e) {
e.preventDefault();
var add_value = add_input.value;
Data.addItem(add_value);
UI.showList(Data.list);
form.reset();
};
var searchItem = function() {
var search_value = search_input.value;
var filter_list = Data.list.filter(function(item) {
return item.content.indexOf(search_value) > -1;
});
UI.showList(filter_list);
}
var removeItem = function(e) {
if(e.target.tagName !== 'I') return;
var item_id = e.target.parentNode.parentNode.id;
var item_index = item_id.split('-')[1];
Data.removeItem(item_index);
UI.showList(Data.list);
}
var checkItem = function(e) {
if(e.target.tagName !== 'INPUT') return;
var item_id = e.target.parentNode.parentNode.id;
var item_index = item_id.split('-')[1];
Data.checkItem(item_index);
UI.showList(Data.list);
}
var form = document.forms['list-form'];
var add_input = form['add-item__input'];
var search_input = form['search-item__input'];
var section = document.querySelector('section');
form.addEventListener('submit', addItem);
search_input.addEventListener('input', searchItem);
section.addEventListener('click', removeItem);
section.addEventListener('change', checkItem);
})();
// view
var UI = (function(){
var to_do_list = document.querySelector('.to-do-list');
var finished_list = document.querySelector('.finished-list');
var showList = function(list) {
finished_list.innerHTML = '';
to_do_list.innerHTML = '';
list.forEach(function(item, i) {
if(!item.finished) {
var to_do_item_HTML =
'<li class="to-do-list__item" id="item-'+ i +'">' +
'<div class="item__content">'+item.content+'</div>' +
'<div class="item__action">' +
'<i class="fa fa-trash" aria-hidden="true"></i>' +
'<input type="checkbox">' +
'</div>' +
'</li>';
to_do_list.insertAdjacentHTML('afterbegin', to_do_item_HTML);
}else {
var finished_item_HTML =
'<li class="to-do-list__item" id="item-'+ i +'">' +
'<div class="item__content">'+item.content+'</div>' +
'<div class="item__action">' +
'<i class="fa fa-trash" aria-hidden="true"></i>' +
'<input type="checkbox" checked>' +
'</div>' +
'</li>';
finished_list.insertAdjacentHTML('afterbegin', finished_item_HTML);
}
});
}
return {
showList: showList
};
})();
실행화면
https://codepen.io/EastSun5566/pen/WdVGJE