我正在尝试使用 Shift + F3 将 Microsoft Word 中提供的大小写更改功能实现到 TinyMCE React 编辑器中。我遇到的问题是最后一部分,它应该保持选择/突出显示相同的文本。只要我没有突出显示节点的最后一个字符,下面的代码就可以正常工作。如果我选择了行尾,则会收到错误:
Uncaught DOMException: Index or size is negative or greater than the allowed amount
到目前为止我有以下内容:
const handleCaseChange = (ed: Editor) => {
ed.on("keydown", (event: KeyboardEvent) => {
if (event.shiftKey && event.key === "F3") {
event.preventDefault();
const selection = ed.selection.getSel();
const selectedText = selection?.toString();
const startOffset = selection?.getRangeAt(0).startOffset;
const endOffset = selection?.getRangeAt(0).endOffset;
if (selectedText !== undefined && selectedText.length > 0) {
let transformedText;
if (selectedText === selectedText.toUpperCase()) {
transformedText = selectedText.toLowerCase();
} else if (selectedText === selectedText.toLowerCase()) {
transformedText = capitalizeEachWord(selectedText);
} else {
transformedText = selectedText.toUpperCase();
}
ed.selection.setContent(transformedText);
const range = ed.getDoc().createRange();
// This is what's currently erroring
range.setStart(selection.anchorNode, startOffset);
if (endOffset === selection?.anchorNode?.textContent?.length) {
range.setEndAfter(selection.anchorNode);
} else {
range.setEnd(selection.anchorNode, endOffset);
}
selection.removeAllRanges();
selection.addRange(range);
}
}
}
}
const capitalizeEachWord = (str: string) => str.replace(/\b\w/g, (char: string) => char.toUpperCase());
我还可以在
range.setStart
中尝试什么才能使其正常工作?
我从 TinyMCE 文档中找到了一个简单的解决方案 - Selection.getBookmark()。
获取书签
返回当前选择的书签位置。然后,在对文档进行一些内容修改后,可以使用此书签对象来恢复选择。
我尝试了以下方法,它可以更改大小写,然后将新内容标记为选中。
const handleCaseChange = (ed: Editor) => {
ed.on("keydown", (event: KeyboardEvent) => {
if (event.shiftKey && event.key === "F3") {
event.preventDefault();
const selection = ed.selection.getSel();
const selectedText = selection?.toString();
if (selectedText !== undefined && selectedText.length > 0) {
let transformedText;
if (selectedText === selectedText.toUpperCase()) {
transformedText = selectedText.toLowerCase();
} else if (selectedText === selectedText.toLowerCase()) {
transformedText = capitalizeEachWord(selectedText);
} else {
transformedText = selectedText.toUpperCase();
}
const bookmark = ed.selection.getBookmark();
ed.selection.setContent(transformedText);
ed.selection.moveToBookmark(bookmark);
}
}
}
}
const capitalizeEachWord = (str: string) => str.replace(/\b\w/g, (char: string) => char.toUpperCase());