| 
									
										
										
										
											2020-08-30 12:18:16 +02:00
										 |  |  |  | Grocy.Api = {}; | 
					
						
							| 
									
										
										
										
											2018-04-18 19:03:39 +02:00
										 |  |  |  | Grocy.Api.Get = function(apiFunction, success, error) | 
					
						
							| 
									
										
										
										
											2017-04-15 23:16:20 +02:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	var xhr = new XMLHttpRequest(); | 
					
						
							| 
									
										
										
										
											2018-04-18 19:03:39 +02:00
										 |  |  |  | 	var url = U('/api/' + apiFunction); | 
					
						
							| 
									
										
										
										
											2017-04-15 23:16:20 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	xhr.onreadystatechange = function() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		if (xhr.readyState === XMLHttpRequest.DONE) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-01-19 14:51:51 +01:00
										 |  |  |  | 			if (xhr.status === 200 || xhr.status === 204) | 
					
						
							| 
									
										
										
										
											2017-04-15 23:16:20 +02:00
										 |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				if (success) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2019-01-19 14:51:51 +01:00
										 |  |  |  | 					if (xhr.status === 200) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						success(JSON.parse(xhr.responseText)); | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 					else | 
					
						
							|  |  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2020-08-30 12:18:16 +02:00
										 |  |  |  | 						success({}); | 
					
						
							| 
									
										
										
										
											2019-01-19 14:51:51 +01:00
										 |  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-04-15 23:16:20 +02:00
										 |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			else | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				if (error) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					error(xhr); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	xhr.open('GET', url, true); | 
					
						
							|  |  |  |  | 	xhr.send(); | 
					
						
							| 
									
										
										
										
											2017-04-16 23:11:03 +02:00
										 |  |  |  | }; | 
					
						
							| 
									
										
										
										
											2017-04-15 23:16:20 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-18 19:03:39 +02:00
										 |  |  |  | Grocy.Api.Post = function(apiFunction, jsonData, success, error) | 
					
						
							| 
									
										
										
										
											2017-04-15 23:16:20 +02:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	var xhr = new XMLHttpRequest(); | 
					
						
							| 
									
										
										
										
											2018-04-18 19:03:39 +02:00
										 |  |  |  | 	var url = U('/api/' + apiFunction); | 
					
						
							| 
									
										
										
										
											2017-04-15 23:16:20 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	xhr.onreadystatechange = function() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		if (xhr.readyState === XMLHttpRequest.DONE) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-01-19 14:51:51 +01:00
										 |  |  |  | 			if (xhr.status === 200 || xhr.status === 204) | 
					
						
							| 
									
										
										
										
											2017-04-15 23:16:20 +02:00
										 |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				if (success) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2019-01-19 14:51:51 +01:00
										 |  |  |  | 					if (xhr.status === 200) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						success(JSON.parse(xhr.responseText)); | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 					else | 
					
						
							|  |  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2020-08-30 12:18:16 +02:00
										 |  |  |  | 						success({}); | 
					
						
							| 
									
										
										
										
											2019-01-19 14:51:51 +01:00
										 |  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-04-15 23:16:20 +02:00
										 |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			else | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				if (error) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					error(xhr); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	xhr.open('POST', url, true); | 
					
						
							| 
									
										
										
										
											2023-09-01 00:53:25 +02:00
										 |  |  |  | 	xhr.setRequestHeader('Content-Type', 'application/json'); | 
					
						
							| 
									
										
										
										
											2017-04-15 23:16:20 +02:00
										 |  |  |  | 	xhr.send(JSON.stringify(jsonData)); | 
					
						
							| 
									
										
										
										
											2017-04-16 23:11:03 +02:00
										 |  |  |  | }; | 
					
						
							| 
									
										
										
										
											2018-07-11 19:43:05 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-19 00:37:21 -07:00
										 |  |  |  | Grocy.Api.Put = function(apiFunction, jsonData, success, error) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	var xhr = new XMLHttpRequest(); | 
					
						
							|  |  |  |  | 	var url = U('/api/' + apiFunction); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	xhr.onreadystatechange = function() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		if (xhr.readyState === XMLHttpRequest.DONE) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-01-19 14:51:51 +01:00
										 |  |  |  | 			if (xhr.status === 200 || xhr.status === 204) | 
					
						
							| 
									
										
										
										
											2019-01-19 00:37:21 -07:00
										 |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				if (success) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2019-01-19 14:51:51 +01:00
										 |  |  |  | 					if (xhr.status === 200) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						success(JSON.parse(xhr.responseText)); | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 					else | 
					
						
							|  |  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2020-08-30 12:18:16 +02:00
										 |  |  |  | 						success({}); | 
					
						
							| 
									
										
										
										
											2019-01-19 14:51:51 +01:00
										 |  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2019-01-19 00:37:21 -07:00
										 |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			else | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				if (error) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					error(xhr); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	xhr.open('PUT', url, true); | 
					
						
							| 
									
										
										
										
											2023-09-01 00:53:25 +02:00
										 |  |  |  | 	xhr.setRequestHeader('Content-Type', 'application/json'); | 
					
						
							| 
									
										
										
										
											2019-01-19 00:37:21 -07:00
										 |  |  |  | 	xhr.send(JSON.stringify(jsonData)); | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Grocy.Api.Delete = function(apiFunction, jsonData, success, error) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	var xhr = new XMLHttpRequest(); | 
					
						
							|  |  |  |  | 	var url = U('/api/' + apiFunction); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	xhr.onreadystatechange = function() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		if (xhr.readyState === XMLHttpRequest.DONE) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-01-19 14:51:51 +01:00
										 |  |  |  | 			if (xhr.status === 200 || xhr.status === 204) | 
					
						
							| 
									
										
										
										
											2019-01-19 00:37:21 -07:00
										 |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				if (success) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2019-01-19 14:51:51 +01:00
										 |  |  |  | 					if (xhr.status === 200) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						success(JSON.parse(xhr.responseText)); | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 					else | 
					
						
							|  |  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2020-08-30 12:18:16 +02:00
										 |  |  |  | 						success({}); | 
					
						
							| 
									
										
										
										
											2019-01-19 14:51:51 +01:00
										 |  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2019-01-19 00:37:21 -07:00
										 |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			else | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				if (error) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					error(xhr); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	xhr.open('DELETE', url, true); | 
					
						
							| 
									
										
										
										
											2023-09-01 00:53:25 +02:00
										 |  |  |  | 	xhr.setRequestHeader('Content-Type', 'application/json'); | 
					
						
							| 
									
										
										
										
											2019-01-19 00:37:21 -07:00
										 |  |  |  | 	xhr.send(JSON.stringify(jsonData)); | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-01 20:20:50 +02:00
										 |  |  |  | Grocy.Api.UploadFile = function(file, group, fileName, success, error) | 
					
						
							| 
									
										
										
										
											2018-09-30 23:22:17 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-10-01 20:20:50 +02:00
										 |  |  |  | 	var xhr = new XMLHttpRequest(); | 
					
						
							| 
									
										
										
										
											2019-01-21 22:13:42 +01:00
										 |  |  |  | 	var url = U('/api/files/' + group + '/' + btoa(fileName)); | 
					
						
							| 
									
										
										
										
											2018-10-01 20:20:50 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	xhr.onreadystatechange = function() | 
					
						
							| 
									
										
										
										
											2018-09-30 23:22:17 +02:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-10-01 20:20:50 +02:00
										 |  |  |  | 		if (xhr.readyState === XMLHttpRequest.DONE) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-01-21 22:13:42 +01:00
										 |  |  |  | 			if (xhr.status === 200 || xhr.status === 204) | 
					
						
							| 
									
										
										
										
											2018-10-01 20:20:50 +02:00
										 |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				if (success) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2019-01-21 22:13:42 +01:00
										 |  |  |  | 					if (xhr.status === 200) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						success(JSON.parse(xhr.responseText)); | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 					else | 
					
						
							|  |  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2020-08-30 12:18:16 +02:00
										 |  |  |  | 						success({}); | 
					
						
							| 
									
										
										
										
											2019-01-21 22:13:42 +01:00
										 |  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-10-01 20:20:50 +02:00
										 |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			else | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				if (error) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					error(xhr); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2018-09-30 23:22:17 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-01 20:20:50 +02:00
										 |  |  |  | 	xhr.open('PUT', url, true); | 
					
						
							| 
									
										
										
										
											2023-09-01 00:53:25 +02:00
										 |  |  |  | 	xhr.setRequestHeader('Content-Type', 'application/octet-stream'); | 
					
						
							| 
									
										
										
										
											2018-10-01 20:20:50 +02:00
										 |  |  |  | 	xhr.send(file); | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Grocy.Api.DeleteFile = function(fileName, group, success, error) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-09-30 23:22:17 +02:00
										 |  |  |  | 	var xhr = new XMLHttpRequest(); | 
					
						
							| 
									
										
										
										
											2019-01-21 22:13:42 +01:00
										 |  |  |  | 	var url = U('/api/files/' + group + '/' + btoa(fileName)); | 
					
						
							| 
									
										
										
										
											2018-09-30 23:22:17 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 	xhr.onreadystatechange = function() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		if (xhr.readyState === XMLHttpRequest.DONE) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-01-21 22:13:42 +01:00
										 |  |  |  | 			if (xhr.status === 200 || xhr.status === 204) | 
					
						
							| 
									
										
										
										
											2018-09-30 23:22:17 +02:00
										 |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				if (success) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2019-01-21 22:13:42 +01:00
										 |  |  |  | 					if (xhr.status === 200) | 
					
						
							|  |  |  |  | 					{ | 
					
						
							|  |  |  |  | 						success(JSON.parse(xhr.responseText)); | 
					
						
							|  |  |  |  | 					} | 
					
						
							|  |  |  |  | 					else | 
					
						
							|  |  |  |  | 					{ | 
					
						
							| 
									
										
										
										
											2020-08-30 12:18:16 +02:00
										 |  |  |  | 						success({}); | 
					
						
							| 
									
										
										
										
											2019-01-21 22:13:42 +01:00
										 |  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2018-09-30 23:22:17 +02:00
										 |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			else | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				if (error) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					error(xhr); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-01 20:20:50 +02:00
										 |  |  |  | 	xhr.open('DELETE', url, true); | 
					
						
							| 
									
										
										
										
											2023-09-01 00:53:25 +02:00
										 |  |  |  | 	xhr.setRequestHeader('Content-Type', 'application/json'); | 
					
						
							| 
									
										
										
										
											2018-10-01 20:20:50 +02:00
										 |  |  |  | 	xhr.send(); | 
					
						
							| 
									
										
										
										
											2018-09-30 23:22:17 +02:00
										 |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-29 20:24:02 +02:00
										 |  |  |  | U = function(relativePath) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	return Grocy.BaseUrl.replace(/\/$/, '') + relativePath; | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-19 17:10:20 +02:00
										 |  |  |  | Grocy.Translator = new window.translator.default(Grocy.LocalizationStrings); | 
					
						
							|  |  |  |  | Grocy.TranslatorQu = new window.translator.default(Grocy.LocalizationStringsQu); | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | __t = function(text, ...placeholderValues) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-05-19 17:10:20 +02:00
										 |  |  |  | 	if (!text) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		return text; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | 	if (Grocy.Mode === "dev") | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		var text2 = text; | 
					
						
							| 
									
										
										
										
											2021-07-12 21:20:39 +02:00
										 |  |  |  | 		if (Grocy.LocalizationStrings && !Grocy.LocalizationStrings.messages[""].hasOwnProperty(text2)) | 
					
						
							| 
									
										
										
										
											2021-07-12 19:10:07 +02:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			Grocy.Api.Post('system/log-missing-localization', { "text": text2 }); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-08-29 16:41:27 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-21 10:56:38 +02:00
										 |  |  |  | 	// sprintf can fail due to invalid placeholders
 | 
					
						
							|  |  |  |  | 	try | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		return sprintf(Grocy.Translator.__(text, ...placeholderValues), ...placeholderValues); | 
					
						
							|  |  |  |  | 	} catch (e) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		return Grocy.Translator.__(text, ...placeholderValues); | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-02-06 21:09:34 +01:00
										 |  |  |  | __n = function(number, singularForm, pluralForm, isQu = false) | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-05-19 17:10:20 +02:00
										 |  |  |  | 	if (!singularForm) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		return singularForm; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | 	if (Grocy.Mode === "dev") | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		var singularForm2 = singularForm; | 
					
						
							| 
									
										
										
										
											2021-07-12 21:20:39 +02:00
										 |  |  |  | 		if (Grocy.LocalizationStrings && !Grocy.LocalizationStrings.messages[""].hasOwnProperty(singularForm2)) | 
					
						
							| 
									
										
										
										
											2021-07-12 19:10:07 +02:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			Grocy.Api.Post('system/log-missing-localization', { "text": singularForm2 }); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-06 20:22:10 +01:00
										 |  |  |  | 	if (!pluralForm) | 
					
						
							| 
									
										
										
										
											2022-05-14 17:10:48 +02:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		pluralForm = singularForm; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-21 10:56:38 +02:00
										 |  |  |  | 	number = Math.abs(number); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-06 21:09:34 +01:00
										 |  |  |  | 	if (isQu) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2023-05-22 21:23:19 +02:00
										 |  |  |  | 		return sprintf(Grocy.TranslatorQu.n__(singularForm, pluralForm, number, number), number.toLocaleString()); | 
					
						
							| 
									
										
										
										
											2022-02-06 21:09:34 +01:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	else | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2023-05-22 21:23:19 +02:00
										 |  |  |  | 		return sprintf(Grocy.Translator.n__(singularForm, pluralForm, number, number), number.toLocaleString()); | 
					
						
							| 
									
										
										
										
											2022-02-06 21:09:34 +01:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-27 19:00:49 +01:00
										 |  |  |  | RefreshContextualTimeago = function(rootSelector = "#page-content") | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-27 19:00:49 +01:00
										 |  |  |  | 	$(rootSelector + " time.timeago").each(function() | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		var element = $(this); | 
					
						
							| 
									
										
										
										
											2019-09-26 13:55:42 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (!element.hasAttr("datetime")) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			element.text("") | 
					
						
							|  |  |  |  | 			return | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | 		var timestamp = element.attr("datetime"); | 
					
						
							| 
									
										
										
										
											2019-07-07 09:04:40 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-06 20:22:10 +01:00
										 |  |  |  | 		if (!timestamp || timestamp.length < 10) | 
					
						
							| 
									
										
										
										
											2019-09-26 13:55:42 +02:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			element.text("") | 
					
						
							|  |  |  |  | 			return | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-07 18:12:49 +02:00
										 |  |  |  | 		if (!moment(timestamp).isValid()) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			element.text("") | 
					
						
							|  |  |  |  | 			return | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | 		var isNever = timestamp && timestamp.substring(0, 10) == "2999-12-31"; | 
					
						
							| 
									
										
										
										
											2019-09-14 13:05:36 +02:00
										 |  |  |  | 		var isToday = timestamp && timestamp.substring(0, 10) == moment().format("YYYY-MM-DD"); | 
					
						
							| 
									
										
										
										
											2019-07-07 19:38:57 +02:00
										 |  |  |  | 		var isDateWithoutTime = element.hasClass("timeago-date-only"); | 
					
						
							| 
									
										
										
										
											2019-07-07 09:04:40 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | 		if (isNever) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			element.prev().text(__t("Never")); | 
					
						
							| 
									
										
										
										
											2019-09-21 13:40:31 +02:00
										 |  |  |  | 			element.text(""); | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-07 09:04:40 +02:00
										 |  |  |  | 		else if (isToday) | 
					
						
							| 
									
										
										
										
											2019-07-06 17:19:28 +02:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			element.text(__t("Today")); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | 		else | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2021-11-15 20:05:10 +01:00
										 |  |  |  | 			element.text(moment(timestamp).fromNow()); | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-07 19:38:57 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (isDateWithoutTime) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			element.prev().text(element.prev().text().substring(0, 10)); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-06 15:43:54 +02:00
										 |  |  |  | 	}); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | RefreshContextualTimeago(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | toastr.options = { | 
					
						
							|  |  |  |  | 	toastClass: 'alert', | 
					
						
							|  |  |  |  | 	closeButton: true, | 
					
						
							|  |  |  |  | 	timeOut: 20000, | 
					
						
							|  |  |  |  | 	extendedTimeOut: 5000 | 
					
						
							|  |  |  |  | }; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 12:18:16 +02:00
										 |  |  |  | Grocy.FrontendHelpers = {}; | 
					
						
							| 
									
										
										
										
											2022-03-26 10:34:00 +01:00
										 |  |  |  | Grocy.FrontendHelpers.ValidateForm = function(formId, reportValidity = false) | 
					
						
							| 
									
										
										
										
											2018-07-11 19:43:05 +02:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	var form = document.getElementById(formId); | 
					
						
							| 
									
										
										
										
											2019-09-20 13:37:53 +02:00
										 |  |  |  | 	if (form === null || form === undefined) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		return; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-26 10:34:00 +01:00
										 |  |  |  | 	$(form).addClass('was-validated'); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (reportValidity) | 
					
						
							| 
									
										
										
										
											2018-07-11 19:43:05 +02:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2022-03-26 10:34:00 +01:00
										 |  |  |  | 		form.reportValidity(); | 
					
						
							| 
									
										
										
										
											2018-07-11 19:43:05 +02:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-26 10:34:00 +01:00
										 |  |  |  | 	return form.checkValidity(); | 
					
						
							| 
									
										
										
										
											2018-07-11 19:43:05 +02:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-09-08 09:26:12 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-24 19:40:50 +01:00
										 |  |  |  | Grocy.FrontendHelpers.BeginUiBusy = function(formId = null) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	$("body").addClass("cursor-busy"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (formId !== null) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		$("#" + formId + " :input").attr("disabled", true); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Grocy.FrontendHelpers.EndUiBusy = function(formId = null) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	$("body").removeClass("cursor-busy"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (formId !== null) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		$("#" + formId + " :input").attr("disabled", false); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-08 09:26:12 +02:00
										 |  |  |  | Grocy.FrontendHelpers.ShowGenericError = function(message, exception) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-05-01 20:19:18 +02:00
										 |  |  |  | 	toastr.error(__t(message) + '<br><br>' + __t('Click to show technical details'), '', { | 
					
						
							| 
									
										
										
										
											2018-09-08 09:26:12 +02:00
										 |  |  |  | 		onclick: function() | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-04-07 18:12:49 +02:00
										 |  |  |  | 			var errorDetails = JSON.stringify(exception, null, 4); | 
					
						
							|  |  |  |  | 			if (typeof exception === "object" && exception !== null && exception.hasOwnProperty("error_message")) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				errorDetails = exception.error_message; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-08 09:26:12 +02:00
										 |  |  |  | 			bootbox.alert({ | 
					
						
							| 
									
										
										
										
											2019-05-01 20:19:18 +02:00
										 |  |  |  | 				title: __t('Error details'), | 
					
						
							| 
									
										
										
										
											2022-04-07 18:12:49 +02:00
										 |  |  |  | 				message: '<p class="text-monospace my-0">' + errorDetails + '</p>', | 
					
						
							| 
									
										
										
										
											2025-01-11 20:04:32 +01:00
										 |  |  |  | 				closeButton: false, | 
					
						
							|  |  |  |  | 				className: "wider" | 
					
						
							| 
									
										
										
										
											2018-09-08 09:26:12 +02:00
										 |  |  |  | 			}); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2019-01-19 00:37:21 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-08 09:26:12 +02:00
										 |  |  |  | 	console.error(exception); | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-09-30 09:57:42 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 19:26:55 +02:00
										 |  |  |  | Grocy.FrontendHelpers.SaveUserSetting = function(settingsKey, value, force = false) | 
					
						
							| 
									
										
										
										
											2020-12-16 18:18:03 +01:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-04-02 19:26:55 +02:00
										 |  |  |  | 	if (Grocy.UserSettings[settingsKey] == value && !force) | 
					
						
							| 
									
										
										
										
											2022-01-16 14:58:42 +01:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		return; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 18:18:03 +01:00
										 |  |  |  | 	Grocy.UserSettings[settingsKey] = value; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	jsonData = {}; | 
					
						
							|  |  |  |  | 	jsonData.value = value; | 
					
						
							|  |  |  |  | 	Grocy.Api.Put('user/settings/' + settingsKey, jsonData, | 
					
						
							|  |  |  |  | 		function(result) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			// Nothing to do...
 | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 		function(xhr) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-01-16 14:58:42 +01:00
										 |  |  |  | 			console.error(xhr); | 
					
						
							| 
									
										
										
										
											2020-12-16 18:18:03 +01:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 	); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | Grocy.FrontendHelpers.DeleteUserSetting = function(settingsKey, reloadPageOnSuccess = false) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	delete Grocy.UserSettings[settingsKey]; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	Grocy.Api.Delete('user/settings/' + settingsKey, {}, | 
					
						
							|  |  |  |  | 		function(result) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			if (reloadPageOnSuccess) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				location.reload(); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		}, | 
					
						
							|  |  |  |  | 		function(xhr) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2023-02-06 20:22:10 +01:00
										 |  |  |  | 			if (xhr.statusText) | 
					
						
							| 
									
										
										
										
											2020-12-16 18:18:03 +01:00
										 |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				Grocy.FrontendHelpers.ShowGenericError('Error while deleting, please retry', xhr.response) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-12 17:21:12 +02:00
										 |  |  |  | Grocy.FrontendHelpers.RunWebhook = function(webhook, data, repetitions = 1) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	Object.assign(data, webhook.extra_data); | 
					
						
							|  |  |  |  | 	var hasAlreadyFailed = false; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	for (i = 0; i < repetitions; i++) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2022-08-25 18:46:49 +02:00
										 |  |  |  | 		if (webhook.json) | 
					
						
							| 
									
										
										
										
											2021-06-12 17:21:12 +02:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-08-25 18:46:49 +02:00
										 |  |  |  | 			$.ajax(webhook.hook, { "data": JSON.stringify(data), "contentType": "application/json", "type": "POST" }).fail(function(req, status, errorThrown) | 
					
						
							| 
									
										
										
										
											2021-06-12 17:21:12 +02:00
										 |  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2022-08-25 18:46:49 +02:00
										 |  |  |  | 				if (!hasAlreadyFailed) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					hasAlreadyFailed = true; | 
					
						
							|  |  |  |  | 					Grocy.FrontendHelpers.ShowGenericError(__t("Error while executing WebHook", { "status": status, "errorThrown": errorThrown })); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			}); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		else | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			$.post(webhook.hook, data).fail(function(req, status, errorThrown) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				if (!hasAlreadyFailed) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					hasAlreadyFailed = true; | 
					
						
							|  |  |  |  | 					Grocy.FrontendHelpers.ShowGenericError(__t("Error while executing WebHook", { "status": status, "errorThrown": errorThrown })); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			}); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-06-12 17:21:12 +02:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-09 08:58:46 +02:00
										 |  |  |  | $(document).on("keyup paste change", "input, textarea", function() | 
					
						
							| 
									
										
										
										
											2018-09-30 09:57:42 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-13 21:00:06 +01:00
										 |  |  |  | 	$(this).addClass("is-dirty").closest("form").addClass("is-dirty"); | 
					
						
							| 
									
										
										
										
											2018-09-30 09:57:42 +02:00
										 |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2019-06-09 08:58:46 +02:00
										 |  |  |  | $(document).on("click", "select", function() | 
					
						
							| 
									
										
										
										
											2018-09-30 09:57:42 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-13 21:00:06 +01:00
										 |  |  |  | 	$(this).addClass("is-dirty").closest("form").addClass("is-dirty"); | 
					
						
							| 
									
										
										
										
											2018-09-30 09:57:42 +02:00
										 |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2018-09-30 17:14:04 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | // Auto saving user setting controls
 | 
					
						
							| 
									
										
										
										
											2020-01-26 15:35:01 +01:00
										 |  |  |  | $(document).on("change", ".user-setting-control", function() | 
					
						
							| 
									
										
										
										
											2018-09-30 17:14:04 +02:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	var element = $(this); | 
					
						
							|  |  |  |  | 	var settingKey = element.attr("data-setting-key"); | 
					
						
							| 
									
										
										
										
											2018-10-20 14:55:49 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 19:11:02 +01:00
										 |  |  |  | 	if (!element[0].checkValidity()) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		return; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-20 14:55:49 +02:00
										 |  |  |  | 	var inputType = "unknown"; | 
					
						
							|  |  |  |  | 	if (typeof element.attr("type") !== typeof undefined && element.attr("type") !== false) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		inputType = element.attr("type").toLowerCase(); | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-01-19 00:37:21 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-30 17:14:04 +02:00
										 |  |  |  | 	if (inputType === "checkbox") | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		value = element.is(":checked"); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	else | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		var value = element.val(); | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-01-19 00:37:21 -07:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 18:18:03 +01:00
										 |  |  |  | 	Grocy.FrontendHelpers.SaveUserSetting(settingKey, value); | 
					
						
							| 
									
										
										
										
											2018-09-30 17:14:04 +02:00
										 |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2018-10-01 20:20:50 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | // Show file name Bootstrap custom file input
 | 
					
						
							|  |  |  |  | $('input.custom-file-input').on('change', function() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	$(this).next('.custom-file-label').html(GetFileNameFromPath($(this).val())); | 
					
						
							|  |  |  |  | }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // Translation of "Browse"-button of Bootstrap custom file input
 | 
					
						
							|  |  |  |  | if ($(".custom-file-label").length > 0) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-05-01 20:19:18 +02:00
										 |  |  |  | 	$("<style>").html('.custom-file-label::after { content: "' + __t("Select file") + '"; }').appendTo("head"); | 
					
						
							| 
									
										
										
										
											2018-10-01 20:20:50 +02:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-10-03 19:05:00 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | ResizeResponsiveEmbeds = function() | 
					
						
							| 
									
										
										
										
											2018-10-03 19:05:00 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | 	$("iframe.embed-responsive").each(function() | 
					
						
							| 
									
										
										
										
											2018-10-03 19:05:00 +02:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2025-01-11 12:06:15 +01:00
										 |  |  |  | 		var iframeBody = $(this)[0].contentWindow.document.body; | 
					
						
							|  |  |  |  | 		if (iframeBody) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			$(this).attr("height", iframeBody.scrollHeight.toString() + "px"); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if ($("body").hasClass("fullscreen-card")) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			$(this).attr("height", $("body").height().toString() + "px"); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | 	}); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var maxHeight = $("body").height() - $("#mainNav").outerHeight() - 62; | 
					
						
							|  |  |  |  | 	if ($("body").hasClass("fullscreen-card")) | 
					
						
							| 
									
										
										
										
											2024-01-13 20:27:35 +01:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | 		maxHeight = $("body").height(); | 
					
						
							| 
									
										
										
										
											2024-01-13 20:27:35 +01:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-01-11 12:06:15 +01:00
										 |  |  |  | 	$("embed.embed-responsive:not(.resize-done)").attr("height", maxHeight.toString() + "px").addClass("resize-done"); | 
					
						
							| 
									
										
										
										
											2018-10-03 19:05:00 +02:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | $(window).on("resize", function() | 
					
						
							| 
									
										
										
										
											2018-10-03 19:05:00 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | 	ResizeResponsiveEmbeds(); | 
					
						
							| 
									
										
										
										
											2018-10-03 19:05:00 +02:00
										 |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | $("iframe").on("load", function() | 
					
						
							| 
									
										
										
										
											2024-02-25 10:40:11 +01:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | 	ResizeResponsiveEmbeds(); | 
					
						
							|  |  |  |  | }); | 
					
						
							|  |  |  |  | $(document).on("shown.bs.modal", function(e) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	ResizeResponsiveEmbeds(); | 
					
						
							|  |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2025-01-11 12:06:15 +01:00
										 |  |  |  | $(document).on("hidden.bs.modal", function(e) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	$("body").removeClass("fullscreen-card"); | 
					
						
							|  |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | $("body").children().each(function(index, child) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	new ResizeObserver(function() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		window.parent.postMessage(WindowMessageBag("ResizeResponsiveEmbeds"), Grocy.BaseUrl); | 
					
						
							|  |  |  |  | 	}).observe(child); | 
					
						
							|  |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2024-02-25 10:40:11 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-17 14:50:52 +01:00
										 |  |  |  | function WindowMessageBag(message, payload = null) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-30 12:18:16 +02:00
										 |  |  |  | 	var obj = {}; | 
					
						
							| 
									
										
										
										
											2018-11-17 14:50:52 +01:00
										 |  |  |  | 	obj.Message = message; | 
					
						
							|  |  |  |  | 	obj.Payload = payload; | 
					
						
							|  |  |  |  | 	return obj; | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2018-11-21 19:08:36 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | // Add border around anchor link section
 | 
					
						
							|  |  |  |  | if (window.location.hash) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	$(window.location.hash).addClass("p-2 border border-info rounded"); | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-02-09 13:41:40 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-27 19:00:49 +01:00
										 |  |  |  | function RefreshLocaleNumberDisplay(rootSelector = "#page-content") | 
					
						
							| 
									
										
										
										
											2019-03-03 16:33:48 +01:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 	$(rootSelector + " .locale-number.locale-number-currency:not('.number-parsing-done')").each(function() | 
					
						
							| 
									
										
										
										
											2019-05-07 19:48:14 +02:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 		var element = $(this); | 
					
						
							|  |  |  |  | 		var text = element.text(); | 
					
						
							| 
									
										
										
										
											2023-02-06 20:22:10 +01:00
										 |  |  |  | 		if (!text || Number.isNaN(text)) | 
					
						
							| 
									
										
										
										
											2019-09-26 15:25:30 +02:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			return; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-06 20:22:10 +01:00
										 |  |  |  | 		var value = Number.parseFloat(text); | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 		element.text(value.toLocaleString(undefined, { style: "currency", currency: Grocy.Currency, minimumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices_display, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices_display })); | 
					
						
							|  |  |  |  | 		element.addClass("number-parsing-done"); | 
					
						
							| 
									
										
										
										
											2019-05-07 19:48:14 +02:00
										 |  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2019-03-05 19:36:14 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 	$(rootSelector + " .locale-number.locale-number-quantity-amount:not('.number-parsing-done')").each(function() | 
					
						
							| 
									
										
										
										
											2019-05-07 19:48:14 +02:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 		var element = $(this); | 
					
						
							|  |  |  |  | 		var text = element.text(); | 
					
						
							| 
									
										
										
										
											2023-02-06 20:22:10 +01:00
										 |  |  |  | 		if (!text || Number.isNaN(text)) | 
					
						
							| 
									
										
										
										
											2019-09-26 15:25:30 +02:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			return; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-06 20:22:10 +01:00
										 |  |  |  | 		var value = Number.parseFloat(text); | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 		element.text(value.toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts })); | 
					
						
							|  |  |  |  | 		element.addClass("number-parsing-done"); | 
					
						
							| 
									
										
										
										
											2019-05-07 19:48:14 +02:00
										 |  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2019-09-20 20:06:24 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 	$(rootSelector + " .locale-number.locale-number-generic:not('.number-parsing-done')").each(function() | 
					
						
							| 
									
										
										
										
											2019-09-20 20:06:24 +02:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 		var element = $(this); | 
					
						
							|  |  |  |  | 		var text = element.text(); | 
					
						
							| 
									
										
										
										
											2023-02-06 20:22:10 +01:00
										 |  |  |  | 		if (!text || Number.isNaN(text)) | 
					
						
							| 
									
										
										
										
											2019-09-26 15:25:30 +02:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			return; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-08-29 16:41:27 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-06 20:22:10 +01:00
										 |  |  |  | 		var value = Number.parseFloat(text); | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 		element.text(value.toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 0 })); | 
					
						
							|  |  |  |  | 		element.addClass("number-parsing-done"); | 
					
						
							| 
									
										
										
										
											2019-09-20 20:06:24 +02:00
										 |  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2019-05-07 19:48:14 +02:00
										 |  |  |  | } | 
					
						
							|  |  |  |  | RefreshLocaleNumberDisplay(); | 
					
						
							| 
									
										
										
										
											2024-12-23 17:20:23 +01:00
										 |  |  |  | $(".locale-number").each(function() | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-12-23 17:20:23 +01:00
										 |  |  |  | 	new MutationObserver(function(mutations) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		mutations.forEach(mutation => | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			if (mutation.type == "childList" || mutation.type == "attributes") | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				$(mutation.target).removeClass("number-parsing-done"); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		}); | 
					
						
							|  |  |  |  | 	}).observe(this, { | 
					
						
							|  |  |  |  | 		attributes: true, | 
					
						
							|  |  |  |  | 		childList: true, | 
					
						
							|  |  |  |  | 		subtree: true | 
					
						
							|  |  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2019-05-03 19:36:27 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-15 14:15:09 +01:00
										 |  |  |  | function RefreshLocaleNumberInput(rootSelector = "#page-content") | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	$(rootSelector + " .locale-number-input.locale-number-currency").each(function() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 		var element = $(this); | 
					
						
							|  |  |  |  | 		var value = element.val(); | 
					
						
							| 
									
										
										
										
											2023-02-06 20:22:10 +01:00
										 |  |  |  | 		if (!value || Number.isNaN(value)) | 
					
						
							| 
									
										
										
										
											2020-11-15 14:15:09 +01:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			return; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 		element.val(Number.parseFloat(value).toLocaleString("en", { minimumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices_input, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_prices_input, useGrouping: false })); | 
					
						
							| 
									
										
										
										
											2020-11-15 14:15:09 +01:00
										 |  |  |  | 	}); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	$(rootSelector + " .locale-number-input.locale-number-quantity-amount").each(function() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 		var element = $(this); | 
					
						
							|  |  |  |  | 		var value = element.val(); | 
					
						
							| 
									
										
										
										
											2023-02-06 20:22:10 +01:00
										 |  |  |  | 		if (!value || Number.isNaN(value)) | 
					
						
							| 
									
										
										
										
											2020-11-15 14:15:09 +01:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			return; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 		element.val(Number.parseFloat(value).toLocaleString("en", { minimumFractionDigits: 0, maximumFractionDigits: Grocy.UserSettings.stock_decimal_places_amounts, useGrouping: false })); | 
					
						
							| 
									
										
										
										
											2020-11-15 14:15:09 +01:00
										 |  |  |  | 	}); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	$(rootSelector + " .locale-number-input.locale-number-generic").each(function() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 		var element = $(this); | 
					
						
							|  |  |  |  | 		var value = element.val(); | 
					
						
							| 
									
										
										
										
											2023-02-06 20:22:10 +01:00
										 |  |  |  | 		if (!value || Number.isNaN(value)) | 
					
						
							| 
									
										
										
										
											2020-11-15 14:15:09 +01:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			return; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-15 09:35:40 +02:00
										 |  |  |  | 		element.val(value.toLocaleString("en", { minimumFractionDigits: 0, maximumFractionDigits: 2, useGrouping: false })); | 
					
						
							| 
									
										
										
										
											2020-11-15 14:15:09 +01:00
										 |  |  |  | 	}); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | RefreshLocaleNumberInput(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-05 19:36:14 +01:00
										 |  |  |  | $(document).on("click", ".easy-link-copy-textbox", function() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	$(this).select(); | 
					
						
							|  |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2019-08-15 14:35:28 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-06 20:22:10 +01:00
										 |  |  |  | if (Grocy.CalendarFirstDayOfWeek) | 
					
						
							| 
									
										
										
										
											2019-09-18 18:46:07 +02:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	moment.updateLocale(moment.locale(), { | 
					
						
							| 
									
										
										
										
											2023-07-31 21:29:28 +02:00
										 |  |  |  | 		"week": { | 
					
						
							|  |  |  |  | 			"dow": Number.parseInt(Grocy.CalendarFirstDayOfWeek) | 
					
						
							| 
									
										
										
										
											2019-09-18 18:46:07 +02:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}); | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-09-20 13:37:53 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-10 20:26:37 +01:00
										 |  |  |  | if (GetUriParam("embedded")) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2025-01-11 12:06:15 +01:00
										 |  |  |  | 	$("body").append('<div class="fixed-top" style="left: unset;"> \ | 
					
						
							|  |  |  |  | 		<button class="btn btn-light btn-sm close-last-modal-button" \ | 
					
						
							| 
									
										
										
										
											2025-01-10 20:26:37 +01:00
										 |  |  |  | 			type="button" \> \ | 
					
						
							|  |  |  |  | 			<i class="fa-solid fa-xmark"></i> \ | 
					
						
							|  |  |  |  | 		</button> \ | 
					
						
							|  |  |  |  | 	</div>'); | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | $(document).on("click", ".close-last-modal-button", function() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	window.parent.postMessage(WindowMessageBag("CloseLastModal"), Grocy.BaseUrl); | 
					
						
							|  |  |  |  | }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | $("body").on("keydown", function(e) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	if (e.key == "Escape") | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		window.parent.postMessage(WindowMessageBag("CloseLastModal"), Grocy.BaseUrl); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-20 13:37:53 +02:00
										 |  |  |  | $(window).on("message", function(e) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	var data = e.originalEvent.data; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | 	if (data.Message == "ShowSuccessMessage") | 
					
						
							| 
									
										
										
										
											2019-09-20 13:37:53 +02:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		toastr.success(data.Payload); | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | 	else if (data.Message == "CloseLastModal") | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2025-01-11 12:06:15 +01:00
										 |  |  |  | 		$(".modal:visible").last().modal("hide"); | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 	else if (data.Message == "ResizeResponsiveEmbeds") | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		ResizeResponsiveEmbeds(); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	else if (data.Message == "IframeModal") | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		IframeModal(data.Payload.Link, data.Payload.DialogType); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	else if (data.Message == "Reload") | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		window.location.reload(); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	else if (data.Message == "BroadcastMessage") | 
					
						
							| 
									
										
										
										
											2019-09-20 13:37:53 +02:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2025-01-11 12:06:15 +01:00
										 |  |  |  | 		// data.Payload is the original WindowMessageBag
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// => Send the original message to this window
 | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | 		window.postMessage(data.Payload, Grocy.BaseUrl); | 
					
						
							| 
									
										
										
										
											2025-01-11 12:06:15 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// => Bubble the broadcast message down to all child iframes
 | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | 		$("iframe.embed-responsive").each(function() | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2025-01-11 12:06:15 +01:00
										 |  |  |  | 			$(this)[0].contentWindow.postMessage(data, Grocy.BaseUrl); | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | 		}); | 
					
						
							| 
									
										
										
										
											2019-09-20 13:37:53 +02:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2019-09-27 16:54:40 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | $(document).on("click", ".show-as-dialog-link", function(e) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	e.preventDefault(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | 	var element = $(e.currentTarget); | 
					
						
							|  |  |  |  | 	var link = element.attr("href"); | 
					
						
							| 
									
										
										
										
											2020-08-29 16:41:27 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | 	var dialogType = "form"; | 
					
						
							|  |  |  |  | 	if (element.hasAttr("data-dialog-type")) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		dialogType = element.attr("data-dialog-type") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	if (window.top != window.self) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		window.top.postMessage(WindowMessageBag("IframeModal", { "Link": link, "DialogType": dialogType }), Grocy.BaseUrl); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	else | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		IframeModal(link, dialogType); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | }); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | function IframeModal(link, dialogClass = "form") | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-09-27 16:54:40 +02:00
										 |  |  |  | 	bootbox.dialog({ | 
					
						
							| 
									
										
										
										
											2024-02-25 10:40:11 +01:00
										 |  |  |  | 		message: '<iframe class="embed-responsive" src="' + link + '"></iframe>', | 
					
						
							| 
									
										
										
										
											2019-09-27 16:54:40 +02:00
										 |  |  |  | 		size: 'large', | 
					
						
							|  |  |  |  | 		backdrop: true, | 
					
						
							|  |  |  |  | 		closeButton: false, | 
					
						
							| 
									
										
										
										
											2025-01-10 20:26:37 +01:00
										 |  |  |  | 		className: dialogClass | 
					
						
							| 
									
										
										
										
											2019-09-27 16:54:40 +02:00
										 |  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2025-01-10 17:15:09 +01:00
										 |  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-10-15 19:38:51 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-19 15:12:11 +02:00
										 |  |  |  | // Init Bootstrap tooltips
 | 
					
						
							| 
									
										
										
										
											2023-05-21 18:01:47 +02:00
										 |  |  |  | $('[data-toggle="tooltip"]').tooltip(); | 
					
						
							| 
									
										
										
										
											2023-05-19 15:12:11 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-11 17:34:37 +01:00
										 |  |  |  | // serializeJSON defaults
 | 
					
						
							|  |  |  |  | $.serializeJSON.defaultOptions.checkboxUncheckedValue = "0"; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-30 12:18:16 +02:00
										 |  |  |  | $(Grocy.UserPermissions).each(function(index, item) | 
					
						
							| 
									
										
										
										
											2020-08-29 12:05:32 +02:00
										 |  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-30 12:18:16 +02:00
										 |  |  |  | 	if (item.has_permission == 0) | 
					
						
							| 
									
										
										
										
											2020-08-29 12:05:32 +02:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-08-30 12:18:16 +02:00
										 |  |  |  | 		$('.permission-' + item.permission_name).addClass('disabled').addClass('not-allowed'); | 
					
						
							| 
									
										
										
										
											2020-08-29 12:05:32 +02:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2023-05-21 18:01:47 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-14 11:20:29 +02:00
										 |  |  |  | $('a.link-return').not(".btn").each(function() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	var base = $(this).data('href'); | 
					
						
							|  |  |  |  | 	if (base.contains('?')) | 
					
						
							| 
									
										
										
										
											2020-08-31 19:11:51 +02:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2022-02-13 20:07:29 +01:00
										 |  |  |  | 		$(this).attr('href', base + '&returnto' + encodeURIComponent(Grocy.CurrentUrlRelative)); | 
					
						
							| 
									
										
										
										
											2020-08-31 19:11:51 +02:00
										 |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-09-14 11:20:29 +02:00
										 |  |  |  | 	else | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2022-02-13 20:07:29 +01:00
										 |  |  |  | 		$(this).attr('href', base + '?returnto=' + encodeURIComponent(Grocy.CurrentUrlRelative)); | 
					
						
							| 
									
										
										
										
											2020-08-31 19:11:51 +02:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-21 18:01:47 +02:00
										 |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2020-08-31 19:11:51 +02:00
										 |  |  |  | $(document).on("click", "a.btn.link-return", function(e) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	e.preventDefault(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var link = GetUriParam("returnto"); | 
					
						
							|  |  |  |  | 	if (!link || !link.length > 0) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		location.href = $(e.currentTarget).attr("href"); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	else | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		location.href = U(link); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2020-09-14 11:15:11 +02:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-14 11:20:29 +02:00
										 |  |  |  | $('.dropdown-item').has('.form-check input[type=checkbox]').on('click', function(e) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	if ($(e.target).is('div.form-check') || $(e.target).is('div.dropdown-item')) | 
					
						
							| 
									
										
										
										
											2020-09-14 11:15:11 +02:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		$(e.target).find('input[type=checkbox]').click(); | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-11 20:14:16 +01:00
										 |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2020-11-08 15:09:10 +01:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-02 17:49:35 +02:00
										 |  |  |  | $('[data-toggle="tooltip"][data-html="true"]').on("shown.bs.tooltip", function() | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	RefreshLocaleNumberDisplay(".tooltip"); | 
					
						
							|  |  |  |  | }) | 
					
						
							| 
									
										
										
										
											2022-04-04 21:07:14 +02:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | $(document).on("click", "#clear-filter-button", function(e) | 
					
						
							|  |  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-05-03 08:32:49 +02:00
										 |  |  |  | 	$(".tooltip").tooltip("hide"); | 
					
						
							| 
									
										
										
										
											2022-04-04 21:07:14 +02:00
										 |  |  |  | }); | 
					
						
							| 
									
										
										
										
											2025-01-14 17:54:06 +01:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | $(document).on("click", '.btn, a, button', function(e) | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	// Remove focus after click
 | 
					
						
							|  |  |  |  | 	document.activeElement.blur(); | 
					
						
							|  |  |  |  | }); |