ToDoList—最简单的待办事项列表
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ToDoList—最简单的待办事项列表</title>
<style>
html
{
background-color: #CCCCCC;
}
body {
margin: 0px;
padding: 0px;
}
.tops {
width: 100%;
height: 50px;
background-color: rgba(47, 47, 47, 0.98);
}
label {
float: left;
width: 100px;
line-height: 50px;
color: #ddd;
font-size: 24px;
cursor: pointer;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
input[type="text"] {
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;
float: right;
outline: none;
}
.topInfo, .infoContent
{
width: 50%;
margin: auto;
}
.undone,.done
{
margin-top: 20px;
font-size: 25px;
font-weight: 900;
position: relative;
}
.info>span
{
position: absolute;
top: 5px;
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;
}
ul{
list-style: none;
font-size: 14px;
font-weight: 400;
margin: 0;
padding: 0;
margin-top: 10px;
}
li{
height: 32px;
line-height: 32px;
background: #fff;
margin-bottom: 10px;
padding: 0 45px;
overflow: hidden;
border-radius: 3px;
border-left: 5px solid #629A9C;
box-shadow: 0 1px 2px rgba(0,0,0,0.07);
position: relative;
}
.doneLi{
border-left: 5px solid #999;
opacity: 0.5;
}
.close {
display: inline-block;
position: absolute;
right: 20px;
top:4px;
border-radius: 10px;
}
input.changeInput{
width: 300px;
display: none;
position: absolute;
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;
outline: none;
}
</style>
</head>
<body>
<div class="tops">
<div class="topInfo">
<label>ToDoList</label>
<input type="text" name="addInfo" class="addInfo" placeholder="添加ToDo" />
</div>
</div>
<div class="infoContent">
<div class="undone">
<div class="info">
正在进行
<span>0</span>
</div>
</div>
<div class="done">
<div class="info">
已经完成
<span>0</span>
</div>
</div>
</div>
<input type="text" class="changeInput">
<script>
var arr,addInfo,undone,done,undoneSpan,doneSpan,undoneUl,doneUl,changeInput;
init();
// TODO 初始化
function init(){
addInfo=document.querySelector(".addInfo");
changeInput=document.querySelector(".changeInput");
undone=document.querySelector(".undone");
done=document.querySelector(".done");
undoneSpan=document.querySelector(".undone span");
doneSpan=document.querySelector(".done span");
// 从localStorage获取todoList,如果没有,就创建一个数组
arr=localStorage.todoList ? JSON.parse(localStorage.todoList) : [];
dataSave();
document.addEventListener("keyup",keyHandler);
}
// TODO 敲回车添加数据
function keyHandler(e){
// 如果不是回车就不进入
if(e.keyCode!==13) return;
if(e.target===addInfo){
if(addInfo.value.trim().length===0) return;
// 获取localStorage存储的todoList;
arr=JSON.parse(localStorage.todoList);
// 创建一个新对象,将当前的文本框中输入的内容放在这个对象的info中,设置finish默认为false
arr.push({finish:false,info:addInfo.value});
// 清空文本框
addInfo.value="";
}
if(e.target===changeInput){
// 回车直接把input隐藏
changeInput.style.display="none";
// 如果数据为空时直接返回返回不改变info
if(changeInput.value.trim().length===0) return;
// 根据changeInput.value改变changeInput.data.info
changeInput.data.info=changeInput.value;
changeInput.data=null;
// 清空文本框
changeInput.value="";
}
// 存储数据,拆分数据
dataSave();
}
// TODO 完成数据整理并且存储,完成数据的分类并且计算总数
function dataSave(){
// 将数组转换为字符串存储在localstorage中
localStorage.todoList=JSON.stringify(arr);
// 将数组中finish时false的元素放在undoneList数组中
var undoneList=arr.filter(item=>{
return !item.finish;
});
// 将数组中finish时true的元素放在doneList数组中
var doneList=arr.filter(item=>{
return item.finish;
})
/* let [undoneList,doneList]=arr.reduce((value,item)=>{
if(item.finish) value[1].push(item);
else value[0].push(item);
return value;
},[[],[]]); */
// 每个项的列表数量。
// 将未完成的数组数量放在undoneSpan中
// 将完成的数组数量放在doneSpan中
undoneSpan.textContent=undoneList.length;
doneSpan.textContent=doneList.length;
// 如果未完成的任务ul列表,已经创建了,我们需要将他删除,并且设为null,以保证每次最新一个
if(undoneUl){
undoneUl.remove();
undoneUl=null;
}
// 如果完成的任务ul列表,已经创建了,我们需要将他删除,并且设为null,以保证每次最新一个
if(doneUl){
doneUl.remove();
doneUl=null;
}
// 通过执行createUl根据undoneList创建ul,并且放在undone容器中,
// 并且将返回ul赋值给全局变量undoneUl
undoneUl=createUl(undoneList,undone);
// 通过执行createUl根据doneList创建ul,并且放在done容器中,
// 并且将返回ul赋值给全局变量doneUl
doneUl=createUl(doneList,done);
}
// 引用关系的参数不可以删除不可以设置null
// 引用的参数如果牵扯到创建,必须返回设置
// TODO 创建UL列表
function createUl(list,parent){
// 创建ul
var ul=document.createElement("ul");
// console.log(list)
// 根据数组遍历创建li
for(var i=0;i<list.length;i++){
var li=document.createElement("li");
// 将选中的元素,li的样式设置为doneLi
if(list[i].finish) li.className="doneLi";
// 创建多选框
var ck=document.createElement("input");
ck.type="checkbox";
ck.data=list[i];
// 根据数据中finish值设置多选框是否被选中
ck.checked=list[i].finish;
// 给多选框添加点击事件
ck.addEventListener("click",clickHandler);
// 将多选框放在li中
li.appendChild(ck);
// 创建span元素
var span=document.createElement("span");
// 给span元素中放入内容时数据的info内容
span.textContent=list[i].info;
span.style.userSelect="none";
// 将span放在li中
li.appendChild(span);
span.data=list[i];
span.addEventListener("dblclick",changeLiTextHandler)
// 创建按钮
var bn=document.createElement("button");
// 按钮内容是一个×
bn.innerHTML="×";
// 设置按钮的样式
bn.className="close";
bn.data=list[i];
// 添加按钮点击事件
bn.addEventListener("click",removeClickHandler);
// 将bn放在li中
li.appendChild(bn);
// 将li放在ul中
ul.appendChild(li);
}
// 将ul放在指定的容器中
parent.appendChild(ul);
// 返回创建好的ul
return ul;
}
// TODO 删除列表
function removeClickHandler(e){
var index=arr.indexOf(this.data);
if(index>-1) arr.splice(index,1);
dataSave();
}
// TODO 修改事项
function clickHandler(e){
this.data.finish=this.checked;
dataSave();
}
function changeLiTextHandler(e){
changeInput.style.display="block";
var rect=this.getBoundingClientRect();
changeInput.style.left=rect.x+"px";
changeInput.style.top=rect.y-16+"px";
changeInput.data=this.data;
// 聚焦
changeInput.focus();
changeInput.addEventListener("keyup",keyHandler);
}
</script>
</body>
</html>