# Undo/Redo

## Content

DsImageViewer provides undo and redo operations to revert the last operations carried out on an image or to redo those reverted operations. The control provides Undo(![undo-pagetool.png](https://cdn.mescius.io/document-site-files/images/8f8ddd13-6a19-4879-8713-7794513e3372/undo-pagetool.4e588b.png)) and Redo(![redo-pagetool.png](https://cdn.mescius.io/document-site-files/images/8f8ddd13-6a19-4879-8713-7794513e3372/redo-pagetool.4e45ff.png)) buttons to fetch the previously performed actions from the undo storage. You can disable the undo and redo command operations by setting the [undo](https://developer.mescius.com/document-solutions/javascript-image-viewer/api/interfaces/ViewerOptions#undo) property of [ViewerOptions](https://developer.mescius.com/document-solutions/javascript-image-viewer/api/interfaces/ViewerOptions) interface to false.
![undo-redo](https://cdn.mescius.io/document-site-files/images/b882ef15-67ec-41e0-8e66-2977bfeb3645/undo-redo.2f6f94.gif)
To undo or redo your previous actions through code, the viewer provides undo() and redo() methods respectively. DsImageViewer class also provides various properties and methods to facilitate these operations as described below:

| Properties/Methods | Description |
| ------------------ | ----------- |
| hasUndo / hasRedo properties | Check whether there are any operations available for undo and redo respectively |
| undoCount property | Fetches the count of operations in the undo storage |
| maxLevels property | Specifies the maximum number of undo operations that can be performed |
| clearUndo method | Removes all the operations from the UndoStorage |

The code snippet below depicts the implementation of the stated API members:

```javascript
// Undo last action using API
function hasUndo() {
    //Get UndoStorage storing the list of actions to undo
    var _undoSt = viewer.undoStorage;

    // Determine if undo is enabled for DsImageViewer
    if (_undoSt.hasUndo) {

        // Undo last action and get the remaining undo actions count
        _undoSt.undo().then(function (e) {
            //Get total undo level count using the undoCount property of DsImageViewer
            console.log("Undo levels count is " + viewer.undoCount + 1);
        })
    } else {
        console.log("No operations for Undo ");
    }
}

// Redo next action using API
function hasRedo() {
    //Get UndoStorage storing the list of actions to undo
    var _undoSt = viewer.undoStorage;

    // Determine if redo is enabled for DsImageViewer
    if (_undoSt.hasRedo) {
        // Redo next action
        _undoSt.redo().then(function (e) {
            console.log("Redo Done");
        })
    } else {
        console.log("No operations for Redo ");
    }
}
```

DsImageViewer also has provision for skipping specific commands while configuring undo options. For example, if you do not wish to track Open or Close and Zoom commands for undo and redo operations, you can set [skipCommands](https://developer.mescius.com/document-solutions/javascript-image-viewer/api/type-aliases/UndoStorageOptions#skipcommands) option of [UndoStorageOptions](https://developer.mescius.com/document-solutions/javascript-image-viewer/api/type-aliases/UndoStorageOptions) to an array of command names as depicted in the code below:

```javascript
var viewer;
function loadImageViewer() {
    //Initialize DsImageViewer
    viewer = new DsImageViewer("#imageviewer", {
                undo: {
                    skipCommands: ["Open", "Zoom"] //Do not track Open/Close/Zoom operations for undo
                }
            });
    viewer.open("https://i.imgur.com/bvcCEnr.jpeg");
}
       
```

In addition, you can also disable the undo and redo command operations by setting the undo property to false.

# Custom Undo Command

DsImageViewer also provides you an option to define custom undo commands. Here’s an example how to implement the custom Undo command that changes the opacity of the main viewer element:

```javascript
//Define custom undo command
function CustomOpacityCommand(opacity) {
      if (opacity !== undefined) {
            this.opacity = opacity;
      }
}
CustomOpacityCommand.prototype = {
   name: "CustomOpacityCommand",
   opacity: "0.5",
   prevOpacity: "",
   execute: function (viewer) {
       return new Promise((resolve) => {
             this.prevOpacity = viewer.hostElement.style.opacity;
             viewer.hostElement.style.opacity = this.opacity;
             resolve();
         })
    },
    undo: function (viewer) {
            return new Promise((resolve) => {
                viewer.hostElement.style.opacity = this.prevOpacity;
                resolve();
              })
        }
  };
        
```

The code snippet below depicts how to use the custom undo command defined above:

```javascript
var viewer = new DsImageViewer("#root");
        
// Open image:
        await      
viewer.open("https://i.imgur.com/bvcCEnr.jpeg");

// Clear undo storage:
viewer.clearUndo();

// Create custom command:
var customOpacityCommand = new CustomOpacityCommand(0.2);

// Execute custom command:
await viewer.executeCommand(customOpacityCommand);

// Undo viewer to a previous state:
await viewer.undo();

// Redo viewer to the next state:
await viewer.redo();
```

To see the custom undo command in action, see [<span class="smart-link-title-wrapper css-0 e158gagu0">Custom undoable command example</span>](https://developer.mescius.com/document-solutions/javascript-image-viewer/demos/features/custom-undo-commands).