<!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>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>div contenteditable光标测试</title>
<style type="text/css">
.div {
width: 600px;
height: 200px;
border: 1px solid #CCC
}
</style>
<script src="http://xxx/jquery-1.8.3.min.js"></script>
<script type="text/javascript">
$(document).ready(function(e) {
$('.toEnd').click(function() {
var body = document.getElementsByClassName("div")[0];
window.getSelection().collapseToEnd();
})
$('.toStart').click(function() {
var body = document.getElementsByClassName("div")[0];
window.getSelection().collapseToStart();
})
$(".toInsertTxt").click(function() {
var body = document.getElementsByTagName("inserTxt")[0];
window.getSelection().collapseToStart();
})
//选择节点================[
var strongs = document.getElementsByTagName("strong");
var s = window.getSelection();
console.log(s.rangeCount)
if (s.rangeCount > 0) s.removeAllRanges();
console.log(strongs.length)
//for (var i = 0; i < strongs.length; i++) {
// var range = document.createRange();
// range.selectNode(strongs[1]);
// s.addRange(range);
// var range = document.createRange();
// range.selectNode(strongs[0]);
// s.addRange(range);
var body = document.getElementsByClassName("div")[0].getElementsByTagName("div")[0];
var s = window.getSelection();
var range = document.createRange();
range.selectNode(body);
s.addRange(range);
s.collapseToEnd();
//}
//选择节点================]
});
</script>
</head>
<body>
<a href="javascript:;" class="toEnd">去选中文字的最后面</a>
<a href="javascripot:;" class="toStart">去选中文字的最前面</a>
<a href="javascripot:;" class="toInsertTxt">插入图片</a>
<div class="div" contenteditable="true">
<div>fasdaffdsfsf</div>
<div>222222222222222222222222</div>
</div>
<span>
<strong>dfdsfdf</strong>
<strong>111111</strong>
<strong >3333</strong>
</span>
<p class="inserTxt">在后面插入[]文字</p>
</body>
</html>
最近在处理公司的html5富文本编辑器,难点在于光标位置的获取和选取,需要用到getSelection和range,
参考文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Selection
集合示例和文档,可以快速的完成简单功能
===========更新于2022-1-7==============
其实对于非编辑状态的标签也是可以使用range来编辑的只是不存在可操作的光标
selection是光标和range的集合
range是一个选中文字区块的对象,一些浏览器可以按住shift按键多选文字,也就同时存在多个range对象
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Demo : Textarea 元素的光标位置</title>
<style>
#result {
font-size: 18px;
line-height: 25px;
padding-left: 20px;
}
#test {
width: 500px;
height: 300px;
border: 1px solid #ddd;
}
</style>
</head>
<body>
<h1>Textarea Div 元素的光标位置</h1>
<ul>
<li>获取 Textarea Div 元素当前的光标位置</li>
<li>设置回原先的 Textarea Div 元素的光标位置</li>
</ul>
<form action="#">
<div id="test" tabindex="1">无数据</div>
<p>
<input type="button" id="get" value="Get Cursor Position" />
<input type="button" id="set" value="Set Cursor Position" />
</p>
</form>
<h2>Textarea Range:</h2>
<div id="result"></div>
<script type="text/javascript">
var cursorPosition = {
get: function(textarea) {
var setSelectionRange = getSelection().getRangeAt(0);
console.log("setSelectionRange", setSelectionRange);
var rangeData = {
text: "",
start: 0,
end: 0,
startDom: "",
endDom: ""
};
if (setSelectionRange) { // W3C
textarea.focus();
rangeData.start = setSelectionRange.startOffset;
rangeData.end = setSelectionRange.endOffset;
rangeData.text = (rangeData.start != rangeData.end) ? textarea.innerText.substring(rangeData.start, rangeData.end) : "";
console.log("setSelectionRange", setSelectionRange)
rangeData.startDom = setSelectionRange.startContainer;
rangeData.endDom = setSelectionRange.endContainer;
}
return rangeData;
},
set: function(textarea, rangeData) {
console.log("rangeData", rangeData)
try {
var startContent = rangeData.startDom;
var endContent = rangeData.endDom;
var selection = window.getSelection();
try {
var range = selection.getRangeAt(0);
range.setStart(startContent, rangeData.start);
range.setEnd(endContent, rangeData.end);
selection.addRange(range);
console.log("设置1", selection.toString(), "xx")
} catch (e1) {
console.log("设置2", endContent.firstChild)
range = document.createRange();
range.setStart(startContent, rangeData.start);
range.setEnd(endContent, rangeData.end - 1);
selection.addRange(range);
console.log("设置2", range, "xx")
}
} catch (e) {
console.log(e);
}
},
}
var tx = document.getElementById("test"),
re = document.getElementById("result"),
pos;
var s = "";
for (let i = 0; i < 12; i++) {
s += `<span class="${i}">${i}</span>`
// s += i;
}
tx.innerHTML = s;
document.getElementById("get").onclick = function() {
pos = cursorPosition.get(tx);
re.innerHTML = ("<strong>Range :</strong> (" + pos.start + ", " + pos.end + ")<br /><strong>Text :</strong> " + (!pos.text ? '//--' : pos.text));
}
document.getElementById("set").onclick = function() {
cursorPosition.set(tx, pos);
}
</script>
</body>
</html>
<body>
点击按钮运行所选内容上的方法,点击 "resetExample" 进行重置。
<p id="p">Example: <i>italic</i> and <b>bold</b></p>
<p id="result"></p>
<script>
let range = new Range();
// 下面演示了上述的每个方法:
let methods = {
deleteContents() {
range.deleteContents()
},
extractContents() {
let content = range.extractContents();
result.innerHTML = "";
result.append("extracted: ", content);
},
cloneContents() {
let content = range.cloneContents();
result.innerHTML = "";
result.append("cloned: ", content);
},
insertNode() {
let newNode = document.createElement('u');
newNode.innerHTML = "NEW NODE";
range.insertNode(newNode);
},
surroundContents() {
let newNode = document.createElement('u');
try {
range.surroundContents(newNode);
} catch (e) {
alert(e)
}
},
resetExample() {
p.innerHTML = `Example: <i>italic</i> and <b>bold</b>`;
result.innerHTML = "";
range.setStart(p.firstChild, 2);
range.setEnd(p.querySelector('b').firstChild, 3);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
};
for (let method in methods) {
document.write(`<div><button onclick="methods.${method}()">${method}</button></div>`);
}
methods.resetExample();
document.onselectionchange = function() {
range = window.getSelection().getRangeAt(0);
}
</script>
相关文档说明:选择(Selection)和范围(Range)