Simple PHP & SQL weight tracker for multiple persons
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

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>