myDoList 文档分析
需求分析
样式分析
-
头部
1.左侧logo是文字
2.右侧文本框,文本框内有placehold
-
body
-
正在完成
-
下设文本框,框内有左侧选择按钮,右上角计数,右边删除
-
-
正在进行
-
下设文本框,框内有左侧删除按钮,右上角计数,右边删除
-
-
已过期
-
下设文本框,框内有左侧删除按钮,右上角计数,右边删除
-
-
-
footer
-
鸣谢作者? 版权? Emmmmm!
-
-
效果图
1.
需求拓展
-
关闭网页时,再次打开,可以仍然拥有数据
-
添加待办事项时,会出现日期,保证出现第三项,已过期事件
-
使用arttemplate 实现页面渲染
功能分析
-
在头部文本框中输入待办事项,点击回车键,可以将待办事项添加到正在进行中
-
在待办事项和已完成中各自点击左侧选择框,可以实现切换。在待办事项和已完成中点击删除按钮,可以将该项删除
-
关闭网页时,再次打开,数据仍然可以找回
-
点击某项事件,可以将其改动为可输入状态
便捷分析
-
当文本框为可输入状态时,点击本项删除按钮,可以直接将该项删除,若点击别项删除,可以将本项变为文本,并将别项删除
-
当文本框为可输入状态时,点击本项切换按钮,可以直接切换状态,若点击别项切换,可以将本项变为文本,并将别项切换
思路分析和功能实现
-
首先引入依赖库函数,要不后面的模板是不能使用的
<script src="./template-web.js"></script>
<script src="./template-web.js"></script> -
将模板写好,我dolist3采用的方式是只写ul内部的模板,dolist4、dolist5,dolist5采用的都是讲body内部所有全部模板化,具体区别自己分析,仅以dolist6作为分析。
共计构建三个模板,分别是正在进行,已完成,和已过期。
-
首先{{if isWork}} 判断是否工作,如果是false,模板直接不起作用
-
{{num1}}是我各项事件的数量
-
each list value i 是遍历我的数组,读取data对象中list数组的每一个元素,value 和 i 分别是值和索引
-
{{if value.hasDo == false && value.hasPast == false}} 是来判断这件事情没有过期而且还没有做
-
{{if value.isWrite == false}}是判断是否被点击,因为我这个p标签提供点击切换可输入的能力,三个代码如下
<script id="waitDo" type="text/html"> {{if isWork}} <div class="body_pre"> <p class="body_text">正在进行</p> <span class="body_num1">{{num1}}</span> </div> <ul id="add"> {{each list value i}} {{if value.hasDo == false && value.hasPast == false}} <li style="position:relative;" index="{{i}}"> <input type="checkbox" class="addbox"> {{if value.isWrite == false}} <p class="convert"> {{value.content}} </p> {{/if}} {{if value.isWrite == true}} <input type="text" value="{{value.content}}" class="away"> {{/if}} <input value="{{value.cal}}" class="day"> <span class="body_hide">------ </span> <!-- <input value="{{cal}}" type= "text"> --> </li> {{/if}} {{/each}} </ul> {{/if}} </script> <script id="hasDone" type="text/html"> {{if isWork}} <div class="body_end"> <p class="body_text">已经完成</p> <span class="body_num2">{{num2}}</span> </div> <ul id="end"> {{each list value i}} {{if value.hasDo == true && value.hasPast == false}} <li style="position:relative;" index="{{i}}"> <input type="checkbox" class="addbox" checked> {{if value.isWrite == false}} <p class="convert"> {{value.content}} </p> {{/if}} {{if value.isWrite == true}} <input type="text" value="{{value.content}}" class="away"> {{/if}} <input value="{{value.cal}}" class="day"> <span class="body_hide">------ </span> </li> {{/if}} {{/each}} </ul>{{/if}} </script> <script id="past" type="text/html"> <div class="body_past"> <p class="body_text">已经过期</p> <span class="body_num3">{{num3}}</span> </div> <ul id="pasted"> {{each list value i}} {{if value.hasPast == true}} <li style="position:relative;" index="{{i}}"> {{if value.isWrite == false}} <p class="convert"> {{value.content}} </p> {{/if}} {{if value.isWrite == true}} <input type="text" value="{{value.content}}" class="away"> {{/if}} <p>{{value.cal}}</p> <span class="body_hide">------ </span> </li> {{/if}} {{/each}} </ul> </script>
<script id="waitDo" type="text/html"> {{if isWork}} <div class="body_pre"> <p class="body_text">正在进行</p> <span class="body_num1">{{num1}}</span> </div> <ul id="add"> {{each list value i}} {{if value.hasDo == false && value.hasPast == false}} <li style="position:relative;" index="{{i}}"> <input type="checkbox" class="addbox"> {{if value.isWrite == false}} <p class="convert"> {{value.content}} </p> {{/if}} {{if value.isWrite == true}} <input type="text" value="{{value.content}}" class="away"> {{/if}} <input value="{{value.cal}}" class="day"> <span class="body_hide">------ </span> <!-- <input value="{{cal}}" type= "text"> --> </li> {{/if}} {{/each}} </ul> {{/if}} </script> <script id="hasDone" type="text/html"> {{if isWork}} <div class="body_end"> <p class="body_text">已经完成</p> <span class="body_num2">{{num2}}</span> </div> <ul id="end"> {{each list value i}} {{if value.hasDo == true && value.hasPast == false}} <li style="position:relative;" index="{{i}}"> <input type="checkbox" class="addbox" checked> {{if value.isWrite == false}} <p class="convert"> {{value.content}} </p> {{/if}} {{if value.isWrite == true}} <input type="text" value="{{value.content}}" class="away"> {{/if}} <input value="{{value.cal}}" class="day"> <span class="body_hide">------ </span> </li> {{/if}} {{/each}} </ul>{{/if}} </script> <script id="past" type="text/html"> <div class="body_past"> <p class="body_text">已经过期</p> <span class="body_num3">{{num3}}</span> </div> <ul id="pasted"> {{each list value i}} {{if value.hasPast == true}} <li style="position:relative;" index="{{i}}"> {{if value.isWrite == false}} <p class="convert"> {{value.content}} </p> {{/if}} {{if value.isWrite == true}} <input type="text" value="{{value.content}}" class="away"> {{/if}} <p>{{value.cal}}</p> <span class="body_hide">------ </span> </li> {{/if}} {{/each}} </ul> </script> -
-
然后在主函数中,声明data对象,分别有num1,num2,num3,iswork属性和list数组
var data = { num1: 0, num2: 0, num3: 0, isWork: true, // 修改可以使这个函数工作与不工作 list: name || [] //空的数组,等会存放我的信息 list里面有三个三个对象 //一个是isWrite 是否可写,一个是content一个是 是否已经完成 };
data = { num1: 0, num2: 0, num3: 0, isWork: true, // 修改可以使这个函数工作与不工作 list: name || [] //空的数组,等会存放我的信息 list里面有三个三个对象 //一个是isWrite 是否可写,一个是content一个是 是否已经完成 };这里的 list中的name 是我本地存储的对象,先判断,本地是否有缓存,如果有,那就用本地的,如果没有,就空数组
-
正式做的第一步,对文本框绑定函数
var inputtext = document.getElementById("logo_input_main"); inputtext.addEventListener("keypress", function () {//键盘事件 var target = event.target;//保存target,避免闭包的发生 if (event.keyCode == 13) {//判断回车事件 var sure = textExame(target.value);//对字符串是否为全空格进行判断 if (sure) {//如果不是,那么 pushObj(trim(target.value));//第一步,将这个字符串传入对象中 document.getElementById("logo_input_main").value = "";//第二部,将文本框里面置空 render(); //进行页面渲染 count();//计算每个项目的数量 save();//将对象data保存到本地 } } });
var inputtext = document.getElementById("logo_input_main"); inputtext.addEventListener("keypress", function () {//键盘事件 var target = event.target;//保存target,避免闭包的发生 if (event.keyCode == 13) {//判断回车事件 var sure = textExame(target.value);//对字符串是否为全空格进行判断 if (sure) {//如果不是,那么 pushObj(trim(target.value));//第一步,将这个字符串传入对象中 document.getElementById("logo_input_main").value = "";//第二部,将文本框里面置空 render(); //进行页面渲染 count();//计算每个项目的数量 save();//将对象data保存到本地 } } }); -
判断字符串是否全空,第四步用到
function textExame(msg) { var flag = true; if (msg.match(/^\s*$/)) {//正则表达式进行匹配,以空格开头的一个或者多个 alert("你还没有输入内容或者输入全是空格哦"); flag = false; } return flag; } //返回值为1那么就是非空,否则为空
function textExame(msg) { var flag = true; if (msg.match(/^\s*$/)) {//正则表达式进行匹配,以空格开头的一个或者多个 alert("你还没有输入内容或者输入全是空格哦"); flag = false; } return flag; } //返回值为1那么就是非空,否则为空 -
pushOBj函数,第四步用到
function pushObj(msg) { //传入一个参数。查看是否与已有的重复,如果有,就不存 if (repet(msg) == false) { alert("你要做的事情已经在待办事项中了哦,请确认是否重复"); } else { data.list.push({ content: msg, hasDo: false, isWrite: false, hasPast: false, cal: getNowFormatDate() }) // reIndex(); extra(); } }
function pushObj(msg) { //传入一个参数。查看是否与已有的重复,如果有,就不存 if (repet(msg) == false) { alert("你要做的事情已经在待办事项中了哦,请确认是否重复"); } else { data.list.push({ content: msg, hasDo: false, isWrite: false, hasPast: false, cal: getNowFormatDate() }) // reIndex(); extra(); } } -
页面渲染函数,第四步用到
function render() { var html1 = template('waitDo', data);//套用模板 var html2 = template('hasDone', data); var html3 = template("past", data); document.getElementsByClassName("body_main")[0].innerHTML = html1 + html2 + html3; }
function render() { var html1 = template('waitDo', data);//套用模板 var html2 = template('hasDone', data); var html3 = template("past", data); document.getElementsByClassName("body_main")[0].innerHTML = html1 + html2 + html3; } -
计算数量的函数,第四步用到
function count() { var num1 = 0, num2 = 0, num3 = 0; for (let i of data.list) { if (i.hasDo == false && i.hasPast == false) { num1++; } else if (i.hasDo == true && i.hasPast == false) { num2++; } if (i.hasPast == true) { num3++; } } data.num1 = num1; data.num2 = num2; data.num3 = num3; }
count() { var num1 = 0, num2 = 0, num3 = 0; for (let i of data.list) { if (i.hasDo == false && i.hasPast == false) { num1++; } else if (i.hasDo == true && i.hasPast == false) { num2++; } if (i.hasPast == true) { num3++; } } data.num1 = num1; data.num2 = num2; data.num3 = num3; } -
保存数据到本地的函数,第四步用到
function save() { if (!window.localStorage) { alert("浏览器支持localstorage"); } else { storage.setItem('key', JSON.stringify(data.list)) } }
save() { if (!window.localStorage) { alert("浏览器支持localstorage"); } else { storage.setItem('key', JSON.stringify(data.list)) } } -
简化用的函数,本质是封装
function extra() { // reIndex(); count(); render(); save(); }
extra() { // reIndex(); count(); render(); save(); } -
正式做的第二步,对全文绑定函数
var dele = document.getElementsByClassName("body_main")[0]; dele.addEventListener("click", function () { var target = event.target; var index = target.parentNode.getAttribute("index"); if (target.nodeName == "SPAN") { check(); var x = data.list.splice(index, 1); extra(); } if (target.nodeName == "INPUT" && target.className == "addbox") { check(); var x = data.list.splice(index, 1); data.list.splice(data.num1 + data.num2 - 1, 0, { content: x[0].content, hasDo: !x[0].hasDo, isWrite: x[0].isWrite, hasPast: false, cal: x[0].cal }) extra(); } if (target.nodeName == "P" && target.className == "convert") { check(); data.list[index].isWrite = true; extra(); document.getElementsByTagName("li")[index].getElementsByClassName("away")[0].addEventListener( "blur", function () { if (repet(trim(document.getElementsByTagName("li")[ index].getElementsByClassName("away")[0].value)) == false) { alert("重复了"); } else { data.list[index].content = trim(document.getElementsByTagName("li")[ index].getElementsByClassName("away")[0].value.toString()); data.list[index].isWrite = false; extra(); } }) } if (target.nodeName == "INPUT" && target.className == "day") { console.log(index); check(); target.addEventListener("blur", function () { data.list[index].cal = target.value; extra(); if (compare(data.list[index].cal, getNowFormatDate()) == 1) { var x = data.list.splice(index, 1); data.list.splice(data.num1 + data.num2 + data.num3 - 1, 0, { content: x[0].content, hasDo: x[0].hasDo, isWrite: x[0].isWrite, hasPast: true, cal: x[0].cal }) extra(); } }) } })
dele = document.getElementsByClassName("body_main")[0]; dele.addEventListener("click", function () { var target = event.target; var index = target.parentNode.getAttribute("index"); if (target.nodeName == "SPAN") { check(); var x = data.list.splice(index, 1); extra(); } if (target.nodeName == "INPUT" && target.className == "addbox") { check(); var x = data.list.splice(index, 1); data.list.splice(data.num1 + data.num2 - 1, 0, { content: x[0].content, hasDo: !x[0].hasDo, isWrite: x[0].isWrite, hasPast: false, cal: x[0].cal }) extra(); } if (target.nodeName == "P" && target.className == "convert") { check(); data.list[index].isWrite = true; extra(); document.getElementsByTagName("li")[index].getElementsByClassName("away")[0].addEventListener( "blur", function () { if (repet(trim(document.getElementsByTagName("li")[ index].getElementsByClassName("away")[0].value)) == false) { alert("重复了"); } else { data.list[index].content = trim(document.getElementsByTagName("li")[ index].getElementsByClassName("away")[0].value.toString()); data.list[index].isWrite = false; extra(); } }) } if (target.nodeName == "INPUT" && target.className == "day") { console.log(index); check(); target.addEventListener("blur", function () { data.list[index].cal = target.value; extra(); if (compare(data.list[index].cal, getNowFormatDate()) == 1) { var x = data.list.splice(index, 1); data.list.splice(data.num1 + data.num2 + data.num3 - 1, 0, { content: x[0].content, hasDo: x[0].hasDo, isWrite: x[0].isWrite, hasPast: true, cal: x[0].cal }) extra(); } }) } }) -
判断是否有文本框未归位
function check() { if (document.getElementsByClassName("away").length != 0) { var biao; for (var i = 0; i != data.list.length; i++) { if (data.list[i].isWrite == true) { biao = i; } } data.list[biao].content = document.getElementsByClassName("away")[0].value; data.list[biao].isWrite = false; extra(); } }
function check() { if (document.getElementsByClassName("away").length != 0) { var biao; for (var i = 0; i != data.list.length; i++) { if (data.list[i].isWrite == true) { biao = i; } } data.list[biao].content = document.getElementsByClassName("away")[0].value; data.list[biao].isWrite = false; extra(); } } -
以xxxx-xx-xx的形式得到当前日期和比较大小
function compare(day1, day2) { day1 = day1.toString(); day2 = day2.toString(); var aday = day1.split("-"); var bday = day2.split("-"); if (parseInt(aday[0]) > parseInt(bday[0]) || (parseInt(aday[0]) == parseInt(bday[0]) && parseInt( aday[1]) > parseInt(bday[1])) || (parseInt(aday[0]) == parseInt(bday[0]) && parseInt(aday[1]) == parseInt(bday[1])) && parseInt(aday[2]) > parseInt(bday[2])) { return 1; } else return 0; } //获取当前时间,格式YYYY-MM-DD function getNowFormatDate() { var date = new Date(); var seperator1 = "-"; var year = date.getFullYear(); var month = date.getMonth() + 1; var strDate = date.getDate(); if (month >= 1 && month <= 9) { month = "0" + month; } if (strDate >= 0 && strDate <= 9) { strDate = "0" + strDate; } var currentdate = year + seperator1 + month + seperator1 + strDate; return currentdate; }
compare(day1, day2) { day1 = day1.toString(); day2 = day2.toString(); var aday = day1.split("-"); var bday = day2.split("-"); if (parseInt(aday[0]) > parseInt(bday[0]) || (parseInt(aday[0]) == parseInt(bday[0]) && parseInt( aday[1]) > parseInt(bday[1])) || (parseInt(aday[0]) == parseInt(bday[0]) && parseInt(aday[1]) == parseInt(bday[1])) && parseInt(aday[2]) > parseInt(bday[2])) { return 1; } else return 0; } //获取当前时间,格式YYYY-MM-DD function getNowFormatDate() { var date = new Date(); var seperator1 = "-"; var year = date.getFullYear(); var month = date.getMonth() + 1; var strDate = date.getDate(); if (month >= 1 && month <= 9) { month = "0" + month; } if (strDate >= 0 && strDate <= 9) { strDate = "0" + strDate; } var currentdate = year + seperator1 + month + seperator1 + strDate; return currentdate; } -
全文代码可以在查看第七部分或者复制弟15小节代码(弟15小节只有html,和js代码,没有模板代码)
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel="stylesheet" href="./dolist.css"> <title>base6</title> </head> <body> <div class="header"> <div class="logo"> <div class="logo_title"> myToDoList </div> <div class="logo_input"> <input type="text" placeholder="请输入日程" cla ss="logo_input_main" id="logo_input_main"> </div> </div> </div> <div class="body"> <div class="body_main"> <div class="body_pre"> <p class="body_text">正在进行</p> <span class="body_num1">0</span> </div> <ul id="add"> </ul> <div class="body_end"> <p class="body_text">已经完成</p> <span class="body_num2">0</span> </div> <ul id="end"> </ul> <div class="body_past"> <p class="body_text">已经过期</p> <span class="body_num2">0</span> </div> <ul id="end"> </ul> </div> </div> <div class="footer"> I CAN ONLY TRY MY BEST </div> <script src="./template-web.js"></script> <script id="waitDo" type="text/html"> {{if isWork}} <div class="body_pre"> <p class="body_text">正在进行</p> <span class="body_num1">{{num1}}</span> </div> <ul id="add"> {{each list value i}} {{if value.hasDo == false && value.hasPast == false}} <li style="position:relative;" index="{{i}}"> <input type="checkbox" class="addbox"> {{if value.isWrite == false}} <p class="convert"> {{value.content}} </p> {{/if}} {{if value.isWrite == true}} <input type="text" value="{{value.content}}" class="away"> {{/if}} <input value="{{value.cal}}" class="day"> <span class="body_hide">------ </span> <!-- <input value="{{cal}}" type= "text"> --> </li> {{/if}} {{/each}} </ul> {{/if}} </script> <script id="hasDone" type="text/html"> {{if isWork}} <div class="body_end"> <p class="body_text">已经完成</p> <span class="body_num2">{{num2}}</span> </div> <ul id="end"> {{each list value i}} {{if value.hasDo == true && value.hasPast == false}} <li style="position:relative;" index="{{i}}"> <input type="checkbox" class="addbox" checked> {{if value.isWrite == false}} <p class="convert"> {{value.content}} </p> {{/if}} {{if value.isWrite == true}} <input type="text" value="{{value.content}}" class="away"> {{/if}} <input value="{{value.cal}}" class="day"> <span class="body_hide">------ </span> </li> {{/if}} {{/each}} </ul>{{/if}} </script> <script id="past" type="text/html"> <div class="body_past"> <p class="body_text">已经过期</p> <span class="body_num3">{{num3}}</span> </div> <ul id="pasted"> {{each list value i}} {{if value.hasPast == true}} <li style="position:relative;" index="{{i}}"> {{if value.isWrite == false}} <p class="convert"> {{value.content}} </p> {{/if}} {{if value.isWrite == true}} <input type="text" value="{{value.content}}" class="away"> {{/if}} <p>{{value.cal}}</p> <span class="body_hide">------ </span> </li> {{/if}} {{/each}} </ul> </script> <script> (function () { var storage = window.localStorage; var name = JSON.parse(storage.getItem('key')); var data = { num1: 0, num2: 0, num3: 0, isWork: true, // 修改可以使这个函数工作与不工作 list: name || [] //空的数组,等会存放我的信息 list里面有三个三个对象 //一个是isWrite 是否可写,一个是content一个是 是否已经完成 }; extra(); //比较两个日期的大小,返回值为1就是大,否则就是小 function compare(day1, day2) { day1 = day1.toString(); day2 = day2.toString(); var aday = day1.split("-"); var bday = day2.split("-"); if (parseInt(aday[0]) > parseInt(bday[0]) || (parseInt(aday[0]) == parseInt(bday[0]) && parseInt( aday[1]) > parseInt(bday[1])) || (parseInt(aday[0]) == parseInt(bday[0]) && parseInt(aday[1]) == parseInt(bday[1])) && parseInt(aday[2]) > parseInt(bday[2])) { return 1; } else return 0; } //获取当前时间,格式YYYY-MM-DD function getNowFormatDate() { var date = new Date(); var seperator1 = "-"; var year = date.getFullYear(); var month = date.getMonth() + 1; var strDate = date.getDate(); if (month >= 1 && month <= 9) { month = "0" + month; } if (strDate >= 0 && strDate <= 9) { strDate = "0" + strDate; } var currentdate = year + seperator1 + month + seperator1 + strDate; return currentdate; } //判断要添加的待办事项是否已经存在,如果是,告诉他不可以添加 function pushObj(msg) { if (repet(msg) == false) { alert("你要做的事情已经在待办事项中了哦,请确认是否重复"); } else { data.list.push({ content: msg, hasDo: false, isWrite: false, hasPast: false, cal: getNowFormatDate() }) // reIndex(); extra(); } } //检查是否重复 function repet(msg) { var flag; for (var i of data.list) { if (i.content == trim(msg)) { flag = false; break; } } return flag; } //将字符串头和尾的空格都删掉 function trim(str) { return str.replace(/(^\s*)|(\s*$)/g, ""); } //检查字符串,如果字符串是空或者全是空格就alert, function textExame(msg) { var flag = true; if (msg.match(/^\s*$/)) { alert("你还没有输入内容或者输入全是空格哦"); flag = false; } return flag; } //页面渲染。 function render() { var html1 = template('waitDo', data); var html2 = template('hasDone', data); var html3 = template("past", data); document.getElementsByClassName("body_main")[0].innerHTML = html1 + html2 + html3; } //计算数量 function count() { var num1 = 0, num2 = 0, num3 = 0; for (let i of data.list) { if (i.hasDo == false && i.hasPast == false) { num1++; } else if (i.hasDo == true && i.hasPast == false) { num2++; } if (i.hasPast == true) { num3++; } } data.num1 = num1; data.num2 = num2; data.num3 = num3; } //重新绑定索引 // function reIndex() { // for (var i = 0; i != data.list.length; i++) { // data.list[i].index = i; // } // } //重新索引,渲染,计数 function extra() { // reIndex(); count(); render(); save(); } function save() { if (!window.localStorage) { alert("浏览器支持localstorage"); } else { storage.setItem('key', JSON.stringify(data.list)) } } //check function check() { if (document.getElementsByClassName("away").length != 0) { var biao; for (var i = 0; i != data.list.length; i++) { if (data.list[i].isWrite == true) { biao = i; } } data.list[biao].content = document.getElementsByClassName("away")[0].value; data.list[biao].isWrite = false; extra(); } } //绑定函数 function bindEvent() { //对文本框的输入绑定函数,如果有重复 ,空格,或者没有输入会报错,否则直接加入数组中 var inputtext = document.getElementById("logo_input_main"); inputtext.addEventListener("keypress", function () { var target = event.target; if (event.keyCode == 13) { var sure = textExame(target.value); if (sure) { pushObj(trim(target.value)); document.getElementById("logo_input_main").value = ""; render(); count(); save(); } } }); var dele = document.getElementsByClassName("body_main")[0]; dele.addEventListener("click", function () { var target = event.target; var index = target.parentNode.getAttribute("index"); if (target.nodeName == "SPAN") { check(); var x = data.list.splice(index, 1); extra(); } if (target.nodeName == "INPUT" && target.className == "addbox") { check(); var x = data.list.splice(index, 1); data.list.splice(data.num1 + data.num2 - 1, 0, { content: x[0].content, hasDo: !x[0].hasDo, isWrite: x[0].isWrite, hasPast: false, cal: x[0].cal }) extra(); } if (target.nodeName == "P" && target.className == "convert") { check(); data.list[index].isWrite = true; extra(); document.getElementsByTagName("li")[index].getElementsByClassName("away")[0].addEventListener( "blur", function () { if (repet(trim(document.getElementsByTagName("li")[ index].getElementsByClassName("away")[0].value)) == false) { alert("重复了"); } else { data.list[index].content = trim(document.getElementsByTagName("li")[ index].getElementsByClassName("away")[0].value.toString()); data.list[index].isWrite = false; extra(); } }) } if (target.nodeName == "INPUT" && target.className == "day") { console.log(index); check(); target.addEventListener("blur", function () { data.list[index].cal = target.value; extra(); if (compare(data.list[index].cal, getNowFormatDate()) == 1) { var x = data.list.splice(index, 1); data.list.splice(data.num1 + data.num2 + data.num3 - 1, 0, { content: x[0].content, hasDo: x[0].hasDo, isWrite: x[0].isWrite, hasPast: true, cal: x[0].cal }) extra(); } }) } }) } function init() { bindEvent(); } init(); })(); </script> </body> </html>
DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <link rel="stylesheet" href="./dolist.css"> <title>base6</title> </head> <body> <div class="header"> <div class="logo"> <div class="logo_title"> myToDoList </div> <div class="logo_input"> <input type="text" placeholder="请输入日程" cla ss="logo_input_main" id="logo_input_main"> </div> </div> </div> <div class="body"> <div class="body_main"> <div class="body_pre"> <p class="body_text">正在进行</p> <span class="body_num1">0</span> </div> <ul id="add"> </ul> <div class="body_end"> <p class="body_text">已经完成</p> <span class="body_num2">0</span> </div> <ul id="end"> </ul> <div class="body_past"> <p class="body_text">已经过期</p> <span class="body_num2">0</span> </div> <ul id="end"> </ul> </div> </div> <div class="footer"> I CAN ONLY TRY MY BEST </div> <script src="./template-web.js"></script> <script id="waitDo" type="text/html"> {{if isWork}} <div class="body_pre"> <p class="body_text">正在进行</p> <span class="body_num1">{{num1}}</span> </div> <ul id="add"> {{each list value i}} {{if value.hasDo == false && value.hasPast == false}} <li style="position:relative;" index="{{i}}"> <input type="checkbox" class="addbox"> {{if value.isWrite == false}} <p class="convert"> {{value.content}} </p> {{/if}} {{if value.isWrite == true}} <input type="text" value="{{value.content}}" class="away"> {{/if}} <input value="{{value.cal}}" class="day"> <span class="body_hide">------ </span> <!-- <input value="{{cal}}" type= "text"> --> </li> {{/if}} {{/each}} </ul> {{/if}} </script> <script id="hasDone" type="text/html"> {{if isWork}} <div class="body_end"> <p class="body_text">已经完成</p> <span class="body_num2">{{num2}}</span> </div> <ul id="end"> {{each list value i}} {{if value.hasDo == true && value.hasPast == false}} <li style="position:relative;" index="{{i}}"> <input type="checkbox" class="addbox" checked> {{if value.isWrite == false}} <p class="convert"> {{value.content}} </p> {{/if}} {{if value.isWrite == true}} <input type="text" value="{{value.content}}" class="away"> {{/if}} <input value="{{value.cal}}" class="day"> <span class="body_hide">------ </span> </li> {{/if}} {{/each}} </ul>{{/if}} </script> <script id="past" type="text/html"> <div class="body_past"> <p class="body_text">已经过期</p> <span class="body_num3">{{num3}}</span> </div> <ul id="pasted"> {{each list value i}} {{if value.hasPast == true}} <li style="position:relative;" index="{{i}}"> {{if value.isWrite == false}} <p class="convert"> {{value.content}} </p> {{/if}} {{if value.isWrite == true}} <input type="text" value="{{value.content}}" class="away"> {{/if}} <p>{{value.cal}}</p> <span class="body_hide">------ </span> </li> {{/if}} {{/each}} </ul> </script> <script> (function () { var storage = window.localStorage; var name = JSON.parse(storage.getItem('key')); var data = { num1: 0, num2: 0, num3: 0, isWork: true, // 修改可以使这个函数工作与不工作 list: name || [] //空的数组,等会存放我的信息 list里面有三个三个对象 //一个是isWrite 是否可写,一个是content一个是 是否已经完成 }; extra(); //比较两个日期的大小,返回值为1就是大,否则就是小 function compare(day1, day2) { day1 = day1.toString(); day2 = day2.toString(); var aday = day1.split("-"); var bday = day2.split("-"); if (parseInt(aday[0]) > parseInt(bday[0]) || (parseInt(aday[0]) == parseInt(bday[0]) && parseInt( aday[1]) > parseInt(bday[1])) || (parseInt(aday[0]) == parseInt(bday[0]) && parseInt(aday[1]) == parseInt(bday[1])) && parseInt(aday[2]) > parseInt(bday[2])) { return 1; } else return 0; } //获取当前时间,格式YYYY-MM-DD function getNowFormatDate() { var date = new Date(); var seperator1 = "-"; var year = date.getFullYear(); var month = date.getMonth() + 1; var strDate = date.getDate(); if (month >= 1 && month <= 9) { month = "0" + month; } if (strDate >= 0 && strDate <= 9) { strDate = "0" + strDate; } var currentdate = year + seperator1 + month + seperator1 + strDate; return currentdate; } //判断要添加的待办事项是否已经存在,如果是,告诉他不可以添加 function pushObj(msg) { if (repet(msg) == false) { alert("你要做的事情已经在待办事项中了哦,请确认是否重复"); } else { data.list.push({ content: msg, hasDo: false, isWrite: false, hasPast: false, cal: getNowFormatDate() }) // reIndex(); extra(); } } //检查是否重复 function repet(msg) { var flag; for (var i of data.list) { if (i.content == trim(msg)) { flag = false; break; } } return flag; } //将字符串头和尾的空格都删掉 function trim(str) { return str.replace(/(^\s*)|(\s*$)/g, ""); } //检查字符串,如果字符串是空或者全是空格就alert, function textExame(msg) { var flag = true; if (msg.match(/^\s*$/)) { alert("你还没有输入内容或者输入全是空格哦"); flag = false; } return flag; } //页面渲染。 function render() { var html1 = template('waitDo', data); var html2 = template('hasDone', data); var html3 = template("past", data); document.getElementsByClassName("body_main")[0].innerHTML = html1 + html2 + html3; } //计算数量 function count() { var num1 = 0, num2 = 0, num3 = 0; for (let i of data.list) { if (i.hasDo == false && i.hasPast == false) { num1++; } else if (i.hasDo == true && i.hasPast == false) { num2++; } if (i.hasPast == true) { num3++; } } data.num1 = num1; data.num2 = num2; data.num3 = num3; } //重新绑定索引 // function reIndex() { // for (var i = 0; i != data.list.length; i++) { // data.list[i].index = i; // } // } //重新索引,渲染,计数 function extra() { // reIndex(); count(); render(); save(); } function save() { if (!window.localStorage) { alert("浏览器支持localstorage"); } else { storage.setItem('key', JSON.stringify(data.list)) } } //check function check() { if (document.getElementsByClassName("away").length != 0) { var biao; for (var i = 0; i != data.list.length; i++) { if (data.list[i].isWrite == true) { biao = i; } } data.list[biao].content = document.getElementsByClassName("away")[0].value; data.list[biao].isWrite = false; extra(); } } //绑定函数 function bindEvent() { //对文本框的输入绑定函数,如果有重复 ,空格,或者没有输入会报错,否则直接加入数组中 var inputtext = document.getElementById("logo_input_main"); inputtext.addEventListener("keypress", function () { var target = event.target; if (event.keyCode == 13) { var sure = textExame(target.value); if (sure) { pushObj(trim(target.value)); document.getElementById("logo_input_main").value = ""; render(); count(); save(); } } }); var dele = document.getElementsByClassName("body_main")[0]; dele.addEventListener("click", function () { var target = event.target; var index = target.parentNode.getAttribute("index"); if (target.nodeName == "SPAN") { check(); var x = data.list.splice(index, 1); extra(); } if (target.nodeName == "INPUT" && target.className == "addbox") { check(); var x = data.list.splice(index, 1); data.list.splice(data.num1 + data.num2 - 1, 0, { content: x[0].content, hasDo: !x[0].hasDo, isWrite: x[0].isWrite, hasPast: false, cal: x[0].cal }) extra(); } if (target.nodeName == "P" && target.className == "convert") { check(); data.list[index].isWrite = true; extra(); document.getElementsByTagName("li")[index].getElementsByClassName("away")[0].addEventListener( "blur", function () { if (repet(trim(document.getElementsByTagName("li")[ index].getElementsByClassName("away")[0].value)) == false) { alert("重复了"); } else { data.list[index].content = trim(document.getElementsByTagName("li")[ index].getElementsByClassName("away")[0].value.toString()); data.list[index].isWrite = false; extra(); } }) } if (target.nodeName == "INPUT" && target.className == "day") { console.log(index); check(); target.addEventListener("blur", function () { data.list[index].cal = target.value; extra(); if (compare(data.list[index].cal, getNowFormatDate()) == 1) { var x = data.list.splice(index, 1); data.list.splice(data.num1 + data.num2 + data.num3 - 1, 0, { content: x[0].content, hasDo: x[0].hasDo, isWrite: x[0].isWrite, hasPast: true, cal: x[0].cal }) extra(); } }) } }) } function init() { bindEvent(); } init(); })(); </script> </body> </html>
依赖库函数
-
本文档使用纯html、css、javascript实现,不依赖jQuery库函数,不依赖bootstrap组件
-
由于本网页使用新思路,即arttemplate函数实现页面渲染,所以需要arttemplate,稍后将介绍arttemplate
artTemplate
-
template(id, data),根据 id 渲染模板。
内部会根据document.getElementById(id)查找模板。
如果没有 data 参数,那么将返回一渲染函数。
-
template.compile(source, options)
将返回一个渲染函数。
-
template.render(source, options)
将返回渲染结果
-
template.helper(name, callback)
添加辅助方法。
-
template.config(name, value)
更改引擎的默认配置。
-
下一章 我将会详细介绍artTemplate的使用
作者
模板引擎大概是腾讯开发的吧,我不知道,百度时看到的,但是似是而非。
toDolist网址是 http://www.todolist.cn/ 作者是谁我也不知道。
myToDolist 是我写的。 可以去我的github上下载,方法是打开item,找到你想要下载到的文件夹 ,然后git clone git@github.com:YJD199798/myDolist.git。
或者联系我,邮箱是1249417038@qq.com
Dolist1,dolist2是失败稿,bug无数。
Dolist3,dolist4是两种不同的渲染方式,一个只渲染了ul,另一个从body处就开始渲染
Dolist5,是dolist3和dolist4的优化,深入的使用了arttemplate模板中i的作用,减少了index的重复添加
dolist是完整版,加上了日期和已过期