gpt4 book ai didi

javascript - 更新选定文本时撤消/重做不起作用

转载 作者:行者123 更新时间:2023-12-04 14:50:10 40 4
gpt4 key购买 nike

我试图创建一些在单击时会添加 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>

最佳答案

因为您正在以编程方式更改内容,所以您将不得不以编程方式撤消它。
在您的按钮单击处理程序中:

  • 在修改之前捕获内容的现有状态
  • 创建一个将其重置为该状态的函数。
  • 将该函数插入一个数组(“撤消堆栈”)

  • const undoStack = [];

    function onButtonClick (e) {
    // capture the existing state
    const textContent = text.innerText;

    // create a function to set the div content to its current value
    const undoFn = () => text.innerText = textContent;

    // push the undo function into the array
    undoStack.push(undoFn);

    // ...then do whatever the button does...
    }
    有了它,您可以收听 ctrl-z并调用最近的撤消函数:
    // convenience to determine whether a keyboard event should trigger an undo
    const isUndo = ({ctrlKey, metaKey, key}) => key === 'z' && (ctrlKey || metaKey);

    // keydown event handler for undo
    const keydown = (e) => {
    if(isUndo(e) && undos.length) {
    e.preventDefault();
    undos.pop()();
    }
    }

    // listen for keydowns
    document.body.addEventListener('keydown', keydown);
    还有一些其他的考虑因素,例如某些用户操作是否应该清除撤消堆栈,但这是基本思想。

    概念验证演示
    为了清楚起见,我已经替换了您的内容修改代码,只需在每次点击时添加一个数字。

    const div = document.getElementById('test');
    const button = document.querySelector('button');

    const undos = [];

    button.addEventListener('click', e => {
    const text = div.innerText;
    undos.push(() => div.innerText = text);
    div.innerText += ` ${undos.length} `;
    });

    const isUndo = ({ctrlKey, metaKey, key}) => key === 'z' && (ctrlKey || metaKey);

    const keydown = (e) => {
    if(isUndo(e) && undos.length) {
    e.preventDefault();
    undos.pop()();
    }
    }

    document.body.addEventListener('keydown', keydown);
    <div contenteditable="true" id="test" placeholder="insertText">
    this is some text
    </div>
    <button id="btn">to strong</button>

    关于javascript - 更新选定文本时撤消/重做不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69230546/

    40 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com