max80.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Get an element by id or an Element object
  2. function getelem(id) {
  3. return (id instanceof Element) ? id : document.getElementById(id);
  4. }
  5. // Read a key=value text file and return it as a Promise of a Map
  6. function fetchconfig(url) {
  7. var xdr = new XMLHttpRequest();
  8. return fetch(url, {cache: "no-store"})
  9. .then(res => {
  10. if (!res.ok) {
  11. throw new Error("HTTP error "+response.status);
  12. } else {
  13. return res.text();
  14. }
  15. })
  16. .then(text => {
  17. var map = new Map();
  18. for (const c of text.split(/[\r\n]+/)) {
  19. const eqs = c.indexOf("=");
  20. if (eqs > 0) {
  21. map.set(c.slice(0, eqs), c.slice(eqs+1));
  22. }
  23. }
  24. return map;
  25. });
  26. }
  27. // Initialize a form from a map
  28. function initform(form,map) {
  29. var button = null;
  30. for (const field of getelem(form).elements) {
  31. if (field instanceof HTMLInputElement) {
  32. var val = map.get(field.name);
  33. if (!val)
  34. val = '';
  35. if (field.type == 'checkbox') {
  36. field.checked = !val.match(/^(0*|[fn].*|of.*)$/i);
  37. } else if (field.type == 'radio') {
  38. field.checked = (val == field.name);
  39. } else {
  40. field.value = val;
  41. }
  42. } else if (field instanceof HTMLButtonElement &&
  43. field.type == 'submit') {
  44. button = field;
  45. }
  46. }
  47. if (button) {
  48. button.disabled = false; // All loaded, enable the submit button
  49. }
  50. }
  51. // Load form initialization data
  52. function loadform(form, url) {
  53. fetchconfig(url)
  54. .then(map => { initform(form, map) })
  55. .catch(() => {});
  56. }
  57. // Insert status data from a map
  58. function initstatus(map)
  59. {
  60. for (const [key,val] of map) {
  61. var e = document.getElementById(key);
  62. if (e) {
  63. e.innerText = val;
  64. }
  65. }
  66. }
  67. // Load status data
  68. function loaddata(url)
  69. {
  70. fetchconfig(url)
  71. .then(map => { initdata(map) })
  72. .catch(() => {});
  73. }
  74. // POST file upload with progress and response text
  75. function uploadfile(event) {
  76. event.preventDefault();
  77. var form = event.currentTarget;
  78. var elem = form.elements;
  79. var files = elem["file"].files;
  80. if (files.length != 1) {
  81. /* Show error */
  82. return;
  83. }
  84. var file = files[0];
  85. var xhr = new XMLHttpRequest();
  86. var progress = form.querySelector("progress");
  87. if (progress != undefined) {
  88. progress.value = 0;
  89. xhr.upload.addEventListener("progress", (event) => {
  90. if (event.lengthComputable) {
  91. progress.max = event.total;
  92. progress.value = event.loaded;
  93. }
  94. });
  95. }
  96. var result = form.querySelector("pre.result");
  97. if (result != undefined) {
  98. result.className = "result hide";
  99. }
  100. xhr.addEventListener("loadend", (event) => {
  101. const ok = xhr.status >= 200 && xhr.status <= 299;
  102. if (progress != undefined) {
  103. progress.value = ok ? progress.max : 0;
  104. }
  105. if (result != undefined) {
  106. result.className = "result " + (ok ? "ok" : "err");
  107. result.innerText = xhr.responseText;
  108. }
  109. });
  110. xhr.open("POST", form.action);
  111. xhr.responseType = 'text';
  112. xhr.send(file);
  113. }
  114. // Enable a button (this ensures that the necessary scripts have been
  115. // run before one can submit)
  116. function enablebutton(id,on) {
  117. getelem(id).disabled = !on;
  118. }
  119. // Flip the status of an INPUT element between text and password
  120. function showpwd(id,me) {
  121. var pwd = getelem(id);
  122. const was_visible = pwd.getAttribute('type') == 'text';
  123. const new_type = was_visible ? 'password' : 'text';
  124. const new_icon = was_visible ? 'show' : 'hide';
  125. pwd.setAttribute('type', new_type);
  126. me.innerHTML = new_icon;
  127. }
  128. // Hack to include an HTML files. Sadly, does not support
  129. // including files with <script> tags.
  130. function inc(url) {
  131. var me = document.currentScript;
  132. fetch(url)
  133. .then((response) => response.text())
  134. .then((text) => { me.outerHTML = text; });
  135. }