一、基本功能
-
任务的增加删除
-
任务完成勾选与全选
-
定时功能
-
延时功能
二、如何实现
本质是对DOM节点的各种操作,添加删除,以及定时器定时延时功能,对节点的遍历筛选等操作
html部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入css -->
<link rel="stylesheet" href="todo.css">
<!-- 引入js -->
<script src="animate.js"></script>
<script src="todo.js"></script>
</head>
<body>
<div class="center">
<!-- 今日任务 -->
<div class="task">
<div class="task-icon"></div>
<div class="today">今日任务</div>
<!-- 日期 -->
<p id="date"></p>
</div>
<!-- 输入框 -->
<div class="new-task">
<input type="text" placeholder="输入任务后 按Enter 添加">
</div>
<!-- 滑动框 -->
<div class="slide">
<div class="slide-input"></div>
</div>
<!-- 任务栏taskbar -->
<div class="taskbar">
<!-- <div class="todo-item">
<div class="left-item"></div>
<div class="center-item">吃饭</div>
<div class="right-item"></div>
</div>
<div class="todo-item">
<div class="left-item"></div>
<div class="center-item">吃饭</div>
<div class="right-item"></div>
</div> -->
</div>
<div class="todo-template">
<div class=" todo-item">
<div class="left-item"></div>
<div class="center-item"></div>
<div class="time-delay">
<!-- 定时 -->
<div class="timing">
定时
<select name="" id="timing-list">
<option value="0">0s</option>
<option value="1">1s</option>
<option value="2">2s</option>
<option value="3">3s</option>
<option value="4">4s</option>
<option value="5">5s</option>
</select>
</div>
<!-- 延时 -->
<div class="delayed">
延时
<select name="" id="delayed-list">
<option value="0">0s</option>
<option value="1">1s</option>
<option value="2">2s</option>
<option value="3">3s</option>
<option value="4">4s</option>
<option value="5">5s</option>
</select>
</div>
</div>
<div class="right-item"></div>
</div>
</div>
<!-- 底部 -->
<footer>
<div class="left-footer"><span class="number">0</span>项任务</div>
<!-- <div class="kong"></div> -->
<button class="all" style="box-shadow:5px 5px 15px rgb(219, 218, 218), -5px -5px 10px #fff ;">所有</button>
<button class="unfinished">未完成</button>
<button class="finished">已完成</button>
<div class="right-footer">删除已完成</div>
</footer>
</div>
</body>
</html>
css样式部分
* {
margin: 0;
padding: 0;
/* css3盒子模型 */
box-sizing: border-box;
}
@font-face {
font-family: 'icomoon';
src: url('fonts/icomoon.eot?2ua1l4');
src: url('fonts/icomoon.eot?2ua1l4#iefix') format('embedded-opentype'),
url('fonts/icomoon.ttf?2ua1l4') format('truetype'),
url('fonts/icomoon.woff?2ua1l4') format('woff'),
url('fonts/icomoon.svg?2ua1l4#icomoon') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
}
@keyframes huaru {
0% {
left: -65px;
}
100% {
left: 0;
}
}
@keyframes Slide {
0% {
left: 10px;
}
100% {
left: 390px;
}
}
@keyframes Color {
0% {
background-color: rgb(195, 200, 216);
}
100% {
background-color: rgb(4, 190, 253);
}
}
@keyframes COLOR {
0% {
background-color: rgb(4, 190, 253);
}
100% {
background-color: rgb(195, 200, 216);
}
}
body {
background-color: rgb(225, 239, 255);
/* background-color: rgb(247, 208, 215);
background-color: rgb(202, 243, 223);
background-color: rgb(216, 245, 253);
background-color: rgb(241, 219, 255); */
}
.center {
width: 550px;
/* height: 90vh; */
background-color: rgb(225, 239, 255);
/* background-color: #fff; */
text-align: center;
margin: 30px auto 30px;
border-radius: 50px;
box-shadow: 5px 5px 15px rgb(201, 198, 198), -5px -5px 10px #fff;
}
.task {
width: 550px;
height: 160px;
font-size: 38px;
color: rgb(4, 190, 253);
font-weight: 700;
text-align: center;
padding-top: 15px;
}
.task-icon {
font-family: 'icomoon';
display: inline-block;
width: 50px;
height: 50px;
margin-top: 50px;
line-height: 50px;
font-size: 35px;
border-radius: 10px;
box-shadow: 5px 5px 15px rgb(201, 198, 198), -5px -5px 10px #fff;
}
.today {
display: inline-block;
}
.task p {
height: 40px;
font-size: 14px;
line-height: 40px;
}
.new-task input {
width: 420px;
height: 55px;
border: none;
outline: none;
font-size: 18px;
color: rgb(163, 176, 203);
background-color: rgb(225, 239, 255);
/* background-color: pink; */
border-radius: 15px;
padding-left: 15px;
box-shadow: 5px 5px 15px rgb(219, 218, 218) inset, -5px -5px 10px #fff inset;
}
.new-task input::-webkit-input-placeholder {
color: rgb(180, 188, 206);
}
.slide {
position: relative;
width: 420px;
height: 30px;
/* background-color: #fff; */
margin: 30px 0 0 65px;
padding-top: 5px;
padding-left: 10px;
border-radius: 15px;
background-color: rgb(225, 239, 255);
box-shadow: 5px 5px 15px rgb(219, 218, 218), -5px -5px 10px #fff;
}
.slide-input {
position: absolute;
left: 10px;
width: 20px;
height: 20px;
background-color: rgb(195, 200, 216);
border-radius: 10px;
}
.todo-item {
/* position: absolute; */
position: relative;
display: flex;
background-color: rgb(225, 239, 255);
left: 0px;
width: 420px;
height: 60px;
line-height: 60px;
box-shadow: 5px 5px 15px rgb(219, 218, 218), -5px -5px 10px #fff;
border-radius: 15px;
margin-top: 20px;
margin-left: 65px;
/* animation: huaru 1.3s cubic-bezier(.45, .03, .2, .94) 1; */
}
.left-item {
font-family: 'icomoon';
font-size: 30px;
margin-left: 10px;
color: rgb(4, 190, 253);
}
.center-item {
flex: 10;
font-size: 26px;
text-align: left;
margin-left: 15px;
color: rgb(168, 182, 206);
}
.right-item {
font-family: 'icomoon';
font-size: 28px;
margin-right: 10px;
color: rgb(195, 200, 216);
}
footer {
display: flex;
width: 420px;
margin: 25px 0 0 65px;
padding-bottom: 80px;
}
.left-footer {
flex: 2;
font-size: 14px;
color: rgb(168, 182, 206);
padding-top: 3px;
}
/* .kong {
flex: 3;
} */
footer button {
/* flex: 1; */
width: 50px;
height: 25px;
margin: 0 5px;
color: rgb(168, 182, 206);
border: none;
border-radius: 5px;
background-color: rgb(225, 239, 255);
/* box-shadow: 5px 5px 15px rgb(219, 218, 218), -5px -5px 10px #fff; */
}
.right-footer {
flex: 2;
font-size: 14px;
color: rgb(168, 182, 206);
padding-top: 3px;
}
.right-footer:hover {
color: rgb(4, 190, 253);
}
.todo-template {
display: none;
}
.task-icon,
.left-item,
.right-item,
.right-footer {
cursor: pointer;
}
.time-delay {
flex: 10;
margin-right: 10px;
}
.timing {
flex: 5;
display: inline-block;
color: rgb(168, 182, 206);
}
#timing-list {
color: rgb(168, 182, 206);
outline: none;
border-color: rgb(4, 190, 253);
border-radius: 5px;
/* background: none; */
}
.delayed {
flex: 5;
display: inline-block;
color: rgb(168, 182, 206);
}
#delayed-list {
color: rgb(168, 182, 206);
outline: none;
border-color: rgb(4, 190, 253);
border-radius: 5px;
}
js代码展示
// 整个页面加载完之后再执行function里的内容
window.addEventListener('load', function () {
// 任务总数
var num = 0;
// 数组a下标
var i = 0;
var a = [i];
// 圆圈左右状态
var bl = false;
var left = 0;
// 节流阀
var throttle = true;
let newTaskInput = document.querySelector('.new-task input');
// 输入空格光标定到搜索框
document.addEventListener('keyup', function (e) {
if (e.keyCode == 32) {
newTaskInput.focus();
}
})
newTaskInput.onkeydown = function (event) {
if (event.keyCode == 13) {
// 读取用户输入内容
let newTaskText = newTaskInput.value.trim();
if (newTaskText != '') {
// console.log(newTaskText);
// 找到.todo.template节点
let template = document.querySelector('.todo-template');
// 复制节点
// true 深度拷贝,会复制节点本身以及里面所有的子节点
// false 浅拷贝,只克隆复制节点本身,不克隆里面的子节点
let newTaskCopy = template.cloneNode(true);
// console.log(newTaskCopy);
// 找到todo.item节点
var newTaskNode = newTaskCopy.querySelector('.todo-item');
// 替换为用户输入内容
newTaskNode.querySelector('.center-item').innerText = newTaskText;
// 拿到第一个节点
let firstTodo = document.querySelector('.taskbar .todo-item');
// insertBefore 将newTaskNode插入到firstTodo节点前面
document.querySelector('.taskbar').insertBefore(newTaskNode, firstTodo).style.animation = "huaru 1.3s cubic-bezier(.45,.03,.2,.94) 1";
newTaskInput.value = '';
num++;
document.querySelector('.number').innerText = num;
newTaskNode.x = 2;
a[i] = newTaskNode;
i++;
// 点击事件
var finish = newTaskNode.querySelector('.left-item');
finish.onclick = function (event) {
// 判断是否完成 x=1已完成 x==2未完成 x==3已删除
if (finish.innerText == '') {
finish.innerText = '';
let todoText = finish.parentElement.querySelector('.center-item');
todoText.style.textDecoration = 'line-through';
newTaskNode.x = 1;
// num--;
document.querySelector('.number').innerText = num;
} else {
finish.innerText = '';
let todoText = finish.parentElement.querySelector('.center-item');
todoText.style.textDecoration = 'none';
newTaskNode.x = 2;
// num++;
document.querySelector('.number').innerText = num;
}
}
// 点击删除
let de = document.querySelector('.right-item');
let item = de.parentElement;
de.onclick = function () {
item.remove();
// let taskBar = document.querySelector('.taskbar');
// taskBar.removeChild(newTaskNode);
newTaskNode.x = 3;
// console.log(a);
num--;
document.querySelector('.number').innerText = num;
}
// 定时延时功能
// 定时
let timingList = document.getElementById('timing-list');
let delayedList = document.getElementById('delayed-list');
let TASK = timingList.parentElement.parentElement.parentElement;
delayedList.disabled = true;
// console.log(TASK.children[1].innerHTML);
var Time = 0; //时间
var TIME = 0; //延时时间
timingList.onchange = function () {
Time = timingList.value;
let time = Time;
delayedList.disabled = true;
if (TASK.x == 2) {
var timer = setInterval(() => { //计时器
time--;
if (TASK.x == 1 || TASK.x == 3) { //如果任务已完成清除计时器
clearInterval(timer);
}
// if (de.onclick) {
// clearInterval(timer);
// }
if (time == 0) {
var popover = confirm('您时间已到,是否进行延时操作'); //confirm返回true或false
delayedList.disabled = false;
// 不延时
if (popover == false) {
finish.innerText = '';
let todoText = finish.parentElement.querySelector('.center-item');
todoText.style.textDecoration = 'line-through';
TASK.x = 1;
} else if (popover == true) {
// 延时
delayedList.onchange = function () {
TIME = delayedList.value;
time = TIME;
var TIMER = setInterval(() => {
time--;
if (TASK.x == 1) {
clearInterval(TIMER);
}
if (time == 0) {
confirm('时间到!任务 ' + TASK.children[1].innerHTML + ' 已完成');
finish.innerText = '';
let todoText = finish.parentElement.querySelector('.center-item');
todoText.style.textDecoration = 'line-through';
TASK.x = 1;
timingList.disabled = true;
delayedList.disabled = true;
}
}, 1000);
}
}
clearInterval(timer);
// TASK.x = 1;
}
}, 1000);
} else if (TASK.x == 1) {
confirm('该任务已完成');
// timingList.value = 0;
}
}
}
let all = document.querySelector('.all');
let unfinished = document.querySelector('.unfinished');
let finished = document.querySelector('.finished');
// let finish1 = document.querySelector('.left-item').parentElement;
// console.log(finish1);
// 所有按钮
all.onclick = function () {
all.setAttribute('style', 'box-shadow:5px 5px 15px rgb(219, 218, 218), -5px -5px 10px #fff ');
unfinished.setAttribute('style', 'box-shadow:none');
finished.setAttribute('style', 'box-shadow:none');
var o = a.length;
for (let i = 0; i < a.length; i++) {
if (a[i].x == 1) {
a[i].style.display = '';
// a[i].style.animation = "huaru 1.3s cubic-bezier(.45,.03,.2,.94) 1";
} else if (a[i].x == 3) {
o--;
} else {
a[i].style.display = '';
}
}
num = o;
document.querySelector('.number').innerText = num;
}
// 点击未完成按钮
unfinished.onclick = function () {
// unfinished.style.boxShadow = '5px 5px 15px rgb(219, 218, 218), -5px -5px 10px #fff';
unfinished.setAttribute('style', 'box-shadow:5px 5px 15px rgb(219, 218, 218), -5px -5px 10px #fff ');
all.setAttribute('style', 'box-shadow:none');
finished.setAttribute('style', 'box-shadow:none');
var m = a.length;
for (let i = 0; i < a.length; i++) {
// console.log(a[i]);
if (a[i].x == 1) {
a[i].style.display = 'none';
m--;
} else if (a[i].x == 3) {
m--;
} else {
a[i].style.display = '';
}
}
num = m;
document.querySelector('.number').innerText = num;
}
// 已完成按钮
finished.onclick = function () {
finished.setAttribute('style', 'box-shadow:5px 5px 15px rgb(219, 218, 218), -5px -5px 10px #fff ');
unfinished.setAttribute('style', 'box-shadow:none');
all.setAttribute('style', 'box-shadow:none');
var n = 0;
for (let i = 0; i < a.length; i++) {
if (a[i].x == 1) {
a[i].style.display = '';
n++;
// a[i].style.animation = "huaru 1.3s cubic-bezier(.45,.03,.2,.94) 1";
} else {
a[i].style.display = 'none';
}
}
num = n;
document.querySelector('.number').innerText = num;
}
// 全选全不选功能
let slide = document.querySelector('.slide');
let slideInput = document.querySelector('.slide-input');
// let count = 0;
// // 不能连续点击
// function done() {
// if (count == 0) {
// clearInterval(flag);
// } else {
// count = count - 1;
// }
// }
slide.onclick = function () {
// clearInterval(Right);
// clearInterval(Left);
// if (count == 0) {
if (throttle) {
throttle = false;
if (bl == false) {
// clearInterval(Left);
// var Right = setInterval(f, 3);
animate(slideInput, 390, function () {
throttle = true;
});
slideInput.style.animation = "Color 1.3s 1 forwards"
bl = true;
for (let i = 0; i < a.length; i++) {
if (a[i].x != 3) {
a[i].children[0].innerText = '';
a[i].children[1].style.textDecoration = 'line-through';
a[i].x = 1;
}
}
} else if (bl == true) {
// clearInterval(Right);
// var Left = setInterval(F, 3);
animate(slideInput, 10, function () {
throttle = true;
});
slideInput.style.animation = "COLOR 1.3s 1 forwards"
bl = false;
for (let i = 0; i < a.length; i++) {
if (a[i].x != 3) {
a[i].children[0].innerText = '';
a[i].children[1].style.textDecoration = 'none';
a[i].x = 2;
}
}
}
}
count = 1;
// flag = setInterval(done, 1000);
// }
// // 圆圈往右
// function f() {
// if (left == 390) {
// clearInterval(Right);
// } else {
// left += 3;
// slideInput.style.left = left + 'px';
// }
// slideInput.style.animation = "Color 1.3s 1 forwards"
// }
// // 圆圈往左
// function F() {
// if (left == 9) {
// clearInterval(Left);
// } else {
// left -= 3;
// slideInput.style.left = left + 'px';
// }
// slideInput.style.animation = "COLOR 1.3s 1 forwards"
// }
}
// 删除已完成
let definished = document.querySelector('.right-footer');
definished.onclick = function () {
for (let i = 0; i < a.length; i++) {
if (a[i].x == 1) {
// delete a[i];
a[i].remove(i);
a[i].x = 3;
num--;
document.querySelector('.number').innerText = num;
}
}
}
}
}
// 改变背景颜色
let taskIcon = document.querySelector('.task-icon');
let bgc = document.querySelector('body');
let today = document.querySelector('.task');
let Q = 1;
taskIcon.onclick = function () {
if (Q == 0) {
bgc.setAttribute('style', 'background-color: rgb(225, 239, 255)');
today.setAttribute('style', 'color: rgb(4, 190, 253)');
taskIcon.setAttribute('style', 'color: rgb(4, 190, 253)');
Q = 1;
} else if (Q == 1) {
bgc.setAttribute('style', 'background-color: rgb(202, 243, 223);');
today.setAttribute('style', 'color: rgb(140, 231, 187)');
taskIcon.setAttribute('style', 'color: rgb(140, 231, 187)');
Q = 2;
} else if (Q == 2) {
bgc.setAttribute('style', 'background-color: rgb(216, 245, 253);');
today.setAttribute('style', 'color: rgb(139, 217, 238)');
taskIcon.setAttribute('style', 'color: rgb(139, 217, 238)');
Q = 3;
} else if (Q == 3) {
bgc.setAttribute('style', 'background-color: rgb(241, 219, 255);');
today.setAttribute('style', 'color: rgb(241, 219, 255)');
taskIcon.setAttribute('style', 'color: rgb(241, 219, 255)');
Q = 4;
} else if (Q == 4) {
bgc.setAttribute('style', 'background-color: rgb(247, 208, 215);');
today.setAttribute('style', 'color: rgb(247, 208, 215)');
taskIcon.setAttribute('style', 'color: rgb(247, 208, 215)');
Q = 0;
}
}
})
// 日期时间
function showTime() {
let date = new Date();
// 年月日
let year = date.getFullYear();
let month = date.getMonth() + 1;
let day = date.getDate();
// 时分秒
let hour = date.getHours();
hour = hour < 10 ? '0' + hour : hour;
let minute = date.getMinutes();
minute = minute < 10 ? '0' + minute : minute;
let second = date.getSeconds();
second = second < 10 ? '0' + second : second;
// 显示
let element = document.getElementById('date');
element.innerHTML = '<p>' + year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second + '</p>';
}
var ShowTime = window.setInterval("showTime()", 1000);
任务全选全不选按钮实现
// 移动动画
function animate(obj, target, callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
var step = (target - obj.offsetLeft) / 20;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
clearInterval(obj.timer);
// if (callback) {
// callback();
// }
callback && callback();
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
源码百度网盘
链接:https://pan.baidu.com/s/10LLViY7RQUAE0OXiFj295A
提取码:1084