Command Pattern

HTML

<ul data-menu-bar>
    <li data-command="Apple">apple</li>
    <li data-command="Banana">banana</li>
    <li data-command="Undo">undo</li>
    <li data-command="Redo">redo</li>
</ul>
<ol data-output><ol>

JavaScript

var outputList = document.querySelector('[data-output]');

/**
*  commands is a map of command objects.
*/
var commands = {

    Undo: function () {
        commandManager.invokeCommand(this);
    },

    Redo: function () {
        commandManager.invokeCommand(this);
    }
}

/**
*  manages two lists: a history list and a redolist, each of which
*  contains command objects: those which have run are in the history list;
*  those which have been 'undone' are in the redo list.
*/
var commandManager = {

    history: [],
    redoList: [],

    invokeCommand: function (command) {
        //  undo command
        if (command instanceof commands.Undo) {

            if (this.history.length > 0) {

                var command = this.history.pop();
                command.undoIt();
                this.redoList.push(command);

            } else {
                alert("cannot undo. no commands in history");
            }

            return;
        //  redo command
        } else if (command instanceof commands.Redo) {

            if (this.redoList.length > 0) {

                var command = this.redoList.pop();
                command.doIt();
                this.history.push(command);

            } else {
                alert("cannot redo. no commands in redo list");
            }

            return;
        // normal commands
        } else {

            command.doIt();
            this.history.push(command);
            //  clear redo list
            this.redoList = [];

        }
    }
}


/*
* 
*  @classs
*/
function Apple() {
    
    this.name = "apple";
    
    commandManager.invokeCommand(this);
    
}

Apple.prototype = {

    doIt: function () {

        var newDiv = document.createElement("li");
        var newContent = document.createTextNode("apple");
        newDiv.appendChild(newContent);
        outputList.appendChild(newDiv);
    },

    undoIt: function () {

        outputList.removeChild(outputList.childNodes[outputList.childNodes.length -...