繁华开满天机
经过几天的实验,我发现了一种看起来很有前途的方法。因为selectNodeContents()不处理<br>标记正确,我编写了一个自定义算法来确定每个标记的文本长度。node在一个contenteditable..为了计算例如选择开始,我总结了前面所有节点的文本长度。那样的话,我可以句柄(多)换行:var editor = null;var output = null;const getTextSelection = function (editor) {
const selection = window.getSelection();
if (selection != null && selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
return {
start: getTextLength(editor, range.startContainer, range.startOffset),
end: getTextLength(editor, range.endContainer, range.endOffset)
};
} else
return null;}const getTextLength = function (parent, node, offset) {
var textLength = 0;
if (node.nodeName == '#text')
textLength += offset;
else for (var i = 0; i < offset; i++)
textLength += getNodeTextLength(node.childNodes[i]);
if (node != parent)
textLength += getTextLength(parent, node.parentNode, getNodeOffset(node));
return textLength;}const getNodeTextLength = function (node) {
var textLength = 0;
if (node.nodeName == 'BR')
textLength = 1;
else if (node.nodeName == '#text')
textLength = node.nodeValue.length;
else if (node.childNodes != null)
for (var i = 0; i < node.childNodes.length; i++)
textLength += getNodeTextLength(node.childNodes[i]);
return textLength;}const getNodeOffset = function (node) {
return node == null ? -1 : 1 + getNodeOffset(node.previousSibling);}window.onload = function () {
editor = document.querySelector('.editor');
output = document.querySelector('#output');
document.addEventListener('selectionchange', handleSelectionChange);}const handleSelectionChange = function () {
if (isEditor(document.activeElement)) {
const textSelection = getTextSelection(document.activeElement);
if (textSelection != null) {
const text = document.activeElement.innerText;
const selection = text.slice(textSelection.start, textSelection.end);
print(`Selection: [${selection}] (Start: ${textSelection.start}, End: ${textSelection.end})`);
} else
print('Selection is null!');
} else
print('Select some text above');}const isEditor = function (element) {
return element != null && element.classList.contains('editor');}const print = function (message) {
if (output != null)
output.innerText = message;
else
console.log('output is null!');}* {
font-family: 'Georgia', sans-serif;
padding: 0;
margin: 0;}body {
margin: 16px;}.p {
font-size: 16px;
line-height: 24px;
padding: 0 2px;}.editor {
border: 1px solid #0000001e;
border-radius: 2px;
white-space: pre-wrap;}#output {
margin-top: 16px;}<!DOCTYPE html><html lang="en"><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="./script.js" async></script>
<link href="./stylesheet.css" rel="stylesheet">
<title>Caret Position</title></head><body>
<p class="editor" contenteditable="true"><em>Write<br></em><br>some <br>awesome <b><em>text </em></b>here...</p>
<p id="output">Select some text above</p></body></html>