diff --git a/src/js/History.js b/src/js/History.js index 60cbf44..45ac433 100644 --- a/src/js/History.js +++ b/src/js/History.js @@ -1,7 +1,5 @@ 'use strict'; -var util = require('./util'); - /** * @constructor History * Store action history, enables undo and redo @@ -14,122 +12,144 @@ function History (editor) { this.clear(); + // helper function to find a Node from a path + function findNode(path) { + return editor.node.findNodeByPath(path) + } + + // helper function to clone a Node + function cloneNode(node) { + return node.clone(); + } + // map with all supported actions this.actions = { 'editField': { 'undo': function (params) { - params.node.updateField(params.oldValue); + findNode(params.path).updateField(params.oldValue); }, 'redo': function (params) { - params.node.updateField(params.newValue); + findNode(params.path).updateField(params.newValue); } }, 'editValue': { 'undo': function (params) { - params.node.updateValue(params.oldValue); + findNode(params.path).updateValue(params.oldValue); }, 'redo': function (params) { - params.node.updateValue(params.newValue); + findNode(params.path).updateValue(params.newValue); } }, 'changeType': { 'undo': function (params) { - params.node.changeType(params.oldType); + findNode(params.path).changeType(params.oldType); }, 'redo': function (params) { - params.node.changeType(params.newType); + findNode(params.path).changeType(params.newType); } }, 'appendNodes': { 'undo': function (params) { - params.nodes.forEach(function (node) { - params.parent.removeChild(node); + var parentNode = findNode(params.parentPath); + params.paths.map(findNode).forEach(function (node) { + parentNode.removeChild(node); }); - }, + }, 'redo': function (params) { - params.nodes.forEach(function (node) { - params.parent.appendChild(node); + var parentNode = findNode(params.parentPath); + params.paths.map(findNode).forEach(function (node) { + parentNode.appendChild(node); }); } }, 'insertBeforeNodes': { 'undo': function (params) { - params.nodes.forEach(function (node) { - params.parent.removeChild(node); + var parentNode = findNode(params.parentPath); + params.paths.map(findNode).forEach(function (node) { + parentNode.removeChild(node); }); }, 'redo': function (params) { - params.nodes.forEach(function (node) { - params.parent.insertBefore(node, params.beforeNode); + var parentNode = findNode(params.parentPath); + var beforeNode = findNode(params.beforePath); + params.paths.map(findNode).forEach(function (node) { + parentNode.insertBefore(node, beforeNode); }); } }, 'insertAfterNodes': { 'undo': function (params) { - params.nodes.forEach(function (node) { - params.parent.removeChild(node); + var parentNode = findNode(params.parentPath); + params.paths.map(findNode).forEach(function (node) { + parentNode.removeChild(node); }); }, 'redo': function (params) { - var afterNode = params.afterNode; - params.nodes.forEach(function (node) { - params.parent.insertAfter(params.node, afterNode); + var parentNode = findNode(params.parentPath); + var afterNode = findNode(params.afterPath); + params.paths.map(findNode).forEach(function (node) { + parentNode.insertAfter(node, afterNode); afterNode = node; }); } }, 'removeNodes': { 'undo': function (params) { - var parent = params.parent; - var beforeNode = parent.childs[params.index] || parent.append; - params.nodes.forEach(function (node) { - parent.insertBefore(node, beforeNode); + var parentNode = findNode(params.parentPath); + var beforeNode = parentNode.childs[params.index] || parentNode.append; + params.paths.map(findNode).forEach(function (node) { + parentNode.insertBefore(node, beforeNode); }); }, 'redo': function (params) { - params.nodes.forEach(function (node) { + params.paths.map(findNode).forEach(function (node) { params.parent.removeChild(node); }); } }, 'duplicateNodes': { 'undo': function (params) { - params.nodes.forEach(function (node) { - params.parent.removeChild(node); + var parentNode = findNode(params.parentPath); + params.paths.map(findNode).forEach(function (node) { + parentNode.removeChild(node); }); }, 'redo': function (params) { - var afterNode = params.afterNode; - params.nodes.forEach(function (node) { - params.parent.insertAfter(node, afterNode); + var parentNode = findNode(params.parentPath); + var afterNode = findNode(params.afterPath); + var nodes = params.paths.map(findNode).map(cloneNode); + nodes.forEach(function (node) { + parentNode.insertAfter(node, afterNode); afterNode = node; }); } }, 'moveNodes': { 'undo': function (params) { - params.nodes.forEach(function (node) { - params.oldBeforeNode.parent.moveBefore(node, params.oldBeforeNode); + var oldBeforeNode = findNode(params.oldBeforePath); + params.paths.map(findNode).forEach(function (node) { + oldBeforeNode.parent.moveBefore(node, oldBeforeNode); }); }, 'redo': function (params) { - params.nodes.forEach(function (node) { - params.newBeforeNode.parent.moveBefore(node, params.newBeforeNode); + var newBeforeNode = findNode(params.newBeforePath); + params.paths.map(findNode).forEach(function (node) { + newBeforeNode.parent.moveBefore(node, newBeforeNode); }); } }, 'sort': { 'undo': function (params) { - var node = params.node; + var node = findNode(params.path); node.hideChilds(); node.childs = params.oldChilds; node.updateDom({updateIndexes: true}); node.showChilds(); }, 'redo': function (params) { - var node = params.node; + var node = findNode(params.path); node.hideChilds(); node.childs = params.newChilds; node.updateDom({updateIndexes: true}); @@ -139,14 +159,12 @@ function History (editor) { 'transform': { 'undo': function (params) { - var node = params.node; - node.setValue(params.oldValue); + findNode(params.path).setValue(params.oldValue); // TODO: would be nice to restore the state of the node and childs }, 'redo': function (params) { - var node = params.node; - node.setValue(params.newValue); + findNode(params.path).setValue(params.newValue); // TODO: would be nice to restore the state of the node and childs } diff --git a/src/js/Node.js b/src/js/Node.js index aa9f582..a24e8e0 100644 --- a/src/js/Node.js +++ b/src/js/Node.js @@ -1404,7 +1404,7 @@ Node.prototype._onChangeValue = function () { } this.editor._onAction('editValue', { - node: this, + path: this.getPath(), oldValue: this.previousValue, newValue: this.value, oldSelection: oldSelection, @@ -1436,7 +1436,7 @@ Node.prototype._onChangeField = function () { } this.editor._onAction('editField', { - node: this, + path: this.getPath(), oldValue: this.previousField, newValue: this.field, oldSelection: oldSelection, @@ -2010,11 +2010,11 @@ Node.onDragEnd = function (nodes, event) { } var params = { - nodes: nodes, + paths: nodes.map(getPath), oldSelection: editor.drag.oldSelection, newSelection: editor.getDomSelection(), - oldBeforeNode: editor.drag.oldBeforeNode, - newBeforeNode: beforeNode + oldBeforePath: editor.drag.oldBeforeNode.getPath(), + newBeforePath: beforeNode.getPath() }; if (params.oldBeforeNode != params.newBeforeNode) { @@ -2811,9 +2811,9 @@ Node.prototype.onKeyDown = function (event) { this.focus(Node.focusElement || this._getElementName(target)); this.editor._onAction('moveNodes', { - nodes: selectedNodes, - oldBeforeNode: oldBeforeNode, - newBeforeNode: nextNode2, + paths: selectedNodes.map(getPath), + oldBeforePath: oldBeforeNode.getPath(), + newBeforePath: nextNode2.getPath(), oldSelection: oldSelection, newSelection: this.editor.getDomSelection() }); @@ -2858,9 +2858,9 @@ Node.prototype.onKeyDown = function (event) { this.focus(Node.focusElement || this._getElementName(target)); this.editor._onAction('moveNodes', { - nodes: selectedNodes, - oldBeforeNode: oldBeforeNode, - newBeforeNode: prevNode, + paths: selectedNodes.map(getPath), + oldBeforePath: oldBeforeNode.getPath(), + newBeforePath: prevNode.getPath(), oldSelection: oldSelection, newSelection: this.editor.getDomSelection() }); @@ -2892,9 +2892,9 @@ Node.prototype.onKeyDown = function (event) { this.focus(Node.focusElement || this._getElementName(target)); this.editor._onAction('moveNodes', { - nodes: selectedNodes, - oldBeforeNode: oldBeforeNode, - newBeforeNode: prevNode, + paths: selectedNodes.map(getPath), + oldBeforePath: oldBeforeNode.getPath(), + newBeforePath: prevNode.getPath(), oldSelection: oldSelection, newSelection: this.editor.getDomSelection() }); @@ -2955,9 +2955,9 @@ Node.prototype.onKeyDown = function (event) { this.focus(Node.focusElement || this._getElementName(target)); this.editor._onAction('moveNodes', { - nodes: selectedNodes, - oldBeforeNode: oldBeforeNode, - newBeforeNode: nextNode2, + paths: selectedNodes.map(getPath), + oldBeforePath: oldBeforeNode.getPath(), + newBeforePath: nextNode2.getPath(), oldSelection: oldSelection, newSelection: this.editor.getDomSelection() }); @@ -3028,8 +3028,8 @@ Node.onRemove = function(nodes) { // store history action editor._onAction('removeNodes', { - nodes: nodes.slice(0), // store a copy of the array! - parent: parent, + paths: nodes.map(getPath), + parentPath: parent.getPath(), index: firstIndex, oldSelection: oldSelection, newSelection: newSelection @@ -3075,9 +3075,9 @@ Node.onDuplicate = function(nodes) { var newSelection = editor.getDomSelection(); editor._onAction('duplicateNodes', { - afterNode: lastNode, - nodes: clones, - parent: parent, + afterPath: lastNode.getPath(), + paths: clones.map(getPath), + parentPath: parent.getPath(), oldSelection: oldSelection, newSelection: newSelection }); @@ -3106,9 +3106,9 @@ Node.prototype._onInsertBefore = function (field, value, type) { var newSelection = this.editor.getDomSelection(); this.editor._onAction('insertBeforeNodes', { - nodes: [newNode], - beforeNode: this, - parent: this.parent, + paths: [newNode.getPath()], + beforePath: this.getPath(), + parentPath: this.parent.getPath(), oldSelection: oldSelection, newSelection: newSelection }); @@ -3136,9 +3136,9 @@ Node.prototype._onInsertAfter = function (field, value, type) { var newSelection = this.editor.getDomSelection(); this.editor._onAction('insertAfterNodes', { - nodes: [newNode], - afterNode: this, - parent: this.parent, + paths: [newNode.getPath()], + afterPath: this.getPath(), + parentPath: this.parent.getPath(), oldSelection: oldSelection, newSelection: newSelection }); @@ -3166,8 +3166,8 @@ Node.prototype._onAppend = function (field, value, type) { var newSelection = this.editor.getDomSelection(); this.editor._onAction('appendNodes', { - nodes: [newNode], - parent: this.parent, + paths: [newNode.getPath()], + parentPath: this.parent.getPath(), oldSelection: oldSelection, newSelection: newSelection }); @@ -3186,7 +3186,7 @@ Node.prototype._onChangeType = function (newType) { var newSelection = this.editor.getDomSelection(); this.editor._onAction('changeType', { - node: this, + path: this.getPath(), oldType: oldType, newType: newType, oldSelection: oldSelection, @@ -3249,7 +3249,7 @@ Node.prototype.sort = function (path, direction) { this._updateDomIndexes(); this.editor._onAction('sort', { - node: this, + path: this.getPath(), oldChilds: oldChilds, newChilds: this.childs }); @@ -3269,7 +3269,7 @@ Node.prototype.update = function (newValue) { this.setValue(newValue); this.editor._onAction('transform', { - node: this, + path: this.getPath(), oldType: oldType, newType: this.type, oldValue: oldValue, @@ -3302,7 +3302,7 @@ Node.prototype.transform = function (query) { this.setValue(newValue); this.editor._onAction('transform', { - node: this, + path: this.getPath(), oldType: oldType, newType: this.type, oldValue: oldValue, @@ -4018,6 +4018,11 @@ Node.prototype._escapeJSON = function (text) { return escaped; }; +// helper function to the get path of a node +function getPath (node) { + return node.getPath(); +} + // TODO: find a nicer solution to resolve this circular dependency between Node and AppendNode // idea: introduce properties .isAppendNode and .isNode and use that instead of instanceof AppendNode checks var AppendNode = appendNodeFactory(Node);