Simple PHP & SQL weight tracker for multiple persons
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.html 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. <html lang="en">
  2. <head>
  3. <meta charset="utf-8" />
  4. <title>Weight-Track</title>
  5. <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.0/dist/Chart.bundle.min.js" integrity="sha256-tSYaQkuUF17Z5HozxXRWckY1j6uVLYFEHGEooJ6YsP0=" crossorigin="anonymous"></script>
  6. </head>
  7. <body>
  8. <div id="content">
  9. <h1>Weight-Track</h1>
  10. <p id="status">Please wait while Weight-Track is loading... (JavaScript needed)</p>
  11. </div>
  12. <div id="footer">
  13. <p>Made with <a href="https://www.chartjs.org/docs/latest/">Chart.js</a></p>
  14. </div>
  15. <script type="text/javascript">
  16. var colorFromIndex = function(index) {
  17. var colors = [
  18. '129, 38, 204',
  19. '48, 181, 36',
  20. '255, 99, 132',
  21. '54, 162, 235',
  22. '255, 206, 86',
  23. '75, 192, 192',
  24. '153, 102, 255',
  25. '255, 159, 64'
  26. ];
  27. if (index < colors.length) {
  28. return colors[index];
  29. } else {
  30. return '120, 120, 120';
  31. }
  32. };
  33. var createDataset = function(name, data, color, id) {
  34. return {
  35. label: name,
  36. data: data,
  37. yAxisID: id,
  38. backgroundColor: [
  39. 'rgba(' + color + ', 0)'
  40. ],
  41. borderColor: [
  42. 'rgba(' + color + ', 1)'
  43. ],
  44. pointBorderColor: 'rgba(' + color + ', 1)',
  45. pointRadius: 2,
  46. borderWidth: 4
  47. };
  48. };
  49. var addToForm = function(form, element, name) {
  50. var fe = document.createElement('p');
  51. fe.innerHTML = name + ' ';
  52. fe.appendChild(element);
  53. form.appendChild(fe);
  54. };
  55. var renderUser = function(data) {
  56. var div = document.createElement('div');
  57. var ctx = document.createElement('canvas');
  58. var min_date = new Date('3000-01-01T00:00:00');
  59. var max_date = new Date('1000-01-01T00:00:00');
  60. var min_kilo = 1000;
  61. var max_kilo = 0;
  62. for (var i = 0; i < data.users.length; i++) {
  63. for (var j = 0; j < data.users[i].data.length; j++) {
  64. temp_date = new Date(data.users[i].data[j].x);
  65. temp_kilo = parseInt(data.users[i].data[j].y);
  66. if (temp_date < min_date) {
  67. min_date = temp_date;
  68. }
  69. if (temp_date > max_date) {
  70. max_date = temp_date;
  71. }
  72. if (temp_kilo < min_kilo) {
  73. min_kilo = temp_kilo;
  74. }
  75. if (temp_kilo > max_kilo) {
  76. max_kilo = temp_kilo;
  77. }
  78. }
  79. }
  80. var days = (max_date - min_date) / 1000 / 60 / 60 / 24;
  81. var pixels_per_day = 3000 / 365;
  82. var width_px = days * pixels_per_day;
  83. var kilos = (max_kilo - min_kilo);
  84. var pixels_per_kilo = 1400 / 100;
  85. var height_px = kilos * pixels_per_kilo;
  86. var datasets = [];
  87. for (var i = 0; i < data.users.length; i++) {
  88. for (var j = 0; j <= 1; j++) {
  89. var set = createDataset(data.users[i].name,
  90. data.users[i].data, colorFromIndex(i), j ? 'A' : 'B');
  91. datasets.push(set);
  92. }
  93. }
  94. var chart = new Chart(ctx, {
  95. type: 'line',
  96. data: {
  97. datasets: datasets
  98. },
  99. options: {
  100. maintainAspectRatio: false,
  101. scales: {
  102. xAxes: [{
  103. type: 'time',
  104. time: {
  105. unit: 'day'
  106. }
  107. }],
  108. yAxes: [{
  109. id: 'A',
  110. type: 'linear',
  111. position: 'left'
  112. }, {
  113. id: 'B',
  114. type: 'linear',
  115. position: 'right'
  116. }]
  117. },
  118. events: [
  119. 'mousemove', 'mouseout', 'click',
  120. 'touchstart', 'touchmove', 'touchend'
  121. ],
  122. tooltips: {
  123. mode: 'nearest',
  124. intersect: false,
  125. axis: 'xy'
  126. }
  127. }
  128. });
  129. if (data.users.length > 0) {
  130. div_wrapper = document.createElement('div');
  131. div_wrapper.setAttribute('style', 'width: ' + Math.ceil(width_px) + 'px;');
  132. div_wrapper.style.width = Math.ceil(width_px) + 'px';
  133. div_wrapper.style.height = height_px + 'px';
  134. div_wrapper.width = Math.ceil(width_px);
  135. div_wrapper.height = height_px;
  136. div_wrapper.appendChild(ctx);
  137. div_wrapper2 = document.createElement('div');
  138. div_wrapper2.id = 'scroller';
  139. div_wrapper2.setAttribute('style', 'overflow-x: auto; overflow-y: auto;');
  140. div_wrapper2.appendChild(div_wrapper);
  141. size_slider = document.createElement('input');
  142. size_slider.setAttribute('type', 'range');
  143. size_slider.setAttribute('min', window.innerWidth);
  144. size_slider.setAttribute('max', Math.ceil(width_px));
  145. size_slider.setAttribute('value', Math.ceil(width_px));
  146. size_slider.oninput = function() {
  147. div_wrapper.setAttribute('style', 'width: ' + Math.ceil(width_px) + 'px;');
  148. div_wrapper.style.width = Math.ceil(width_px) + 'px';
  149. div_wrapper.width = Math.ceil(width_px);
  150. }
  151. div.appendChild(size_slider);
  152. div.appendChild(div_wrapper2);
  153. div.appendChild(document.createElement('hr'));
  154. var date = new Date();
  155. var hours = date.getHours();
  156. hours = (hours < 10) ? '0' + hours : hours;
  157. var minutes = date.getMinutes();
  158. minutes = (minutes < 10) ? '0' + minutes : minutes;
  159. var form_append = document.createElement('form');
  160. form_append.setAttribute('method', 'post');
  161. form_append.setAttribute('action', 'weight.php');
  162. var p_append = document.createElement('p');
  163. p_append.innerHTML = 'Add new Data-Point:';
  164. form_append.appendChild(p_append);
  165. var name_append = document.createElement('select');
  166. for (var i = 0; i < data.users.length; i++) {
  167. var option = document.createElement('option');
  168. option.text = data.users[i].name;
  169. option.value = 'user_' + data.users[i].id;
  170. name_append.add(option);
  171. }
  172. name_append.setAttribute('name', 'username');
  173. name_append.required = true;
  174. addToForm(form_append, name_append, 'Username:');
  175. var date_append = document.createElement('input');
  176. date_append.setAttribute('type', 'date');
  177. date_append.setAttribute('name', 'date');
  178. date_append.setAttribute('placeholder', 'Date');
  179. date_append.required = true;
  180. date_append.value = date.toISOString().slice(0, 10);
  181. addToForm(form_append, date_append, 'Date:');
  182. var time_append = document.createElement('input');
  183. time_append.setAttribute('type', 'time');
  184. time_append.setAttribute('name', 'time');
  185. time_append.setAttribute('placeholder', 'Time');
  186. time_append.required = true;
  187. time_append.value = hours + ':' + minutes;
  188. addToForm(form_append, time_append, 'Time:');
  189. var weight_append = document.createElement('input');
  190. weight_append.setAttribute('type', 'number');
  191. weight_append.setAttribute('name', 'weight');
  192. weight_append.setAttribute('step', '0.1');
  193. weight_append.min = 42.0;
  194. weight_append.max = 999.9;
  195. weight_append.setAttribute('placeholder', 'Weight');
  196. weight_append.required = true;
  197. addToForm(form_append, weight_append, 'Weight:');
  198. var submit_append = document.createElement('input');
  199. submit_append.setAttribute('type', 'submit');
  200. submit_append.setAttribute('value', 'Add Data');
  201. form_append.appendChild(submit_append);
  202. div.appendChild(form_append);
  203. div.appendChild(document.createElement('hr'));
  204. }
  205. var form_new = document.createElement('form');
  206. form_new.setAttribute('method', 'post');
  207. form_new.setAttribute('action', 'weight.php');
  208. var p_new = document.createElement('p');
  209. p_new.innerHTML = 'Add new User:';
  210. form_new.appendChild(p_new);
  211. var name_new = document.createElement('input');
  212. name_new.setAttribute('type', 'text');
  213. name_new.setAttribute('name', 'username');
  214. name_new.setAttribute('placeholder', 'Name');
  215. name_new.required = true;
  216. addToForm(form_new, name_new, 'Username:');
  217. var submit_new = document.createElement('input');
  218. submit_new.setAttribute('type', 'submit');
  219. submit_new.setAttribute('value', 'Add User');
  220. form_new.appendChild(submit_new);
  221. div.appendChild(form_new);
  222. div.appendChild(document.createElement('hr'));
  223. document.getElementById("content").appendChild(div);
  224. document.getElementById("scroller").scrollLeft += width_px * 4;
  225. };
  226. var getJSON = function(url, callback) {
  227. var xhr = new XMLHttpRequest();
  228. xhr.open('GET', url, true);
  229. xhr.responseType = 'json';
  230. xhr.onload = function() {
  231. if (xhr.status === 200) {
  232. callback(null, xhr.response);
  233. } else {
  234. callback(xhr.status, xhr.response);
  235. }
  236. };
  237. xhr.send();
  238. };
  239. document.getElementById("status").textContent = "Loading from Database...";
  240. getJSON('weight.php', function(err, data) {
  241. if (err !== null) {
  242. document.getElementById("status").textContent = 'Error: ' + err;
  243. return;
  244. }
  245. if (typeof data.error !== 'undefined') {
  246. document.getElementById("status").textContent = 'Error: ' + data.error;
  247. return;
  248. }
  249. if (typeof data.users !== 'undefined') {
  250. var s = 'Received data for ' + data.users.length + ' users';
  251. if (data.users.length > 0) {
  252. s += ': ';
  253. for (var i = 0; i < data.users.length; i++) {
  254. s += '"' + data.users[i].name + '"';
  255. if (i < (data.users.length - 1)) {
  256. s += ', ';
  257. }
  258. }
  259. s += '. Rendering...';
  260. } else {
  261. s += '. Nothing to show!';
  262. }
  263. document.getElementById("status").textContent = s;
  264. renderUser(data);
  265. } else {
  266. document.getElementById("status").textContent = 'Error: no data';
  267. return;
  268. }
  269. });
  270. </script>
  271. </body>
  272. </html>