miércoles, 24 de agosto de 2011

Rehacer - Deshacer en javascript

En este tutorial intentaré explicar la forma de implementar la funcionalidad de deshacer y rehacer, una característica muy usada en los programas de escritorio y que muchas aplicaciones web no tienen (y hace mucha falta ya que errar es de humanos).
Descargar código
La idea consiste en tener objetos que representen las acciones (mover, eliminar, resaltar...), los cuales deben guardar el estado anterior del objeto afectado.
ChangeColorCommand = function(obj, color) {
  this.obj = obj;
  this.new_color = color;

  // guardar estado anterior
  this.prev_color = obj.style.backgroundColor;
}
		
ChangeColorCommand.prototype.execute = function() {
  this.obj.style.backgroundColor = this.new_color;
}
		
ChangeColorCommand.prototype.undo = function() {
  this.obj.style.backgroundColor = this.prev_color;
}
Cada objeto cuenta con dos métodos
  • execute: ejecuta la acción (dah)
  • undo: deshace la acción valiéndose de los datos guardados previamente en el constructor.
Las acciones son administradas por un objeto que mantiene dos pilas de acciones: las que se pueden deshacer y las que se pueden rehacer:
  • cuando ejecuta una acción, la guarda en undo_stack y borra toda acción que se podía rehacer
  • cuando se deshace algo, saca el ultimo objeto de la pila undo_stack, ejecuta el método undo y guarda la acción en la pila redo_stack.
CommandManager = function(max_undo) {
  // máxima cantidad de acciones guardadas
  max_undo = max_undo || 30;  

  // pilas de acciones
  this.undo_stack = [];
  this.redo_stack = [];

  // ejecutar comando cmd
  this.executeCommand = function(cmd){
    cmd.execute();

    // si se sobrepasa cantidad de acciones
    // eliminar primer elemento
    if (this.undo_stack.length >= max_undo) {
      this.undo_stack.shift();
    }
    this.undo_stack.push(cmd);
    this.redo_stack = [];
  }

  // deshacer acción 
  this.undoCommand = function() {
    var cmd = this.undo_stack.pop();
    
    // si existe acción
    if ( cmd ) {
      cmd.undo();
      this.redo_stack.push(cmd);
    }
  }
}
Para realizar una acción creamos una instancia del objeto apropiado y la pasamos al CommandManager (previamente creado).
var UndoRedo = new CommandManager(),
    box = document.getElementById("box");

// cambiar color a rojo
UndoRedo.executeCommand(new ChangeColorCommand(box, "red"));

// cambiar color a verde
UndoRedo.executeCommand(new ChangeColorCommand(box, "green"));

// cambiar de verde a rojo
UndoRedo.undoCommand();

// cambiar de rojo a blanco
UndoRedo.undoCommand();
Ahora solo resta crear mas acciones (mover, negrita, itálica...) dependiendo de la aplicación que estemos desarrollando.

Eso es todo, espero les haya servido; si tienen alguna duda o critica no duden en dejarla en los comentarios.
 
© 2009 NovatoZ. All Rights Reserved | Powered by Blogger
Design by psdvibe | Bloggerized By LawnyDesignz