Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 046703c1

Přidáno uživatelem Pavel Fidranský před více než 6 roky(ů)

created Header and Navbar JS classes

Zobrazit rozdíly:

sources/src/main/webapp/js/components/header.js
1
class Header {
2
	constructor() {
3
		document.addEventListener(LoggedInEvent.name, e => {
4
			this._loggedInUserLabel.innerText = e.detail.username;
5
		});
6

  
7
		document.addEventListener(LoggedOutEvent.name, () => {
8
			this._loggedInUserLabel.innerText = '';
9
		});
10
	}
11

  
12
	render() {
13
		this._loggedInUserLabel = DOM.h('span', {
14
			class: 'username',
15
		});
16
		this._loginPopup = new LoginPopup;
17
		this._registerPopup = new RegisterPopup;
18

  
19
		this._rootElement = DOM.h('div', {
20
			class: 'header',
21
		}, [
22
			DOM.h('img', {
23
				src: 'images/logo.png',
24
				class: 'header-logo',
25
				alt: 'logo of University of West Bohemia',
26
				title: 'University of West Bohemia',
27
			}),
28
			DOM.h('h2', {
29
				class: 'header-title',
30
				innerText: 'Interactive Multimodal Graph Explorer',
31
			}),
32
			DOM.h('div', {
33
				class: 'user-menu loggedInOnly',
34
			}, [
35
				this._loggedInUserLabel,
36
				DOM.h('a', {
37
					href: Constants.API.logOut,
38
					class: 'button',
39
					innerText: 'Log out',
40
					onClick: this._onLogoutButtonClick.bind(this),
41
				}),
42
			]),
43
			DOM.h('div', {
44
				class: 'user-menu loggedOutOnly',
45
			}, [
46
				DOM.h('button', {
47
					class: 'button',
48
					innerText: 'Log in',
49
					onClick: () => {
50
						this._registerPopup.close();
51
						this._loginPopup.toggle();
52
					},
53
				}),
54
				DOM.h('button', {
55
					class: 'button',
56
					innerText: 'Register',
57
					onClick: () => {
58
						this._loginPopup.close();
59
						this._registerPopup.toggle();
60
					},
61
				}),
62
			]),
63
			this._loginPopup.render(),
64
			this._registerPopup.render(),
65
		]);
66

  
67
		return this._rootElement;
68
	}
69

  
70
	get height() {
71
		return this._rootElement.offsetHeight;
72
	}
73

  
74
	async _onLogoutButtonClick(e) {
75
		e.preventDefault();
76

  
77
		try {
78
			await AJAX.get(e.target.href);
79

  
80
			document.dispatchEvent(new LoggedOutEvent);
81

  
82
			document.body.classList.remove('loggedIn');
83
			document.body.classList.add('loggedOut');
84

  
85
		} catch (error) {
86
			alert('Something went wrong. Check console for more details.');
87
			console.error(error);
88
	}
89
	}
90
}
sources/src/main/webapp/js/components/navbar.js
1
class Navbar {
2

  
3
	render() {
4
		this._rootElement = DOM.h('nav', {
5
			class: 'navbar',
6
		});
7

  
8
		// list of buttons
9
		this._rootElement.appendChild(DOM.h('ul', {}, [
10
			this._createZoomListItem(),
11
			this._createSeparatorListItem(),
12

  
13
			this._createSearchListItem(),
14
			this._createSeparatorListItem(),
15

  
16
			this._createSwitchModeListItem(),
17
			this._createSeparatorListItem(),
18

  
19
			this._createExcludeNodeWithMostEdgesListItem(),
20
			this._createSeparatorListItem(),
21

  
22
			this._createExcludeNodeWithMostEdgesToGroupListItem(),
23
			this._createSeparatorListItem(),
24

  
25
			this._createBackToUploadListItem(),
26
			this._createSeparatorListItem(),
27

  
28
			this._createApplyLayoutListItem(),
29
			this._createSeparatorListItem(),
30

  
31
			this._createSaveDiagramAsPNGListItem(),
32
			this._createSeparatorListItem(true),
33

  
34
			this._createSaveDiagramListItem(),
35
			this._createSeparatorListItem(),
36

  
37
			this._createRefreshDiagramListItem(),
38
			this._createSeparatorListItem(),
39

  
40
			this._createResetDiagramListItem(),
41
		]));
42

  
43
		return this._rootElement;
44
	}
45

  
46
	get height() {
47
		return this._rootElement.offsetHeight;
48
	}
49

  
50
	_createSeparatorListItem(loggedInOnly = false) {
51
		return DOM.h('li', {
52
			class: loggedInOnly ? 'loggedInOnly' : '',
53
		}, [
54
			DOM.h('hr', {
55
				class: 'navbar-separator',
56
			}),
57
		]);
58
	}
59

  
60
	_createZoomListItem() {
61
		return DOM.h('li', {}, [
62
			DOM.h('button', {
63
				class: 'btn zoom',
64
				id: 'zoomOut',
65
				title: 'zoom -',
66
				onClick: () => app.zoom.zoomOut(),
67
			}, [
68
				DOM.h('img', {
69
					src: 'images/zoom_out.png',
70
					alt: 'zoom -',
71
				}),
72
			]),
73
			DOM.h('span', {
74
				class: 'zoom-value',
75
				id: 'zoomValue',
76
				innerText: '',
77
			}),
78
			DOM.h('button', {
79
				class: 'btn zoom',
80
				id: 'zoomIn',
81
				title: 'zoom +',
82
				onClick: () => app.zoom.zoomIn(),
83
			}, [
84
				DOM.h('img', {
85
					src: 'images/zoom_in.png',
86
					alt: 'zoom +',
87
				}),
88
			])
89
		]);
90
	}
91

  
92
	_createSearchListItem() {
93
		let searchInput = DOM.h('input', {
94
			type: 'search',
95
			placeholder: 'Search components...',
96
			class: 'search-text',
97
			id: 'searchText',
98
			onKeyUp: e => {
99
				switch (e.keyCode) {
100
					// enter key
101
					case 13:
102
						search(e.target.value);
103
						break;
104

  
105
					// escape key
106
					case 27:
107
						resetSearch();
108
						break;
109
				}
110
			},
111
		});
112

  
113
		let searchButton = DOM.h('button', {
114
			class: 'btn search',
115
			id: 'searchButton',
116
			onClick: () => {
117
				search(searchInput.value);
118
			},
119
		}, [
120
			DOM.h('img', {
121
				src: 'images/search.png',
122
				title: 'search',
123
				alt: 'search',
124
			}),
125
		]);
126

  
127
		let searchCounter = DOM.h('span', {
128
			class: 'search-count',
129
			id: 'searchCount',
130
			title: 'Count of components found',
131
			innerText: 0,
132
			onClick: () => resetSearch(),
133
		});
134

  
135
		function search(term) {
136
			if (term.length < 2) return;
137

  
138
			var found = 0;
139
			
140
			app.viewportComponent.nodeList.forEach(function(node) {
141
				if (node.name.toLowerCase().includes(term.toLowerCase())) {
142
					node.setFound(true);
143
					found++;
144
				} else {
145
					node.setFound(false);
146
				}
147
			});
148

  
149
			searchCounter.innerText = found;
150
		}
151

  
152
		function resetSearch() {
153
			app.viewportComponent.nodeList.forEach(function(node) {
154
				node.setFound(false);
155
			});
156

  
157
			searchInput.value = '';
158
			searchCounter.innerText = 0;
159
		}
160

  
161
		return DOM.h('li', {}, [
162
			searchInput,
163
			searchButton,
164
			searchCounter,
165
		]);
166
	}
167

  
168
	_createSwitchModeListItem() {
169
		return DOM.h('li', {}, [
170
			DOM.h('form', {
171
				name: 'modeForm',
172
			}, [
173
				DOM.h('label', {
174
					for: 'move',
175
				}, [
176
					DOM.h('input', {
177
						type: 'radio',
178
						name: 'mode',
179
						value: 'move',
180
						id: 'move',
181
						checked: 'checked',
182
					}),
183
					DOM.createTextElement('move'),
184
					DOM.h('img', {
185
						src: 'images/move.png',
186
						alt: 'move',
187
						class: 'navbar-image',
188
					}),
189
				]),
190
				DOM.h('label', {
191
					for: 'exclude',
192
				}, [
193
					DOM.h('input', {
194
						type: 'radio',
195
						name: 'mode',
196
						value: 'exclude',
197
						id: 'exclude',
198
					}),
199
					DOM.createTextElement('exclude'),
200
					DOM.h('img', {
201
						src: 'images/remove2.png',
202
						alt: 'exclude',
203
						class: 'navbar-image',
204
					}),
205
				]),
206
			]),
207
		]);
208
	}
209

  
210
	_createExcludeNodeWithMostEdgesListItem() {
211
		return DOM.h('li', {}, [
212
			DOM.h('button', {
213
				class: 'btn exclude-separately',
214
				id: 'mostEdge',
215
				title: 'Exclude components with the most count of edges separately.',
216
				onClick: () => {
217
					var vertexList = app.viewportComponent.getVertexList();
218
					if (vertexList.length === 0) return;
219

  
220
					// find vertex with most edges
221
					var vertexWithMostEdges = vertexList.reduce(function(prev, vertex) {
222
						return vertex.countEdges() > prev.countEdges() ? vertex : prev;
223
					});
224

  
225
					if (vertexWithMostEdges !== null) {
226
						vertexWithMostEdges.exclude();
227
						app.sidebarComponent.excludedNodeListComponent.add(vertexWithMostEdges);
228
					}
229
				},
230
			}, [
231
				DOM.h('img', {
232
					src: 'images/excludeSeparately.png',
233
					alt: 'excludeSeparately',
234
				}),
235
			]),
236
		]);
237
	}
238

  
239
	_createExcludeNodeWithMostEdgesToGroupListItem() {
240
		return DOM.h('li', {}, [
241
			DOM.h('button', {
242
				class: 'btn exclude-to-group',
243
				id: 'vertexToGroup',
244
				title: 'Exclude components with the most count of edges to group.',
245
				onClick: () => {
246
					var vertexList = app.viewportComponent.getVertexList();
247
					if (vertexList.length === 0) return;
248

  
249
					// find vertex with most edges
250
					var vertexWithMostEdges = vertexList.reduce(function(prev, vertex) {
251
						return vertex.countEdges() > prev.countEdges() ? vertex : prev;
252
					});
253

  
254
					// filter vertices with most edges
255
					var verticesWithMostEdges = vertexList.filter(function(vertex) {
256
						return vertex.countEdges() === vertexWithMostEdges.countEdges();
257
					});
258

  
259
					if (verticesWithMostEdges.length > 0) {
260
						var group = new Group({});
261

  
262
						verticesWithMostEdges.forEach(function(vertex) {
263
							group.addVertex(vertex);
264
						});
265

  
266
						app.nodeList.push(group);
267
						app.groupList.push(group);
268

  
269
						app.viewportComponent.addGroup(group);
270
					}
271
				},
272
			}, [
273
				DOM.h('img', {
274
					src: 'images/package.png',
275
					alt: 'Exclude components to group',
276
				}),
277
			]),
278
		]);
279
	}
280

  
281
	_createBackToUploadListItem() {
282
		return DOM.h('li', {}, [
283
			DOM.h('a', {
284
				href: app.HOME_URL,
285
				class: 'btn btn-block back-to-upload',
286
				id: 'backToUpload',
287
				title: 'Back to upload',
288
			}),
289
		]);
290
	}
291

  
292
	_createApplyLayoutListItem() {
293
		let layouting = false;
294
		let layoutingInterval;
295

  
296
		const applyLayoutImg = DOM.h('img', {
297
			src: 'images/layout_off.png',
298
			alt: 'Apply layout to current graph',
299
		});
300

  
301
		return DOM.h('li', {}, [
302
			DOM.h('button', {
303
				class: 'btn',
304
				title: 'Apply layout to current graph',
305
				onClick: () => {
306
					if (layouting) {
307
						applyLayoutImg.setAttribute('src', 'images/layout_off.png');
308
		
309
						layouting = false;
310
						clearInterval(layoutingInterval);
311
		
312
					} else {
313
						applyLayoutImg.setAttribute('src', 'images/layout_on.png');
314

  
315
						layouting = true;
316
						layoutingInterval = window.setInterval(app.viewportComponent.forceDirected.run, 10);
317
					}
318
				},
319
			}, [
320
				applyLayoutImg,
321
			]),
322
		]);
323
	}
324

  
325
	_createSaveDiagramAsPNGListItem() {
326
		return DOM.h('li', {}, [
327
			DOM.h('button', {
328
				class: 'btn save-diagram',
329
				title: 'Save diagram as PNG',
330
				onClick: () => saveSvgAsPng(document.getElementById('svg1'), 'diagram.png', { scale: 1 }),
331
			}, [
332
				DOM.h('img', {
333
					src: 'images/png_save.png',
334
					alt: 'Save diagram as PNG',
335
				}),
336
			]),
337
		]);
338
	}
339

  
340
	_createSaveDiagramListItem() {
341
		return DOM.h('li', {
342
			class: 'loggedInOnly'
343
		}, [
344
			DOM.h('button', {
345
				class: 'btn save-diagram',
346
				title: 'Save diagram',
347
				onClick: () => app.modalWindowComponent.open(),
348
			}, [
349
				DOM.h('img', {
350
					src: 'images/icon_save.png',
351
					alt: 'Save diagram',
352
				}),
353
			]),
354
		]);
355
	}
356

  
357
	_createRefreshDiagramListItem() {
358
		const refreshDiagramLink = DOM.h('a', {
359
			href: location.href,
360
			class: 'btn btn-block view-refresh-diagram',
361
			title: 'Refresh diagram',
362
		});
363

  
364
		document.addEventListener(DiagramUpdatedEvent.name, e => {
365
			refreshDiagramLink.setAttribute('href', app.HOME_URL + 'graph?diagramId=' + e.detail.id);
366
		});
367

  
368
		return DOM.h('li', {}, [
369
			refreshDiagramLink,
370
		]);
371
	}
372

  
373
	_createResetDiagramListItem() {
374
		return DOM.h('li', {}, [
375
			DOM.h('button', {
376
				class: 'btn btn-block view-refresh-reset-diagram',
377
				title: 'Refresh diagram - reset positions',
378
			}),
379
		]);
380
	}
381
}

Také k dispozici: Unified diff