Revize 716a1d9e
Přidáno uživatelem Pavel Fidranský před téměř 6 roky(ů)
sources/src/main/webapp/js/components/navbar.js | ||
---|---|---|
226 | 226 |
|
227 | 227 |
if (vertexWithMostEdges !== null) { |
228 | 228 |
vertexWithMostEdges.exclude(); |
229 |
app.sidebarComponent.excludedNodeListComponent.add(vertexWithMostEdges); |
|
229 |
app.sidebarComponent.excludedNodeListComponent.addNode(vertexWithMostEdges);
|
|
230 | 230 |
} |
231 | 231 |
}, |
232 | 232 |
}, [ |
sources/src/main/webapp/js/components/node.js | ||
---|---|---|
278 | 278 |
if (this instanceof Vertex && this._group !== null) return; |
279 | 279 |
|
280 | 280 |
if (newValue) { |
281 |
// set floater
|
|
281 |
// set proxy
|
|
282 | 282 |
this._proxy = new NodeProxy(this); |
283 |
app.sidebarComponent.addFloater(this._proxy);
|
|
283 |
app.proxyList.push(this._proxy);
|
|
284 | 284 |
|
285 | 285 |
} else { |
286 |
// remove floater
|
|
287 |
app.sidebarComponent.removeFloater(this._proxy);
|
|
286 |
// remove proxy
|
|
287 |
app.proxyList.splice(app.proxyList.indexOf(this._proxy), 1);
|
|
288 | 288 |
this._proxy = null; |
289 | 289 |
} |
290 | 290 |
} |
... | ... | |
399 | 399 |
case 'exclude': |
400 | 400 |
this.exclude(); |
401 | 401 |
|
402 |
app.sidebarComponent.excludedNodeListComponent.add(this); |
|
402 |
app.sidebarComponent.excludedNodeListComponent.addNode(this);
|
|
403 | 403 |
break; |
404 | 404 |
} |
405 | 405 |
} |
sources/src/main/webapp/js/components/sidebar.js | ||
---|---|---|
1 |
/** |
|
2 |
* @constructor |
|
3 |
*/ |
|
4 |
function Sidebar() { |
|
5 |
var rootElement; |
|
6 |
|
|
7 |
/** @prop {SidebarUnconnectedNodeList} unconnectedNodeListComponent */ |
|
8 |
this.unconnectedNodeListComponent = null; |
|
9 |
/** @prop {SidebarExcludedNodeList} excludedNodeListComponent */ |
|
10 |
this.excludedNodeListComponent = null; |
|
11 |
/** @prop {Minimap} minimapComponent */ |
|
12 |
this.minimapComponent = null; |
|
13 |
/** @prop {StatusBar} statusBarComponent */ |
|
14 |
this.statusBarComponent = null; |
|
15 |
|
|
16 |
var floaterList = []; |
|
17 |
|
|
18 |
this.getFloaters = function() { |
|
19 |
return floaterList; |
|
20 |
}; |
|
21 |
|
|
22 |
this.refreshFloaters = function() { |
|
23 |
floaterList.forEach(floater => { |
|
24 |
floater.updatePosition(); |
|
25 |
}); |
|
26 |
}; |
|
27 |
|
|
28 |
this.addFloater = function(floater) { |
|
29 |
floaterList.push(floater); |
|
30 |
}; |
|
31 |
|
|
32 |
this.removeFloater = function(floater) { |
|
33 |
floaterList.splice(floaterList.indexOf(floater), 1); |
|
34 |
}; |
|
35 |
|
|
36 |
this.render = function() { |
|
37 |
rootElement = DOM.createHtmlElement('div', { |
|
38 |
'class': 'sidebar', |
|
39 |
'id': 'sidebar', |
|
40 |
}); |
|
41 |
|
|
42 |
var sidebarNav = DOM.createHtmlElement('nav', { |
|
43 |
'class': 'sidebar-navbar', |
|
44 |
'id': 'uploadMenu', |
|
45 |
}); |
|
46 |
rootElement.appendChild(sidebarNav); |
|
47 |
|
|
48 |
// unconnected |
|
49 |
var unconnectedButton = DOM.createHtmlElement('button', { |
|
50 |
'class': 'button', |
|
51 |
'id': 'unconnectedButton', |
|
52 |
'title': 'Unconnected vertices', |
|
53 |
}); |
|
54 |
unconnectedButton.appendChild(DOM.createHtmlElement('img', { |
|
55 |
'src': 'images/tochange/unconnected.gif', |
|
56 |
'alt': 'Icon of "toggle unconnected vertices list" action', |
|
57 |
})); |
|
58 |
unconnectedButton.appendChild(DOM.createTextElement('Unconnected vertices')); |
|
59 |
unconnectedButton.addEventListener('click', function() { |
|
60 |
document.getElementById('unconnectedNodeListComponent').classList.toggle('hidden'); |
|
61 |
app.redrawEdges(); |
|
62 |
}); |
|
63 |
sidebarNav.appendChild(unconnectedButton); |
|
64 |
|
|
65 |
|
|
66 |
var sidebarContainer = DOM.createHtmlElement('div', { |
|
67 |
'class': 'sidebar-container', |
|
68 |
}); |
|
69 |
rootElement.appendChild(sidebarContainer); |
|
70 |
|
|
71 |
// unconnected components |
|
72 |
this.unconnectedNodeListComponent = new SidebarUnconnectedNodeList({ |
|
73 |
'id': 'unconnectedNodeListComponent', |
|
74 |
'class': 'hidden', |
|
75 |
}); |
|
76 |
sidebarContainer.appendChild(this.unconnectedNodeListComponent.render()); |
|
77 |
|
|
78 |
// excluded nodes |
|
79 |
this.excludedNodeListComponent = new SidebarExcludedNodeList({ |
|
80 |
'id': 'excludedNodeListComponent', |
|
81 |
}); |
|
82 |
rootElement.appendChild(this.excludedNodeListComponent.render()); |
|
83 |
|
|
84 |
|
|
85 |
var sidebarBottom = DOM.createHtmlElement('div', { |
|
86 |
'class': 'sidebar-bottom', |
|
87 |
}); |
|
88 |
rootElement.appendChild(sidebarBottom); |
|
89 |
|
|
90 |
// minimap |
|
91 |
this.minimapComponent = new Minimap('#graph'); |
|
92 |
sidebarBottom.appendChild(this.minimapComponent.render()); |
|
93 |
|
|
94 |
// status bar |
|
1 |
class Sidebar { |
|
2 |
/** |
|
3 |
* @constructor |
|
4 |
*/ |
|
5 |
constructor() { |
|
6 |
/** @prop {SidebarUnconnectedNodeList} unconnectedNodeListComponent */ |
|
7 |
this.unconnectedNodeListComponent = new SidebarUnconnectedNodeList; |
|
8 |
/** @prop {SidebarExcludedNodeList} excludedNodeListComponent */ |
|
9 |
this.excludedNodeListComponent = new SidebarExcludedNodeList; |
|
10 |
/** @prop {Minimap} minimapComponent */ |
|
11 |
this.minimapComponent = new Minimap; |
|
12 |
/** @prop {StatusBar} statusBarComponent */ |
|
95 | 13 |
this.statusBarComponent = new StatusBar; |
96 |
sidebarBottom.appendChild(this.statusBarComponent.render()); |
|
97 |
|
|
98 |
return rootElement; |
|
99 |
}; |
|
100 |
|
|
101 |
this.reset = function() { |
|
14 |
} |
|
15 |
|
|
16 |
render() { |
|
17 |
this._rootElement = DOM.h('div', { |
|
18 |
class: 'sidebar', |
|
19 |
id: 'sidebar', |
|
20 |
}, [ |
|
21 |
DOM.h('nav', { |
|
22 |
class: 'sidebar-navbar', |
|
23 |
id: 'uploadMenu', |
|
24 |
}, [ |
|
25 |
// toggle unconnected list button |
|
26 |
DOM.h('button', { |
|
27 |
class: 'button', |
|
28 |
id: 'unconnectedButton', |
|
29 |
title: 'Unconnected nodes', |
|
30 |
innerText: 'Unconnected nodes', |
|
31 |
onClick: () => { |
|
32 |
this.unconnectedNodeListComponent.toggle(); |
|
33 |
app.redrawEdges(); |
|
34 |
}, |
|
35 |
}, [ |
|
36 |
DOM.h('img', { |
|
37 |
src: 'images/tochange/unconnected.gif', |
|
38 |
alt: 'Icon of "toggle unconnected nodes list" action', |
|
39 |
}), |
|
40 |
]), |
|
41 |
]), |
|
42 |
DOM.h('div', { |
|
43 |
class: 'sidebar-container', |
|
44 |
}, [ |
|
45 |
this.unconnectedNodeListComponent.render(), |
|
46 |
]), |
|
47 |
this.excludedNodeListComponent.render(), |
|
48 |
DOM.h('div', { |
|
49 |
class: 'sidebar-bottom', |
|
50 |
}, [ |
|
51 |
this.minimapComponent.render(), |
|
52 |
this.statusBarComponent.render(), |
|
53 |
]), |
|
54 |
]); |
|
55 |
|
|
56 |
return this._rootElement; |
|
57 |
} |
|
58 |
|
|
59 |
reset() { |
|
102 | 60 |
// reset lists |
103 | 61 |
this.unconnectedNodeListComponent.reset(); |
104 | 62 |
this.excludedNodeListComponent.reset(); |
105 | 63 |
|
106 | 64 |
// reset status bar |
107 | 65 |
this.statusBarComponent.reset(); |
108 |
};
|
|
66 |
} |
|
109 | 67 |
} |
sources/src/main/webapp/js/components/sidebarExcludedNodeList.js | ||
---|---|---|
2 | 2 |
* @constructor |
3 | 3 |
* @param {object} props Properties of the node list. |
4 | 4 |
*/ |
5 |
function SidebarExcludedNodeList(props) { |
|
6 |
/** @prop {string} id Identifier of the component. */ |
|
7 |
this.id = props.id; |
|
8 |
|
|
9 |
var rootElement; |
|
10 |
var buttonGroup; |
|
11 |
var sortListElement; |
|
12 |
var nodeListElement; |
|
13 |
|
|
14 |
var nodeList = []; |
|
15 |
|
|
16 |
this.getNodeList = function() { |
|
17 |
return nodeList; |
|
18 |
}; |
|
19 |
|
|
20 |
this.add = function(node) { |
|
21 |
if (!(node instanceof Node)) { |
|
22 |
throw new TypeError(node.toString() + ' is not an instance of Node'); |
|
23 |
} |
|
24 |
|
|
25 |
// set remove hook |
|
26 |
node.removeFromSidebarList = this.remove.bind(this, node); |
|
27 |
|
|
28 |
nodeList.push(node); |
|
29 |
nodeListElement.appendChild(node.render()); |
|
30 |
|
|
31 |
app.redrawEdges(); |
|
32 |
|
|
33 |
toggleControls.call(this); |
|
34 |
}; |
|
35 |
|
|
36 |
this.remove = function(node) { |
|
37 |
if (!(node instanceof Node)) { |
|
38 |
throw new TypeError(node.toString() + ' is not an instance of Node'); |
|
39 |
} |
|
40 |
|
|
41 |
// unset remove hook |
|
42 |
node.removeFromSidebarList = Utils.noop; |
|
43 |
|
|
44 |
nodeList.splice(nodeList.indexOf(node), 1); |
|
45 |
node.remove(false); |
|
46 |
|
|
47 |
app.redrawEdges(); |
|
48 |
|
|
49 |
toggleControls.call(this); |
|
50 |
}; |
|
51 |
|
|
52 |
this.render = function() { |
|
53 |
rootElement = DOM.createHtmlElement('div', { |
|
54 |
'id': props.id, |
|
55 |
'class': 'node-container excluded-nodes ' + (props.class ? props.class : ''), |
|
56 |
}); |
|
57 |
rootElement.addEventListener('scroll', function() { |
|
58 |
app.redrawEdges(); |
|
59 |
}); |
|
60 |
|
|
61 |
// title |
|
62 |
rootElement.appendChild(DOM.htmlStringToElement('<h2 class="node-container-title">Excluded components</h2>')); |
|
63 |
|
|
64 |
// buttons |
|
65 |
buttonGroup = DOM.createHtmlElement('div', { |
|
66 |
'class': 'button-group hidden', |
|
67 |
}); |
|
68 |
rootElement.appendChild(buttonGroup); |
|
69 |
|
|
70 |
// include all button |
|
71 |
var includeAllButton = DOM.createHtmlElement('button', { |
|
72 |
'class': 'include-all-button button', |
|
73 |
'title': 'Display all excluded nodes in viewport', |
|
74 |
}); |
|
75 |
includeAllButton.appendChild(DOM.createHtmlElement('img', { |
|
76 |
'src': 'images/button_cancel.png', |
|
77 |
'alt': 'Icon of "display all excluded nodes in viewport" action', |
|
78 |
})); |
|
79 |
includeAllButton.addEventListener('click', includeAll.bind(this)); |
|
80 |
buttonGroup.appendChild(includeAllButton); |
|
81 |
|
|
82 |
// sorting options |
|
83 |
sortListElement = DOM.createHtmlElement('ul', { |
|
84 |
'class': 'sort-list hidden', |
|
85 |
}); |
|
86 |
rootElement.appendChild(sortListElement); |
|
87 |
|
|
88 |
var sortByNameAscListItem = DOM.createHtmlElement('li', { |
|
89 |
'class': 'sort-asc', |
|
90 |
}); |
|
91 |
sortByNameAscListItem.appendChild(DOM.createTextElement('name')); |
|
92 |
sortByNameAscListItem.addEventListener('click', sortByName.bind(this, 1)); |
|
93 |
sortListElement.appendChild(sortByNameAscListItem); |
|
94 |
|
|
95 |
var sortByNameDescListItem = DOM.createHtmlElement('li', { |
|
96 |
'class': 'sort-desc', |
|
5 |
class SidebarExcludedNodeList extends SidebarNodeList { |
|
6 |
/** |
|
7 |
* @constructor |
|
8 |
*/ |
|
9 |
constructor() { |
|
10 |
super({ |
|
11 |
title: 'Excluded nodes', |
|
12 |
class: 'node-container excluded-nodes', |
|
13 |
id: '', // TODO: remove as soon as Sidebar is reworked |
|
97 | 14 |
}); |
98 |
sortByNameDescListItem.appendChild(DOM.createTextElement('name')); |
|
99 |
sortByNameDescListItem.addEventListener('click', sortByName.bind(this, -1)); |
|
100 |
sortListElement.appendChild(sortByNameDescListItem); |
|
101 |
|
|
102 |
var sortByCountAscListItem = DOM.createHtmlElement('li', { |
|
103 |
'class': 'sort-asc', |
|
104 |
}); |
|
105 |
sortByCountAscListItem.appendChild(DOM.createTextElement('#components')); |
|
106 |
sortByCountAscListItem.addEventListener('click', sortByCount.bind(this, 1)); |
|
107 |
sortListElement.appendChild(sortByCountAscListItem); |
|
108 |
|
|
109 |
var sortByCountDescListItem = DOM.createHtmlElement('li', { |
|
110 |
'class': 'sort-desc', |
|
111 |
}); |
|
112 |
sortByCountDescListItem.appendChild(DOM.createTextElement('#components')); |
|
113 |
sortByCountDescListItem.addEventListener('click', sortByCount.bind(this, -1)); |
|
114 |
sortListElement.appendChild(sortByCountDescListItem); |
|
115 |
|
|
116 |
// list |
|
117 |
nodeListElement = DOM.createHtmlElement('ul', { |
|
118 |
'class': 'node-list', |
|
119 |
}); |
|
120 |
rootElement.appendChild(nodeListElement); |
|
121 |
|
|
122 |
return rootElement; |
|
123 |
}; |
|
124 |
|
|
125 |
this.reset = function() { |
|
126 |
nodeList = []; |
|
127 |
|
|
128 |
nodeListElement.innerHTML = ''; |
|
129 |
|
|
130 |
toggleControls.call(this); |
|
131 |
}; |
|
132 |
|
|
133 |
function includeAll() { |
|
134 |
var nodeListCopy = nodeList.slice(0); |
|
135 |
nodeListCopy.forEach(node => { |
|
136 |
node.include(); |
|
137 |
}); |
|
138 |
|
|
139 |
toggleControls.call(this); |
|
140 |
} |
|
141 |
|
|
142 |
function sortByName(sortOrder) { |
|
143 |
nodeList.sort(function(a, b) { |
|
144 |
return sortOrder * a.name.localeCompare(b.name); |
|
145 |
}); |
|
146 |
|
|
147 |
sort.call(this); |
|
148 | 15 |
} |
149 | 16 |
|
150 |
function sortByCount(sortOrder) { |
|
151 |
nodeList.sort(function(a, b) { |
|
152 |
var aCount = (a instanceof Group) ? a.getVertexList().length : 1; |
|
153 |
var bCount = (b instanceof Group) ? b.getVertexList().length : 1; |
|
154 |
|
|
155 |
return sortOrder * (aCount - bCount); |
|
156 |
}); |
|
157 |
|
|
158 |
sort.call(this); |
|
17 |
_renderButtons() { |
|
18 |
return [ |
|
19 |
DOM.h('button', { |
|
20 |
class: 'button include-all-button', |
|
21 |
title: 'Display all excluded nodes in viewport', |
|
22 |
onClick: this._onIncludeAllClick.bind(this), |
|
23 |
}, [ |
|
24 |
DOM.h('img', { |
|
25 |
src: 'images/button_cancel.png', |
|
26 |
alt: 'Icon of "display all excluded nodes in viewport" action', |
|
27 |
}), |
|
28 |
]) |
|
29 |
]; |
|
159 | 30 |
} |
160 | 31 |
|
161 |
function sort() {
|
|
162 |
nodeList.forEach(node => {
|
|
163 |
node.remove(true);
|
|
164 |
nodeListElement.appendChild(node.render());
|
|
32 |
_onIncludeAllClick() {
|
|
33 |
let nodeListCopy = this.nodeList.slice(0);
|
|
34 |
nodeListCopy.forEach(node => {
|
|
35 |
node.include();
|
|
165 | 36 |
}); |
166 |
} |
|
167 | 37 |
|
168 |
function toggleControls() { |
|
169 |
if (nodeList.length > 0) { |
|
170 |
buttonGroup.classList.remove('hidden'); |
|
171 |
sortListElement.classList.remove('hidden'); |
|
172 |
} else { |
|
173 |
buttonGroup.classList.add('hidden'); |
|
174 |
sortListElement.classList.add('hidden'); |
|
175 |
} |
|
38 |
this._toggleControls(); |
|
176 | 39 |
} |
177 | 40 |
} |
sources/src/main/webapp/js/components/sidebarNodeList.js | ||
---|---|---|
1 |
class SidebarNodeList { |
|
2 |
|
|
3 |
constructor(props) { |
|
4 |
this._properties = props; |
|
5 |
|
|
6 |
this._nodeList = []; |
|
7 |
} |
|
8 |
|
|
9 |
get nodeList() { |
|
10 |
return this._nodeList; |
|
11 |
} |
|
12 |
|
|
13 |
addNode(node) { |
|
14 |
if (!(node instanceof Node)) { |
|
15 |
throw new TypeError(node.toString() + ' is not an instance of Node'); |
|
16 |
} |
|
17 |
|
|
18 |
// set remove hook |
|
19 |
node.removeFromSidebarList = this.removeNode.bind(this, node); |
|
20 |
|
|
21 |
this._nodeList.push(node); |
|
22 |
this._nodeListElement.appendChild(node.render()); |
|
23 |
|
|
24 |
app.redrawEdges(); |
|
25 |
this._toggleControls(); |
|
26 |
} |
|
27 |
|
|
28 |
removeNode(node) { |
|
29 |
if (!(node instanceof Node)) { |
|
30 |
throw new TypeError(node.toString() + ' is not an instance of Node'); |
|
31 |
} |
|
32 |
|
|
33 |
// unset remove hook |
|
34 |
node.removeFromSidebarList = Utils.noop; |
|
35 |
|
|
36 |
this._nodeList.splice(this._nodeList.indexOf(node), 1); |
|
37 |
|
|
38 |
node.remove(false); |
|
39 |
|
|
40 |
app.redrawEdges(); |
|
41 |
this._toggleControls(); |
|
42 |
} |
|
43 |
|
|
44 |
render() { |
|
45 |
// buttons |
|
46 |
this._buttonGroupElement = DOM.h('div', { |
|
47 |
class: 'button-group', |
|
48 |
hidden: 'hidden', |
|
49 |
}, this._renderButtons()); |
|
50 |
|
|
51 |
// sorting options |
|
52 |
this._sortOptionsElement = DOM.h('ul', { |
|
53 |
class: 'sort-list', |
|
54 |
hidden: 'hidden', |
|
55 |
}, [ |
|
56 |
DOM.h('li', { |
|
57 |
class: 'sort-asc', |
|
58 |
innerText: 'name', |
|
59 |
onClick: this._sortByName.bind(this, 1), |
|
60 |
}), |
|
61 |
DOM.h('li', { |
|
62 |
class: 'sort-desc', |
|
63 |
innerText: 'name', |
|
64 |
onClick: this._sortByName.bind(this, -1), |
|
65 |
}), |
|
66 |
DOM.h('li', { |
|
67 |
class: 'sort-asc', |
|
68 |
innerText: '#components', |
|
69 |
onClick: this._sortByCount.bind(this, 1), |
|
70 |
}), |
|
71 |
DOM.h('li', { |
|
72 |
class: 'sort-desc', |
|
73 |
innerText: '#components', |
|
74 |
onClick: this._sortByCount.bind(this, -1), |
|
75 |
}), |
|
76 |
]); |
|
77 |
|
|
78 |
// node list |
|
79 |
this._nodeListElement = DOM.h('ul', { |
|
80 |
class: 'node-list', |
|
81 |
}); |
|
82 |
|
|
83 |
// root |
|
84 |
this._rootElement = DOM.h('div', { |
|
85 |
class: this._properties.class, |
|
86 |
id: this._properties.id, |
|
87 |
onScroll: () => app.redrawEdges(), |
|
88 |
}, [ |
|
89 |
// title |
|
90 |
DOM.h('h2', { |
|
91 |
class: 'node-container-title', |
|
92 |
innerText: this._properties.title, |
|
93 |
}), |
|
94 |
this._buttonGroupElement, |
|
95 |
this._sortOptionsElement, |
|
96 |
this._nodeListElement, |
|
97 |
]); |
|
98 |
|
|
99 |
return this._rootElement; |
|
100 |
} |
|
101 |
|
|
102 |
reset() { |
|
103 |
this._nodeList = []; |
|
104 |
this._nodeListElement.innerHTML = ''; |
|
105 |
|
|
106 |
this.toggleControls(); |
|
107 |
} |
|
108 |
|
|
109 |
_sortByName(sortOrder) { |
|
110 |
this._nodeList.sort((a, b) => { |
|
111 |
return sortOrder * a.name.localeCompare(b.name); |
|
112 |
}); |
|
113 |
|
|
114 |
this._sort(); |
|
115 |
} |
|
116 |
|
|
117 |
_sortByCount(sortOrder) { |
|
118 |
nodeList.sort((a, b) => { |
|
119 |
var aCount = (a instanceof Group) ? a.countVertices : 1; |
|
120 |
var bCount = (b instanceof Group) ? b.countVertices : 1; |
|
121 |
|
|
122 |
return sortOrder * (aCount - bCount); |
|
123 |
}); |
|
124 |
|
|
125 |
this._sort(); |
|
126 |
} |
|
127 |
|
|
128 |
_sort() { |
|
129 |
this._nodeList.forEach(node => { |
|
130 |
node.remove(true); |
|
131 |
this._nodeListElement.appendChild(node.render()); |
|
132 |
}); |
|
133 |
} |
|
134 |
|
|
135 |
_renderButtons() { |
|
136 |
throw new AbstractMethodError; |
|
137 |
} |
|
138 |
|
|
139 |
_displayControls() { |
|
140 |
this._buttonGroupElement.removeAttribute('hidden'); |
|
141 |
this._sortOptionsElement.removeAttribute('hidden'); |
|
142 |
} |
|
143 |
|
|
144 |
_hideControls() { |
|
145 |
this._buttonGroupElement.setAttribute('hidden', 'hidden'); |
|
146 |
this._sortOptionsElement.setAttribute('hidden', 'hidden'); |
|
147 |
} |
|
148 |
|
|
149 |
_toggleControls() { |
|
150 |
if (this._nodeList.length > 0) { |
|
151 |
this._displayControls(); |
|
152 |
} else { |
|
153 |
this._hideControls(); |
|
154 |
} |
|
155 |
} |
|
156 |
} |
sources/src/main/webapp/js/components/sidebarUnconnectedNodeList.js | ||
---|---|---|
1 |
/** |
|
2 |
* @constructor |
|
3 |
* @param {object} props Properties of the node list. |
|
4 |
*/ |
|
5 |
function SidebarUnconnectedNodeList(props) { |
|
6 |
/** @prop {string} id Identifier of the component. */ |
|
7 |
this.id = props.id; |
|
8 |
|
|
9 |
var rootElement; |
|
10 |
var buttonGroup; |
|
11 |
var nodeListElement; |
|
12 |
|
|
13 |
var nodeList = []; |
|
14 |
|
|
15 |
this.getNodeList = function() { |
|
16 |
return nodeList; |
|
17 |
}; |
|
18 |
|
|
19 |
this.add = function(node) { |
|
20 |
if (!(node instanceof Vertex)) { |
|
21 |
throw new TypeError(node.toString() + ' is not an instance of Vertex'); |
|
22 |
} |
|
23 |
|
|
24 |
// set remove hook |
|
25 |
node.removeFromSidebarList = this.remove.bind(this, node); |
|
26 |
|
|
27 |
nodeList.push(node); |
|
28 |
nodeListElement.appendChild(node.render()); |
|
29 |
|
|
30 |
app.redrawEdges(); |
|
31 |
}; |
|
32 |
|
|
33 |
this.remove = function(node) { |
|
34 |
if (!(node instanceof Vertex)) { |
|
35 |
throw new TypeError(node.toString() + ' is not an instance of Vertex'); |
|
36 |
} |
|
37 |
|
|
38 |
// unset remove hook |
|
39 |
node.removeFromSidebarList = Utils.noop; |
|
40 |
|
|
41 |
nodeList.splice(nodeList.indexOf(node), 1); |
|
42 |
|
|
43 |
node.remove(false); |
|
44 |
|
|
45 |
app.redrawEdges(); |
|
46 |
}; |
|
47 |
|
|
48 |
this.render = function() { |
|
49 |
rootElement = DOM.createHtmlElement('div', { |
|
50 |
'id': props.id, |
|
51 |
'class': 'node-container unconnected-nodes ' + (props.class ? props.class : ''), |
|
1 |
class SidebarUnconnectedNodeList extends SidebarNodeList { |
|
2 |
/** |
|
3 |
* @constructor |
|
4 |
*/ |
|
5 |
constructor() { |
|
6 |
super({ |
|
7 |
title: 'Unconnected vertices', |
|
8 |
class: 'node-container unconnected-nodes', |
|
9 |
id: 'unconnectedNodeListComponent', |
|
10 |
hidden: 'hidden', |
|
52 | 11 |
}); |
53 |
rootElement.addEventListener('scroll', function() { |
|
54 |
app.redrawEdges(); |
|
55 |
}); |
|
56 |
|
|
57 |
// title |
|
58 |
rootElement.appendChild(DOM.htmlStringToElement('<h2 class="node-container-title">Unconnected vertices</h2>')); |
|
59 |
|
|
60 |
// buttons |
|
61 |
buttonGroup = DOM.createHtmlElement('div', { |
|
62 |
'class': 'button-group', |
|
63 |
}); |
|
64 |
rootElement.appendChild(buttonGroup); |
|
65 |
|
|
66 |
// include all button |
|
67 |
var includeAllButton = DOM.createHtmlElement('button', { |
|
68 |
'class': 'include-all-button button', |
|
69 |
'title': 'Display all unconnected nodes in viewport', |
|
70 |
}); |
|
71 |
includeAllButton.appendChild(DOM.createHtmlElement('img', { |
|
72 |
'src': 'images/unconnected/uncon_left.png', |
|
73 |
'alt': 'Icon of "display all unconnected nodes in viewport" action', |
|
74 |
})); |
|
75 |
includeAllButton.addEventListener('click', includeAll.bind(this)); |
|
76 |
buttonGroup.appendChild(includeAllButton); |
|
12 |
} |
|
77 | 13 |
|
78 |
// exclude all button |
|
79 |
var excludeAllButton = DOM.createHtmlElement('button', { |
|
80 |
'class': 'exclude-all-button button', |
|
81 |
'title': 'Display all unconnected nodes in sidebar', |
|
82 |
}); |
|
83 |
excludeAllButton.appendChild(DOM.createHtmlElement('img', { |
|
84 |
'src': 'images/unconnected/uncon_right.png', |
|
85 |
'alt': 'Icon of "display all unconnected nodes in sidebar" action', |
|
86 |
})); |
|
87 |
excludeAllButton.addEventListener('click', excludeAll.bind(this)); |
|
88 |
buttonGroup.appendChild(excludeAllButton); |
|
14 |
render() { |
|
15 |
this._rootElement = super.render(); |
|
16 |
this._displayControls(); |
|
89 | 17 |
|
90 |
// list |
|
91 |
nodeListElement = DOM.createHtmlElement('ul', { |
|
92 |
'class': 'node-list', |
|
93 |
}); |
|
94 |
rootElement.appendChild(nodeListElement); |
|
18 |
return this._rootElement; |
|
19 |
} |
|
95 | 20 |
|
96 |
return rootElement; |
|
97 |
}; |
|
21 |
toggle() { |
|
22 |
if (this._rootElement.hasAttribute('hidden')) { |
|
23 |
this._rootElement.removeAttribute('hidden'); |
|
24 |
} else { |
|
25 |
this._rootElement.setAttribute('hidden', 'hidden'); |
|
26 |
} |
|
27 |
} |
|
98 | 28 |
|
99 |
this.reset = function() { |
|
100 |
nodeList = []; |
|
29 |
_renderButtons() { |
|
30 |
return [ |
|
31 |
// include all button |
|
32 |
DOM.h('button', { |
|
33 |
class: 'button include-all-button', |
|
34 |
title: 'Display all unconnected nodes in viewport', |
|
35 |
onClick: this._onIncludeAllClick.bind(this), |
|
36 |
}, [ |
|
37 |
DOM.h('img', { |
|
38 |
src: 'images/unconnected/uncon_left.png', |
|
39 |
alt: 'Icon of "display all unconnected nodes in viewport" action', |
|
40 |
}), |
|
41 |
]), |
|
42 |
// exclude all button |
|
43 |
DOM.h('button', { |
|
44 |
class: 'exclude-all-button button', |
|
45 |
title: 'Display all unconnected nodes in sidebar', |
|
46 |
onClick: this._onExcludeAllClick.bind(this), |
|
47 |
}, [ |
|
48 |
DOM.h('img', { |
|
49 |
src: 'images/unconnected/uncon_right.png', |
|
50 |
alt: 'Icon of "display all unconnected nodes in sidebar" action', |
|
51 |
}) |
|
52 |
]), |
|
53 |
]; |
|
54 |
} |
|
101 | 55 |
|
102 |
nodeListElement.innerHTML = ''; |
|
103 |
}; |
|
56 |
_toggleControls() { |
|
57 |
// do nothing |
|
58 |
} |
|
104 | 59 |
|
105 |
function includeAll() {
|
|
106 |
var nodeListCopy = nodeList.slice(0);
|
|
60 |
_onIncludeAllClick() {
|
|
61 |
let nodeListCopy = this.nodeList.slice(0);
|
|
107 | 62 |
nodeListCopy.forEach(node => { |
108 | 63 |
node.include(); |
109 | 64 |
}); |
110 | 65 |
} |
111 | 66 |
|
112 |
function excludeAll() {
|
|
67 |
_onExcludeAllClick() {
|
|
113 | 68 |
app.vertexList.filter(vertex => { |
114 | 69 |
return vertex.isUnconnected; |
115 | 70 |
}).forEach(vertex => { |
116 | 71 |
vertex.exclude(); |
117 |
this.add(vertex); |
|
72 |
this.addNode(vertex);
|
|
118 | 73 |
}); |
119 | 74 |
} |
120 | 75 |
} |
sources/src/main/webapp/js/components/vertex.js | ||
---|---|---|
133 | 133 |
this._group = newValue; |
134 | 134 |
|
135 | 135 |
if (newValue && this.isExcluded) { |
136 |
// remove floater
|
|
137 |
app.sidebarComponent.removeFloater(this._proxy);
|
|
136 |
// remove proxy
|
|
137 |
app.proxyList.splice(app.proxyList.indexOf(proxy), 1);
|
|
138 | 138 |
this._proxy = null; |
139 | 139 |
} |
140 | 140 |
} |
... | ... | |
400 | 400 |
_onNodeContextMenu(e) { |
401 | 401 |
e.preventDefault(); |
402 | 402 |
|
403 |
let excludedNodeList = app.sidebarComponent.excludedNodeListComponent.getNodeList();
|
|
403 |
let excludedNodeList = app.sidebarComponent.excludedNodeListComponent.nodeList;
|
|
404 | 404 |
let includedGroupList = app.viewportComponent.groupList; |
405 | 405 |
|
406 | 406 |
let nodeList = [].concat(excludedNodeList, includedGroupList); |
sources/src/main/webapp/js/components/vertexContextMenuList.js | ||
---|---|---|
108 | 108 |
app.nodeList.push(group); |
109 | 109 |
app.groupList.push(group); |
110 | 110 |
|
111 |
app.sidebarComponent.excludedNodeListComponent.add(group); |
|
112 |
app.sidebarComponent.excludedNodeListComponent.remove(node); |
|
111 |
app.sidebarComponent.excludedNodeListComponent.addNode(group);
|
|
112 |
app.sidebarComponent.excludedNodeListComponent.removeNode(node);
|
|
113 | 113 |
|
114 | 114 |
node.remove(true); |
115 | 115 |
|
sources/src/main/webapp/js/services/graphExporter.js | ||
---|---|---|
4 | 4 |
*/ |
5 | 5 |
run() { |
6 | 6 |
// nodes excluded to the sidebar |
7 |
let excludedNodeList = app.sidebarComponent.excludedNodeListComponent.getNodeList();
|
|
7 |
let excludedNodeList = app.sidebarComponent.excludedNodeListComponent.nodeList;
|
|
8 | 8 |
let sideBar = excludedNodeList.map(node => { |
9 | 9 |
return { |
10 | 10 |
id: Utils.getUniqueId(node), |
sources/src/main/webapp/js/services/graphLoader.js | ||
---|---|---|
117 | 117 |
return vertex.isUnconnected; |
118 | 118 |
}).forEach(vertex => { |
119 | 119 |
vertex.exclude(); |
120 |
app.sidebarComponent.unconnectedNodeListComponent.add(vertex); |
|
120 |
app.sidebarComponent.unconnectedNodeListComponent.addNode(vertex);
|
|
121 | 121 |
}); |
122 | 122 |
|
123 | 123 |
// construct groups |
... | ... | |
175 | 175 |
if (Utils.isDefined(node)) { |
176 | 176 |
node.exclude(); |
177 | 177 |
|
178 |
app.sidebarComponent.excludedNodeListComponent.add(node); |
|
178 |
app.sidebarComponent.excludedNodeListComponent.addNode(node);
|
|
179 | 179 |
} |
180 | 180 |
}); |
181 | 181 |
|
sources/src/main/webapp/js/showGraphApp.js | ||
---|---|---|
25 | 25 |
this.vertexList = []; |
26 | 26 |
/** @prop {array<Group>} groupList */ |
27 | 27 |
this.groupList = []; |
28 |
/** @prop {array<NodeProxy>} proxyList */ |
|
29 |
this.proxyList = []; |
|
28 | 30 |
|
29 | 31 |
/** @prop {Diagram} diagram */ |
30 | 32 |
this.diagram = null; |
... | ... | |
63 | 65 |
this.nodeList = []; |
64 | 66 |
this.vertexList = []; |
65 | 67 |
this.groupList = []; |
68 |
this.proxyList = []; |
|
66 | 69 |
} |
67 | 70 |
|
68 | 71 |
/** |
... | ... | |
78 | 81 |
* Redraws edges leading from viewport to sidebar. |
79 | 82 |
*/ |
80 | 83 |
redrawEdges() { |
81 |
this.sidebarComponent.refreshFloaters(); |
|
84 |
this.proxyList.forEach(proxy => { |
|
85 |
proxy.updatePosition(); |
|
86 |
}); |
|
82 | 87 |
} |
83 | 88 |
|
84 | 89 |
/** |
sources/src/main/webapp/showGraph.jsp | ||
---|---|---|
54 | 54 |
<script src="js/components/registerPopup.js"></script> |
55 | 55 |
<script src="js/components/saveDiagramModalWindow.js"></script> |
56 | 56 |
<script src="js/components/sidebar.js"></script> |
57 |
<script src="js/components/sidebarNodeList.js"></script> |
|
57 | 58 |
<script src="js/components/sidebarExcludedNodeList.js"></script> |
58 | 59 |
<script src="js/components/sidebarUnconnectedNodeList.js"></script> |
59 | 60 |
<script src="js/components/spinLoader.js" type="module"></script> |
Také k dispozici: Unified diff
reworked Sidebar and its lists to ES6 classes