zoukankan      html  css  js  c++  java
  • Javascript之网页版待办事项

    本文使用原生JS实现站点 http://www.todolist.cn/ 的基本功能。
    其中页面的HTML布局和CSS样式取用原站,JS部分为自己编写。

    效果图

    待办事项效果图

    完整代码

    HTML、JS部分

    <!DOCTYPE html>
    <html>
    	<head>
    		<title>ToDoList—最简单的待办事项列表</title>
    		<link rel="stylesheet" href="todolist.css">
    	</head>
    	<body>
    		<header>
    			<section>
    				<form action="javascript: void(0)" id="form">
    					<label for="title">ToDoList</label>
    					<input type="text" id="title" placeholder="添加ToDo" autocomplete="off"/>
    				</form>
    			</section>
    		</header>
    		<section id="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>
    		
            <script>
                var title_ele = document.getElementById("title");
                var todolist_ele = document.getElementById("todolist");
                var donelist_ele = document.getElementById("donelist");
    			var section_ele = document.getElementById("section");
    			
    			// 功能1,添加待办事项
                addEvent(title_ele, "keydown", function(e){
    				var keyCode = e.which || e.keyCode;
    				var obj = {
    					tag_name : "li",
    					children : [
    							{
    								tag_name : "input",
    								attributes : {
    										type : "checkbox",
    										class : "checkbox"
    									}
    							},
    							{
    								tag_name : "p",
    								content : title_ele.value
    							},
    							{
    								tag_name : "a",
    								attributes : {
    										href : "javascript:void(0)"
    									},
    								content : "-"
    							}]
    				}
    				if(keyCode === 13){
    					console.log(title_ele.value);
    					if(title_ele.value === ""){
    						alert("请输入待办事项内容,再按Enter确认")
    					}else{
    						todolist_ele.insertBefore(createEle(obj), todolist_ele.childNodes[0]);
    						title_ele.value = "";
    					}
    				}
    			})
    
    			// 功能2,完成待办事项
    			addEvent(todolist_ele, "change", ".checkbox", function(){
    				donelist_ele.insertBefore(this.parentNode, donelist_ele.childNodes[0]);
    			})
    
    			// 功能3,重置已完成事项
    			addEvent(donelist_ele, "change", ".checkbox", function(){
    				todolist_ele.insertBefore(this.parentNode, todolist_ele.childNodes[0]);
    			})
    
    			// 功能4,删除事项
    			addEvent(section_ele, "click", "a", function(){
    				this.parentNode.remove();
    			})
    
    			// 功能5,修改事项内容
    			addEvent(todolist_ele, "click", "p", function(){
    				var insert_html = '<input value="' + this.innerText + '">';
    				this.innerHTML = insert_html;
    				this.children[0].select();
    				addEvent(this.children[0], "blur", function(){
    					this.parentNode.innerText = this.value;
    				})
    				addEvent(this.children[0], "keydown", function(e){
    					var keyCode = e.which || e.keyCode;
    					if(keyCode === 13){
    						this.parentNode.innerText = this.value;
    					}
    				})
    			})
    
    
    			// 封装创建元素的函数
    			function createEle(obj){
    				var node = document.createElement(obj.tag_name);
    				if(obj.attributes){
    					// 若属性存在,则遍历属性添加给node
    					for(var attr in obj.attributes){
    						node.setAttribute(attr, obj.attributes[attr]);
    					}
    				}
    				if(obj.content){
    					// 若内容存在,则将内容插入节点中
    					node.innerText = obj.content;
    				}
    				if(obj.children && obj.children.length > 0){
    					// 若子集存在,则遍历子集,递归调用createEle()
    					for(var i = 0; i < obj.children.length; i++){
    						node.appendChild(createEle(obj.children[i]));
    					}
    				}
    				return node;
    			}
    
    
    			// 封装事件委托和事件监听
    			function addEvent(ele, event_type, cb_or_selector, cb){
    				// 若传入的是4个参数且第三个参数是字符串,说明是添加事件委托
    				if(arguments.length === 4 && typeof cb_or_selector === "string"){
    					// 添加事件委托,获取事件目标
    					ele.addEventListener(event_type, function(evt){
    						var e = evt || event;
    						var target = e.target || e.srcElement;
    						// 根据传入的字符串判断选择器类型
    						switch(cb_or_selector.substr(0, 1)){
    							case ".":
    								var selector_type = "className";
    								var selector_name = cb_or_selector.slice(1);
    								break;
    							case "#":
    								var selector_type = "id";
    								var selector_name = cb_or_selector.slice(1);
    								break;
    							default:
    								var selector_type = "nodeName";
    								var selector_name = cb_or_selector.toUpperCase();
    						}
    						// 封装事件冒泡逐层向上查找事件目标
    						while(target !== ele){
    							// 验证事件目标
    							if(target[selector_type] === selector_name){
    								// 使用call改变this指向
    								cb.call(target, e);
    								break;
    							}
    							target = target.parentNode;
    						}
    					})
    					// 若逻辑只有两种,可以使用 return false
    					return false;
    				}
    				// 若传入三个参数,说明是添加事件监听
    				ele.addEventListener(event_type, cb_or_selector);
    			}
            </script>
    	</body>
    </html>
    

    CSS部分

    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;100px;line-height:50px;color:#DDD;font-size:24px;cursor:pointer;font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;}
    header input{float:right;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-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;22px;height:22px;cursor:pointer;}
    p{margin: 0;}
    li p input{top:3px;left:40px;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;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- 620px) {section{96%;padding:0 2%;}}
    @media screen and (min- 620px) {section{600px;padding:0 10px;}}
    

    注意点

    案例封装了两个功能函数(可以在其他项目中复用):

    1. 创建元素函数。该函数以对象的形式传入需要创建元素的基本信息,包括元素标签元素属性元素内容子元素等,通过递归调用,实现批量创建元素,便于渲染到HTML中。
    2. 添加事件函数。该函数将 事件监听事件委托 两项功能封装到一起,给元素添加事件时可以直接调用,保证了代码结构的清晰明确。
  • 相关阅读:
    SpringMVC中的适配器
    JVM的理解
    设计模式 特点比较
    AOP代理模式
    Spring配置补充
    MayBatis与Spring的整合
    增强和注解
    注入
    Mybatis的执行过程
    k8s认证与授权
  • 原文地址:https://www.cnblogs.com/qs-cnblogs/p/12500709.html
Copyright © 2011-2022 走看看