Todo - Application
by ti2005
HTML
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<script src="https://unpkg.com/vue"></script>
<div id="app">
<h2>{{ title }}</h2>
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="todo-tab" data-toggle="tab" href="#todo" role="tab" aria-controls="todo" aria-selected="true">Todo</a>
</li>
<li class="nav-item">
<a class="nav-link" id="user-tab" data-toggle="tab" href="#user" role="tab" aria-controls="user" aria-selected="false">Users</a>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div class="tab-pane active" id="todo" role="tabpanel" aria-labelledby="todo-tab">
<input class="form-control new-todo" v-model="newTodo" v-on:keyup.enter="onPressEnter" placeholder="New Todo (Type and press 'enter' key)" @change="checkExistOrNot" />
<small v-if="duplicateFound" class="error-message">Todo already exists.</small>
<ol>
<li v-for="(todo, index) in todos" v-if="checkPropertyExists(todo, 'completed')" v-bind:class="index === 0 ? newItemCss : ''">
<span v-if="!todo.isEdit" v-bind:class="todo.completed ? 'completed' : ''">
{{todo.title}}</span>
<input class="form-control form-control-sm" v-if="todo.isEdit" v-model="todo.title" />
<button @click="changeStatus(todo)" class="btn btn-sm" v-bind:class="todo.completed ? 'btn-warning' : 'btn-success'">
{{todo.completed ? 'Reopen' : 'Done'}}
</button>
<button v-if="!todo.isEdit && !todo.completed" class="btn btn-sm btn-primary" @click="editTodo(todo, true)">
Edit
</button>
<button v-if="todo.isEdit"...
CSS
.completed {
text-decoration: line-through;
}
li {
padding: 5px;
border-bottom: 1px solid #ccc;
}
li:last-child {
border-bottom: none;
}
.error-message {
color: red;
padding-left: 15px;
position: relative;
top: -5px;
font-size: 11px;
}
.new-todo {
margin: 5px;
width: 98%;
}
.li-added-css {
background-color: rgba(255, 235, 59, 0.55);
}
JavaScript
new Vue({
el: '#app',
data: {
title: '',
todos: [{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
},
{
"userId": 1,
"id": 2,
"title": "quis ut nam facilis et officia qui",
"completed": true
},
{
"userId": 1,
"id": 3,
"title": "fugiat veniam minus",
"completed": false
},
{
"userId": 1,
"id": 4,
"title": "et porro tempora",
"completed": true
},
{
"userId": 3,
"id": 45,
"title": "velit soluta adipisci molestias reiciendis harum"
},
{
"userId": 1,
"id": 5,
"title": "laboriosam mollitia et enim quasi adipisci quia provident illum",
"completed": false
}
],
users: [],
duplicateFound: false,
newItemCss: ''
},
created() {
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => response.json())
.then(json => this.users = json)
},
methods: {
checkPropertyExists(todo, key) {
return (key in todo) ? true : false;
},
changeStatus(todo) {
todo.completed = !todo.completed;
},
editTodo(todo, value) {
this.$set(todo, 'isEdit', value)
},
checkExistOrNot() {
const idx = this.todos.findIndex(o => o.title === this.newTodo.trim());
this.duplicateFound = (idx === -1) ? false : true;
},
onPressEnter() {
const idx = this.todos.findIndex(o => o.title === this.newTodo);
if (idx === -1) {
this.todos.unshift({
"userId": 1,
"id": new Date().getTime(),
"title": this.newTodo,
"completed": false
});
this.newItemCss = 'li-added-css';
setTimeout(() => {
this.newItemCss = '';
}, 1000);
}
},
}
})