summaryrefslogtreecommitdiff
path: root/internal/mdedit/res/app.js
blob: c934697c55fb982d5b7b74cde39780025a23f8a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
(() => {
  const $ = selector => document.querySelector(selector);

  const handleResponse = (promise, action) => {
    const error = promise.then(response => {
      if (!response.ok) {
        throw new Error(`HTTP error, status = ${response.status} from ${response.url}`);
      }
      const title = response.headers.get("X-Mdedit-Path");
      if (title !== null && title !== "") {
        window.document.title = "mdedit: " + title;
        $("span#title").innerText = title;
      }
      return response.text();
    }).then(body => {
      action(body);
      return null;
    }).catch((error) => {
      return error;
    }).then((error) => {
      if (error != null) {
        console.log(error);
        $("span#status").innerText = `Error: ${error.message}`;
      }
    });
  };

  // handler for receiving a rendered HTML from the server
  const receiveHTML = body => {
    $("div#preview").innerHTML = body;
    $("span#status").innerText = "Saved";
  };

  // whenever the <textedit> changes, wait 3 seconds and then save all changes
  let timeoutID = null;
  const onTextChange = event => {
    if (timeoutID !== null) {
      window.clearTimeout(timeoutID);
    }
    timeoutID = window.setTimeout(uploadMarkdown, 1000);
    $("span#status").innerText = "Changed";
  };
  const uploadMarkdown = () => {
    window.clearTimeout(timeoutID);
    timeoutID = null;
    $("span#status").innerText = "Saving...";

    const opts = {
      method: "PUT",
      body: $("textarea#editor").value,
    };
    handleResponse(fetch("/data.md", opts), receiveHTML);
  };

  // load Markdown and rendered HTML on startup
  handleResponse(fetch("/data.md"), body => {
    const editor = $("textarea#editor");
    $("textarea#editor").value = body;
    handleResponse(fetch("/data.html"), receiveHTML);

    // avoid a useless upload on startup by attaching this only after the initial load is done
    for (const eventType of ["change", "input", "textInput"]) {
      editor.addEventListener(eventType, onTextChange);
    }
  });

})();