一個簡單的輸入關鍵字添加標簽效果
阿新 • • 發佈:2018-03-02
click 多余 單元 con order http per script clear
效果
訪問:https://bxcn.github.io/keyWord/
目錄結構
參考
https://github.com/bxcn/keyWord
readme.md
一個簡單的輸入關鍵字添加標簽效果 實現功能: 輸入關鍵字加空格鍵添加tag標簽 按Backspace鍵刪除一個標簽 輸入關鍵字後,鼠標失去焦點添加tag標簽 keyWord.init方法初始化方法 防止輸入重復的關鍵字 限止最多輸入幾個關鍵字 <style> .block { display:flex; flex-direction:row; align-items:center; width:500px; height:30px; border:1px solid #ddd; padding:10px; margin:100px auto 0; } #wordTags { display:flex; flex-wrap:nowrap; } input{ width:100%; height:20px; border:none; }</style> <div class="block"> <div id="wordTags"></div> <input id="wordInput" type="text" name="" placeholder="請輸入關鍵詞以空格結尾"> <input id="wordHiddenInput" type="hidden" name=""> </div> <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.js"></script> <script type="text/javascript" src="aspect.js"></script> <script type="text/javascript" src="keyWord.js"></script> $(function () { var keyWord = $("#wordInput").keyWord({ panel: ‘#wordTags‘, value: ‘#wordHiddenInput‘, max: 3, tips: ‘最多只能輸入3項‘ }); keyWord.init(‘php,java,前端開發‘) }); 屬性說明: panel:面板的id value:隱藏字段的id max:最多輸入關鍵字個數 tips:提示語
index.html
<!DOCTYPE html> <html> <head> <title>keyWord--一個簡單的輸入關鍵字添加標簽效果</title> <meta charset="utf-8"> <link rel="stylesheet" type="text/css" href="index.css"> </head> <body> <style> .block { display:flex; flex-direction:row; align-items:center; width:500px; height:30px; border:1px solid #ddd; padding:10px; margin:100px auto 0; } #wordTags { display:flex; flex-wrap:nowrap; } input{ width:100%; height:20px; border:none; } </style> </body> <div class="block"> <div id="wordTags"></div> <input id="wordInput" type="text" name="" placeholder="請輸入關鍵詞以空格結尾"> <input id="wordHiddenInput" type="hidden" name=""> </div> <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.js"></script> <script type="text/javascript" src="aspect.js"></script> <script type="text/javascript" src="keyWord.js"></script> <script type="text/javascript"> $(function () { var keyWord = $("#wordInput").keyWord({ panel: ‘#wordTags‘, value: ‘#wordHiddenInput‘, max: 3, tips: ‘最多只能輸入3項‘ }); keyWord.init(‘php,php,java,前端開發‘) }); </script> </html>
index.css
@charset "UTF-8"; @font-face { font-family: ‘iconfont‘; src: url("../fonts/iconfont.eot"); /* IE9*/ src: url("../fonts/iconfont.eot?#iefix") format("embedded-opentype"), url("../fonts/iconfont.woff") format("woff"), url("../fonts/iconfont.ttf") format("truetype"), url("../fonts/iconfont.svg#iconfont") format("svg"); /* iOS 4.1- */ } html { position: relative; min-height: 100%; -webkit-overflow-scrolling: touch; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; -webkit-tap-highlight-color: transparent; } article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, body, div, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, fieldset, legend, button, input, textarea, form, th, td { margin: 0; padding: 0; vertical-align: baseline; } article, aside, details, figcaption, figure, footer, header, hgroup, nav, section, summary { display: block; } audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; } body, button, input, select, textarea { outline: none; } h1, h2, h3, h4, h5, h6 { font-size: 100%; font-weight: normal; } address, cite, dfn, em, var, i { font-style: normal; } body { line-height: 120%; font-size: 14px; color: #4d4d4d; font-family: Arial, sans-serif;} small { font-size: 80%; } ul, ol { list-style: none outside none; } a { text-decoration: none; } a:hover { text-decoration: none; outline: 0; } a:active { text-decoration: none; outline: 0; } a:focus { text-decoration: none; outline: 0; } abbr[title], acronym[title] { border-bottom: 1px dotted; cursor: help; } q:before, q:after { content: ‘‘; } mark { background-color: #ff0; color: #000; } pre { /** normal 默認。空白會被瀏覽器忽略。 pre 空白會被瀏覽器保留。其行為方式類似 HTML 中的 <pre> 標簽。 nowrap 文本不會換行,文本會在在同一行上繼續,直到遇到 <br> 標簽為止。 pre-wrap 保留空白符序列,但是正常地進行換行。 pre-line 合並空白符序列,但是保留換行符。 inherit 規定應該從父元素繼承 white-space 屬性的值。 */ white-space: pre-wrap; word-wrap: break-word; } sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } legend { display: none; border: 0; padding: 0; white-space: normal; } fieldset, iframe { border: 0 none; } img { border: 0 none; vertical-align: middle; -ms-interpolation-mode: bicubic; } button, input, select, textarea { font-family: inherit; font-size: 100%; vertical-align: baseline; } button, input[type="button"], input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 改正iOS設備中“input”類型表單樣式不可用的問題 */ cursor: pointer; /* 增強光標樣式在input表單和其他表單的可用性和一致性 */ } button[disabled], html input[disabled] { cursor: default; /* 為禁用表單重設定默認光標樣式 */ } button::-moz-focus-inner, button::-moz-focus-outer, input::-moz-focus-inner, input::-moz-focus-outer { border: 0 none; padding: 0; margin: 0; } input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 調整IE 8/9中尺寸屬性設置為“內容框”的盒子模型 */ padding: 0; /* 去除IE 8/9中的多余的外邊距留白部分 */ } input[type="search"] { -webkit-appearance: textfield; /* 兼容Safari 5 and Chrome上 “searchfield” 上設置 “appearance”屬性 */ /* 兼容Safari 5 and Chrome上 “border-box” 上設置 “box-sizing”屬性 */ box-sizing: content-box; } input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; /* 去除OS X系統上Safari 5和Chrome中容器內邊距和搜索取消按鈕屬性 */ } input:-webkit-autofill, textarea:-webkit-autofill, select:-webkit-autofill { -webkit-box-shadow: 0 0 0 1000px white inset; } textarea { overflow: auto; vertical-align: top; resize: vertical; } table { /* 刪除表格單元格之間的間距。 */ border-collapse: collapse; border-spacing: 0; } strong { font-weight: normal; } img { vertical-align: middle; } .clearfix { zoom: 1; clear: both; height: 0; overflow: hidden; width: 100%; display: block; } .clearfix:before, .clearfix:after { content: ""; display: block; height: 0; overflow: hidden; visibility: hidden; } .fl { float: left; } .fr { float: right; } .mauto { float: inherit !important; margin-left: auto; margin-right: auto; } fieldset { border: none; } input::-webkit-input-placeholder { color: #bfbfbf; } input:-ms-input-placeholder { color: #bfbfbf; } input:-moz-placeholder { color: #bfbfbf; } input::-moz-placeholder { color: #bfbfbf; } /* 刪除選中標簽 */ .tag-checked-name { display:inline-block; position:relative; height: 24px; border-radius: 1px; color:#4abee0; font-size:12px; line-height:24px; padding:0 20px 0 8px; background-color: #f7fdff; border: solid 1px #4abee0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-right:5px; } .tag-checked-name:first-of-type { margin-left: 0px; } .tag-checked-name em { display:block; position:absolute; top:5px; right:5px; width:13px; height: 13px; cursor:pointer; transform: rotate(45deg); } .tag-checked-name em:after { display:block; position:absolute; content:‘‘; top:6px; width:13px; height:1px; background:#4abee0; } .tag-checked-name em:before { display:block; position:absolute; content:‘‘; top:0px; left:5px; width:1px; height: 13px; background:#4abee0; }
aspect.js
/** * @file aspect * @fork https://github.com/ecomfe/saber-lang/blob/master/src/function/aspect.js */ (function () { /** * Aspect * * @inner * @type {Object} */ var Aspect = {}; /** * before AOP * * @private * @param {string} method 欲AOP的目標方法名 * @param {Function} fn AOP處理函數 * @param {*} context `fn`調用時的上下文 * @return {Object} 目標對象 */ Aspect.before = function (method, fn, context) { return aspectTo(this, ‘before‘, method, fn, context); }; /** * after AOP * * @private * @param {string} method 欲AOP的目標方法名 * @param {Function} fn AOP處理函數 * @param {*} context `fn`調用時的上下文 * @return {Object} 目標對象 */ Aspect.after = function (method, fn, context) { return aspectTo(this, ‘after‘, method, fn, context); }; /** * 對`目標對象`的`指定方法`進行`AOP`包裝 * * @inner * @param {Object} target 目標對象 * @param {string} type AOP方式,可取值 `before` | `after` * @param {string} method 欲AOP的目標對象的方法名 * @param {Function} fn AOP處理函數 * @param {*} context `fn`調用時的上下文 * @return {Object} 目標對象 */ function aspectTo(target, type, method, fn, context) { var oriMethod = target[method]; if (oriMethod) { if (type === ‘before‘) { target[method] = function () { // abort support if (fn.apply(context || fn, arguments) !== false) { oriMethod.apply(this, arguments); } }; } else if (type === ‘after‘) { target[method] = function () { oriMethod.apply(this, arguments); fn.apply(context || fn, arguments); }; } } return target; } /** * Aspect * * @exports Aspect * @type {Object} */ var exports = {}; /** * 將 `Aspect` 混入到目標對象 * * @public * @param {Object} obj 目標對象 * @return {Object} 混入 `Aspect` 後的目標對象 */ exports.mixin = function (obj) { // 省略了 hasOwnProperty 校驗 /* eslint-disable guard-for-in */ for (var method in Aspect) { obj[method] = Aspect[method]; } /* eslint-enable guard-for-in */ return obj; }; window.AOP = exports; })();
keyWord.js
/** * 定義一個列表數據結構 * 作用:添加元素、刪除元素、清除所有元素,將數據中的元素組裝成對象返回一個數據 * 只針對數據處理 * @constructor */ function List() { this.dataStore = new Array(); this.listSize = 0; this.pos = 0; } List.prototype = { constructor: List, append: function(name) { this.dataStore[this.listSize++] = name; }, cusPos: function() { return this.pos; }, front: function() { this.pos = 0; }, end: function() { this.pos = this.listSize - 1; }, length: function() { return this.listSize; }, prev: function() { if (this.pos > 0) { --this.pos; } }, next: function() { if (this.pos < this.listSize) { ++this.pos; } }, find: function(name) { var index = -1; this.dataStore.forEach(function(data, i, array) { if (data == name) { index = i; } }); return index; }, remove: function(name) { var index = this.find(name); if (index > -1) { this.dataStore.splice(index, 1); --this.listSize; return true; } return false; }, getElement: function() { return this.dataStore[this.pos]; }, clear: function() { delete this.dataStore; this.dataStore = []; this.pos = this.listSize = 0; } } /** * 定義一個用來對列表操作的對象 * 對列表的一個包裝 * @param options */ var doKeyWord = function(options) { var settings = options; var list = new List(); return AOP.mixin({ init: function(arr) { var that = this; // 初始化 if (typeof arr == "string") { arr = arr == ‘‘ ? [] : arr.split(‘,‘); } if (typeof arr == ‘undefined‘) { arr = []; } // 清空數據 list.clear(); // 便利添加數據中 arr.forEach(function(data, i, array) { that.add(data); }) }, render: function() { // 渲染效果 var valueArr = [], html = [], name; for (list.front(); list.cusPos() < list.length(); list.next()) { name = list.getElement(); valueArr.push(name); html.push(‘<div class="tag-checked-name">‘ + name.substr(0, 10) + ‘<em data-word-tag-close="‘ + name + ‘"></em></div>‘) } $(settings.panel).html(html.join(‘‘)); $(settings.value).val(valueArr.join(‘,‘)); }, add: function(name) { name = $.trim(name); if (name == ‘‘) { return false; } // 添加數據 if (list.find(name) > -1) { return false; } list.append(name); }, remove: function(name) { list.remove(name); }, clear: function() { list.clear(); }, front: function() { return list.front(); }, end: function() { return list.end() }, getElement: function() { return list.getElement(); }, length: function() { return list.length(); } }); } $(function() { $.fn.keyWord = function(options) { var keyWord = doKeyWord(options); // 對添加的數據進行檢查 function doCheck() { if (options.max < keyWord.length() + 1) { alert(options.tips); return false; } return true; } var render = keyWord.render; // 添加前檢查 keyWord.before(‘add‘, doCheck); // 初始化後渲染效果 keyWord.after(‘init‘, render); // 添加後渲染效果 keyWord.after(‘add‘, render); // 刪除後渲染效果 keyWord.after(‘remove‘, render); var that = $(this); // 刪除元素 $(document).on(‘click‘, ‘[data-word-tag-close]‘, function() { var name = $(this).data(‘word-tag-close‘); // 過濾掉不刪除的 keyWord.remove(name); }); /** * Backspace刪除 對應的鍵盤編碼 * e.keyCode == 8 :Backspace鍵 */ that.keydown(function(e) { var that = $(this); var val = $.trim(that.val()); if (val == "" && e.keyCode == 8) { keyWord.end(); keyWord.remove(keyWord.getElement()); } }); // 添加數據 function doAdd(name) { name = $.trim(that.val()); that.val(‘‘); if (name == ‘‘) { return; } keyWord.add(name); } /** * 判斷有輸入空格嗎 * e.keyCode == 32 空格鍵 */ that.keyup(function(e) { var that = $(this); var isSpaceKey = /\s+$/gi.test(that.val()); // 是空格鍵輸入了一個空格字符 if (e.keyCode == 32 && isSpaceKey) { doAdd(that.val()) } }); // 鼠標失去焦點 that.blur(function(e) { doAdd(that.val()) }); this.init = function(arr) { keyWord.init(arr); } return this; } });
一個簡單的輸入關鍵字添加標簽效果