1
0

convert.js 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // The converter form: sends the address to /api/convert (rekopub-web) and
  2. // shows the download links on this page. Without this script the form still
  3. // works, and the server answers with a page of its own.
  4. (function () {
  5. "use strict";
  6. var form = document.getElementById("convert-form");
  7. var fields = document.getElementById("convert-fields");
  8. var result = document.getElementById("convert-result");
  9. var keepHours = document.getElementById("keep-hours");
  10. var button = form.querySelector("button");
  11. if (!window.fetch || !window.URLSearchParams) return;
  12. function el(tag, attrs, text) {
  13. var node = document.createElement(tag);
  14. for (var k in attrs) node.setAttribute(k, attrs[k]);
  15. if (text) node.textContent = text;
  16. return node;
  17. }
  18. function show(nodes) {
  19. result.replaceChildren.apply(result, nodes);
  20. }
  21. function message(text, isError) {
  22. show([el("p", isError ? { "class": "convert-error" } : {}, text)]);
  23. }
  24. function hours(n) {
  25. return n === 1 ? "1 hour" : n + " hours";
  26. }
  27. // pause disables the form while conversions are paused.
  28. function pause(text) {
  29. fields.disabled = true;
  30. message(text, true);
  31. }
  32. function size(bytes) {
  33. return bytes < 1024 * 1024
  34. ? Math.ceil(bytes / 1024) + " KB"
  35. : (bytes / 1024 / 1024).toFixed(1) + " MB";
  36. }
  37. // The server's reply, or a stand-in when nginx answered instead (a
  38. // limit, a timeout or the converter being down).
  39. function readReply(res) {
  40. return res.json().catch(function () {
  41. if (res.status === 429) return { error: "Too many requests at once. Please wait a minute and try again." };
  42. if (res.status === 503) return { error: "The converter is busy. Please try again in a minute." };
  43. if (res.status === 504) return { error: "That page took too long to convert." };
  44. return { error: "The converter isn't available right now. Please try again later." };
  45. });
  46. }
  47. fetch("/api/status", { headers: { Accept: "application/json" } })
  48. .then(readReply)
  49. .then(function (st) {
  50. if (st.keepHours) keepHours.textContent = st.keepHours;
  51. if (st.paused) pause(st.error);
  52. })
  53. .catch(function () {});
  54. form.addEventListener("submit", function (event) {
  55. event.preventDefault();
  56. var body = new URLSearchParams(new FormData(form));
  57. fields.disabled = true;
  58. button.textContent = "Converting…";
  59. message("Converting… this can take up to a minute.");
  60. fetch(form.action, {
  61. method: "POST",
  62. headers: { Accept: "application/json" },
  63. body: body
  64. })
  65. .then(readReply)
  66. .then(function (rep) {
  67. fields.disabled = false;
  68. button.textContent = "Convert";
  69. if (rep.paused) return pause(rep.error);
  70. if (rep.error) return message(rep.error, true);
  71. var list = el("ul", { "class": "convert-files" });
  72. rep.files.forEach(function (f) {
  73. var li = el("li");
  74. li.append(el("a", { href: f.url, download: "" }, f.name), " ",
  75. el("span", { "class": "small" }, f.format + ", " + size(f.size)));
  76. list.append(li);
  77. });
  78. var nodes = [el("p", { "class": "small" }, "Links work for " + hours(rep.keepHours) + "."), list];
  79. if (rep.warning) nodes.push(el("p", { "class": "convert-error" }, rep.warning));
  80. show(nodes);
  81. })
  82. .catch(function () {
  83. fields.disabled = false;
  84. button.textContent = "Convert";
  85. message("Couldn't reach the converter. Check your connection and try again.", true);
  86. });
  87. });
  88. })();