需求
1. 将用户输入添加至待办项
2. 可以对todolist进行分类(待办项和已完成组),用户勾选既将待办项分入已完成组
3. todolist的每一项可删除和编辑
4. 下方有clear按钮,并清空所有todolist项
html
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
6 <title>ToDoList—最简单的待办事项列表</title>
7 <meta name="description" content="ToDoList无须注册即可使用!" />
8 <link rel="stylesheet" href="mystyle.css">
9 </head>
10 <body>
11 <div class="header">
12 <div class="box">
13 <form action="javascript:postaction()" id="form">
14 <label for="title">ToDoList</label>
15 <input type="text" id="title" name="title" placeholder="添加ToDo" required="required" autocomplete="off" />
16 </form>
17 </div>
18 </div>
19 <div class="content">
20 <h2 onclick="save()">正在进行 <span id="todocount"></span></h2>
21 <ol id="todolist" class="demo-box">
22 </ol>
23 <h2>已经完成 <span id="donecount"></span></h2>
24 <ul id="donelist">
25 </ul>
26 </div>
27 <div class="footer">
28 Copyright © 2019 todolist.cn <a href="javascript:clear();">clear</a>
29 </div>
30 <script type="text/javascript" src="myjs.js"></script>
31 </body>
32 </html>
css
1 body {
2 margin: 0;
3 padding: 0;
4 font-size: 16px;
5 background: #CDCDCD;
6 }
7
8 .header {
9 height: 50px;
10 background: #333;
11 background: rgba(47,47,47,0.98);
12 }
13
14 .header .box,.content{
15 width: 600px;
16 padding: 0 10px;
17 margin: 0 auto;
18 }
19 .content{
20 margin: 0 auto;
21 }
22
23 label {
24 float: left;
25 width: 100px;
26 line-height: 50px;
27 color: #DDD;
28 font-size: 24px;
29 cursor: pointer;
30 font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
31 }
32
33 .header input {
34 float: right;
35 width: 60%;
36 height: 24px;
37 margin-top: 12px;
38 text-indent: 10px;
39 border-radius: 5px;
40 box-shadow: 0 1px 0 rgba(255,255,255,0.24), 0 1px 6px rgba(0,0,0,0.45) inset;
41 border: none
42 }
43
44 input:focus {
45 outline-width: 0
46 }
47
48 h2 {
49 position: relative;
50 }
51
52 span {
53 position: absolute;
54 top: 2px;
55 right: 5px;
56 display: inline-block;
57 padding: 0 5px;
58 height: 20px;
59 border-radius: 20px;
60 background: #E6E6FA;
61 line-height: 22px;
62 text-align: center;
63 color: #666;
64 font-size: 14px;
65 }
66
67 ol,ul {
68 padding: 0;
69 list-style: none;
70 }
71
72 li input {
73 position: absolute;
74 top: 2px;
75 left: 10px;
76 width: 22px;
77 height: 22px;
78 cursor: pointer;
79 }
80
81 p {
82 margin: 0;
83 }
84
85 li p input {
86 top: 3px;
87 left: 40px;
88 width: 70%;
89 height: 20px;
90 line-height: 14px;
91 text-indent: 5px;
92 font-size: 14px;
93 }
94
95 li {
96 height: 32px;
97 line-height: 32px;
98 background: #fff;
99 position: relative;
100 margin-bottom: 10px;
101 padding: 0 45px;
102 border-radius: 3px;
103 border-left: 5px solid #629A9C;
104 box-shadow: 0 1px 2px rgba(0,0,0,0.07);
105 }
106
107 ol li {
108 cursor: move;
109 }
110
111 ul li {
112 border-left: 5px solid #999;
113 opacity: 0.5;
114 }
115
116 li a {
117 position: absolute;
118 top: 2px;
119 right: 5px;
120 display: inline-block;
121 width: 14px;
122 height: 12px;
123 border-radius: 14px;
124 border: 6px double #FFF;
125 background: #CCC;
126 line-height: 14px;
127 text-align: center;
128 color: #FFF;
129 font-weight: bold;
130 font-size: 14px;
131 cursor: pointer;
132 }
133
134 .footer {
135 color: #666;
136 font-size: 14px;
137 text-align: center;
138 }
139
140 .footer a {
141 color: #666;
142 text-decoration: none;
143 color: #999;
144 }
JS
1 function $(id) {
2 return document.getElementById(id);
3 }
4
5 function clear() {
6 localStorage.clear();
7 load();
8 }
9
10 function postaction() {
11 if($('title').value == ''){
12 alert('不可为空!')
13 }else{
14 var data = loadData();
15 var todo = {'title':$('title').value,'done':false};
16 data.push(todo);
17 saveData(data);
18 $('form').reset();
19 load();
20 }
21 }
22
23 function loadData() {
24 var collection = localStorage.getItem('todo');
25 if(collection){
26 return JSON.parse(collection);
27 }else{
28 return [];
29 }
30 }
31
32 function saveData(data) {
33 localStorage.setItem('todo',JSON.stringify(data))
34 }
35
36 function remove(i) {
37 var data = loadData();
38 data.splice(i,1);
39 saveData(data);
40 load();
41 }
42
43 function update(i,field,value) {
44 var data = loadData();
45 var todo = data.splice(i,1)[0];
46 todo[field] = value;
47 data.splice(i,0,todo);
48 saveData(data);
49 load();
50 }
51
52 function edit(i) {
53 load();
54 var p = document.getElementById('p-'+i);
55 title = p.innerHtml;
56 p.innerHTML = "<input id='input-" + i + "' value='" + title + "' />";
57 var input = $("input-" + i);
58 input.setSelectionRange(0,input.value.length); // 选中value
59 input.focus();
60 input.onblur = function () {
61 if(input.value.length == 0){
62 p.innerHTML = title;
63 alert('不能为空!');
64 }else{
65 update(i,'title',input.value);
66 }
67 }
68 }
69
70 function load() {
71 var todolist = $('todolist');
72 var donelist = $('donelist');
73 var collection = localStorage.getItem('todo');
74 if(collection != null){
75 var data = JSON.parse(collection);
76 var todoCount = 0;
77 var doneCount = 0;
78 var todoString = "";
79 var doneString = "";
80 for(var i = data.length - 1;i >= 0; i--){
81 if(data[i].done){
82 doneString += "<li draggable='true'><input type='checkbox' onchange='update(" + i + ","done",false)' checked='checked' />" +
83 "<p id='p-" + i + "' onclick='edit(" + i + ")'>" + data[i].title + "</p>" +
84 "<a href='javascript:remove(" + i + ")'>-</a></li>";
85 doneCount++;
86 }else{
87 todoString += "<li draggable='true'><input type='checkbox' onchange='update(" + i + ","done",true)' />" +
88 "<p id='p-" + i + "' onclick='edit(" + i + ")'>" + data[i].title + "</p>" +
89 "<a href='javascript:remove(" + i + ")'>-</a></li>";
90 todoCount++;
91 }
92 }
93 todocount.innerHTML = todoCount;
94 todolist.innerHTML = todoString;
95 donecount.innerHTML = doneCount;
96 donelist.innerHTML = doneString;
97 }else{
98 todocount.innerHTML = 0;
99 todolist.innerHTML = "";
100 donecount.innerHTML = 0;
101 donelist.innerHTML = "";
102 }
103 }
104
105 window.onload = load;