Javascript “撤消”仅适用于第一个替换的文本?
在这里,我使用Ctrl+Z撤销替换的文本,我有一个场景,在文本区域中,我有一个包含多个单词的句子,我选择第一个单词并替换为星形,然后选择另一个单词并替换为星形。但当Ctrl+Z组合键执行时,它只对最近选定的单词起作用,而对以前的单词不起作用 JavaScript:Javascript “撤消”仅适用于第一个替换的文本?,javascript,jquery,css,Javascript,Jquery,Css,在这里,我使用Ctrl+Z撤销替换的文本,我有一个场景,在文本区域中,我有一个包含多个单词的句子,我选择第一个单词并替换为星形,然后选择另一个单词并替换为星形。但当Ctrl+Z组合键执行时,它只对最近选定的单词起作用,而对以前的单词不起作用 JavaScript: var selection = {}; function undo(e) { var evtobj = window.event? window.event : e; if (evtobj.keyCode ==
var selection = {};
function undo(e) {
var evtobj = window.event? window.event : e;
if (evtobj.keyCode == 90 && evtobj.ctrlKey && selection.text) {
evtobj.preventDefault();
var txtarea = document.getElementById("mytextarea");
var allText = txtarea.value;
var newText = allText.substring(0, selection.start) + selection.text + allText.substring(selection.finish, allText.length);
txtarea.value = newText;
}
}
function getSel() {
// obtain the object reference for the textarea>
var txtarea = document.getElementById("mytextarea");
// obtain the index of the first selected character
var start = txtarea.selectionStart;
// obtain the index of the last selected character
var finish = txtarea.selectionEnd;
//obtain all Text
var allText = txtarea.value;
selection.text = allText.substring(start, finish);
selection.start = start;
selection.finish = finish;
// obtain the selected text
var sel = allText.substring(start, finish);
sel = sel.replace(/[\S]/g, "*"); //append te text;
var newText = allText.substring(0, start) + sel + allText.substring(finish, allText.length);
txtarea.value = newText;
$('#newpost').offset({top: 0, left: 0}).hide();
}
function closePopUp() {
$('#newpost').offset({top: 0, left: 0}).hide();
}
$(document).ready(function () {
closePopUp();
var newpost = $('#newpost');
$('#mytextarea').on('select', function (e) {
var txtarea = document.getElementById("mytextarea");
var start = txtarea.selectionStart;
var finish = txtarea.selectionEnd;
newpost.offset(getCursorXY(txtarea, start, 20)).show();
newpost.find('div').text('replace with stars');
}).on('input', () => selection.text = null);
document.onkeydown = undo;
});
var getCursorXY = function getCursorXY(input, selectionPoint, offset) {
var inputX = input.offsetLeft,
inputY = input.offsetTop;
// create a dummy element that will be a clone of our input
var div = document.createElement('div');
// get the computed style of the input and clone it onto the dummy element
var copyStyle = getComputedStyle(input);
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = copyStyle[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done) ; _iteratorNormalCompletion = true) {
var prop = _step.value;
div.style[prop] = copyStyle[prop];
}
// we need a character that will replace whitespace when filling our dummy element
// if it's a single line <input/>
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
var swap = '.';
var inputValue = input.tagName === 'INPUT' ? input.value.replace(/ /g, swap) : input.value;
// set the div content to that of the textarea up until selection
var textContent = inputValue.substr(0, selectionPoint);
// set the text content of the dummy element div
div.textContent = textContent;
if (input.tagName === 'TEXTAREA') div.style.height = 'auto';
// if a single line input then the div needs to be single line and not break out like a text area
if (input.tagName === 'INPUT') div.style.width = 'auto';
// create a marker element to obtain caret position
var span = document.createElement('span');
// give the span the textContent of remaining content so that the recreated dummy element
// is as close as possible
span.textContent = inputValue.substr(selectionPoint) || '.';
// append the span marker to the div
div.appendChild(span);
// append the dummy element to the body
document.body.appendChild(div);
// get the marker position, this is the caret position top and left relative to the input
var spanX = span.offsetLeft,
spanY = span.offsetTop;
// lastly, remove that dummy element
// NOTE:: can comment this out for debugging purposes if you want to see where that span is rendered
document.body.removeChild(div);
// return an object with the x and y of the caret. account for input positioning
// so that you don't need to wrap the input
return {
left: inputX + spanX,
top: inputY + spanY + offset
};
};
var选择={};
函数撤消(e){
var evtobj=window.event?window.event:e;
if(evtobj.keyCode==90&&evtobj.ctrlKey&&selection.text){
evtobj.preventDefault();
var txtarea=document.getElementById(“mytextarea”);
var allText=txtarea.value;
var newText=allText.substring(0,selection.start)+selection.text+allText.substring(selection.finish,allText.length);
txtarea.value=newText;
}
}
函数getSel(){
//获取textarea>
var txtarea=document.getElementById(“mytextarea”);
//获取第一个选定字符的索引
var start=txtarea.selectionStart;
//获取最后选定字符的索引
var finish=txtarea.selectionEnd;
//获取所有文本
var allText=txtarea.value;
selection.text=allText.substring(开始、结束);
selection.start=开始;
selection.finish=完成;
//获取所选文本
var sel=allText.substring(开始、结束);
sel=sel.replace(//[\S]/g,“*”);//追加文本;
var newText=allText.substring(0,开始)+sel+allText.substring(结束,allText.length);
txtarea.value=newText;
$('#newpost').offset({top:0,left:0}).hide();
}
函数closePopUp(){
$('#newpost').offset({top:0,left:0}).hide();
}
$(文档).ready(函数(){
closePopUp();
var newpost=$(“#newpost”);
$('#mytextarea')。在('select',函数(e)上{
var txtarea=document.getElementById(“mytextarea”);
var start=txtarea.selectionStart;
var finish=txtarea.selectionEnd;
offset(getCursorXY(txtarea,start,20)).show();
newpost.find('div').text('replace with stars');
}).on('input',()=>selection.text=null);
document.onkeydown=undo;
});
var getCursorXY=函数getCursorXY(输入、选择点、偏移){
var inputX=input.offsetLeft,
inputY=input.offsetTop;
//创建一个虚拟元素,它将是我们输入的克隆
var div=document.createElement('div');
//获取输入的计算样式,并将其克隆到虚拟元素上
var copyStyle=getComputedStyle(输入);
var\u iteratorNormalCompletion=true;
var _diditorerror=false;
var _iteratorError=未定义;
试一试{
对于(var _iterator=copyStyle[Symbol.iterator](),_step;!(_iteratorNormalCompletion=(_step=_iterator.next()).done);_iteratorNormalCompletion=true){
var prop=_step.value;
div.style[prop]=复制样式[prop];
}
//在填充虚拟元素时,我们需要一个字符来替换空白
//如果是单行线
}捕捉(错误){
_didIteratorError=true;
_迭代器错误=错误;
}最后{
试一试{
if(!\u iteratorNormalCompletion&&u iterator.return){
_return();
}
}最后{
如果(_diditorerror){
抛出迭代错误;
}
}
}
风险值互换=';
var inputValue=input.tagName=='input'?input.value.replace(//g,swap):input.value;
//将div内容设置为文本区域的内容,直到选择为止
var textContent=inputValue.substr(0,selectionPoint);
//设置虚拟元素div的文本内容
div.textContent=textContent;
如果(input.tagName=='TEXTAREA')div.style.height='auto';
//如果是单行输入,则div需要是单行,而不是像文本区域那样断开
如果(input.tagName=='input')div.style.width='auto';
//创建标记元素以获取插入符号位置
var span=document.createElement('span');
//为跨度指定剩余内容的textContent,以便重新创建的虚拟元素
//越近越好
span.textContent=inputValue.substr(selectionPoint)| |';
//将跨度标记附加到div
子类(span);
//将虚拟元素附加到主体
文件.正文.附件(div);
//获取标记位置,这是相对于输入的顶部和左侧插入符号位置
var spanX=span.offsetLeft,
spanY=span.offsetTop;
//最后,删除该虚拟元素
//注意::如果您想查看呈现跨度的位置,可以出于调试目的对此进行注释
文件.正文.删除文件(div);
//返回带有插入符号x和y的对象。输入定位的帐户
//这样就不需要包装输入
返回{
左:inputX+spanX,
顶部:输入+跨距+偏移
};
};
这是我的。您需要将逻辑从使用单个
选择
对象更改为使用选择
对象数组,如下所示:
选择
而不是选择
var selections = [];
getSel()
时,确保更新到push
到数组:
function getSel() {
// obtain the object reference for the textarea>
var txtarea = document.getElementById("mytextarea");
// obtain the index of the first selected character
var start = txtarea.selectionStart;
// obtain the index of the last selected character
var finish = txtarea.selectionEnd;
//obtain all Text
var allText = txtarea.value;
selections.push({
start: start,
finish: finish,
text: allText.substring(start, finish)
});
// obtain the selected text
var sel = allText.substring(start, finish);
sel = sel.replace(/[\S]/g, "*"); //append te text;
var newText = allText.substring(0, start) + sel + allText.substring(finish, allText.length);
txtarea.value = newText;
$('#newpost').offset({top: 0, left: 0}).hide();
}
undo
函数,如下所示:
function undo(e) {
var evtobj = window.event? window.event : e;
if (evtobj.keyCode == 90 && evtobj.ctrlKey) {
evtobj.preventDefault();
if (selections.length === 0) alert ("Can't do more undos");
else {
var thisSelection = selections.pop();
var txtarea = document.getElementById("mytextarea");
var allText = txtarea.value;
var newText = allText.substring(0, thisSelection.start) + thisSelection.text + allText.substring(thisSelection.finish, allText.length);
txtarea.value = newText;
}
}
}
$(“#mytextarea”)
中删除('input')事件侦听器上的,因为我认为不需要它
以下是您必须手动控制所有
文本区域的更改
在这里,我创建了edits
数组,该数组每隔几秒钟填充textarea
text on change(您可以使用saveInterval
变量控制它)。
您还可以使用maxHistorySi设置此数组的最大长度