diff --git a/extension/Resources/Public/Json/fabric.buttons.json b/extension/Resources/Public/Json/fabric.buttons.json
index 0e2674b07597130f322fd3f90135bac87ebe751b..5dd0f782b5b81630f0d2aa872a8c04fa98486cdf 100644
--- a/extension/Resources/Public/Json/fabric.buttons.json
+++ b/extension/Resources/Public/Json/fabric.buttons.json
@@ -9,6 +9,8 @@
             "toggle": "isDrawingMode",
             "hasToggleElement": false,
             "toggleElement": "",
+            "disabled": false,
+            "tooltip": "Draw with a pencil",
             "icon": "glyphicon-pencil"
         },
         {
@@ -20,6 +22,8 @@
             "toggle": "isHighlightMode",
             "hasToggleElement": false,
             "toggleElement": "",
+            "disabled": false,
+            "tooltip": "Highlighter",
             "icon": "glyphicon-pencil"
         },
 
@@ -32,6 +36,8 @@
           "toggle": "emojiMode",
           "hasToggleElement": true,
           "toggleElement": "emojiContainer",
+          "disabled": false,
+          "tooltip": "Emojis",
           "icon": "glyphicon-ice-lolly-tasted"
         },
         {
@@ -43,6 +49,8 @@
             "toggle": "drawRectangleMode",
             "hasToggleElement": false,
             "toggleElement": "",
+          "disabled": false,
+          "tooltip": "Draw a rectangle to highlight areas",
             "icon": "glyphicon-stop"
         },
       {
@@ -54,6 +62,8 @@
         "toggle": "",
         "hasToggleElement": false,
         "toggleElement": "",
+        "disabled": false,
+        "tooltip": "Adds a customizable text to canvas",
         "icon": "glyphicon-text-height"
       },
         {
@@ -65,6 +75,8 @@
             "toggle": "moveMode",
             "hasToggleElement": false,
             "toggleElement": "",
+          "disabled": false,
+          "tooltip": "Move the viewport, useful if zoomed",
             "icon": "glyphicon-move"
         },
         {
@@ -76,6 +88,8 @@
             "toggle": "",
             "hasToggleElement": false,
             "toggleElement": "",
+          "disabled": false,
+          "tooltip": "Delete selected object",
             "icon": "glyphicon-trash"
         },
         {
@@ -87,6 +101,8 @@
           "toggle": "isZoomMode",
           "hasToggleElement": false,
           "toggleElement": "",
+          "disabled": false,
+          "tooltip": "Zoom viewport",
           "icon": "glyphicon-search"
         },
       {
@@ -98,8 +114,37 @@
         "toggle": "isMouseMode",
         "hasToggleElement": false,
         "toggleElement": "",
+        "disabled": false,
+        "tooltip": "Normal mouse to select objects in canvas",
         "icon": "glyphicon-hand-up"
+      },
+      {
+        "name": "undo",
+        "selector": "undo",
+        "requiresDrawing": false,
+        "requiresSelection": false,
+        "isToggle": false,
+        "toggle": "",
+        "hasToggleElement": false,
+        "toggleElement": "",
+        "disabled": true,
+        "tooltip": "Undo",
+        "icon": "glyphicon-repeat icon-flipped"
+      },
+      {
+        "name": "redo",
+        "selector": "redo",
+        "requiresDrawing": false,
+        "requiresSelection": false,
+        "isToggle": false,
+        "toggle": "",
+        "hasToggleElement": false,
+        "toggleElement": "",
+        "disabled": true,
+        "tooltip": "Redo",
+        "icon": "glyphicon-repeat"
       }
+
     ],
     "currentMode": "draw",
   "colors": [
diff --git a/javascript/src/History.js b/javascript/src/History.js
new file mode 100644
index 0000000000000000000000000000000000000000..9169d6f07c537ebe1d657ba2be811ad5912fd4ea
--- /dev/null
+++ b/javascript/src/History.js
@@ -0,0 +1,77 @@
+/**
+ * @author Benjamin Baer <benjamin.baer@math.uzh.ch>
+ */
+
+/* global $ */
+
+/**
+ * Qfq Namespace
+ *
+ * @namespace QfqNS
+ */
+var QfqNS = QfqNS || {};
+
+(function (n) {
+    'use strict';
+
+/**
+ * A custom history to use for undo and redo functionality.
+ **/
+
+    n.History = function() {
+        this.history = [];
+        this.pointer = 0;
+    };
+
+    n.History.prototype.put = function(object) {
+        if (this.history.length > 1) {
+            if (this.canGoForward()) {
+                console.log("trying to remove history");
+                this._removeForwardHistory();
+            }
+        }
+        if (JSON.stringify(this.history[this.pointer]) !== JSON.stringify(object)) {
+            this.history.push(object);
+            this.pointer = this.history.length - 1;
+        }
+        console.log(this);
+    };
+
+    n.History.prototype.back = function() {
+        if (this.canGoBack()) {
+            this.pointer = this.pointer - 1;
+            console.log(this.pointer + "/" + this.history.length);
+            console.log(this.history);
+            return this.history[this.pointer];
+        } else {
+            console.log("At the beginning of history");
+            return false;
+        }
+    };
+
+    n.History.prototype.forward = function() {
+        console.log(this.pointer);
+        if (this.canGoForward()) {
+            this.pointer = this.pointer + 1;
+            return this.history[this.pointer];
+        } else {
+            console.log("At the end of history");
+            return false;
+        }
+    };
+
+    n.History.prototype.canGoBack = function() {
+        return this.pointer > 0;
+    };
+
+    n.History.prototype.canGoForward = function() {
+        return this.pointer < this.history.length - 1;
+    };
+
+    n.History.prototype._removeForwardHistory = function() {
+        this.history.splice(this.pointer + 1, this.history.length - this.pointer);
+    };
+
+
+
+})(QfqNS);
\ No newline at end of file
diff --git a/javascript/src/Plugins/qfq.fabric.js b/javascript/src/Plugins/qfq.fabric.js
index 0bdbf51db8f5d0de5fd9671ca30344165c09b002..37dd18cbfb8a74369f237dd03caa7e08acf7b689 100644
--- a/javascript/src/Plugins/qfq.fabric.js
+++ b/javascript/src/Plugins/qfq.fabric.js
@@ -26,6 +26,7 @@ $(function (n) {
         this.emojiContainer = {};
         this.eventEmitter = new EventEmitter();
         this.qfqPage = {};
+        this.changeHistory = true;
         this.scaled = false;
         this.textContainer = {};
         this.userTextInput = {};
@@ -63,6 +64,8 @@ $(function (n) {
         this.mouseInsideCanvas = false;
         this.imageOutput = '';
         this.localStore = new n.LocalStorage("fabric");
+        this.history = new n.History();
+        this.firstLoad = false;
 
         // Handles button states and generation of said buttons. Should be renamed.
         function ModeSettings() {
@@ -110,6 +113,8 @@ $(function (n) {
                 $button.on("click", function() {
                     that.qFabric.buttonPress(modePressed, $button)
                 });
+                $button.prop("disabled", o.disabled);
+                $button.prop("title", o.tooltip)
             });
             $controlWrapper.append($buttonGroup);
 
@@ -186,6 +191,11 @@ $(function (n) {
             }
         };
 
+        ModeSettings.prototype.disableButton = function(id, bool) {
+            var $button = this.getButtonById(id);
+            $button.prop("disabled",bool);
+        };
+
         ModeSettings.prototype.getModeByName = function (string) {
             $.each(this.myModes.modes, function(i, o) {
                 if (o.name === string) {
@@ -314,7 +324,9 @@ $(function (n) {
         this.generateCanvas(width, height);
         if (this.outputField.val()) {
             var fabricJSON = this.prepareJSON(this.outputField.val());
+            this.history.put(fabricJSON);
             this.canvas.loadFromJSON(fabricJSON, function() {
+                this.firstLoad = true;
                 that.setBackground();
                 that.resizeCanvas();
                 that.setBrush();
@@ -326,6 +338,7 @@ $(function (n) {
             that.setBrush();
             that.canvas.renderAll();
             that.userChangePossible = true;
+            this.history.put(this.canvas.toJSON());
         }
         var defaultColor = $fabricElement.data('fabric-color') || false;
         if (defaultColor) {
@@ -530,6 +543,7 @@ $(function (n) {
             this.setBackground();
             this.canvas.renderAll();
         }
+
     };
 
     n.Fabric.prototype.zoomCanvas = function(o, zoomCalc) {
@@ -558,7 +572,10 @@ $(function (n) {
                      centeredScaling: true,
                      centeredRotation: true
                  });
-                 that.canvas.setBackgroundImage(img, that.canvas.renderAll.bind(that.canvas));
+                 that.canvas.setBackgroundImage(img, function() {
+                     that.canvas.renderAll.bind(that.canvas);
+                     that.canvas.renderAll();
+                 });
              });
         } else {
             var $image = document.getElementsByClassName("qfq-fabric-image")[0];
@@ -574,9 +591,12 @@ $(function (n) {
                     centeredRotation: true
                 });
                 img.rotate(that.rotation);
-                that.canvas.setBackgroundImage(img, that.canvas.renderAll.bind(that.canvas));
-                that.canvas.renderAll();
+                that.canvas.setBackgroundImage(img, function() {
+                    that.canvas.renderAll.bind(that.canvas);
+                    that.canvas.renderAll();
+                });
             };
+            that.canvas.renderAll();
 
         }
     };
@@ -843,6 +863,12 @@ $(function (n) {
             case "exportImage":
                 this.prepareForExport();
                 break;
+            case "undo":
+                this.changeState("undo");
+                break;
+            case "redo":
+                this.changeState("redo");
+                break;
             default:
                 console.error("unrecognized mode");
         }
@@ -980,6 +1006,38 @@ $(function (n) {
         this.setBrush();
     };
 
+    /**
+     * Calls state from attached history and moves in defined
+     * direction. (undo / redo)
+     * @param direction string, undo or redo
+     */
+    n.Fabric.prototype.changeState = function(direction) {
+        var state = {};
+        console.log(direction);
+        if (direction === "undo") {
+            state = this.history.back();
+        } else {
+            state = this.history.forward();
+        }
+
+        if (state) {
+            this.changeHistory = false;
+            var that = this;
+            this.canvas.loadFromJSON(state, function() {
+                that.setBackground();
+                that.canvas.renderAll();
+                that.changeHistory = true;
+            });
+        }
+        this.updateHistoryButtons();
+    };
+
+    n.Fabric.prototype.updateHistoryButtons = function() {
+        this.modeSettings.disableButton("undo", !this.history.canGoBack());
+        this.modeSettings.disableButton("redo", !this.history.canGoForward());
+    };
+
+
     n.Fabric.prototype.rectangle = function() {
         this.drawRectangleMode = true;
     };
@@ -1000,7 +1058,12 @@ $(function (n) {
 
     n.Fabric.prototype.defaultChangeHandler = function () {
         /* Important! Changes only possible after initialisation */
+
         if (this.userChangePossible) {
+            if (this.changeHistory) {
+                this.history.put(this.canvas.toJSON());
+                this.updateHistoryButtons();
+            }
             var that = this;
             this.outputField.val(JSON.stringify(that.canvas.toJSON()));
             if (this.qfqPage.qfqForm) {
diff --git a/less/qfq-bs.css.less b/less/qfq-bs.css.less
index 7b95336e1af8b6114434d9d067d758bcf46699c5..0c7bf520760af7f7a410c55a12e9694eabf5e0bd 100644
--- a/less/qfq-bs.css.less
+++ b/less/qfq-bs.css.less
@@ -765,7 +765,9 @@ select.qfq-locked:invalid {
 }
 
 legend {
-  margin-bottom: 5px;
+  margin-bottom: 25px;
+  margin-top: 15px;
+  padding-bottom: 5px;
 }
 
 /* glyphicon functions */
diff --git a/mockup/mockData/fabric.buttons.json b/mockup/mockData/fabric.buttons.json
index f6d432e5846b9d85414d652f49dd2a1d98a3f429..493a6e2bbc8b625cb59974fffc5fac4770464f1e 100644
--- a/mockup/mockData/fabric.buttons.json
+++ b/mockup/mockData/fabric.buttons.json
@@ -89,8 +89,18 @@
             "icon": "glyphicon-trash"
         },
       {
-        "name": "rotateRight",
-        "selector": "turn-right",
+        "name": "undo",
+        "selector": "undo",
+        "requiresDrawing": false,
+        "requiresSelection": false,
+        "isToggle": false,
+        "toggle": "",
+        "hasToggleElement": false,
+        "toggleElement": "",
+        "icon": "glyphicon-repeat"
+      }, {
+        "name": "redo",
+        "selector": "redo",
         "requiresDrawing": false,
         "requiresSelection": false,
         "isToggle": false,