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.

4 Responses to “Rehacer - Deshacer en javascript”

Neonius dijo...

Lo que quiero hacer es bastante más simple a lo que se muestra aquí. Buen artículo, por cierto.

Sólo quiero cambiar el color de un texto y después volverlo al estado original. Ya puedo cambiar el texto de color, sólo me queda resolver cómo volver al color anterior.

sney2002 dijo...

Debes guardar el color original en una propiedad antes de cambiarlo. el problema es que si no se ha especificado de forma explicita el color, elem.style.color retorna "".

Puedes usar el mismo codigo del ejemplo pero en lugar de acceder al estilo directamente usas esta función http://tmont.com/blargh/2010/4/get-computed-style-in-javascript

texto = document.getElementById("mi-texto");

// guardar color antes de cambiarlo
texto.old_color = getComputedStyle(texto, "color");
// cambiar color
texto.style.color = "new_color";

// Restaurar color
texto.style.color = texto.old_color;

Espero que esto sea de ayuda :)

Neonius dijo...

Aah, muchas gracias por responder. Veré como me sale :)

Anónimo dijo...

no entiendo una goma

Deja una respuesta

 
© 2009 NovatoZ. All Rights Reserved | Powered by Blogger
Design by psdvibe | Bloggerized By LawnyDesignz