目录
-
- html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
- <title>ToDoList—最简单的待办事项列表title>
- <meta name="description" content="ToDoList无须注册即可使用,数据存储在用户浏览器的html5本地数据库里,是最简单最安全的待办事项列表应用!" />
- <link rel="stylesheet" href="index.css">
- head>
- <body>
- <header>
- <section>
- <form action="" id="form" onclick="">
- <label for="title">ToDoListlabel>
- <input type="text" id="title" name="title" placeholder="添加ToDo" required="required" autocomplete="off" />
- form>
- section>
- header>
- <section>
- <h2>正在进行 <span id="todocount">span>h2>
- <ol id="todolist" class="demo-box">
-
- ol>
- <h2>已经完成 <span id="donecount">span>h2>
- <ul id="donelist">
- ul>
- section>
- <footer>
- Copyright © 2014 todolist.cn <a href="javascript:clear();">cleara>
- footer>
- <script type="text/javascript" src="index4.js">script>
- body>
- html>
- body {
- margin:0;
- padding:0;
- font-size:16px;
- background: #CDCDCD;
- }
- header {
- height:50px;
- background:#333;
- background:rgba(47,47,47,0.98);
- }
- section{
- margin:0 auto;
- }
- label{
- float:left;
- width:100px;
- line-height:50px;
- color:#DDD;
- font-size:24px;
- cursor:pointer;
- font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
- }
- header input{
- float:right;
- width:60%;
- height:24px;
- margin-top:12px;
- text-indent:10px;
- border-radius:5px;
- box-shadow: 0 1px 0 rgba(255,255,255,0.24), 0 1px 6px rgba(0,0,0,0.45) inset;
- border:none}
- input:focus{
- outline-width:0
- }
- h2{
- position:relative;
- }
- span{
- position:absolute;
- top:2px;
- right:5px;
- display:inline-block;
- padding:0 5px;
- height:20px;
- border-radius:20px;
- background:#E6E6FA;
- line-height:22px;
- text-align:center;
- color:#666;
- font-size:14px;
- }
- ol,ul{
- padding:0;
- list-style:none;
- }
- li input{
- position:absolute;
- top:2px;
- left:10px;
- width:22px;
- height:22px;
- cursor:pointer;
- }
- p{
- margin: 0;
- }
- li p input{
- top:3px;
- left:40px;
- width:70%;
- height:20px;
- line-height:14px;
- text-indent:5px;
- font-size:14px;
- }
- li{
- height:32px;
- line-height:32px;
- background: #fff;
- position:relative;
- margin-bottom: 10px;
- padding:0 45px;
- border-radius:3px;
- border-left: 5px solid #629A9C;
- box-shadow: 0 1px 2px rgba(0,0,0,0.07);
- }
- ol li{
- cursor:move;
- }
- ul li{
- border-left: 5px solid #999;
- opacity: 0.5;
- }
- li a{
- position:absolute;
- top:2px;right:5px;
- display:inline-block;
- width:14px;
- height:12px;
- border-radius:14px;
- border:6px double #FFF;
- background:#CCC;
- line-height:14px;
- text-align:center;
- color:#FFF;
- font-weight:bold;
- font-size:14px;
- cursor:pointer;
- }
- footer{
- color:#666;
- font-size:14px;
- text-align:center;
- }
- footer a{
- color:#666;
- text-decoration:none;
- color:#999;
- }
- @media screen and (max-device-width: 620px) {section{width:96%;padding:0 2%;}}
- @media screen and (min-width: 620px) {section{width:600px;padding:0 10px;}}
- var title = document.querySelector('#title') //表单
- var ol = document.querySelector('#todolist') //正在进行
- var ul = document.querySelector('#donelist') //已完成
- var todoCount = document.querySelector('#todocount')
- var doneCount = document.querySelector('#donecount')
- load()
- /* 回车存储数据 */
- title.addEventListener('keydown', function(e) {
- /* var e = window.event || e */
- var arr = getData() //在获取数据的基础上 拿到数组
- if (e.keyCode == 13) {
- var todo = {
- title: title.value,
- done: false
- }
- arr.push(todo)
- saveData(arr)
- var form = document.querySelector('#form') //让表单返回默认值
- form.reset()
- load()
- }
- })
-
- //获取数据
- function getData() {
- var data = window.localStorage.getItem('todo')
- if (data != null) {
- return JSON.parse(data)
- } else {
- return []
- }
- }
- //存储数据
- function saveData(tdlist) {
- window.localStorage.setItem('todo', JSON.stringify(tdlist))
- }
-
- //加载数据
- function load() {
- var todocount = 0;
- var donecount = 0;
- /* 删除原来的子节点 */
- var olchilds = ol.childNodes;
- for (var i = olchilds.length - 1; i >= 0; i--) {
- ol.removeChild(olchilds[i]);
- }
- var ulchilds = ul.childNodes;
- for (var i = ulchilds.length - 1; i >= 0; i--) {
- ul.removeChild(ulchilds[i]);
- }
- var data = getData()
- data.forEach((item, index) => {
- var li = document.createElement('li')
- /* li.innerHTML = "
"+item.title+"
-"*/ - li.innerHTML =
- if (item.done) {
- ul.insertBefore(li, ul.children[0])
- li.children[0].checked = 'checked'
- donecount++
- } else {
- ol.insertBefore(li, ol.children[0])
- todocount++
- }
- })
- todoCount.innerText = todocount
- doneCount.innerText = donecount
- }
- //编辑数据
- function edit() {
- ol.addEventListener('click', function(e) {
- var p = e.target
- if (p.nodeName == 'P') {
- p.innerHTML = `${p.innerText}" id="input${p.id}"/>`
- p.children[0].select()
- p.children[0].addEventListener('blur', function() {
- var data = getData()
- var i = p.id.substring(1)
- data[i].title = this.value
- saveData(data)
- load()
- })
- }
- })
- }
- edit()
-
- //删除数据
- function remove() {
- ol.addEventListener('click', function(e) {
- var a = e.target
- if (a.nodeName == 'A') {
- var i = a.id
- var data = getData()
- data.splice(i, 1)
- saveData(data)
- load()
- }
- })
- }
- remove()
- //切换正在进行和完成
- function change() {
- ol.addEventListener('click', function(e) {
- var input = e.target
- if (input.nodeName == 'INPUT') {
- var i = input.nextElementSibling.nextElementSibling.id
- console.log(i);
- var data = getData()
- data[i].done = true
- saveData(data)
- load()
-
- }
- })
- ul.addEventListener('click', function(e) {
- var input = e.target
- if (input.nodeName == 'INPUT') {
- var i = input.nextElementSibling.nextElementSibling.id
- console.log(i);
- var data = getData()
- data[i].done = false
- saveData(data)
- load()
- }
- })
- }
- change()
给表单文本框绑定一个keydown事件,判断用户是否按下enter键
确定是按下enter键后,声明一个数组用来获取本地存储中原来的数据
再把最新的从表单获取的数据追加到数组里面
最后把数组存储给本地存储并渲染到加载页面
注意:
在存储事件之前需要进行本地存储以获取并存储数据,保证刷新是数据不会丢失。
其监听事件的过程是先把数据存储到本地存储中,在从本地存储取出数据加载到页面。
title.addEventListener('keydown', function(e) {
/* var e = window.event || e */ //兼容IE浏览器
var arr = getData() //在获取数据的基础上 拿到数组
if (e.keyCode == 13) {
var todo = {
title: title.value,
done: false
}
arr.push(todo)
saveData(arr)
var form = document.querySelector('#form') //让表单返回默认值
form.reset()
load()
}
})
作用:把数据转化为JSON字符串,再存到本地
用户按下enter之后,按理来说,应该给本地存储添加数据,但是没有直接的方法,所以,先给本地存储的数组local追加数据,再把这个数组保存到本地;因为本地存储里存储的是字符串,所以要把获取过来的对象数组转换成字符串形式(JSON.stringify)
function saveData(tdlist) {
window.localStorage.setItem('todo', JSON.stringify(tdlist))
}
因为本地存储中的数据是字符串型,但是我们希望数组里面存储的是对象数组类型,所以需要用JSON.parse()将字符串转换成数组
function getData() {
var data = window.localStorage.getItem('todo')
if (data != null) {
return JSON.parse(data)
} else {
return []
}
}
数据在页面中的形式是
- -
function load() {
var todocount = 0;
var donecount = 0;
/* 删除原来的子节点 */
var olchilds = ol.childNodes;
for (var i = olchilds.length - 1; i >= 0; i--) {
ol.removeChild(olchilds[i]);
}
var ulchilds = ul.childNodes;
for (var i = ulchilds.length - 1; i >= 0; i--) {
ul.removeChild(ulchilds[i]);
}
var data = getData()
data.forEach((item, index) => {
var li = document.createElement('li')
/* li.innerHTML = "
"+item.title+"
-"*/li.innerHTML =
`
${item.title}
-`if (item.done) {
ul.insertBefore(li, ul.children[0])
li.children[0].checked = 'checked'
donecount++
} else {
ol.insertBefore(li, ol.children[0])
todocount++
}
})
todoCount.innerText = todocount
doneCount.innerText = donecount
}
这里要注意删除节点是因为避免增加一个数据到本地存储 ,再添加到项目里渲染函数时保留之前存储的列表数据;即在数组[a, b]里添加一个c 时,理论是[a, b, c],但执行结果是[a, b, a, b, c],保留了之前存储的数据,所以要删除原来的子节点,使结果是[a, b, c].
function edit() {
ol.addEventListener('click', function(e) {
var p = e.target
if (p.nodeName == 'P') {
p.innerHTML = ``
p.children[0].select()
p.children[0].addEventListener('blur', function() {
var data = getData()
var i = p.id.substring(1)
data[i].title = this.value
saveData(data)
load()
})
}
})
}
edit()
点击里面的a链接,不是删除的li,而是删除本地存储对应的数据。
核心原理:先获取本地存储数据,删除对应的数据,保存给本地存储,重新渲染列表li。
function remove() {
ol.addEventListener('click', function(e) {
var a = e.target
if (a.nodeName == 'A') {
var i = a.id
var data = getData()
data.splice(i, 1)
saveData(data)
load()
}
})
}
remove()
点击复选框,修改本地存储数据,再重新渲染数据列表。再获取本地存储数据。修改对应数据属性 done 的值添加到正在进行和已完成这两个项目里。保存数据到本地存储,重新渲染加载数据列表。
function change() {
ol.addEventListener('click', function(e) {
var input = e.target
if (input.nodeName == 'INPUT') {
var i = input.nextElementSibling.nextElementSibling.id
console.log(i);
var data = getData()
data[i].done = true
saveData(data)
load()
}
})
ul.addEventListener('click', function(e) {
var input = e.target
if (input.nodeName == 'INPUT') {
var i = input.nextElementSibling.nextElementSibling.id
console.log(i);
var data = getData()
data[i].done = false
saveData(data)
load()
}
})
}
change()