Skip to content
This repository was archived by the owner on Sep 16, 2021. It is now read-only.

Commit f5a88ad

Browse files
Merge pull request #131 from symfony-cmf/issue-128/use-unique-key
Use unique keys and avoid duplicated or false nodes
2 parents 7dbeab0 + 9994b77 commit f5a88ad

14 files changed

+171
-135
lines changed

.travis.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
language: php
22

33
php:
4-
- 5.5
54
- 5.6
65
- 7.0
7-
- hhvm
6+
- 7.1
87

98
sudo: false
109

Resources/assets/js/adapter/fancytree.js

Lines changed: 80 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,19 @@ import '../../css/fontawesome-style.css'
1515

1616
var cache = new Map();
1717

18-
function getPropertyFromString(propertyPath, list) {
19-
var isOptional = propertyPath.substr(0, 1) === '?';
20-
var props = propertyPath.substr(1).split('.');
21-
var currentNode = list;
22-
for (let prop in props) {
23-
currentNode = currentNode[props[prop]];
24-
25-
if (undefined === currentNode) {
26-
if (isOptional) {
27-
break;
28-
}
18+
function getPropertyFromString(name, list) {
19+
var isOptional = name.substr(0, 1) === '?';
20+
var nameWithoutPrefix = (isOptional ? name.substr(1) : name);
2921

30-
throw 'Attribute "' + props[prop] + '" does not exists';
22+
if (undefined === list[nameWithoutPrefix]) {
23+
if (isOptional) {
24+
return undefined;
3125
}
26+
27+
throw 'Attribute "' + props[prop] + '" does not exists';
3228
}
3329

34-
return currentNode;
30+
return list[nameWithoutPrefix];
3531
}
3632

3733
/**
@@ -60,6 +56,8 @@ export class FancytreeAdapter {
6056
this.tree = null;
6157
// the tree element (jQuery)
6258
this.$tree = null;
59+
// a map of path and related keys
60+
this.pathKeyMap = {};
6361
}
6462

6563
bindToElement($elem) {
@@ -74,23 +72,31 @@ export class FancytreeAdapter {
7472
this.$tree = $elem;
7573
var actions = this.actions;
7674
var requestNode = this.requestNode;
77-
var requestNodeToFancytreeNode = function (requestNode) {
75+
var requestNodeToFancytreeNode = (requestNode) => {
7876
if (requestNode.length === 0) {
7977
return;
8078
}
8179

80+
if ('//' == requestNode.path || '/' == requestNode.path) {
81+
return requestNodeToFancytreeNode(requestNode.children[Object.keys(requestNode.children)[0]]);
82+
}
83+
84+
var key = "" + jQuery.ui.fancytree._nextNodeKey++;
8285
var fancytreeNode = {
8386
title: requestNode.label,
84-
key: requestNode.node_name,
87+
key: key,
8588
children: [],
86-
actions: {}
89+
actions: {},
90+
refPath: requestNode.path.replace('\/', '/').replace('//', '/')
8791
};
8892

93+
this.pathKeyMap[fancytreeNode.refPath] = key;
94+
8995
for (let actionName in actions) {
9096
var action = actions[actionName];
9197
var url = action.url;
9298
if (typeof action.url == 'object' && action.url.hasOwnProperty('data')) {
93-
url = getPropertyFromString(action.url.data, requestNode);
99+
url = getPropertyFromString(action.url.data, requestNode.descriptors);
94100
}
95101

96102
if (url === undefined) {
@@ -112,9 +118,13 @@ export class FancytreeAdapter {
112118
childrenCount++;
113119
}
114120

115-
if (childrenCount) {
121+
if (0 != childrenCount) {
116122
fancytreeNode.folder = true;
117123
fancytreeNode.lazy = true;
124+
125+
if (0 === fancytreeNode.children.length) {
126+
fancytreeNode.children = null;
127+
}
118128
}
119129

120130
return fancytreeNode;
@@ -128,7 +138,7 @@ export class FancytreeAdapter {
128138

129139
// lazy load the children when a node is collapsed
130140
lazyLoad: function (event, data) {
131-
var path = data.node.getKeyPath();
141+
var path = data.node.data.refPath;
132142
if (useCache && cache.has(path)) {
133143
data.result = cache.get(path);
134144
} else {
@@ -146,27 +156,33 @@ export class FancytreeAdapter {
146156

147157
// transform the JSON response into a data structure that's supported by FancyTree
148158
postProcess: function (event, data) {
149-
if (null == data.error) {
150-
var result = requestNodeToFancytreeNode(data.response);
151-
if ("" === result.key) {
152-
result = result.children;
153-
} else {
154-
result = [result];
155-
}
156-
157-
if (result.length == 1) {
158-
result[0].expanded = true;
159-
}
160-
161-
data.result = result;
162-
if (useCache) {
163-
cache.set(data.node.getKeyPath(), result);
164-
}
165-
} else {
159+
if (data.hasOwnProperty('error') && null != data.error) {
166160
data.result = {
167161
// todo: maybe use a more admin friendly error message in prod?
168162
error: 'An error occured while retrieving the nodes: ' + data.error
169163
};
164+
165+
return;
166+
}
167+
168+
let result = requestNodeToFancytreeNode(data.response);
169+
let nodeIsDuplicate = function (node, parentPath) {
170+
return parentPath == node.refPath;
171+
};
172+
173+
if (nodeIsDuplicate(result, data.node.data.refPath)) {
174+
result = result.children;
175+
} else {
176+
result = [result];
177+
}
178+
179+
if (result.length == 1 && undefined !== result[0].folder) {
180+
result[0].expanded = true;
181+
}
182+
183+
data.result = result;
184+
if (useCache) {
185+
cache.set(data.node.data.refPath, result);
170186
}
171187
},
172188

@@ -186,44 +202,56 @@ export class FancytreeAdapter {
186202
}
187203

188204
this.tree = this.$tree.fancytree('getTree');
205+
206+
this.tree.getNodeByRefPath = function (refPath) {
207+
return this.findFirst((node) => {
208+
return node.data.refPath == refPath;
209+
});
210+
};
189211
}
190212

191213
bindToInput($input) {
192-
var root = this.rootNode;
193-
if (root.substr(-1) == '/') {
194-
var root = this.rootNode.substr(0, -1);
195-
}
196-
var rootParent = root.substr(0, root.lastIndexOf('/'));
197-
198214
// output active node to input field
199215
this.$tree.fancytree('option', 'activate', (event, data) => {
200-
$input.val(rootParent + data.node.getKeyPath());
216+
$input.val(data.node.data.refPath);
201217
});
202218

203-
var showKey = (key) => {
204-
this.tree.loadKeyPath(key, function (node, status) {
219+
var showPath = (path) => {
220+
if (!this.pathKeyMap.hasOwnProperty(path)) {
221+
return;
222+
}
223+
224+
this.tree.loadKeyPath(generateKeyPath(path), function (node, status) {
205225
if ('ok' == status) {
206226
node.setExpanded();
207227
node.setActive();
208228
}
209229
});
210230
};
211-
var removeRoot = (path) => {
212-
if (0 === path.indexOf(rootParent + '/')) {
213-
return path.substr(rootParent.length + 1);
214-
}
231+
var generateKeyPath = (path) => {
232+
var keyPath = '';
233+
var refPath = '';
234+
var subPaths = path.split('/');
235+
236+
subPaths.forEach((subPath) => {
237+
if (subPath == '' || !this.pathKeyMap.hasOwnProperty(refPath += '/' + subPath)) {
238+
return;
239+
}
240+
241+
keyPath += '/' + this.pathKeyMap[refPath];
242+
});
215243

216-
return path;
244+
return keyPath;
217245
};
218246

219247
// use initial input value as active node
220248
this.$tree.bind('fancytreeinit', function (event, data) {
221-
showKey(removeRoot($input.val()));
249+
showPath($input.val());
222250
});
223251

224252
// change active node when the value of the input field changed
225253
$input.on('change', function (e) {
226-
showKey(removeRoot($(this).val()));
254+
showPath($(this).val());
227255
});
228256
}
229257

Resources/public/css/cmf_tree_browser.fancytree.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
5.38 KB
Loading
852 Bytes
Loading
5.39 KB
Loading

Resources/public/js/cmf_tree_browser.fancytree.js

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Resources/public/vendor/jquery-ui/jquery-ui.min.js

Lines changed: 11 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Resources/public/vendor/jquery/dist/jquery.min.js

Lines changed: 4 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Resources/views/Base/scripts.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
<script>window.jQuery.ui || document.write('<script src="{{ asset(assetsBasePath ~ '/jquery-ui/jquery-ui.min.js') }}"><\/script>')</script>
66
{% endif %}
77

8-
<script src="{{ asset('bundles/cmftreebrowser/js/cmf_tree_browser.' ~ treeAdapter ~ '.js') }}" type="text/javascript"></script>
8+
<script src="{{ asset('bundles/cmftreebrowser/js/cmf_tree_browser.' ~ treeAdapter ~ '.js?' ~ 'now'|format('u')) }}" type="text/javascript"></script>
99

1010
<link rel="stylesheet" href="{{ asset('bundles/cmftreebrowser/css/cmf_tree_browser.' ~ treeAdapter ~ '.css') }}" media="all"/>

0 commit comments

Comments
 (0)