选中textarea特定范围的内容(该textarea已被focused):
IE9以上浏览器:
textarea.focus();
textarea.setSelectionRange(rangeData.start, rangeData.end, [optional] selectionDirection)
IE9及以下:
textarea.focus();
var range = textarea.createTextRange();
range.moveStart("character", rangeData.startDev); // 偏移量
range.moveEnd("character", rangeData.endDev);
range.collapse(false); //强制光标移动到结束位置
range.select(); //选择范围内文本
获取textarea选中范围的起始位置及内容:
IE9以上浏览器:
textarea.focus();
rangeData.start = textarea.selectionStart;
rangeData.end = textarea.selectionEnd;
rangeData.text = (rangeData.start != rangeData.end) ? textarea.value.substring(rangeData.start, rangeData.end) : "";
IE9及以下:
textarea.focus();
var i,
oS = document.selection.createRange(),
// 为了使 oR 与 oS 在同一等级上比较 Don't: oR = textarea.createTextRange()
oR = document.body.createTextRange();
// 移动文本范围以便范围的开始和结束位置能够完全包含给定元素的文本
// 移动body的范围,使其范围的开始和结束位置包含textarea的整个文本
oR.moveToElementText(textarea);
rangeData.text = oS.text;
// 比较textarea的文本开始位置与当前选中范围的开始位置,不断先去移动开始位置,直至到达文本开始位置
for (i = 0; oR.compareEndPoints('StartToStart', oS) < 0 && oS.moveStart("character", -1) !== 0; i++) {
// IE下回车也会占到一个字符
if (textarea.value.charAt(i) == '\r') {
i++;
}
}
rangeData.start = i;
rangeData.end = rangeData.text.length + rangeData.start;
向textarea指定位置添加文本:
// 当textarea选中文本时,添加的文本替换当前选中文本
// textarea未选中时,文本插入到光标位置(start与end相同)
this.set(textarea, rangeData); // 选中textarea特定范围的内容
IE9以上浏览器:
oValue = textarea.value;
nValue = oValue.substring(0, rangeData.start) + text + oValue.substring(rangeData.end);
nStart = nEnd = rangeData.start + text.length;
st = textarea.scrollTop;
textarea.value = nValue;
// 保持textarea滚动位置不改变
if (textarea.scrollTop != st) {
textarea.scrollTop = st;
}
// 光标指向该位置
textarea.setSelectionRange(nStart, nEnd);
IE9及以下:
// 获取当前选中文本
sR = document.selection.createRange();
// 替换文本
sR.text = text;
// 将sR的End位置不变,起始位置与End位置合并
sR.setEndPoint('StartToEnd', sR);
// 光标指向该位置
sR.select();
实现回车时在名称后自动添加 「;」,删除时选中;前的整个名称的效果:
// 注册keydown事件
textarea.addEventListener('keydown', function(e) {
// enter回车
if(e.keyCode == 13) {...}
// backspace删除
if(e.keyCode == 8) {...}
})
// enter回车处理 e.keyCode == 13
e.preventDefault();
rangeData = cursorPosition.get(this);
//此时未选中文本,获取光标位置
if (rangeData.start == rangeData.end) {
if (0 == rangeData.end) return;
if (str.charAt(rangeData.end - 1) != ";"){ //光标前一个字符不是;
cursorPosition.add(this, rangeData, ";"); //在光标位置插入;
}
}
// backspace删除 e.keyCode == 8
//获取选择文本及光标位置
rangeData = cursorPosition.get(this);
if (rangeData.start == rangeData.end) { //此时未选中文本,获取光标位置
if (0 == rangeData.end) return; //光标在最开头
// 光标前的字符是;
if (str.charAt(rangeData.end - 1) == ";"){
// 第一个字符是;
if (1 == rangeData.end) return;
e.preventDefault();
// 找到前一个;的位置
var start = str.lastIndexOf(";", rangeData.end - 2),
end = rangeData.end;
setData = {
start: start + 1,
end: end,
startDev: start - rangeData.start + 1,
endDev: 0
}
// 选中该账号
cursorPosition.set(textarea, setData);
}
}
vue自定义指令实现如下:IE9部分无效
var textareaEvent = {
bind(el, binding, vnode) {
var cursorPosition = {
get: function(textarea) { //获取选中内容
var rangeData = { text: "", start: 0, end: 0 };
textarea.focus();
if (textarea.setSelectionRange) { //W3C
rangeData.start = textarea.selectionStart;
rangeData.end = textarea.selectionEnd;
rangeData.text = (rangeData.start != rangeData.end) ? textarea.value.substring(rangeData.start, rangeData.end) : "";
} else if (document.selection) { //IE
var i, oS = document.selection.createRange(),
// 为了使 oR 与 oS 在同一等级上比较 Don't: oR = textarea.createTextRange()
oR = document.body.createTextRange();
// 移动文本范围以便范围的开始和结束位置能够完全包含给定元素的文本
// 移动body的范围,使其范围的开始和结束位置包含textarea的整个文本
oR.moveToElementText(textarea);
rangeData.text = oS.text;
// 比较textarea的文本开始位置与当前选中范围的开始位置,不断先去移动开始位置,直至到达文本开始位置
for (i = 0; oR.compareEndPoints('StartToStart', oS) < 0 && oS.moveStart("character", -1) !== 0; i++) {
// IE下回车也会占到一个字符
if (textarea.value.charAt(i) == '\r') {
i++;
}
}
rangeData.start = i;
rangeData.end = rangeData.text.length + rangeData.start;
}
return rangeData;
},
set: function(textarea, rangeData) {
var oR;
if (!rangeData) {
alert("You must get cursor position first.")
}
textarea.focus();
if (textarea.setSelectionRange) { // W3C
textarea.setSelectionRange(rangeData.start, rangeData.end);
} else if (textarea.createTextRange) { // IE
oR = textarea.createTextRange();
range.moveStart("character", rangeData.startDev); // 偏移量
range.moveEnd("character", rangeData.endDev);
range.collapse(false); //强制光标移动到结束位置
range.select(); //选择范围内文本
}
},
add: function(textarea, rangeData, text) { //插入文本
var oValue, nValue, sR, nStart, nEnd, st;
this.set(textarea, rangeData);
if (textarea.setSelectionRange) { // W3C
oValue = textarea.value;
nValue = oValue.substring(0, rangeData.start) + text + oValue.substring(rangeData.end);
nStart = nEnd = rangeData.start + text.length;
st = textarea.scrollTop;
textarea.value = nValue;
// 保持textarea滚动位置不改变
if (textarea.scrollTop != st) {
textarea.scrollTop = st;
}
// 光标指向该位置
textarea.setSelectionRange(nStart, nEnd);
} else if (textarea.createTextRange) { // IE
// 获取当前选中文本
sR = document.selection.createRange();
// 替换文本
sR.text = text;
// 将sR的End位置不变,起始位置与End位置合并
sR.setEndPoint('StartToEnd', sR);
// 光标指向该位置
sR.select();
}
}
};
function textareaEvent(e) {
var str = this.value,
rangeData = {};
if (e.keyCode == 13) { //enter
e.preventDefault();
rangeData = cursorPosition.get(this);
if (rangeData.start == rangeData.end) { //此时未选中文本,获取光标位置
if (0 == rangeData.end) return; //光标在最开头
if (str.charAt(rangeData.end - 1) != ";") { //光标前一个字符不是;
cursorPosition.add(this, rangeData, ";"); //在光标位置插入;
}
}
} else if (e.keyCode == 8) { //backspace
//获取选择文本及光标位置
rangeData = cursorPosition.get(this);
if (rangeData.start == rangeData.end) { //此时未选中文本,获取光标位置
if (0 == rangeData.end) return; //光标在最开头
// 光标前的字符是;
if (str.charAt(rangeData.end - 1) == ";") {
// 第一个字符是;
if (1 == rangeData.end) return;
e.preventDefault();
// 找到前一个;的位置
var start = str.lastIndexOf(";", rangeData.end - 2),
end = rangeData.end;
setData = {
start: start + 1,
end: end,
startDev: start - rangeData.start + 1,
endDev: 0
}
// 选中该账号
cursorPosition.set(this, setData);
}
}
}
}
el.__textareaEvent__ = textareaEvent;
el.addEventListener('keydown', el.__textareaEvent__);
},
unbind(el, binding, vnode) {
el.removeEventLister('keydown', el.__textareaEvent__);
delete el.__textareaEvent__;
}
}
参考链接:
https://www.cnblogs.com/ranzige/p/4360457.html
http://www.planabc.net/demo/range/textarea-cursor-position.html
https://blog.csdn.net/lsy649241354/article/details/9081659
https://blog.csdn.net/skiof007/article/details/6181145?locationNum=5&fps=1