Commit e1370d7e authored by Tymoteusz Motylewski's avatar Tymoteusz Motylewski Committed by Andreas Fernandez
Browse files

[BUGFIX] Change behavior of new element during drag & drop into node

- place input correctly
- open node with children while holding the mouse over
this node for one second (when drag-adding new node)
- add chevron and expand it when adding first child
- refactor node.open to node.expand because they did the same thing
- show icons for custom doktypes (fix regex)

Releases: master
Resolves: #83306
Change-Id: I0255fa50f836d002392ed7791eed1ac3517cb400
Reviewed-on: https://review.typo3.org/55061

Tested-by: default avatarTYPO3com <no-reply@typo3.com>
Reviewed-by: Tymoteusz Motylewski's avatarTymoteusz Motylewski <t.motylewski@gmail.com>
Tested-by: Tymoteusz Motylewski's avatarTymoteusz Motylewski <t.motylewski@gmail.com>
Reviewed-by: Andreas Fernandez's avatarAndreas Fernandez <typo3@scripting-base.de>
Tested-by: Andreas Fernandez's avatarAndreas Fernandez <typo3@scripting-base.de>
parent 5103a47f
......@@ -412,7 +412,7 @@ define(['jquery',
.append('input')
.attr('class', 'node-edit')
.style('top', function () {
var top = node.y + 15; //svg margin top
var top = node.y + _this.settings.marginTop;
return top + 'px';
})
.style('left', (node.x + _this.textPosition + 5) + 'px')
......
......@@ -173,8 +173,10 @@ define([
tree.settings.nodeDragPosition = false;
_this.openNodeTimeout();
if (node.isOver
|| (tree.settings.nodeOver.node && tree.settings.nodeOver.node.parentsUid.indexOf(node.stateIdentifier) !== -1)
|| (tree.settings.nodeOver.node && tree.settings.nodeOver.node.parentsStateIdentifier.indexOf(node.stateIdentifier) !== -1)
|| !tree.isOverSvg) {
_this.addNodeDdClass({ $nodeDd: $nodeDd, $nodesWrap: $nodesWrap, className: 'nodrop' });
......@@ -250,7 +252,7 @@ define([
if (
!(node.isOver
|| (tree.settings.nodeOver.node && tree.settings.nodeOver.node.parentsUid.indexOf(node.stateIdentifier) !== -1)
|| (tree.settings.nodeOver.node && tree.settings.nodeOver.node.parentsStateIdentifier.indexOf(node.stateIdentifier) !== -1)
|| !tree.settings.canNodeDrag
|| !tree.isOverSvg
)
......@@ -332,6 +334,33 @@ define([
.on('end', self.dragEnd);
},
/**
* Open node with children while holding the node/element over this node for one second
*/
openNodeTimeout: function () {
var _this = this;
if (!_this.timeout) {
_this.timeout = {}
}
if (_this.tree.settings.nodeOver.node.hasChildren && !_this.tree.settings.nodeOver.node.expanded) {
if (_this.timeout.node != _this.tree.settings.nodeOver.node) {
_this.timeout.node = _this.tree.settings.nodeOver;
clearTimeout(_this.timeout.time);
_this.timeout.time = setTimeout(function () {
if (_this.tree.settings.nodeOver.node) {
_this.tree.showChildren(_this.tree.settings.nodeOver.node);
_this.tree.prepareDataForVisibleNodes();
_this.tree.update();
}
}, 1000);
}
} else {
clearTimeout(_this.timeout.time);
}
},
changeNodeClasses: function () {
var elementNodeBg = this.tree.svg.select('.node-over');
var $svg = $(this.tree.svg.node());
......@@ -340,7 +369,7 @@ define([
var nodeBgBorder = this.tree.nodesBgContainer.selectAll('.node-bg__border');
if (elementNodeBg.size() && this.tree.isOverSvg) {
//line between nodes
// line between nodes
if (nodeBgBorder.empty()) {
nodeBgBorder = this.tree.nodesBgContainer
.append('rect')
......@@ -382,7 +411,7 @@ define([
nodeBgBorder
.style('display', 'none');
if (this.tree.settings.nodeOver.node.open && this.tree.settings.nodeOver.node.hasChildren) {
if (this.tree.settings.nodeOver.node.expanded && this.tree.settings.nodeOver.node.hasChildren) {
this.addNodeDdClass({
$nodeDd: $nodeDd,
$nodesWrap: $nodesWrap,
......@@ -550,6 +579,8 @@ define([
top += d3.event.sourceEvent.pageY;
}
_this.openNodeTimeout();
$(document).find('.node-dd').css({
left: left,
top: top,
......@@ -652,10 +683,10 @@ define([
var data = {
node: tree.settings.nodeDrag,
uid: uid, //dragged node id
target: target, //hovered node
position: position, //before, in, after
command: options.command, //element is copied or moved
uid: uid, // dragged node id
target: target, // hovered node
position: position, // before, in, after
command: options.command, // element is copied or moved
};
$.extend(data, options);
......@@ -703,8 +734,16 @@ define([
var index = _this.tree.nodes.indexOf(target);
var newNode = {};
var removeNode = function (newNode) {
_this.tree.nodes.splice(_this.tree.nodes.indexOf(newNode), 1);
_this.tree.setParametersNode(_this.tree.nodes);
var index = _this.tree.nodes.indexOf(newNode);
// if newNode is only one child
if (_this.tree.nodes[index - 1].depth != newNode.depth
&& (!_this.tree.nodes[index + 1] || _this.tree.nodes[index + 1].depth != newNode.depth)) {
_this.tree.nodes[index - 1].hasChildren = false;
}
_this.tree.nodes.splice(index, 1);
_this.tree.setParametersNode();
_this.tree.prepareDataForVisibleNodes();
_this.tree.update();
_this.tree.removeEditedText();
......@@ -715,15 +754,19 @@ define([
newNode.identifier = -1;
newNode.target = target;
newNode.parents = target.parents;
newNode.parentsUid = target.parentsUid;
newNode.parentsStateIdentifier = target.parentsStateIdentifier;
newNode.depth = target.depth;
newNode.position = options.position;
newNode.name = (typeof options.title !== 'undefined') ? options.title : TYPO3.lang['tree.defaultPageTitle'];
newNode.y = newNode.y || newNode.target.y;
newNode.x = newNode.x || newNode.target.x;
if (options.position === 'in') {
newNode.depth++;
_this.tree.nodes[index].open = true;
newNode.parents.unshift(index);
newNode.parentsStateIdentifier.unshift(_this.tree.nodes[index].stateIdentifier);
_this.tree.nodes[index].hasChildren = true;
_this.tree.showChildren(_this.tree.nodes[index]);
}
if (options.position === 'in' || options.position === 'after') {
......@@ -741,21 +784,17 @@ define([
}
_this.tree.nodes.splice(index, 0, newNode);
_this.tree.setParametersNode(_this.tree.nodes);
_this.tree.setParametersNode();
_this.tree.prepareDataForVisibleNodes();
_this.tree.update();
_this.tree.removeEditedText();
_this.tree.nodeIsEdit = true;
d3.select(_this.tree.svg.node().parentNode)
.append('input')
.attr('class', 'node-edit')
.style('top', function () {
var top = newNode.y + 15; //svg margin top
return top + 'px';
})
.style('left', (newNode.x + _this.tree.textPosition + 5) + 'px')
.style('top', newNode.y + _this.tree.settings.marginTop + 'px')
.style('left', newNode.x + _this.tree.textPosition + 5 + 'px')
.style('width', _this.tree.settings.width - (newNode.x + _this.tree.textPosition + 20) + 'px')
.style('height', _this.tree.settings.nodeHeight + 'px')
.attr('text', 'text')
......@@ -763,7 +802,7 @@ define([
.on('keydown', function () {
var code = d3.event.keyCode;
if (code === 13 || code === 9) { //enter || tab
if (code === 13 || code === 9) { // enter || tab
_this.tree.nodeIsEdit = false;
var newName = this.value.trim();
......@@ -774,7 +813,7 @@ define([
} else {
removeNode(newNode);
}
} else if (code === 27) { //esc
} else if (code === 27) { // esc
_this.tree.nodeIsEdit = false;
removeNode(newNode);
}
......
......@@ -204,16 +204,16 @@ define(['jquery',
var _this = this;
var name = $(input).val();
this.tree.nodes[0].open = false;
this.tree.nodes[0].expanded = false;
this.tree.nodes.forEach(function (node) {
var regex = new RegExp(name, 'i');
if (regex.test(node.name) || regex.test(node.alias)) {
_this.showParents(node);
node.open = true;
node.expanded = true;
node.hidden = false;
} else if (node.depth !== 0) {
node.hidden = true;
node.open = false;
node.expanded = false;
}
});
......@@ -235,11 +235,11 @@ define(['jquery',
this.tree.nodes.forEach(function (node) {
if (node.checked) {
_this.showParents(node);
node.open = true;
node.expanded = true;
node.hidden = false;
} else {
node.hidden = true;
node.open = false;
node.expanded = false;
}
});
} else {
......@@ -267,7 +267,7 @@ define(['jquery',
parent.hidden = false;
//expand parent node
parent.open = true;
parent.expanded = true;
this.showParents(parent);
};
......
......@@ -37,6 +37,7 @@ define(
showCheckboxes: false,
showIcons: false,
allowRecursiveDelete: false,
marginTop: 15,
nodeHeight: 20,
indentWidth: 16,
width: 300,
......@@ -283,29 +284,41 @@ define(
}
var nodes = Array.isArray(json) ? json : [];
_this.setParametersNode(nodes);
_this.dispatch.call('loadDataAfter', _this);
_this.prepareDataForVisibleNodes();
_this.nodesContainer.selectAll('.node').remove();
_this.nodesBgContainer.selectAll('.node-bg').remove();
_this.linksContainer.selectAll('.link').remove();
_this.update();
_this.replaceData(nodes);
_this.nodesRemovePlaceholder();
});
},
/**
* Set parameters like node parents, parentsUid, checked
* Delete old tree and create new one
*
* @param {Node[]} nodes
*/
replaceData: function (nodes) {
var _this = this;
_this.setParametersNode(nodes);
_this.dispatch.call('loadDataAfter', _this);
_this.prepareDataForVisibleNodes();
_this.nodesContainer.selectAll('.node').remove();
_this.nodesBgContainer.selectAll('.node-bg').remove();
_this.linksContainer.selectAll('.link').remove();
_this.update();
},
/**
* Set parameters like node parents, parentsStateIdentifier, checked
*
* @param {Node[]} nodes
*/
setParametersNode: function (nodes) {
var _this = this;
nodes = nodes || this.nodes;
nodes = nodes.map(function (node, index) {
node.open = (_this.settings.expandUpToLevel !== null) ? node.depth < _this.settings.expandUpToLevel : Boolean(node.expanded);
node.expanded = (_this.settings.expandUpToLevel !== null) ? node.depth < _this.settings.expandUpToLevel : Boolean(node.expanded);
node.parents = [];
node.parentsUid = [];
node.parentsStateIdentifier = [];
node._isDragged = false;
if (node.depth > 0) {
var currentDepth = node.depth;
......@@ -313,12 +326,12 @@ define(
var currentNode = nodes[i];
if (currentNode.depth < currentDepth) {
node.parents.push(i);
node.parentsUid.push(nodes[i].stateIdentifier);
node.parentsStateIdentifier.push(nodes[i].stateIdentifier);
currentDepth = currentNode.depth;
}
}
} else if (node.hasChildren) {
node.open = true;
node.expanded = true;
}
// create stateIdentifier if doesn't exist (for category tree)
......@@ -347,7 +360,7 @@ define(
nodesAddPlaceholder: function (node) {
if (node) {
$('.svg-tree').find('.node-loader').css({ top: node.y + 15 }).show();
$('.svg-tree').find('.node-loader').css({ top: node.y + this.settings.marginTop }).show();
} else {
$('.svg-tree').find('.svg-tree-loader').show();
}
......@@ -363,7 +376,7 @@ define(
var blacklist = {};
this.nodes.map(function (node, index) {
if (!node.open) {
if (!node.expanded) {
blacklist[index] = true;
}
});
......@@ -424,7 +437,7 @@ define(
icon: '',
};
Icons.getIcon(iconName, Icons.sizes.small, null, null, 'inline').done(function (icon) {
_this.data.icons[iconName].icon = icon.match(/<svg.*<\/svg>/im)[0];
_this.data.icons[iconName].icon = icon.match(/<svg.*<\/svg>/is)[0];
if (update) {
_this.update();
......@@ -467,7 +480,7 @@ define(
.attr('class', function (node, i) {
return _this.getNodeBgClass(node, i, nodeBgClass);
})
.attr('style', function (node, i) {
.attr('style', function (node) {
return node.backgroundColor ? 'fill: ' + node.backgroundColor + ';' : '';
});
......@@ -486,6 +499,10 @@ define(
.style('fill', this.getChevronColor)
.attr('class', this.getChevronClass);
nodes
.select('.toggle')
.attr('visibility', this.getToggleVisibility);
if (this.settings.showIcons) {
nodes
.select('use.node-icon')
......@@ -661,7 +678,9 @@ define(
.attr('class', 'toggle')
.attr('visibility', this.getToggleVisibility)
.attr('transform', 'translate(-8, -8)')
.on('click', _this.chevronClick.bind(this));
.on('click', function (node) {
_this.chevronClick(node);
});
// improve usability by making the click area a 16px square
chevron
......@@ -864,7 +883,7 @@ define(
* @returns {String}
*/
getChevronTransform: function (node) {
return node.open ? 'translate(16,0) rotate(90)' : ' rotate(0)';
return node.expanded ? 'translate(16,0) rotate(90)' : ' rotate(0)';
},
/**
......@@ -874,7 +893,7 @@ define(
* @returns {String}
*/
getChevronColor: function (node) {
return node.open ? '#000' : '#8e8e8e';
return node.expanded ? '#000' : '#8e8e8e';
},
/**
......@@ -894,7 +913,7 @@ define(
* @returns {String}
*/
getChevronClass: function (node) {
return 'chevron ' + (node.open ? 'expanded' : 'collapsed');
return 'chevron ' + (node.expanded ? 'expanded' : 'collapsed');
},
/**
......@@ -1066,7 +1085,7 @@ define(
* @param {Node} node
*/
chevronClick: function (node) {
if (node.open) {
if (node.expanded) {
this.hideChildren(node);
} else {
this.showChildren(node);
......@@ -1082,7 +1101,7 @@ define(
* @param {Node} node
*/
hideChildren: function (node) {
node.open = false;
node.expanded = false;
},
/**
......@@ -1091,7 +1110,7 @@ define(
* @param {Node} node
*/
showChildren: function (node) {
node.open = true;
node.expanded = true;
},
/**
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment