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.
  1. ChangeColorCommand = function(obj, color) {  
  2.   this.obj = obj;  
  3.   this.new_color = color;  
  4.   
  5.   // guardar estado anterior  
  6.   this.prev_color = obj.style.backgroundColor;  
  7. }  
  8.           
  9. ChangeColorCommand.prototype.execute = function() {  
  10.   this.obj.style.backgroundColor = this.new_color;  
  11. }  
  12.           
  13. ChangeColorCommand.prototype.undo = function() {  
  14.   this.obj.style.backgroundColor = this.prev_color;  
  15. }  
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.
  1. CommandManager = function(max_undo) {  
  2.   // máxima cantidad de acciones guardadas  
  3.   max_undo = max_undo || 30;    
  4.   
  5.   // pilas de acciones  
  6.   this.undo_stack = [];  
  7.   this.redo_stack = [];  
  8.   
  9.   // ejecutar comando cmd  
  10.   this.executeCommand = function(cmd){  
  11.     cmd.execute();  
  12.   
  13.     // si se sobrepasa cantidad de acciones  
  14.     // eliminar primer elemento  
  15.     if (this.undo_stack.length >= max_undo) {  
  16.       this.undo_stack.shift();  
  17.     }  
  18.     this.undo_stack.push(cmd);  
  19.     this.redo_stack = [];  
  20.   }  
  21.   
  22.   // deshacer acción   
  23.   this.undoCommand = function() {  
  24.     var cmd = this.undo_stack.pop();  
  25.       
  26.     // si existe acción  
  27.     if ( cmd ) {  
  28.       cmd.undo();  
  29.       this.redo_stack.push(cmd);  
  30.     }  
  31.   }  
  32. }  
Para realizar una acción creamos una instancia del objeto apropiado y la pasamos al CommandManager (previamente creado).
  1. var UndoRedo = new CommandManager(),  
  2.     box = document.getElementById("box");  
  3.   
  4. // cambiar color a rojo  
  5. UndoRedo.executeCommand(new ChangeColorCommand(box, "red"));  
  6.   
  7. // cambiar color a verde  
  8. UndoRedo.executeCommand(new ChangeColorCommand(box, "green"));  
  9.   
  10. // cambiar de verde a rojo  
  11. UndoRedo.undoCommand();  
  12.   
  13. // cambiar de rojo a blanco  
  14. 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