Memento Example (Typescript)

In this example below you will see how to do a Memento Example (Typescript) with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by Frontender, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright Frontender ©
  • HTML
  • CSS
  • JavaScript
    <h1>Memento Example (Typescript)</h1>
<p>This pattern provides the ability to restore an object to its previous state. Memento is implemented with three objects: the Originator, a Caretaker and a Memento. The Originator is some object that has an internal state. This internal state can be saved in a Memento object. The Caretaker first asks the Originator for a Memento object and stores it. Then some actions are performed on the Originator. To roll back to the state before the actions, Caretaker returns the corresponding Memento object to the Originator. The Memento object itself is an opaque object (the Caretaker cannot, or should not, change it).</p>
<button id="sender1">Underline Text</button>
<button id="sender2">Strong Text</button>
<button id="sender3">Italic Text</button>
<button id="sender4">Undo</button>
<button id="reset">Reset</button>
<br><br>
<div id="result">
No result. Press a button above.
</div>
<br>
<div class="items" id="logs">
  <header>Logs:</header>
</div>
<br> 

/*Downloaded from https://www.codeseek.co/curveball/memento-example-typescript-jyKKwy */
    body {padding:10px;}
#receiver {
  border:1px solid gray;
  width:25%;
  margin-top:1em;
  padding: 5px;
}
div.items {
  overflow:auto; 
  padding:10px; 
  border:1px solid #222; 
  margin-top:10px; 
  display:inline-block;
}
div.items div, div.items header {
  border-bottom:1px solid #000;
  margin-bottom:10px;
}


/*Downloaded from https://www.codeseek.co/curveball/memento-example-typescript-jyKKwy */
    namespace MementoArea {
  // Originator
  class Text {
    constructor(private txt: string) {}
    public getText(): string {
      return this.txt;
    }
    public underline(): void {
      this.txt = '<u>' + this.txt + '</u>';
    }
    public strong(): void {
      this.txt = '<b>' + this.txt + '</b>';
    }
    public italic(): void {
      this.txt = '<i>' + this.txt + '</i>';
    }
    public storeState(action: string): Memento {
      return new Memento(this.txt, action);
    }
    public restoreState(memento: Memento): void {
      setup.addRecord(memento, true);
      this.txt = memento.getState();
    }
  }
  // Memento
  class Memento {
    constructor(private state: string, private action: string) {}

    public getState(): string {
      return this.state;
    }
    public getAction(): string {
      return this.action;
    }
  }
  // CareTaker
  class CareTaker {
    private results: Array<Memento> = [];
    public setMemento(memento: Memento): void {
      this.results.push(memento);
      setup.addRecord(memento);
    }
    public getMemento = function(): Memento {
      return this.results.pop();
    }
  }
  // Run it all
  class Setup {
    private logCont: HTMLElement = document.getElementById('logs');
    private resCont: HTMLElement = document.getElementById('result');
    private showResult(res: string): void {
      this.resCont.innerHTML = res;
    }
    private removeResult = function(): void {
      this.resCont.innerHTML = 'No result. Press a button above.';
    }
    public addRecord = function(memento: Memento, undo?: boolean) { // add record
      let record: HTMLElement = document.createElement('div');
      let msg: string = '';
      if(undo) msg = 'Undone ';
      record.textContent = msg + memento.getAction();
      this.logCont.appendChild(record);
    }
    private removeMsg = function(elem: HTMLElement) {
      let msgs: Array<HTMLElement> = Array.prototype.slice.call(elem.children);
      msgs.forEach((element: HTMLElement, index: number) => {
       if(msgs[index].tagName != 'header'.toUpperCase()) msgs[index].remove();
      });
    }
    public run(): void {
      let text: string = prompt('Insert some text', '');
      let txt = new Text(text);
      let careTaker = new CareTaker();
      this.showResult(txt.getText());

      let btn1: HTMLElement = document.getElementById("sender1");
      btn1.addEventListener("click", () => {
      careTaker.setMemento(txt.storeState('Underline text'));
      txt.underline();
      this.showResult(txt.getText());
      });
      let btn2: HTMLElement = document.getElementById("sender2");
      btn2.addEventListener("click", () => {
      careTaker.setMemento(txt.storeState('Strong text'));
      txt.strong();
      this.showResult(txt.getText());
      });
      let btn3: HTMLElement = document.getElementById("sender3");
      btn3.addEventListener("click", () => {
      careTaker.setMemento(txt.storeState('Italic text'));
      txt.italic();
      this.showResult(txt.getText());
      });
      let btn4: HTMLElement = document.getElementById("sender4");
      btn4.addEventListener("click", () => {
      txt.restoreState(careTaker.getMemento());
      this.showResult(txt.getText());
      });
      let reset:HTMLElement = document.getElementById("reset"); // clean table
      reset.addEventListener("click", () => {
      this.removeResult();
      this.removeMsg(this.logCont);
      });
    }
  }
  let setup = new Setup();
  setup.run();
} 

Comments