Skip to content

Instantly share code, notes, and snippets.

@QuadFlask
Last active March 28, 2016 14:47
Show Gist options
  • Save QuadFlask/30ba6dcefaa037b3ec7e to your computer and use it in GitHub Desktop.
Save QuadFlask/30ba6dcefaa037b3ec7e to your computer and use it in GitHub Desktop.
[CodeWars] Undo/Redo

link

function undoRedo(object) {
  function History(type, key, oldValue, newValue) {
    this.type = type;
    this.key = key;
    this.oldValue = oldValue;
    this.newValue = newValue;
  }
  function UndoLimitException() {
    this.name = 'UndoLimitException';
    this.message =  'cannot undo';
  }
  function RedoLimitException() {
    this.name = 'RedoLimitException';
    this.message =  'cannot redo';
  }

  var history = [];
  var index = 0;
  return {
    set: function(key, value) {
      if (object.hasOwnProperty(key))
        history.push(new History('set', key, object[key], value));
      else 
        history.push(new History('new', key, null, value));
      object[key] = value;
      index++;
      history.length = index;
    },
    get: function(key) {
      return object[key];
    },
    del: function(key) {
      history.push(new History('del', key, object[key], null));
      delete object[key];
      index++;
      history.length = index;
    },
    undo: function() {
      if (index <= 0) throw new UndoLimitException();
      index--;

      var h = history[index];
      if (h.type == 'set') object[h.key] = h.oldValue;
      else if (h.type == 'new') delete object[h.key];
      else if (h.type == 'del') object[h.key] = h.oldValue;
    },
    redo: function() {
      if (index >= history.length) throw new RedoLimitException();
      
      var h = history[index];
      if (h.type == 'set') object[h.key] = h.newValue;
      else if (h.type == 'new') object[h.key] = h.newValue;
      else if (h.type == 'del') delete object[h.key];

      index++;
    }
  };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment