// 解决 IE 和非 IE 浏览器在事件绑定方面的兼容性 function addEventHandler(elem, event, handler) { if (elem.addEventListener) { elem.addEventListener(event, handler, false); } else if (elem.attachEvent) { elem.attachEvent("on" + event, handler); } else { elem["on" + event] = handler; } } // 用于偷懒的 $ 方法 function $(selector) { var elem = null; if (selector[0] === '#') { elem = document.getElementById(selector.slice(1)); } else if (selector[0] === '.') { elem = document.getElementsByClassName(selector.slice(1)); } return elem; } /** * DOM */ var ul = $(".queue")[0]; var textArea = $("#queue-input"); var searchArea = $("#queue-search-input"); var btnsWrapper = $(".panel")[0]; var queue = (function() { // 利用 JS 的 Array 类型模拟队列 var data = []; var highlight = []; var SPLITRE = /,|,|、|\u3000|\s/; // input 验证函数 function filterEmptyValue(rawInput) { // rawInput 可以为:数字、中文、英文等 // rawInput 的分隔符可以是:逗号(全角半角均可),顿号,回车,空格(全角半角、Tab等均可)等符号 var data = rawInput.split(SPLITRE).filter(function(elem) { if (elem !== "") { return true; } }); if (data.length > 0) { return data; } throw new Error("输入为空,请重新输入~"); // return data.length > 0 ? data : false; } // !?以下两个函数如果也返回的话,无法被返回的公有函数调用OAO // 不过,这两个函数目前仅被公有函数使用,令成私有似乎合情合理。。 var isQueueEmpty = function() { if (data.length > 0) { return true; } throw new Error("队列已经空了~"); }; var isQueueFull = function() { return true; // no limit temporarily /*if (data.length < 60) { return true; } throw new Error("队列已达到 60 上限,请在添加元素之前删除元素~");*/ }; var highlightQueue = function() { highlight.forEach(function(elem,index){ var clsName = elem ? "highlight" : ""; ul.children[index].className = clsName; }); }; var drawQueue = function() { // 纠结 drawQueue 的位置和写法:1. 返回的对象的内部方法可以调用;2. 外部 queue 可以调用(公共方法) var res = ""; data.map(function(elem) { res += '<li>' + elem + '</li>'; }); ul.innerHTML = res; highlightQueue(); }; return { /*'drawQueue': drawQueue,*/ /*function() { var res = ""; data.map(function(elem, i) { res += '<li style="height:' + elem + 'px;" title="' + elem + '"></li>'; }); ul.innerHTML = res; },*/ leftIn: function(value) { isQueueFull(); var vals = filterEmptyValue(value); data = vals.concat(data); highlight = vals.map(function(){ return false; }).concat(highlight); drawQueue(); return this; }, rightIn: function(value) { isQueueFull(); var vals = filterEmptyValue(value); data = data.concat(vals); highlight = highlight.concat(vals.map(function(){ return false; })); drawQueue(); return this; }, leftOut: function() { isQueueEmpty(); highlight.shift(); alert("你去掉了左边的" + data.shift() + "~"); drawQueue(); return this; }, rightOut: function() { isQueueEmpty(); highlight.pop(); alert("你去掉了右边的" + data.pop() + "~"); drawQueue(); return this; }, deleteElemAt: function(index) { isQueueEmpty(); data.splice(index, 1); highlight.splice(index, 1); drawQueue(); return this; // 可以来一波 链式写法 里么 www ! }, // generateRandomQueue: function(length) { // for (var i = 0; i < length; i++) { // data.push(Math.floor(Math.random() * (100 - 10 + 1) + 10)); // status.push(0); // } // drawQueue(); // return this; // }, searchQueue: function() { var searchText = searchArea.value; highlight = data.map(function(elem, index){ return elem.indexOf(searchText) !== -1; }); highlightQueue(); } }; })(); /* 利用事件委托,避开循环绑定事件 */ // 编写 html 时为 input[button] 添加的 id 包含按钮将触发事件的方向(direction)和增删(operate)信息, // 以此结合数组的 push/pop/unshift/shift 方法来模拟队列的操作 btnsWrapper.addEventListener("click", function(e) { if (e.target.nodeName === "INPUT" && e.target.getAttribute("type") === "button" && e.target.id !== "") { var funcName = e.target.id //.replace("-i",'I').replace("-o",'O');// 这里有更好的解决方法么??? .replace(/\-[a-z]/, function(str) { return str[1].toUpperCase(); }); var value = textArea.value; try { queue[funcName](value); } catch (e) { alert(e.message); } textArea.value = ""; } /* else { console.log("Whoops.."); }*/ }, false); // 利用 [].indexOf 确定被点击的 li 元素的序号,并利用 splice 方法更新 queue ul.addEventListener("click", function(e) { if (e.target.nodeName === "LI") { var index = parseInt([].indexOf.call(e.target.parentNode.children, e.target)); // [!!NOTE] .children 和 .childNodes 的区别 try { queue.deleteElemAt(index); } catch (e) { alert(e.message); } } }, false);
<div class="panel"> <!-- <input type="text" id="queue-input" /> --> <textarea name="queue-input" id="queue-input" rows="8"></textarea> <div class="btns"> <input type="button" id="left-in" value="左侧入->|" /> <input type="button" id="right-in" value="右侧入|<-" /> <input type="button" id="left-out" value="左侧出<-|" /> <input type="button" id="right-out" value="右侧出|->" /> </div> <div class="search"> <input type="text" id="queue-search-input" placeholder="请输入搜索内容.." /> <input type="button" id="search-queue" value="搜索内容" /> </div> </div> <ul class="queue"> </ul>
body { font-family: 微软雅黑; } .panel { padding: 10px; background-color: #ddd; } /* .panel > input { display: block; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; border: 1px solid; width: 100%; padding: 0 10px; font-size: 16px; line-height: 24px; } */ .panel > textarea { padding: 0; width: 100%; font-size: 18px; resize: none; outline: none; } .btns { display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: -o-flex; display: flex; flex-flow: row nowrap; justify-content: space-around; padding: 10px 0; } .btns input { /*display: block;*/ flex-grow: 1; margin: 0 3px; border: none; border-radius: 2px; padding: 6px; background-color: lightpink; } .search { overflow: hidden; } .search input { float: left; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; display: block; border: 0; padding: 0 10px; outline: none; line-height: 30px; } .search input[type="text"] { width: 70%; } .search input[type="button"] { width: 30%; } #queue-search { float: left; padding: 0 20px; width: 70%; line-height: 40px; } #search-btn { float: left; padding: 0; width: 30%; color: #fff; background-color: orange; line-height: 40px; } .queue { overflow: hidden; margin: 0; padding: 10px; background-color: #ccc; } .queue li { float: left; box-sizing: border-box; display: block; margin: 3px; border: 2px solid deeppink; padding: 6px 10px; background-color: deeppink; color: #fff; font-size: 16px; } .queue .highlight { border: 2px dashed deeppink; background-color: white; color: deeppink; }