I really like undos. If I could undo that that last beer… Unfortunately, I can't. But, I can offer undo to users of my application.

When I thought about undo before, I thought about a complicated Rails plugin that would keep an anonymous ID linking to any table in the database with an “action” field that would contain the action to undo. Pretty complicated stuff for something as simple.

The javascript solution

One day while I was writing some javascript, the solution struck me : I could handle this completely with javascript. The basic idea is that whenever an action is completed, I can save its undo function in an array and call it whenever I need it.

Example, if I'm saving a user in a database with Ajax :

  1. I send the data to server to save a new user
  2. The server returns the ID of the new user
  3. I create a function with an ajax request that will send a delete of this user to the server
  4. I add the previous function to a stack of undo functions to be able to call it later

That, when I call that last function, it will undo that user creation without having to keep it in memory server-side.

Introducing jsKata.undo

I wrote a little something called jsKata.undo on GitHub that contains the logic describe earlier. It's quite simple but it may grow over time. It has no requirement, not even jQuery. It's very simple to use.

The complete doc is on GitHub.

1. Adding an action that can you can undo

I'll use the “add a user” example with jQuery.

$.post(
    "http://yoursite.com/users/new", // The url to add a user
    {name:"John Boucher"}, // The name of the user
    function(newUser, textStatus, XMLHttpRequest) { 
      // This is called when the post is over
      var newUserId = newUser.id;
  
      // We begin by creating a function to delete the user
      var undoNewUser = function() {
        $.post(
          "http://yoursite.com/users/delete", // The url to delete a user
          {id:newUserId} // The ID of the new user to delete
        );
      }
  
      // We add the undo function to the stack
      jskataUndo.push(undoNewUser);
    }
  );

2. Undo the last action you made

jsKata.undo.undo();

3. Events

Each time there's a change, an onChange event is called. To assign yours, simply write :

jsKata.undo.onChange = function() {
    // Show the undo button
     $("#undoButton").show();
  }

There's also an onEmpty event that is called when the stack of undoable actions is empty.

jsKata.undo.onEmpty = function() {
    // Hide the undo button
     $("#undoButton").hide();
  }

Complete demo

There is a complete demo on GitHub as well as the HTML and Javascript code for it. Take a look!

comments powered by Disqus