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

时间:2016-10-06 14:13:38

标签: 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').click(function() {
    console.log(stack.pop());
 })

jQuery('#redo_text').click(function() {
    // how to redo onclik where user undo text
})

我创建了jsfiddle

https://jsfiddle.net/k0nr53e0/4/

4 个答案:

答案 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的值:

&#13;
&#13;
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;
&#13;
&#13;