commit edd0c51ecf65749a6a107f239d4ab0d46581172d
Author: Pavel Fidranský <fidransky@outlook.com>
Date:   Mon Oct 22 23:46:24 2018 +0200

    reworked all jQuery-backed AJAX calls to use AJAX JS class

diff --git a/sources/src/main/webapp/js/app.js b/sources/src/main/webapp/js/app.js
index e85caf6..62535be 100644
--- a/sources/src/main/webapp/js/app.js
+++ b/sources/src/main/webapp/js/app.js
@@ -293,49 +293,49 @@ function App() {
 	 * Loads graph data of a diagram.
 	 * @param {string} diagramId Identifier of the diagram to be loaded.
 	 */
-	function loadGraphData(diagramId) {
-		var self = this;
-
-		self.loader.enable();
+	async function loadGraphData(diagramId) {
+		this.loader.enable();
 
-		var loadGraphDataPromise;
+		let loadGraphDataPromise;
 
 		if (diagramId === '') {
-			loadGraphDataPromise = $.getJSON(self.API.loadGraphData);
+			loadGraphDataPromise = AJAX.getJSON(this.API.loadGraphData);
 
 		} else {
-			loadGraphDataPromise = $.getJSON(self.API.getDiagram + '?id=' + diagramId).then(function(data) {
-				self.diagram = new Diagram(data);
+			const diagramData = await AJAX.getJSON(this.API.getDiagram + '?id=' + diagramId);
 
-				document.title = self.NAME + ' - ' + self.diagram.name;
+			this.diagram = new Diagram(diagramData);
 
-				// return graph data as a new promise
-				var deferred = new $.Deferred();
-				deferred.resolve(JSON.parse(data.graph_json));
+			document.title = this.NAME + ' - ' + this.diagram.name;
 
-				return deferred.promise();
-			});
+			loadGraphDataPromise = Promise.resolve(JSON.parse(diagramData.graph_json));
 		}
 
-		// get vertex position data
-		loadGraphDataPromise.then(function(data) {
-			// construct graph
-			self.graphLoader.run(data);
-
-			self.loader.disable();
+		try {
+			// get vertex position data
+			const graphData = await loadGraphDataPromise;
 
-		}, function(xhr) {
-			switch (xhr.status) {
-				case 401:
-					alert('You are not allowed to view the diagram.');
-					break;
-				default:
-					alert('Something went wrong.');
+			// construct graph
+			this.graphLoader.run(graphData);
+
+			this.loader.disable();
+
+		} catch (error) {
+			if (error instanceof HttpError) {
+				switch (error.response.status) {
+					case 401:
+						alert('You are not allowed to view the diagram.');
+						break;
+					default:
+						alert('Something went wrong.');
+				}
+			} else {
+				alert('Server has probably gone away.');
 			}
 
 			// go to the upload page
 			window.location.replace('./');
-		});
+		}
 	}
 
 	/**
diff --git a/sources/src/main/webapp/js/components/modalWindow.js b/sources/src/main/webapp/js/components/modalWindow.js
index b8e19b8..0759ed5 100644
--- a/sources/src/main/webapp/js/components/modalWindow.js
+++ b/sources/src/main/webapp/js/components/modalWindow.js
@@ -69,38 +69,39 @@ function ModalWindow() {
 	 * Saves diagram.
 	 * @param {Event} e Submit event.
 	 */
-	function saveDiagram(e) {
+	async function saveDiagram(e) {
 		e.preventDefault();
 
-		var self = this;
-
-		$.ajax({
-			'type': 'POST',
-			'url': app.API.saveDiagram,
-			'data': {
-				'id': app.diagram === null ? '' : app.diagram.id,
-				'name': e.target.diagramName.value,
-				'graphJson': JSON.stringify(app.graphExporter.run()),
-				'public': (e.target.diagramPublic.checked | 0).toString(),
-			},
-			'success': function(data) {
-				app.diagram = new Diagram(data);
-
-				document.title = app.NAME + ' - ' + app.diagram.name;
-				history.replaceState({} , document.title, app.HOME_URL + 'graph?diagramId=' + app.diagram.id);
-
-				self.close();
-				alert('Diagram was successfully saved.');
-			},
-			'error': function(xhr) {
-				switch (xhr.status) {
+		const body = new URLSearchParams;
+		body.set('id', app.diagram === null ? '' : app.diagram.id);
+		body.set('name', e.target.diagramName.value);
+		body.set('graphJson', JSON.stringify(app.graphExporter.run()));
+		body.set('public', (e.target.diagramPublic.checked | 0).toString());
+
+		try {
+			const response = await AJAX.post(app.API.saveDiagram, body);
+			const data = await response.json();
+
+			app.diagram = new Diagram(data);
+
+			document.title = app.NAME + ' - ' + app.diagram.name;
+			history.replaceState({} , document.title, app.HOME_URL + 'graph?diagramId=' + app.diagram.id);
+
+			this.close();
+			alert('Diagram was successfully saved.');
+
+		} catch (error) {
+			if (error instanceof HttpError) {
+				switch (error.response.status) {
 					case 401:
 						alert('You are either not logged in or not an owner of this diagram.');
 						break;
 					default:
 						alert('Something went wrong.');
 				}
-			},
-		});
+			} else {
+				alert('Server has probably gone away.');
+			}
+		}
 	}
 }
diff --git a/sources/src/main/webapp/js/uploadFiles.js b/sources/src/main/webapp/js/uploadFiles.js
new file mode 100644
index 0000000..50664c0
--- /dev/null
+++ b/sources/src/main/webapp/js/uploadFiles.js
@@ -0,0 +1,76 @@
+document.addEventListener('DOMContentLoaded', function() {
+	var privateDiagramList = document.getElementById('privateDiagramList');
+
+	privateDiagramList.querySelectorAll('.remove-diagram-button').forEach(function(button) {
+		button.addEventListener('click', removeDiagram);
+	});
+
+	document.addEventListener('imiger.userLoggedIn', function() {
+		loadPrivateDiagrams();
+	});
+
+	document.addEventListener('imiger.userLoggedOut', function() {
+		privateDiagramList.innerHTML = '';
+	});
+
+	async function loadPrivateDiagrams() {
+		try {
+			const data = await AJAX.getJSON(Constants.API.getPrivateDiagrams);
+
+			data.forEach(function(diagram) {
+				var openDiagramLink = document.createElement('a');
+				openDiagramLink.setAttribute('href', './graph?diagramId=' + diagram.id);
+				openDiagramLink.innerText = diagram.name;
+
+				var removeDiagramIcon = document.createElement('img');
+				removeDiagramIcon.setAttribute('src', 'images/button_cancel.png');
+				removeDiagramIcon.setAttribute('alt', 'odstranit');
+
+				var removeDiagramButton = document.createElement('button');
+				removeDiagramButton.setAttribute('class', 'remove-diagram-button');
+				removeDiagramButton.setAttribute('data-id', diagram.id);
+				removeDiagramButton.setAttribute('data-name', diagram.name);
+				removeDiagramButton.addEventListener('click', removeDiagram);
+				removeDiagramButton.appendChild(removeDiagramIcon);
+
+				var diagramListItem = document.createElement('li');
+				diagramListItem.appendChild(openDiagramLink);
+				diagramListItem.appendChild(removeDiagramButton);
+
+				privateDiagramList.appendChild(diagramListItem);
+			});
+		} catch (error) {
+			if (error instanceof HttpError) {
+				alert('Something went wrong.');
+			} else {
+				alert('Server has probably gone away.');
+			}
+		}
+	}
+
+	async function removeDiagram() {
+		let diagramId = this.getAttribute('data-id');
+		let diagramName = this.getAttribute('data-name');
+
+		if (confirm('Do you really want to delete ' + diagramName + '?')) {
+			try {
+				await AJAX.delete(Constants.API.removeDiagram + '?diagramId=' + diagramId);
+
+				location.reload(true);
+
+			} catch (error) {
+				if (error instanceof HttpError) {
+					switch (error.response.status) {
+						case 401:
+							alert('You are either not logged in or not an owner of this diagram.');
+							break;
+						default:
+							alert('Something went wrong.');
+					}
+				} else {
+					alert('Server has probably gone away.');
+				}
+			}
+		}
+	}
+});
diff --git a/sources/src/main/webapp/js/userMenu.js b/sources/src/main/webapp/js/userMenu.js
index 916a50e..18dd262 100644
--- a/sources/src/main/webapp/js/userMenu.js
+++ b/sources/src/main/webapp/js/userMenu.js
@@ -24,50 +24,57 @@ document.addEventListener('DOMContentLoaded', function() {
 		registerForm.name.focus();
 	});
 
-	logoutButton.addEventListener('click', function(e) {
+	logoutButton.addEventListener('click', async function(e) {
 		e.preventDefault();
 
-		$.ajax({
-			'type': 'GET',
-			'url': logoutButton.href,
-			'success': function() {
-				document.dispatchEvent(new CustomEvent('imiger.userLoggedOut'));
+		try {
+			await AJAX.get(logoutButton.href);
 
-				usernameLabel.innerText = '';
+			document.dispatchEvent(new CustomEvent('imiger.userLoggedOut'));
 
-				document.body.classList.remove('loggedIn');
-				document.body.classList.add('loggedOut');
-			},
-			'error': function() {
+			usernameLabel.innerText = '';
+
+			document.body.classList.remove('loggedIn');
+			document.body.classList.add('loggedOut');
+
+		} catch (error) {
+			if (error instanceof HttpError) {
 				alert('Something went wrong.');
-			},
-		});
+			} else {
+				alert('Server has probably gone away.');
+			}
+		}
 	});
 
-	loginForm.addEventListener('submit', function(e) {
+	loginForm.addEventListener('submit', async function(e) {
 		e.preventDefault();
 
-		$.ajax({
-			'type': loginForm.method,
-			'url': loginForm.action,
-			'data': {
-				'username': loginForm.username.value,
-				'password': loginForm.password.value,
-			},
-			'success': function(data) {
-				document.dispatchEvent(new CustomEvent('imiger.userLoggedIn'));
-
-				usernameLabel.innerText = data.user.username;
-
-				document.body.classList.remove('loggedOut');
-				document.body.classList.add('loggedIn');
-
-				loginPopup.classList.add('hidden');
-			},
-			'error': function(xhr) {
-				switch (xhr.status) {
+		const body = new URLSearchParams;
+		body.set('username', loginForm.username.value);
+		body.set('password', loginForm.password.value);
+
+		try {
+			const response = await AJAX.do(loginForm.action, {
+				method: loginForm.method,
+				credentials: 'same-origin',
+				body,
+			});
+			const data = await response.json();
+
+			document.dispatchEvent(new CustomEvent('imiger.userLoggedIn'));
+
+			usernameLabel.innerText = data.user.username;
+
+			document.body.classList.remove('loggedOut');
+			document.body.classList.add('loggedIn');
+
+			loginPopup.classList.add('hidden');
+
+		} catch (error) {
+			if (error instanceof HttpError) {
+				switch (error.response.status) {
 					case 400:
-						printErrors(xhr);
+						printErrors(error.response);
 						break;
 					case 401:
 						alert('Invalid credentials.');
@@ -75,47 +82,54 @@ document.addEventListener('DOMContentLoaded', function() {
 					default:
 						alert('Something went wrong.');
 				}
-			},
-		});
+			} else {
+				alert('Server has probably gone away.');
+			}
+		}
 	});
 
-	registerForm.addEventListener('submit', function(e) {
+	registerForm.addEventListener('submit', async function(e) {
 		e.preventDefault();
 
-		$.ajax({
-			'type': registerForm.method,
-			'url': registerForm.action,
-			'data': {
-				'name': registerForm.name.value,
-				'email': registerForm.email.value,
-				'username': registerForm.username.value,
-				'password': registerForm.password.value,
-				'passwordCheck': registerForm.passwordCheck.value,
-			},
-			'success': function() {
-				document.dispatchEvent(new CustomEvent('imiger.userRegistered'));
-
-				registerPopup.classList.add('hidden');
-				alert('You were successfully registered.');
-			},
-			'error': function(xhr) {
-				switch (xhr.status) {
+		const body = new URLSearchParams;
+		body.set('name', registerForm.name.value);
+		body.set('email', registerForm.email.value);
+		body.set('username', registerForm.username.value);
+		body.set('password', registerForm.password.value);
+		body.set('passwordCheck', registerForm.passwordCheck.value);
+
+		try {
+			await AJAX.do(registerForm.action, {
+				method: registerForm.method,
+				credentials: 'same-origin',
+				body,
+			});
+
+			document.dispatchEvent(new CustomEvent('imiger.userRegistered'));
+
+			registerPopup.classList.add('hidden');
+			alert('You were successfully registered.');
+
+		} catch (error) {
+			if (error instanceof HttpError) {
+				switch (error.response.status) {
 					case 400:
-						printErrors(xhr);
+						printErrors(error.response);
 						break;
 					default:
 						alert('Something went wrong.');
 				}
-			},
-		});
+			} else {
+				alert('Server has probably gone away.');
+			}
+		}
 	});
 });
 
-function printErrors(xhr) {
-	var data = JSON.parse(xhr.responseText);
-
-	for (var key in data.error) {
-		if (!data.error.hasOwnProperty(key)) continue;
+async function printErrors(response) {
+	const data = await response.json();
+	for (let key in data.error) {
+		if (data.error.hasOwnProperty(key) === false) continue;
 
 		alert(data.error[key]);
 	}
diff --git a/sources/src/main/webapp/uploadFiles.jsp b/sources/src/main/webapp/uploadFiles.jsp
index bbc08d9..f49bb51 100644
--- a/sources/src/main/webapp/uploadFiles.jsp
+++ b/sources/src/main/webapp/uploadFiles.jsp
@@ -13,6 +13,10 @@
 		<link rel="stylesheet" href="css/main.css">
 
 		<script src="js/libs/jquery-3.3.1.min.js"></script>
+		<script src="js/errors/httpError.js"></script>
+		<script src="js/utils/ajax.js"></script>
+		<script src="js/constants.js"></script>
+		<script src="js/uploadFiles.js"></script>
 		<script src="js/userMenu.js"></script>
 
 		<title>IMiGEr</title>
@@ -58,7 +62,7 @@
 					<c:forEach items="${diagramsPrivate}" var="diagram">
 						<li>
 							<a href="${HOME_URL}graph?diagramId=${diagram.id}">${diagram.name}</a>
-							<button class="removeDiagramButton" data-name="${diagram.name}" data-id="${diagram.id}"><img src="images/button_cancel.png" alt="odstranit"></button>
+							<button class="remove-diagram-button" data-id="${diagram.id}" data-name="${diagram.name}"><img src="images/button_cancel.png" alt="odstranit"></button>
 						</li>
 					</c:forEach>
 				</ul>
@@ -76,60 +80,5 @@
 				</ul>
 			</div>
 		</main>
-
-		<script>
-			var privateDiagramList = document.getElementById('privateDiagramList');
-
-			$(privateDiagramList).on('click', '.removeDiagramButton', function(e) {
-				if (confirm('Do you really want to delete ' + $(this).data('name') + '?')) {
-					$.ajax({
-						'type': 'delete',
-						'url': 'api/remove-diagram?diagramId=' + $(this).data('id'),
-						'success': function () {
-							location.reload(true);
-						},
-						'error': function (xhr) {
-							switch (xhr.status) {
-								case 401:
-									alert('You are either not logged in or not an owner of this diagram.');
-									break;
-								default:
-									alert('Something went wrong.');
-							}
-						},
-					});
-				}
-			});
-
-			document.addEventListener('imiger.userLoggedIn', function() {
-				$.getJSON('api/get-private-diagrams').then(function(data) {
-					data.forEach(function(diagram) {
-						var openDiagramLink = document.createElement('a');
-						openDiagramLink.setAttribute('href', './graph?diagramId=' + diagram.id);
-						openDiagramLink.innerText = diagram.name;
-
-						var removeDiagramIcon = document.createElement('img');
-						removeDiagramIcon.setAttribute('src', 'images/button_cancel.png');
-						removeDiagramIcon.setAttribute('alt', 'odstranit');
-
-						var removeDiagramButton = document.createElement('button');
-						removeDiagramButton.setAttribute('class', 'removeDiagramButton');
-						removeDiagramButton.setAttribute('data-id', diagram.id);
-						removeDiagramButton.setAttribute('data-name', diagram.name);
-						removeDiagramButton.appendChild(removeDiagramIcon);
-
-						var diagramListItem = document.createElement('li');
-						diagramListItem.appendChild(openDiagramLink);
-						diagramListItem.appendChild(removeDiagramButton);
-
-						privateDiagramList.appendChild(diagramListItem);
-					});
-				});
-			});
-
-			document.addEventListener('imiger.userLoggedOut', function() {
-				privateDiagramList.innerHTML = '';
-			});
-		</script>
 	</body>
 </html>
