我有textarea
并存储在数组onclick中我需要从最后一个元素逐个显示,然后从用户点击的位置逐个重做onclick。我正在做自定义撤消和重做功能。
var stack =[];
jQuery('#enter-text').keypress(function() {
console.log(jQuery('#enter-text').val());
stack.push(jQuery('#enter-text').val());
})
jQuery('#undo_text').click(function() {
console.log(stack.pop());
})
jQuery('#redo_text').click(function() {
// how to redo onclik where user undo text
})
我创建了jsfiddle
答案 0 :(得分:2)
创建一个旧值数组,如下所示:
var deleted_stack = [];
// your other code
jQuery('#undo_text').click(function() {
deleted_stack.push(stack.pop());
})
jQuery('#redo_text').click(function () {
stack.push(deleted_stack.pop());
}
如果您还需要在文本中间执行此操作,则应跟踪光标位置。然后你删除的堆栈看起来应该更像这样:
deleted_stack = [
{
char_idx: 2, // index of position in string where it was deleted, but
// then you shouldn't be deleting characters with .pop()
char_val: 'a'
},
... // other objects like first one
]
但是删除也变得更加复杂......
答案 1 :(得分:1)
这是一项设计决策,它完全取决于您的用户需求以及您愿意做出的复杂程度。
通常的做法是保留2个列表,一个用于撤消,一个用于重做。 每次撤消操作时,都会将其添加到重做列表中。撤消后每次执行新操作时,重做列表都会被销毁。
var stack = [];
var redo = [];
jQuery('#enter-text').keypress(function() {
console.log(jQuery('#enter-text').val());
stack.push(jQuery('#enter-text').val());
redo = []; // <-----
})
jQuery('#undo_text').click(function() {
redo.push(stack.pop()); // <-----
})
jQuery('#redo_text').click(function() {
stack.push(redo.pop()) // <-----
})
答案 2 :(得分:1)
相反,如果为您已完成和撤消的操作保留不同的堆栈,则可以将它们保存在一个数组中,并记住当前位置:
var stack = [ jQuery('#enter-text').val() ], index = 0;
updateButtonsDisabled();
jQuery('#enter-text').keypress(function() {
//adding the current action
stack[++index] = jQuery('#enter-text').val();
//removing the entries after the last one you added: they belong to a different redo-stack
stack.length = index+1;
updateButtonsDisabled();
})
jQuery('#undo_text').click(function() {
if(!index) return;
jQuery('#enter-text').val(stack[--index]);
updateButtonsDisabled();
})
jQuery('#redo_text').click(function() {
if(index === stack.length-1) return;
jQuery('#enter-text').val(stack[++index]);
updateButtonsDisabled();
})
//just some sugar
function updateButtonsDisabled(){
jQuery('#undo_text').toggleClass("disabled", index === 0);
jQuery('#redo_text').toggleClass("disabled", index === stack.length-1);
}
index
保持当前显示值的堆栈位置。您可以根据需要撤消和重做,但只要您开始输入,就会清除重做堆栈。
您应该考虑限制要保留在堆栈中的项目,或者您将分配相当多的内存。并且您可以在更新堆栈之前更改按键的逻辑以等待300ms的暂停。这会极大地减少堆栈中的项目。
编辑做了一点小事,实现了我提到的可能的更改,比如分离更新和有限的堆栈大小。看看那个
https://jsfiddle.net/q8qks3xj/1/
//this value is kept small for testing purposes, you'd probably want to use sth. between 50 and 200
const stackSize = 10;
//left and right define the first and last "index" you can actually navigate to, a frame with maximum stackSize-1 items between them.
//These values are continually growing as you push new states to the stack, so that the index has to be clamped to the actual index in stack by %stackSize.
var stack = Array(stackSize), left=0, right=0, index = 0, timeout;
//push the first state to the stack, usually an empty string, but not necessarily
stack[0] = $("#enter-text").val();
updateButtons();
$("#enter-text").on("keydown keyup change", detachedUpdateText);
$("#undo").on("click", undo);
$("#redo").on("click", redo);
//detach update
function detachedUpdateText(){
clearTimeout(timeout);
timeout = setTimeout(updateText, 500);
}
function updateButtons(){
//disable buttons if the index reaches the respective border of the frame
//write the amount of steps availabe in each direction into the data-count attribute, to be processed by css
$("#undo")
.prop("disabled", index === left)
.attr("data-count", index-left);
$("#redo")
.prop("disabled", index === right)
.attr("data-count", right-index);
//show status
$("#stat").html(JSON.stringify({
left,
right,
index,
"index in stack": index % stackSize,
stack
}, null, 4))
}
function updateText(){
var val = $("#enter-text").val().trimRight();
//skip if nothing really changed
if(val === stack[index % stackSize]) return;
//add value
stack[++index % stackSize] = val;
//clean the undo-part of the stack
while(right > index)
stack[right-- % stackSize] = null;
//update boundaries
right = index;
left = Math.max(left, right+1-stackSize);
updateButtons();
}
function undo(){
if(index > left){
$("#enter-text").val(stack[--index % stackSize]);
updateButtons();
}
}
function redo(){
if(index < right){
$("#enter-text").val(stack[++index % stackSize]);
updateButtons();
}
}
答案 3 :(得分:0)
您可以使用keyup
事件并始终将输入的数据保留在stack
数组中。通过这些方式,您可以使用将在变量$('#enter-text')
中更新的相应数组索引更新字段index
的值:
var $textEnter = $('#enter-text'),
stack = [],
index = 0;
$textEnter.on('keyup', function () {
stack.push($textEnter.val());
index = stack.length - 1;
});
$('#undo_text').on('click', function () {
if (index >= 0) {
$textEnter.val(stack[--index]);
}
});
$('#redo_text').on('click', function () {
if (index < stack.length - 1) {
$textEnter.val(stack[++index]);
}
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="enter-text"></textarea>
<div id="drag-area-selected">
</div>
<button id="undo_text">
Undo
</button>
<button id="redo_text">
Redo
</button>
&#13;