如何在javascript中逐个显示数组元素onclick事件?

如何在javascript中逐个显示数组元素onclick事件?,javascript,jquery,Javascript,Jquery,我有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'

我有
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
})
我已经创建了JSFIDLE


创建一个旧值数组,如下所示:

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
]

如果你还需要在文本中间做这件事,你应该跟踪光标位置。那么您删除的堆栈应该更像这样:

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
]

但是删除也变得更加复杂…

创建一个旧值数组,如下所示:

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
]

如果你还需要在文本中间做这件事,你应该跟踪光标位置。那么您删除的堆栈应该更像这样:

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
]

但是删除也会变得更复杂…

这是一个设计决策,完全取决于您的用户需求以及您愿意使其变得多复杂

通常的做法是保留两个列表,一个用于撤消,一个用于重做。 每次撤消操作时,都会将其添加到重做列表中。每次撤消后执行新操作时,重做列表都会被销毁

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())  // <-----
})
var堆栈=[];
var redo=[];
jQuery(“#输入文本”).keypress(函数(){
log(jQuery(“#输入文本”).val();
stack.push(jQuery('#enter text').val());

redo=[];//这是一个设计决策,它完全取决于您的用户需求以及您愿意使其变得多么复杂

通常的做法是保留两个列表,一个用于撤消,一个用于重做。 每次撤消操作时,都会将其添加到重做列表中。每次撤消后执行新操作时,重做列表都会被销毁

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())  // <-----
})
var堆栈=[];
var redo=[];
jQuery(“#输入文本”).keypress(函数(){
log(jQuery(“#输入文本”).val();
stack.push(jQuery('#enter text').val());

重做=[];//相反,如果为已完成的操作保留不同的堆栈,然后撤消,则可以将它们保留在一个数组中,并记住当前位置:

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
保留当前显示值在堆栈中的位置。您可以根据需要撤消和重做,但一旦开始键入,重做堆栈将被清除

你应该考虑限制你要在堆栈中保存的项目,或者你会分配相当多的内存。你可以改变键按下的逻辑,在更新堆栈之前等待像300毫秒的暂停。这会极大地减少堆栈中的项目。

编辑:制作了一个片段,实现了我提到的可能的更改,如分离更新和限制堆栈大小。请看一下

//出于测试目的,此值保持较小,您可能希望使用50到200之间的某个值
常数stackSize=10;
//左侧和右侧定义您可以实际导航到的第一个和最后一个“索引”,这是一个在它们之间具有最大stackSize-1项的框架。
//当您将新状态推送到堆栈时,这些值会不断增加,因此索引必须按%stackSize钳制到堆栈中的实际索引。
var stack=数组(stackSize),
左=0,
右=0,
指数=0,
超时;
//将第一个状态推送到堆栈,通常为空字符串,但不一定是空字符串
堆栈[0]=$(“#输入文本”).val();
updateButtons();
$(“#输入文本”)。打开(“向下键向上键更改”,detachedUpdateText);
$(“撤消”)。在(“单击”,撤消);
$(“#重做”)。点击(“点击”,重做);
//分离更新
函数detachedUpdateText(){
clearTimeout(超时);
超时=设置超时(updateText,500);
}
函数updateButtons(){
//如果索引到达帧的相应边界,则禁用按钮
//将每个方向上可用的步数写入data count属性,由css处理
$(“撤消”)
.prop(“禁用”,索引===左)
.attr(“数据计数”,索引-左);
$(“重做”)
.prop(“禁用”,索引===右侧)
.attr(“数据计数”,右-索引);
//显示状态
$(“#stat”).text(JSON.stringify({
左边
正确的,
指数
“堆栈中的索引”:索引%stackSize,
堆栈
},空,2))
}
函数updateText(){
var val=$(“#输入文本”).val().trimRight();
//如果没有任何变化,请跳过
if(val==堆栈[索引%stackSize])返回;
//增值
堆栈[++索引%stackSize]=val;
//清理堆栈的撤消部分
while(右>索引)
堆栈[右--%stackSize]=null;
//更新边界
右=索引;
左=数学最大值(左、右+1-堆栈大小);
updateButtons();
}
函数undo(){
如果(索引>左){
$(“#输入文本”).val(堆栈[--索引%stackSize]);
updateButtons();
}
}
函数redo(){
如果(索引<右){
$(“#输入文本”).val(堆栈[++索引%stackSize]);
updateButtons();
}
}
#输入文本{
宽度:100%;
高度:100px;
}
#撤销,
#重做{
位置:相对位置;
右侧填充:1em;
}
#撤销:之后,
#重做:之后{
内容:attr(数据计数);
位置:绝对位置;
底部:0;
右:0;
字体大小:0.75em;
}

解开
重做

相反,如果为已执行的操作保留不同的堆栈,然后撤消,则可以将它们保留在一个数组中,并记住当前位置:

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
保留当前显示值在堆栈中的位置。您可以根据需要撤消和重做,但一旦开始键入,重做堆栈将被清除

你应该考虑限制你要在堆栈中保存的项目,或者你会分配相当多的内存。你可以改变键按下的逻辑,在更新堆栈之前等待像300毫秒的暂停。这会极大地减少堆栈中的项目。

编辑:制作了一个片段,实现了我提到的可能的更改,如分离更新和限制堆栈大小。请看一下

//出于测试目的,此值保持较小,您可能希望使用50到200之间的某个值
常数stackSize=10;
//左右定义