在本文中,我们将会达到一下目的
将 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:yiminghe@gmail.com
* @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.当用户输入信息时,给出提示信息