Fixes in history

This commit is contained in:
jos 2018-08-08 15:00:43 +02:00
parent 3e518e4742
commit 0cebd8f618
3 changed files with 130 additions and 60 deletions

View File

@ -17,19 +17,18 @@ function History (editor) {
return editor.node.findNodeByPath(path) return editor.node.findNodeByPath(path)
} }
// helper function to clone a Node
function cloneNode(node) {
return node.clone();
}
// map with all supported actions // map with all supported actions
this.actions = { this.actions = {
'editField': { 'editField': {
'undo': function (params) { 'undo': function (params) {
findNode(params.path).updateField(params.oldValue); var parentNode = findNode(params.parentPath);
var node = parentNode.childs[params.index];
node.updateField(params.oldValue);
}, },
'redo': function (params) { 'redo': function (params) {
findNode(params.path).updateField(params.newValue); var parentNode = findNode(params.parentPath);
var node = parentNode.childs[params.index];
node.updateField(params.newValue);
} }
}, },
'editValue': { 'editValue': {
@ -58,7 +57,7 @@ function History (editor) {
}, },
'redo': function (params) { 'redo': function (params) {
var parentNode = findNode(params.parentPath); var parentNode = findNode(params.parentPath);
params.paths.map(findNode).forEach(function (node) { params.nodes.forEach(function (node) {
parentNode.appendChild(node); parentNode.appendChild(node);
}); });
} }
@ -73,7 +72,7 @@ function History (editor) {
'redo': function (params) { 'redo': function (params) {
var parentNode = findNode(params.parentPath); var parentNode = findNode(params.parentPath);
var beforeNode = findNode(params.beforePath); var beforeNode = findNode(params.beforePath);
params.paths.map(findNode).forEach(function (node) { params.nodes.forEach(function (node) {
parentNode.insertBefore(node, beforeNode); parentNode.insertBefore(node, beforeNode);
}); });
} }
@ -88,7 +87,7 @@ function History (editor) {
'redo': function (params) { 'redo': function (params) {
var parentNode = findNode(params.parentPath); var parentNode = findNode(params.parentPath);
var afterNode = findNode(params.afterPath); var afterNode = findNode(params.afterPath);
params.paths.map(findNode).forEach(function (node) { params.nodes.forEach(function (node) {
parentNode.insertAfter(node, afterNode); parentNode.insertAfter(node, afterNode);
afterNode = node; afterNode = node;
}); });
@ -98,45 +97,57 @@ function History (editor) {
'undo': function (params) { 'undo': function (params) {
var parentNode = findNode(params.parentPath); var parentNode = findNode(params.parentPath);
var beforeNode = parentNode.childs[params.index] || parentNode.append; var beforeNode = parentNode.childs[params.index] || parentNode.append;
params.paths.map(findNode).forEach(function (node) { params.nodes.forEach(function (node) {
parentNode.insertBefore(node, beforeNode); parentNode.insertBefore(node, beforeNode);
}); });
}, },
'redo': function (params) { 'redo': function (params) {
var parentNode = findNode(params.parentPath);
params.paths.map(findNode).forEach(function (node) { params.paths.map(findNode).forEach(function (node) {
params.parent.removeChild(node); parentNode.removeChild(node);
}); });
} }
}, },
'duplicateNodes': { 'duplicateNodes': {
'undo': function (params) { 'undo': function (params) {
var parentNode = findNode(params.parentPath); var parentNode = findNode(params.parentPath);
params.paths.map(findNode).forEach(function (node) { params.clonePaths.map(findNode).forEach(function (node) {
parentNode.removeChild(node); parentNode.removeChild(node);
}); });
}, },
'redo': function (params) { 'redo': function (params) {
var parentNode = findNode(params.parentPath); var parentNode = findNode(params.parentPath);
var afterNode = findNode(params.afterPath); var afterNode = findNode(params.afterPath);
var nodes = params.paths.map(findNode).map(cloneNode); var nodes = params.paths.map(findNode);
nodes.forEach(function (node) { nodes.forEach(function (node) {
parentNode.insertAfter(node, afterNode); var clone = node.clone();
afterNode = node; parentNode.insertAfter(clone, afterNode);
afterNode = clone;
}); });
} }
}, },
'moveNodes': { 'moveNodes': {
'undo': function (params) { 'undo': function (params) {
var oldBeforeNode = findNode(params.oldBeforePath); var oldParentNode = findNode(params.oldParentPath);
params.paths.map(findNode).forEach(function (node) { var newParentNode = findNode(params.newParentPath);
oldBeforeNode.parent.moveBefore(node, oldBeforeNode); var offset = (oldParentNode === newParentNode && params.oldIndex > params.newIndex) ? params.count : 0;
}); var oldBeforeNode = oldParentNode.childs[params.oldIndex + offset] || oldParentNode.append;
for (var i = 0; i < params.count; i++) {
var node = newParentNode.childs[params.newIndex];
oldParentNode.moveBefore(node, oldBeforeNode);
}
}, },
'redo': function (params) { 'redo': function (params) {
var newBeforeNode = findNode(params.newBeforePath); var oldParentNode = findNode(params.oldParentPath);
params.paths.map(findNode).forEach(function (node) { var newParentNode = findNode(params.newParentPath);
newBeforeNode.parent.moveBefore(node, newBeforeNode); var offset = (oldParentNode === newParentNode && params.oldIndex < params.newIndex) ? params.count : 0;
}); var newBeforeNode = newParentNode.childs[params.newIndex + offset] || newParentNode.append;
for (var i = 0; i < params.count; i++) {
var node = oldParentNode.childs[params.oldIndex];
newParentNode.moveBefore(node, newBeforeNode);
}
} }
}, },
@ -247,8 +258,13 @@ History.prototype.undo = function () {
if (action && action.undo) { if (action && action.undo) {
action.undo(obj.params); action.undo(obj.params);
if (obj.params.oldSelection) { if (obj.params.oldSelection) {
try {
this.editor.setDomSelection(obj.params.oldSelection); this.editor.setDomSelection(obj.params.oldSelection);
} }
catch (err) {
console.error(err);
}
}
} }
else { else {
console.error(new Error('unknown action "' + obj.action + '"')); console.error(new Error('unknown action "' + obj.action + '"'));
@ -274,8 +290,13 @@ History.prototype.redo = function () {
if (action && action.redo) { if (action && action.redo) {
action.redo(obj.params); action.redo(obj.params);
if (obj.params.newSelection) { if (obj.params.newSelection) {
try {
this.editor.setDomSelection(obj.params.newSelection); this.editor.setDomSelection(obj.params.newSelection);
} }
catch (err) {
console.error(err);
}
}
} }
else { else {
console.error(new Error('unknown action "' + obj.action + '"')); console.error(new Error('unknown action "' + obj.action + '"'));

View File

@ -285,10 +285,16 @@ Node.prototype.updateError = function() {
/** /**
* Get the index of this node: the index in the list of childs where this * Get the index of this node: the index in the list of childs where this
* node is part of * node is part of
* @return {number} Returns the index, or -1 if this is the root node * @return {number | null} Returns the index, or null if this is the root node
*/ */
Node.prototype.getIndex = function () { Node.prototype.getIndex = function () {
return this.parent ? this.parent.childs.indexOf(this) : -1; if (this.parent) {
var index = this.parent.childs.indexOf(this);
return index !== -1 ? index : null;
}
else {
return -1;
}
}; };
/** /**
@ -781,7 +787,7 @@ Node.prototype.moveBefore = function(node, beforeNode) {
node.parent.removeChild(node); node.parent.removeChild(node);
} }
if (beforeNode instanceof AppendNode) { if (beforeNode instanceof AppendNode || !beforeNode) {
// the this.childs.length + 1 is to reckon with the node that we're about to add // the this.childs.length + 1 is to reckon with the node that we're about to add
if (this.childs.length + 1 > this.visibleChilds) { if (this.childs.length + 1 > this.visibleChilds) {
var lastVisibleNode = this.childs[this.visibleChilds - 1]; var lastVisibleNode = this.childs[this.visibleChilds - 1];
@ -832,7 +838,7 @@ Node.prototype.insertBefore = function(node, beforeNode) {
if (this._hasChilds()) { if (this._hasChilds()) {
this.visibleChilds++; this.visibleChilds++;
if (beforeNode == this.append) { if (beforeNode === this.append) {
// append to the child nodes // append to the child nodes
// adjust the link to the parent // adjust the link to the parent
@ -1407,7 +1413,8 @@ Node.prototype._onChangeField = function () {
} }
this.editor._onAction('editField', { this.editor._onAction('editField', {
path: this.getPath(), parentPath: this.parent.getPath(),
index: this.getIndex(),
oldValue: this.previousField, oldValue: this.previousField,
newValue: this.field, newValue: this.field,
oldSelection: oldSelection, oldSelection: oldSelection,
@ -1757,7 +1764,6 @@ Node.onDragStart = function (nodes, event) {
var firstNode = nodes[0]; var firstNode = nodes[0];
var lastNode = nodes[nodes.length - 1]; var lastNode = nodes[nodes.length - 1];
var draggedNode = Node.getNodeFromTarget(event.target); var draggedNode = Node.getNodeFromTarget(event.target);
var beforeNode = lastNode.nextSibling();
var editor = firstNode.editor; var editor = firstNode.editor;
// in case of multiple selected nodes, offsetY prevents the selection from // in case of multiple selected nodes, offsetY prevents the selection from
@ -1780,7 +1786,9 @@ Node.onDragStart = function (nodes, event) {
editor.drag = { editor.drag = {
oldCursor: document.body.style.cursor, oldCursor: document.body.style.cursor,
oldSelection: editor.getDomSelection(), oldSelection: editor.getDomSelection(),
oldBeforeNode: beforeNode, oldPaths: nodes.map(getPath),
oldParent: firstNode.parent,
oldIndex: firstNode.getIndex(),
mouseX: event.pageX, mouseX: event.pageX,
offsetY: offsetY, offsetY: offsetY,
level: firstNode.getLevel() level: firstNode.getLevel()
@ -1971,9 +1979,6 @@ Node.onDragEnd = function (nodes, event) {
var firstNode = nodes[0]; var firstNode = nodes[0];
var editor = firstNode.editor; var editor = firstNode.editor;
var parent = firstNode.parent;
var firstIndex = parent.childs.indexOf(firstNode);
var beforeNode = parent.childs[firstIndex + nodes.length] || parent.append;
// set focus to the context menu button of the first node // set focus to the context menu button of the first node
if (nodes[0]) { if (nodes[0]) {
@ -1981,14 +1986,17 @@ Node.onDragEnd = function (nodes, event) {
} }
var params = { var params = {
paths: nodes.map(getPath), count: nodes.length,
oldParentPath: editor.drag.oldParent.getPath(),
newParentPath: firstNode.parent.getPath(),
oldIndex: editor.drag.oldIndex,
newIndex: firstNode.getIndex(),
oldSelection: editor.drag.oldSelection, oldSelection: editor.drag.oldSelection,
newSelection: editor.getDomSelection(), newSelection: editor.getDomSelection()
oldBeforePath: editor.drag.oldBeforeNode.getPath(),
newBeforePath: beforeNode.getPath()
}; };
if (params.oldBeforeNode != params.newBeforeNode) { if (JSON.stringify(params.oldParentPath) !== JSON.stringify(params.newParentPath) ||
params.oldIndex !== params.newIndex) {
// only register this action if the node is actually moved to another place // only register this action if the node is actually moved to another place
editor._onAction('moveNodes', params); editor._onAction('moveNodes', params);
} }
@ -2665,6 +2673,8 @@ Node.prototype.onKeyDown = function (event) {
var editable = this.editor.options.mode === 'tree'; var editable = this.editor.options.mode === 'tree';
var oldSelection; var oldSelection;
var oldBeforeNode; var oldBeforeNode;
var oldParent;
var oldIndex;
var nodes; var nodes;
var multiselection; var multiselection;
var selectedNodes = this.editor.multiselection.nodes.length > 0 var selectedNodes = this.editor.multiselection.nodes.length > 0
@ -2774,7 +2784,8 @@ Node.prototype.onKeyDown = function (event) {
!(lastNode.parent.childs.length == 1) && !(lastNode.parent.childs.length == 1) &&
nextNode2 && nextNode2.parent) { nextNode2 && nextNode2.parent) {
oldSelection = this.editor.getDomSelection(); oldSelection = this.editor.getDomSelection();
oldBeforeNode = lastNode.nextSibling(); oldParent = firstNode.parent;
oldIndex = firstNode.getIndex();
selectedNodes.forEach(function (node) { selectedNodes.forEach(function (node) {
nextNode2.parent.moveBefore(node, nextNode2); nextNode2.parent.moveBefore(node, nextNode2);
@ -2782,9 +2793,11 @@ Node.prototype.onKeyDown = function (event) {
this.focus(Node.focusElement || this._getElementName(target)); this.focus(Node.focusElement || this._getElementName(target));
this.editor._onAction('moveNodes', { this.editor._onAction('moveNodes', {
paths: selectedNodes.map(getPath), count: selectedNodes.length,
oldBeforePath: oldBeforeNode.getPath(), oldParentPath: oldParent.getPath(),
newBeforePath: nextNode2.getPath(), newParentPath: firstNode.parent.getPath(),
oldIndex: oldIndex,
newIndex: firstNode.getIndex(),
oldSelection: oldSelection, oldSelection: oldSelection,
newSelection: this.editor.getDomSelection() newSelection: this.editor.getDomSelection()
}); });
@ -2821,7 +2834,8 @@ Node.prototype.onKeyDown = function (event) {
prevNode = firstNode._previousNode(); prevNode = firstNode._previousNode();
if (prevNode && prevNode.parent) { if (prevNode && prevNode.parent) {
oldSelection = this.editor.getDomSelection(); oldSelection = this.editor.getDomSelection();
oldBeforeNode = lastNode.nextSibling(); oldParent = firstNode.parent;
oldIndex = firstNode.getIndex();
selectedNodes.forEach(function (node) { selectedNodes.forEach(function (node) {
prevNode.parent.moveBefore(node, prevNode); prevNode.parent.moveBefore(node, prevNode);
@ -2829,9 +2843,11 @@ Node.prototype.onKeyDown = function (event) {
this.focus(Node.focusElement || this._getElementName(target)); this.focus(Node.focusElement || this._getElementName(target));
this.editor._onAction('moveNodes', { this.editor._onAction('moveNodes', {
paths: selectedNodes.map(getPath), count: selectedNodes.length,
oldBeforePath: oldBeforeNode.getPath(), oldParentPath: oldParent.getPath(),
newBeforePath: prevNode.getPath(), newParentPath: firstNode.parent.getPath(),
oldIndex: oldIndex,
newIndex: firstNode.getIndex(),
oldSelection: oldSelection, oldSelection: oldSelection,
newSelection: this.editor.getDomSelection() newSelection: this.editor.getDomSelection()
}); });
@ -2855,7 +2871,8 @@ Node.prototype.onKeyDown = function (event) {
prevNode = Node.getNodeFromTarget(prevDom); prevNode = Node.getNodeFromTarget(prevDom);
if (prevNode && prevNode.parent && !prevNode.isVisible()) { if (prevNode && prevNode.parent && !prevNode.isVisible()) {
oldSelection = this.editor.getDomSelection(); oldSelection = this.editor.getDomSelection();
oldBeforeNode = lastNode.nextSibling(); oldParent = firstNode.parent;
oldIndex = firstNode.getIndex();
selectedNodes.forEach(function (node) { selectedNodes.forEach(function (node) {
prevNode.parent.moveBefore(node, prevNode); prevNode.parent.moveBefore(node, prevNode);
@ -2863,9 +2880,11 @@ Node.prototype.onKeyDown = function (event) {
this.focus(Node.focusElement || this._getElementName(target)); this.focus(Node.focusElement || this._getElementName(target));
this.editor._onAction('moveNodes', { this.editor._onAction('moveNodes', {
paths: selectedNodes.map(getPath), count: selectedNodes.length,
oldBeforePath: oldBeforeNode.getPath(), oldParentPath: oldParent.getPath(),
newBeforePath: prevNode.getPath(), newParentPath: firstNode.parent.getPath(),
oldIndex: oldIndex,
newIndex: firstNode.getIndex(),
oldSelection: oldSelection, oldSelection: oldSelection,
newSelection: this.editor.getDomSelection() newSelection: this.editor.getDomSelection()
}); });
@ -2918,7 +2937,8 @@ Node.prototype.onKeyDown = function (event) {
var nextNode2 = nextNode && (nextNode._nextNode() || nextNode.parent.append); var nextNode2 = nextNode && (nextNode._nextNode() || nextNode.parent.append);
if (nextNode2 && nextNode2.parent) { if (nextNode2 && nextNode2.parent) {
oldSelection = this.editor.getDomSelection(); oldSelection = this.editor.getDomSelection();
oldBeforeNode = lastNode.nextSibling(); oldParent = firstNode.parent;
oldIndex = firstNode.getIndex();
selectedNodes.forEach(function (node) { selectedNodes.forEach(function (node) {
nextNode2.parent.moveBefore(node, nextNode2); nextNode2.parent.moveBefore(node, nextNode2);
@ -2926,9 +2946,11 @@ Node.prototype.onKeyDown = function (event) {
this.focus(Node.focusElement || this._getElementName(target)); this.focus(Node.focusElement || this._getElementName(target));
this.editor._onAction('moveNodes', { this.editor._onAction('moveNodes', {
paths: selectedNodes.map(getPath), count: selectedNodes.length,
oldBeforePath: oldBeforeNode.getPath(), oldParentPath: oldParent.getPath(),
newBeforePath: nextNode2.getPath(), newParentPath: firstNode.parent.getPath(),
oldIndex: oldIndex,
newIndex: firstNode.getIndex(),
oldSelection: oldSelection, oldSelection: oldSelection,
newSelection: this.editor.getDomSelection() newSelection: this.editor.getDomSelection()
}); });
@ -2992,6 +3014,9 @@ Node.onRemove = function(nodes) {
Node.blurNodes(nodes); Node.blurNodes(nodes);
var newSelection = editor.getDomSelection(); var newSelection = editor.getDomSelection();
// store the paths before removing them (needed for history)
var paths = nodes.map(getPath);
// remove the nodes // remove the nodes
nodes.forEach(function (node) { nodes.forEach(function (node) {
node.parent._remove(node); node.parent._remove(node);
@ -2999,7 +3024,8 @@ Node.onRemove = function(nodes) {
// store history action // store history action
editor._onAction('removeNodes', { editor._onAction('removeNodes', {
paths: nodes.map(getPath), nodes: nodes,
paths: paths,
parentPath: parent.getPath(), parentPath: parent.getPath(),
index: firstIndex, index: firstIndex,
oldSelection: oldSelection, oldSelection: oldSelection,
@ -3046,8 +3072,9 @@ Node.onDuplicate = function(nodes) {
var newSelection = editor.getDomSelection(); var newSelection = editor.getDomSelection();
editor._onAction('duplicateNodes', { editor._onAction('duplicateNodes', {
paths: nodes.map(getPath),
clonePaths: clones.map(getPath),
afterPath: lastNode.getPath(), afterPath: lastNode.getPath(),
paths: clones.map(getPath),
parentPath: parent.getPath(), parentPath: parent.getPath(),
oldSelection: oldSelection, oldSelection: oldSelection,
newSelection: newSelection newSelection: newSelection
@ -3071,14 +3098,18 @@ Node.prototype._onInsertBefore = function (field, value, type) {
type: type type: type
}); });
newNode.expand(true); newNode.expand(true);
var beforePath = this.getPath();
this.parent.insertBefore(newNode, this); this.parent.insertBefore(newNode, this);
this.editor.highlighter.unhighlight(); this.editor.highlighter.unhighlight();
newNode.focus('field'); newNode.focus('field');
var newSelection = this.editor.getDomSelection(); var newSelection = this.editor.getDomSelection();
this.editor._onAction('insertBeforeNodes', { this.editor._onAction('insertBeforeNodes', {
nodes: [newNode],
paths: [newNode.getPath()], paths: [newNode.getPath()],
beforePath: this.getPath(), beforePath: beforePath,
parentPath: this.parent.getPath(), parentPath: this.parent.getPath(),
oldSelection: oldSelection, oldSelection: oldSelection,
newSelection: newSelection newSelection: newSelection
@ -3107,6 +3138,7 @@ Node.prototype._onInsertAfter = function (field, value, type) {
var newSelection = this.editor.getDomSelection(); var newSelection = this.editor.getDomSelection();
this.editor._onAction('insertAfterNodes', { this.editor._onAction('insertAfterNodes', {
nodes: [newNode],
paths: [newNode.getPath()], paths: [newNode.getPath()],
afterPath: this.getPath(), afterPath: this.getPath(),
parentPath: this.parent.getPath(), parentPath: this.parent.getPath(),
@ -3137,6 +3169,7 @@ Node.prototype._onAppend = function (field, value, type) {
var newSelection = this.editor.getDomSelection(); var newSelection = this.editor.getDomSelection();
this.editor._onAction('appendNodes', { this.editor._onAction('appendNodes', {
nodes: [newNode],
paths: [newNode.getPath()], paths: [newNode.getPath()],
parentPath: this.parent.getPath(), parentPath: this.parent.getPath(),
oldSelection: oldSelection, oldSelection: oldSelection,

View File

@ -75,6 +75,22 @@ function appendNodeFactory(Node) {
return trAppend; return trAppend;
}; };
/**
* Append node doesn't have a path
* @returns {null}
*/
AppendNode.prototype.getPath = function() {
return null;
};
/**
* Append node doesn't have an index
* @returns {null}
*/
AppendNode.prototype.getIndex = function() {
return null;
};
/** /**
* Update the HTML dom of the Node * Update the HTML dom of the Node
*/ */