我试图创建一些按钮,当点击它们时,它们将添加 Markdown 字符,所以我使用 Selection API
获取选定的文本,然后添加字符,并将 caret
移回到选定文本的末尾位置,所有操作都没有问题。
当我尝试按下撤消键 Ctrl+Z 时,它不能回到添加 Markdown 字符之前的最后一个文本,我知道这是因为我更改了文本节点值。
有没有一种方法可以在不影响节点文本并应用撤消和重做的情况下完成上述操作?
let text = document.getElementById('test'),
btn = document.getElementById('btn')
//function to replace text by index
String.prototype.replaceAt = function(start, end, replacement) {
let text = '';
for (let i = 0; i < this.length; i++) {
if (i >= start && i < end) {
text += ''
if (i === end - 1) {
text += replacement
}
} else {
text += this[i]
}
}
return text
}
function addNewStr(callback) {
var sel = window.getSelection()
try {
var range = sel.getRangeAt(0),
r = document.createRange()
//check if there's text is selected
if (!sel.isCollapsed) {
let startPos = sel.anchorOffset,
endPos = sel.focusOffset,
node = sel.anchorNode,
value = sel.anchorNode.nodeValue,
selectedText = value.substring(startPos, endPos),
parent = node.parentNode
//function to determine if selection start from left to right or right to left
function checkPos(callback) {
if (startPos > endPos) {
return callback(startPos, endPos)
} else {
return callback(endPos, startPos)
}
}
if (typeof callback === 'function') {
//getting the new str from the callback
var replacement = callback(selectedText),
caretIndex;
//apply changes
node.nodeValue = checkPos(function(end, start) {
return node.nodeValue.replaceAt(start, end, replacement)
})
//check if the returned text from the callback is less or bigger than selected text to move caret to the end of selected text
if (replacement.length > selectedText.length) {
caretIndex = checkPos(function(pos) {
return pos + (replacement.length - selectedText.length);
})
} else if (selectedText.length > replacement.length) {
caretIndex = checkPos(function(pos) {
return (pos - selectedText.length) + (replacement.length);
})
}
//back caret to the end of the new position
r.setStart(parent.childNodes[0], caretIndex)
r.collapse(true)
sel.removeAllRanges()
sel.addRange(r)
}
}
} catch (err) {
console.log("Nothing is selected")
}
}
btn.addEventListener("click", function() {
addNewStr(function(str) {
return '__' + str + '__'
})
})
<div contenteditable="true" id="test" placeholder="insertText">
try to select me
</div>
<button id="btn">to strong</button>
Ctrl+z
时它会被应用,我的意思是有没有一种方法可以使浏览器在不添加额外的代码的情况下本地化地实现撤销和重做。 - JSX