TodoList案例

 
一、HTML骨架:
 1 <header>
 2         <section>
 3             <form action="javascript:void(0)" id="form">
 4                 <label for="title">ToDoList</label>
 5                 <input type="text" id="title" name="title" placeholder="添加ToDo" autocomplete="off" />
 6             </form>
 7         </section>
 8     </header>
 9     <section id="sec">
10         <h2>正在进行 <span id="todocount"></span></h2>
11         <ol id="todolist" class="demo-box">
12            
13         </ol>
14         <h2>已经完成 <span id="donecount"></span></h2>
15         <ul id="donelist">
16         </ul>
17     </section>

 

 
二、写上表现:
  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 section {
 15     margin: 0 auto;
 16 }
 17  
 18 label {
 19     float: left;
 20     width: 100px;
 21     line-height: 50px;
 22     color: #DDD;
 23     font-size: 24px;
 24     cursor: pointer;
 25     font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
 26 }
 27  
 28 header input {
 29     float: right;
 30     width: 60%;
 31     height: 24px;
 32     margin-top: 12px;
 33     text-indent: 10px;
 34     border-radius: 5px;
 35     box-shadow: 0 1px 0 rgba(255, 255, 255, 0.24), 0 1px 6px rgba(0, 0, 0, 0.45) inset;
 36     border: none
 37 }
 38  
 39 input:focus {
 40     outline-width: 0
 41 }
 42  
 43 h2 {
 44     position: relative;
 45 }
 46  
 47 span {
 48     position: absolute;
 49     top: 2px;
 50     right: 5px;
 51     display: inline-block;
 52     padding: 0 5px;
 53     height: 20px;
 54     border-radius: 20px;
 55     background: #E6E6FA;
 56     line-height: 22px;
 57     text-align: center;
 58     color: #666;
 59     font-size: 14px;
 60 }
 61  
 62 ol,
 63 ul {
 64     padding: 0;
 65     list-style: none;
 66 }
 67  
 68 li input {
 69     position: absolute;
 70     top: 2px;
 71     left: 10px;
 72     width: 22px;
 73     height: 22px;
 74     cursor: pointer;
 75 }
 76  
 77 p {
 78     margin: 0;
 79 }
 80  
 81 li p input {
 82     top: 3px;
 83     left: 40px;
 84     width: 70%;
 85     height: 20px;
 86     line-height: 14px;
 87     text-indent: 5px;
 88     font-size: 14px;
 89 }
 90  
 91 li {
 92     height: 32px;
 93     line-height: 32px;
 94     background: #fff;
 95     position: relative;
 96     margin-bottom: 10px;
 97     padding: 0 45px;
 98     border-radius: 3px;
 99     border-left: 5px solid #629A9C;
100     box-shadow: 0 1px 2px rgba(0, 0, 0, 0.07);
101 }
102  
103 ol li {
104     cursor: move;
105 }
106  
107 ul li {
108     border-left: 5px solid #999;
109     opacity: 0.5;
110 }
111  
112 li a {
113     position: absolute;
114     top: 2px;
115     right: 5px;
116     display: inline-block;
117     width: 14px;
118     height: 12px;
119     border-radius: 14px;
120     border: 6px double #FFF;
121     background: #CCC;
122     line-height: 14px;
123     text-align: center;
124     color: #FFF;
125     font-weight: bold;
126     font-size: 14px;
127     cursor: pointer;
128 }
129  
130 footer {
131     color: #666;
132     font-size: 14px;
133     text-align: center;
134 }
135  
136 footer a {
137     color: #666;
138     text-decoration: none;
139     color: #999;
140 }
141  
142 @media screen and (max-device-width: 620px) {
143     section {
144         width: 96%;
145         padding: 0 2%;
146     }
147 }
148  
149 @media screen and (min-width: 620px) {
150     section {
151         width: 600px;
152         padding: 0 10px;
153     }
154 }

 

 
 
三、最后添加行为:
  1 <script>
  2        //选择元素
  3         var title_ele = document.getElementById("title");
  4         var todo_list_ele = document.getElementById("todolist");
  5         var done_list_ele = document.getElementById("donelist");
  6         var sec_ele = document.getElementById("sec");
  7         // 初始化todo_list数据;
  8         var todo_list = initTodoData();
  9         function initTodoData(){
 10             // 1. localstorage 里面没有数据;
 11             if(localStorage.getItem("todo_data") === null){
 12                 // 返回基础结构;
 13                 return {
 14                     todo:[],
 15                     done:[]
 16                 }
 17             }
 18             // todo_data 里面存在数据;  把数据转换成对象, 然后把对象返回回去;
 19             // 特殊情况 :  如果JSON.parse 解析的字符串不符合json规则报错;
 20             var obj = null;
 21             try{
 22                 obj = JSON.parse(localStorage.getItem("todo_data"));
 23             }catch( e ){
 24                 obj = {
 25                     todo:[],
 26                     done:[]
 27                 }
 28             }
 29             return obj;
 30         }
 31  
 32         // 渲染初始页面结构;
 33         function renderTodoList( todo_list ){
 34             // 数据为空不需要渲染;
 35             if(todo_list.todo.length === 0 && todo_list.done.length === 0){
 36                 return false;
 37             }
 38             // 拼接字符串;
 39             var todo_html = "";
 40             todo_list.todo.forEach( function( item ){
 41                 todo_html += `
 42                 <li>
 43                     <input type="checkbox">
 44                     <p>${item}</p>
 45                     <a herf="javascrit:void(0)">-</a>
 46                 </li>`
 47             })
 48             todo_list_ele.innerHTML = todo_html;
 49             var done_html = "";
 50             todo_list.done.forEach( function( item ){
 51                 done_html += `
 52                 <li>
 53                     <input type="checkbox" checked>
 54                     <p>${item}</p>
 55                     <a herf="javascrit:void(0)">-</a>
 56                 </li>`
 57             })
 58             done_list_ele.innerHTML = done_html;
 59         }
 60         renderTodoList(todo_list);
 61         // 删除数据;
 62         function removeLocalData( type , value ){
 63             todo_list[type].splice( todo_list[type].indexOf(value) , 1);
 64             localStorage.setItem("todo_data" , JSON.stringify(todo_list));
 65         }
 66         // 更新数据;
 67         function updateLocalData( type , old_value , new_value){
 68             todo_list[type].splice( todo_list[type].indexOf(old_value) , 1 , new_value);
 69             localStorage.setItem("todo_data" , JSON.stringify(todo_list));
 70         }
 71  
 72         title_ele.onkeydown = function( evt ){
 73             var e = evt || event;
 74             var keyCode = e.which || e.keyCode;
 75             if( keyCode === 13){
 76                 var value = createTodoElement();
 77                 saveLocalData("todo",value);
 78             }
 79         }
 80         //将数据存入localstorage;
 81         function saveLocalData( type , value ){
 82             todo_list[type].unshift(value);
 83             localStorage.setItem("todo_data" , JSON.stringify(todo_list));
 84         }
 85  
 86         function createTodoElement(){
 87             var title_value = title_ele.value;
 88             var todo_li = createEle({
 89                 tag : "li",
 90                 children : [
 91                     {
 92                         tag : "input",
 93                         attributes : {
 94                             type : "checkbox"
 95                         }
 96                     },
 97                     {
 98                         tag : "p",
 99                         content : title_value
100                     },
101                     {
102                         tag : "a",
103                         attributes : {
104                             href : "javascript:void(0)"
105                         },
106                         content : "-"
107                     }
108                 ]
109             })
110             // 插入元素到todolist位置 : 
111             todo_list_ele.insertBefore( todo_li , todo_list_ele.childNodes[0] );
112             title_ele.value = "";
113             return title_value;
114         }
115  
116         function createEle( options ){
117             // 1. 创建标签 : 
118             var node = document.createElement( options.tag );
119             if( options.attributes ){
120                 // 遍历属性列表 : 
121                 for(var attr in options.attributes){
122                     // 给元素设置属性;
123                     node.setAttribute( attr , options.attributes[attr])
124                 }
125             }
126             // 3. 给元素添加内容 : 
127             if( options.content ){
128                 node.innerHTML = options.content;
129             }
130             // 4. 判定是否存在子集元素;
131             if( options.children && options.children.length > 0 ){
132                 for(var i = 0 ; i < options.children.length ; i ++){
133                     // 如果存在子集 : 创建子集元素插入父级之中;
134                     node.appendChild( createEle( options.children[i] ) );
135                 }
136             }
137             return node;
138         }
139  
140         // 事件委托;
141         on(todo_list_ele , "change" , "input" , function( e , node ){
142             // 判定checkbox 是否选中  node.checked; 选中为true , 没有选则为false;
143             if(node.checked){
144                 done_list_ele.appendChild(node.parentNode);
145                 // 删除数据 , 添加数据;
146                 var value = node.parentNode.children[1].innerHTML;
147                 removeLocalData( "todo" , value );
148                 saveLocalData  ( "done" , value );
149             }
150         });
151         // 同理给done_list 绑定事件;
152         on(done_list_ele , "change" , "input" , function( e , node ){
153             if(!node.checked){
154                 todo_list_ele.appendChild(node.parentNode);
155                 var value = node.parentNode.children[1].innerHTML;
156                 removeLocalData( "done" , value );
157                 saveLocalData  ( "todo" , value );
158             }
159         });
160         on( sec_ele , "click" , "a" , function( e , node ){
161             node.parentNode.remove();
162             var type  = node.parentNode.children[0].checked ? "done" : "todo";
163             var value = node.parentNode.children[1].innerHTML;
164             removeLocalData( type , value);
165         });
166         on(todo_list_ele , "click" , "p" , function( e , node ){
167             if( node.children.length === 1 ){ 
168                 return false;
169             };
170             var old_value = node.innerHTML;
171             node.innerHTML = "<input class='ipt' value='"+ node.innerHTML +"'>";
172             node.children[0].select();
173             on( node.children[0], "blur"  , eventHanlder)
174             on( node.children[0], "click" , eventHanlder)
175             var has_remove_input = false;
176             function eventHanlder(){
177                 if(has_remove_input) return false;
178                 console.log("todo" , old_value ,  this.value)
179                 updateLocalData( "todo" , old_value ,  this.value)
180                 has_remove_input = true
181                 node.innerHTML = this.value;
182                 
183             }
184         });
185         
186         //事件委托封装
187         function on(ele, type, cb_selector, cb) {
188             if (arguments.length === 4 && typeof cb_selector === "string") {
189                 ele.addEventListener(type, function (evt) {
190                     var e = evt || event;
191                     var target = e.target || e.srcElement;
192                     var node = target;
193                     var selector_start = cb_selector.substr(0, 1);
194                     var selector_type = null;
195                     var selector = cb_selector;
196                     switch (selector_start) {
197                         case ".":
198                             selector_type = "className";
199                             selector = cb_selector.slice(1);
200                             break;
201                         case "#":
202                             selector_type = "id";
203                             selector = cb_selector.slice(1);
204                             break;
205                         default:
206                             selector_type = "nodeName";
207                             break;
208                     }
209                     while (node !== ele) {
210                         if (!node) break;
211                         if (node[selector_type] === (selector_type === "nodeName" ? selector.toUpperCase() : selector)) {
212                             cb( e , node );
213                             break;
214                         }
215                         node = node.parentNode;
216                     }
217                 });
218                 return false;
219             }
220             ele.addEventListener(type, cb_selector);
221         }
222  
223     </script>

 

 
 
 
 
 
 
 
posted @ 2020-03-22 20:03  和平的home  阅读(475)  评论(0编辑  收藏  举报