OrangePineapple
OrangePineapple

Reputation: 65

remove and re-add same element to array on click event

I'm currently making a small app to practice JavaScript and jQuery. I have an array of fruits.

var fruits = [apples, bananas, grapes, watermelons, tomatoes];

And on a click event I want to remove tomatoes but if I change my mind clicking the same button, it will add tomatoes back to the array fruits. I've been using splice to remove but I don't know what to use to add the splice element back into the array.

Edit for clarification:

The element is not necessary going to be tomatoes, but it could be any random element in the fruits array. I'm using

fruits.splice(i,1);

Upvotes: 1

Views: 12062

Answers (3)

trincot
trincot

Reputation: 350365

To insert a value back into an array (at the same position) after you spliced it, can in general be done like this:

// delete:
var deleted = fruits.splice(i, 1);
// restore:
fruits.splice(i, 0, deleted);

Note that deleted is an array with one element here.

It can also done by taking a kind of backup of the original array:

// backup
var backup = fruits.slice(); // copy
// delete:
fruits.splice(i, 1);
// restore:
fruits = backup;

Undo Stack

To support multiple undo actions, you could use an undo stack, which would just keep track of all the versions of your array. When the user performs an undo-action, the previous version is popped from that stack. This way you can undo more than one removal:

var fruits = ['Apples', 'Bananas', 'Grapes', 'Watermelons', 'Tomatoes'];
var undoStack = [];

function showFruits() {
    $('#fruits').html('').append(
        // translate the array to a list of LI elements with delete buttons 
        fruits.map(function(fruit) {
            return $('<li>').text(fruit).append(
                $('<button>').addClass('delete').text('Delete'));
        })
    );
}

$(document).on('click', 'button.delete', function () {
    undoStack.push(fruits.slice()); // save a copy of the current array on the stack
    fruits.splice($(this).parent().index(), 1); // remove from array at index
    showFruits(); // update display
});

$('#undo').click(function () {
    if (!undoStack.length) return; // cannot undo 
    fruits = undoStack.pop(); // get previous state
    showFruits(); // update display
});

showFruits(); // show initial list
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="fruits"></ul>
<button id="undo">Undo</button>

More memory efficient alternative

If you are troubled by the memory usage of storing the complete array each time you delete an element, you could use the following alternative functions, which will only store the index and deleted value at every delete action:

$(document).on('click', 'button.delete', function () {
    var i = $(this).parent().index(); // get index where to delete
    var deleted = fruits.splice(i, 1); // remove from array at that index
    undoStack.push([i, deleted]); // save the index and value on the stack
    showFruits(); // update display
});

$('#undo').click(function () {
    if (!undoStack.length) return; // cannot undo 
    var restore = undoStack.pop(); // get information for re-inserting
    fruits.splice(restore[0], 0, restore[1]); // insert the value 
    showFruits(); // update display
});

If you would use the undo principle also for other modifications, like undoing an insert, or a modification of the label, then the first solution would not need much modification, while the more memory-efficient one would need a bit more.

For a more generic and elaborated solution on undo/redo operations on any object (not only arrays), see How to version control an object?

Upvotes: 5

connexo
connexo

Reputation: 56753

If the array position does not matter:

fruits.push(tomatoes);

If you want to insert it at a specific position (index) in the array:

fruits.splice(index, 0, tomatoes);

will insert tomatoes into fruits at the specified index (deleting 0 items first, so it's just an insert).

Array.prototype.splice()

The splice() method changes the content of an array by removing existing elements and/or adding new elements.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice

Temp-storing deleted elements and re-adding them

var deletedFruits = fruits.splice(i,1); will contain an array of the removed element(s) because that is the return value of splice(). So

fruits = fruits.concat(deletedFruits);

will re-add the deleted fruits.

Re-adding deleted elements at their original position

Store the position of the deleted element:

var deletedFruit = { fruit: fruits.splice(i,1)[0], index: i } 

If need be you can restore deleted fruits at their original array position using the aforementioned

fruits.splice(deletedFruit.index, 0, deletedFruit.fruit);

Upvotes: 2

Kyle Lin
Kyle Lin

Reputation: 833

You can add and remove fruits with these two functions:

function addFruit(fruit) {
  fruits.push(fruit);
}

function removeFruit(fruit) {
  // indexOf method returns index of fruit in the list, or -1 if fruit is not found.
  var index = fruits.indexOf(fruit);
  if (index > -1) {
    fruits.splice(index, 1);
  }
}

This assumes you have already defined an array named fruits. Then you can do something like

<script>
  function updateOutput() {
    document.getElementById('output').innerHTML = fruits.join(', ');
  }

  function addSelectedFruit() {
    var selectedFruit = document.getElementById('fruit-select').value;
    addFruit(selectedFruit);
    updateOutput();
  }

  function removeSelectedFruit() {
    var selectedFruit = document.getElementById('fruit-select').value;
    removeFruit(selectedFruit);
    updateOutput();
  }
</script>
<input type="text" id="fruit-select"/>
<button onclick="addSelectedFruit();">Add</button>
<button onclick="removeSelectedFruit();">Remove</button>
List of fruits:
<p id="output"></p>

Example:

<script>
  var fruits = ['Apples', 'Pears', 'Pineapples'];
function addFruit(fruit) {
  fruits.push(fruit);
}
function removeFruit(fruit) {
  var i = fruits.indexOf(fruit);
  if (i > -1) {fruits.splice(i, 1);}else{alert(fruit + ' cannot be removed, as it is not present in the array of fruits.');}
}
function selectedFruit() {
  return document.getElementById('fruit-select').value;
}
function updateOutput() {
  document.getElementById('output').innerHTML = fruits.join(', ');
}
  </script>
Fruit:
<input type="text" id="fruit-select" value="Orange"/>
<button onclick="addFruit(selectedFruit());updateOutput();">Add</button>
<button onclick="removeFruit(selectedFruit());updateOutput();">Remove</button>
<p id="output">Apples, Pears, Pineapples</p>

Upvotes: 0

Related Questions