在本文中,我们将会达到一下目的
将 input 文本输入框的内容格式化处理,即用户输入的内容我们会自动处理成规则的格式,以便后续的处理
当光标定位到 input 输入框中的某个元素时,js会将这个有效的部分文本选中,而不是选中全部的文本
当用户在输入框中输入信息时,系统给出输入提示信息
注意,本例需要jquery.js文件,读者请先自行下载jquery.js文件,然后把文件引入下面的网页中。
代码实现如下:
test.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> <meta charset="utf-8"/> <style type="text/css"> .search { left: 0; position: relative; } #auto_div { display: none; /*width: 100px;*/ border: 1px #74c0f9 solid; background: #FFF; position: absolute; /*top: 24px;*/ /*left: 0;*/ color: #323232; } </style> <script src="jquery.js" type="text/javascript"></script> <script type="text/javascript" src="textarea-editor.js?ver=1"></script> <script type="text/javascript"> var old_value = ""; var highlightindex = -1; //高亮 var tx; var te; /** * 获取光标在input中的位置 * @param auto 提示信息显示的地方 * @param data DOM对象 * @param mylist json对象,要提示的信息 */ function AutoComplete(auto, data, mylist) { if (data.value != old_value || old_value == "") { var autoNode =auto; //缓存对象(弹出框) var framePos = getLablePosition(data); auto[0].style.top = framePos.h + framePos.y + "px"; auto[0].style.left = framePos.x+"px"; var carlist = new Array(); var n = 0; var temp = data.value, tempid = 0; var po = getPosition(data); for (var j = po; j >= 0; j--) { if (j - 1 == 0 || temp.charAt(j - 1) === ' ') { old_value = temp.substring(j - 1, po).replace(/(^\s*)|(\s*$)/g, ""); tempid = j; break; } } for (i in mylist) { if (mylist[i].indexOf(old_value) >= 0) { carlist[n++] = mylist[i]; } } if (carlist.length == 0) { auto.hide(); return; } auto.empty(); //清空上次的记录 for (i in carlist) { var wordNode = carlist[i]; //弹出框里的每一条内容 var newDivNode = $("<div>").attr("id", i); //设置每个节点的id值 newDivNode.attr("style", "font:14px/25px arial;height:25px;width:" + (framePos.w - 17) + "px" + ";padding:0 8px;cursor: pointer;"); newDivNode.html(wordNode).appendTo(auto); //追加到弹出框 //鼠标移入高亮,移开不高亮 newDivNode.mouseover(function () { if (highlightindex != -1) { //原来高亮的节点要取消高亮(是-1就不需要了) auto.children("div").eq(highlightindex).css("background-color", "white"); } //记录新的高亮节点索引 highlightindex = $(this).attr("id"); $(this).css("background-color", "#ebebeb"); }); newDivNode.mouseout(function () { $(this).css("background-color", "white"); }); //鼠标点击文字上屏 newDivNode.click(function () { //取出高亮节点的文本内容 var comText = auto.hide().children("div").eq(highlightindex).text(); highlightindex = -1; //文本框中的内容变成高亮节点的内容 if (temp.indexOf("; ") >= 0) { var tempVal = temp.substring(0, tempid); data.value = tempVal + comText + "; "; } else { data.value = comText + "; "; } // data.value = comText; }) if (carlist.length > 0) { //如果返回值有内容就显示出来 auto.show(); } else { //服务器端无内容返回 那么隐藏弹出框 auto.hide(); //弹出框隐藏的同时,高亮节点索引值也变成-1 highlightindex = -1; } } } //点击页面隐藏自动补全提示框 document.onclick = function (e) { var e = e ? e : window.event; var tar = e.srcElement || e.target; if (tar.id != "search") { if (auto.is(":visible")) { auto.css("display", "none") } } } } /** * 当光标聚焦此处时 * @param data 当前DOM对象 */ function onFocus(data) { if ($(data).val() == "") { var value = $(data).nextAll("input").val(); var test_list = eval("("+value+")"); AutoComplete($(data).nextAll("div"), data, test_list); } } /** * 监听键盘松开 * @param input DOM对象 */ function onKeyUp(data) { var value = $(data).nextAll("input").val(); var test_list = eval("("+value+")"); AutoComplete($(data).nextAll("div"), data, test_list); } /** * 根据光标所在位置选中部分文字 * @param input DOM对象 */ function getComponentValue(data) { tx = data; te = new TextareaEditor(tx); var valuetemp = data.value; if (valuetemp === '') { return; } var begin; var end; var pos = te.getSelection(); var temp = pos.selectionStart; if (temp != 0) { if (temp == valuetemp.length) { return; } } for (var i = temp; i >= 0; i--) { if (i == 0 || valuetemp.charAt(i - 1) === ' ') { begin = i; break; } } for (var i = temp; i <= valuetemp.length; i++) { if (valuetemp.charAt(i) === ' ') { end = i + 1; break; } } te.setSelectionRange(begin, end); } /** * 监听键盘按下的哪个键 * @param data DOM对象 * @param 事件 */ function getKey(data, evt) { tx = data; te = new TextareaEditor(tx); var evt = window.event || evt; if (evt.keyCode == 13 || evt.keyCode == 108 || evt.keyCode == 32 || evt.keyCode == 186) { te.insertData("; "); evt.keyCode = 0; evt.returnValue = false; } } /** * 获取光标在input中的位置 * @param input DOM对象 * @returns {Object} 位置坐标 */ function getPosition(input) { var pos = 0; if (document.selection) { input.focus(); var selection = document.selection.createRange(); selection.moveStart('character', -input.value.length); pos = selection.text.length; } else if (input.selectionStart || input.selectionStart == '0') pos = input.selectionStart; return pos; } /** * 获取dom对象在窗口的位置 * @param data DOM对象 * @returns {Object} json对象,包含DOM的坐标信息 */ function getLablePosition(data) { var t = data.offsetTop; var l = data.offsetLeft; var h = data.offsetHeight; var w = data.offsetWidth; while (data = data.offsetParent) { t += data.offsetTop; l += data.offsetLeft; } var point = eval("({x:" + l + ",y:" + t + ",h:" + h + ",w:" + w + "})"); return point; } </script> </head> <body> <input type="button" value="afdsafdsagsdfg"/> <input type="text" id="stringInput" onkeyup="onKeyUp(this)" onclick="getComponentValue(this)" onkeydown="getKey(this)"/> <input type="hidden" value ='["小张", "小苏", "小妹妹", "老奶奶", "大鹏", "大明", "你好", "hello", "hi"]'/> <div id="auto_div"> </div> </body> </html>
textarea-editor.js文件如下:
(function() { function log(s) { return; if (window.console) console.log(s); } var OLD_IE = !window.getSelection,IE = window.ActiveXObject; /** * author:[email protected] * @refer:http://yiminghe.javaeye.com/blog/508999 * @param textarea */ function TextareaEditor(textarea) { this.textarea = textarea; if (IE) { var savedRange; textarea.onmousedown //onfocus 也要存储,如果直接外部设置selection,则也要讲设置后产生的range存起来 = textarea.onfocus = textarea.onmouseup = textarea.onkeydown = textarea.onkeyup = function() { var r = document.selection.createRange(); //当从 console 过来点击页面时,textarea focus 事件被触发但是范围却不是textarea! if (r.parentElement() == textarea) savedRange = r; log("savedRange : " + event.type + " : " + r.parentElement().nodeName); }; textarea.onfocusin = function() { var r = document.selection.createRange(); log("onfocusin" + " : " + r.parentElement().nodeName); //log(document.activeElement.outerHTML);; savedRange && savedRange.select(); }; textarea.onblur = function() { log("blur"); }; textarea.onfocusout = function() { log("onfocusout"); return; savedRange = document.selection.createRange(); log("focusout " + " : " + savedRange.parentElement().outerHTML); log(document.activeElement.outerHTML); } } } TextareaEditor.prototype = { constructor:TextareaEditor, getSelection:OLD_IE ? function() { var textarea = this.textarea; alert(textarea); textarea.focus(); var pos = {}, i, range = document.selection.createRange(); //parentElement : 获取给定文本范围的父元素。 if (textarea != range.parentElement()) { log(range.parentElement().outerHTML); return; } var range_all = document.body.createTextRange(); //开始和结束的位置范围包含给定元素中的文本。 range_all.moveToElementText(textarea); for (var sel_start = 0; range_all.compareEndPoints('StartToStart', range) < 0; sel_start++) { //每次越过了 \r\n,text.value里 \r\n 算两个 range_all.moveStart('character', 1); } for (i = 0; i <= sel_start; i++) { if (textarea.value.charAt(i) == '\n') { sel_start++; } } pos.selectionStart = sel_start; // create a selection of the whole textarea range_all = document.body.createTextRange(); range_all.moveToElementText(textarea); // calculate selection end point by moving beginning of range_all to end of range var flag = 0; for (var sel_end = 0; (flag = range_all.compareEndPoints('StartToEnd', range)) < 0; sel_end++) { if (textarea.value.charAt(sel_end) == '\n') { sel_end++; } range_all.moveStart('character', 1); } //光标不可能停在\r,\n之间 if (textarea.value.charAt(sel_end) == '\n') { sel_end++; } pos.selectionEnd = sel_end; // get selected and surrounding text return pos; } : function() { var textarea = this.textarea; textarea.focus(); return { selectionStart:textarea.selectionStart, selectionEnd:textarea.selectionEnd }; }, setSelectionRange:OLD_IE ? function(start, end) { log("setSelectionRange start"); var v = this.textarea.value,range = this.textarea.createTextRange(); range.collapse(true); start = getLengthForRange(v, start); end = getLengthForRange(v, end); range.moveEnd("character", end); range.moveStart("character", start); range.select(); log("setSelectionRange end"); } : function(start, end) { this.textarea.setSelectionRange(start, end); this.textarea.focus(); }, insertData :OLD_IE ? function(text) { var textarea = this.textarea; textarea.focus(); var range = document.selection.createRange(); range.text = text; } : function(text) { var textarea = this.textarea, value = textarea.value; textarea.focus(); var range = this.getSelection(); var start = value.substring(0, range.selectionStart); var end = value.substring(range.selectionEnd, value.length); var sl = textarea.scrollLeft,st = textarea.scrollTop; textarea.value = start + text + end; textarea.scrollLeft = sl; textarea.scrollTop = st; var np = start.length + text.length; this.setSelectionRange(np, np); } }; function getLengthForRange(text, v) { return text.substring(0, v).replace(/\r\n/g, "\n").length; } window.TextareaEditor = TextareaEditor; })();
上述代码实现的效果如下图所示:
1.输入值时,代码会监听enter键、空格键、;键,当点击这些按键时,会在input中按照既定格式生成如下的格式,方便回显和进行后续处理;
2.当鼠标点击这个输入框中的任何一个字符时,js会将符合上述格式的文字部分选定,如下图:
当然,选定后,就可以方便的一下子删除部分文字了。
3.当用户输入信息时,给出提示信息