Eloquent JavaScript #13# HTTP and Forms

Notes

基本是直接拷贝代码了。。原书《Eloquent JavaScript》

1、fetch

Fetch vs Ajax - Xul.fr

Why I won't be using Fetch API in my apps – Shahar Talmi – Medium(这篇文章的评论区有精彩辩论:p)

Fetch API - Web APIs | MDN

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <script type="text/javascript">
            let resp;
            fetch("example/data.txt").then(response => {
                console.log(response.status);
                // → 200
                console.log(response.headers.get("Content-Type")); // header是一种类似map的对象,大小写无关紧要
                // → text/plain
                resp = response;
            }); // 只有在网络错误或者无法找到请求服务器时,promise才会被reject

            fetch("example/data.txt")
                .then(resp => resp.text()) // 读取响应也是个耗时操作,因此仍然用promise来读它
                .then(text => console.log(text));
            // → hello world

            fetch("example/data.txt", {headers: {Range: "bytes=8-19"}})
                  .then(resp => resp.text())
                  .then(console.log);
            // → the content(本机测试还是整段话输出来了?)
            
            // 默认是GET方法
            fetch("example/data.txt", {method: "DELETE" }).then(resp => {
                console.log(resp.status);
                // → 405 (本机测试是500)
            }).catch(reason => console.log(reason));
            

        </script>
    </body>

</html>

2、form

form是在还没有js的时代被设计出来的,在有js的时代,form并不是必要的。

3、focus

可以用focus()和blur()方法控制focus:

<input type="text">
<script>
  document.querySelector("input").focus();
  console.log(document.activeElement.tagName);
  // → INPUT
  document.querySelector("input").blur();
  console.log(document.activeElement.tagName);
  // → BODY
</script>

自定义tab切换focus顺序:

<input type="text" tabindex=1> <a href=".">(help)</a>
<button onclick="console.log('ok')" tabindex=2>OK</button>

4、Disabled fields

例如在执行异步操作时,不希望用户反复点击按钮:

<button>I'm all right</button>
<button disabled>I'm out</button>

5、form’s elements property

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <form action="example/submit.html">
            Name: <input type="text" name="name"><br> Password: <input type="password" name="password"><br>
            <button type="submit">Log in</button>
        </form>
        <script>
            let form = document.querySelector("form");
            console.log(form.elements[1].type);
            // → password
            console.log(form.elements.password.type);
            // → password
            console.log(form.elements.name.form == form);
            // → true
        </script>
    </body>

</html>

6、阻止提交

然后自己用js提交(fetch,ajax等)

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <form action="example/submit.html">
            Value: <input type="text" name="value">
            <button type="submit">Save</button>
        </form>
        <script>
            let form = document.querySelector("form");
            form.addEventListener("submit", event => {
                console.log("Saving value", form.elements.value.value);
                event.preventDefault();
            });
        </script>
    </body>

</html>

7、快速插入单词

借助selectionStart和selectionEnd以及value属性:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <textarea></textarea>
        <script>
            let textarea = document.querySelector("textarea");
            textarea.addEventListener("keydown", event => {
                // The key code for F2 happens to be 113
                if(event.keyCode == 113) {
                    replaceSelection(textarea, "Khasekhemwy");
                    event.preventDefault();
                }
            });

            function replaceSelection(field, word) {
                let from = field.selectionStart,
                    to = field.selectionEnd;
                field.value = field.value.slice(0, from) + word +
                    field.value.slice(to);
                // Put the cursor after the word
                field.selectionStart = from + word.length;
                field.selectionEnd = from + word.length;
            }
        </script>
    </body>

</html>

8、实时统计字数

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <input type="text"> length: <span id="length">0</span>
        <script>
            let text = document.querySelector("input");
            let output = document.querySelector("#length");
            text.addEventListener("input", () => {
                output.textContent = text.value.length;
            });
        </script>
    </body>

</html>

9、监听checkbox和radio

<label>
  <input type="checkbox" id="purple"> Make this page purple
</label>
<script>
  let checkbox = document.querySelector("#purple");
  checkbox.addEventListener("change", () => {
    document.body.style.background =
      checkbox.checked ? "mediumpurple" : "";
  });
</script>

X

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        Color:
        <label>
              <input type="radio" name="color" value="orange"> Orange
        </label>
        <label>
              <input type="radio" name="color" value="lightgreen"> Green
        </label>
        <label>
              <input type="radio" name="color" value="lightblue"> Blue
        </label>
        <script>
            let buttons = document.querySelectorAll("[name=color]");
            for(let button of Array.from(buttons)) {
                button.addEventListener("change", () => {
                    document.body.style.background = button.value;
                });
            }
        </script>
    </body>

</html>

10、监听select

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <select multiple>
            <option value="1">0001</option>
            <option value="2">0010</option>
            <option value="4">0100</option>
            <option value="8">1000</option>
        </select> = <span id="output">0</span>
        <script>
            let select = document.querySelector("select");
            let output = document.querySelector("#output");
            select.addEventListener("change", () => {
                let number = 0;
                for(let option of Array.from(select.options)) {
                    if(option.selected) {
                        number += Number(option.value);
                    }
                }
                output.textContent = number;
            });
        </script>
    </body>

</html>

11、上传文件

<input type="file">
<script>
  let input = document.querySelector("input");
  input.addEventListener("change", () => {
    if (input.files.length > 0) {
      let file = input.files[0];
      console.log("You chose", file.name);
      if (file.type) console.log("It has type", file.type);
    }
  });
</script>

异步读内容:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <input type="file" multiple>
        <script>
            let input = document.querySelector("input");
            input.addEventListener("change", () => {
                for(let file of Array.from(input.files)) {
                    let reader = new FileReader();
                    reader.addEventListener("load", () => {
                        console.log("File", file.name, "starts with",
                            reader.result.slice(0, 20));
                    });
                    reader.readAsText(file);
                }
            });
        </script>
    </body>

</html>

12、本地存储数据

有时仅将数据保留在浏览器中就足够了。

localStorage。setItem(“username”,“marijn”);
控制台。日志(localStorage的。的getItem(“用户名”));
//→marijn 
localStorage。removeItem(“username”);

localStorage特点:容量小,不可跨域。

类似的是sessionStorage,关掉浏览器就没有了。

简单笔记本↓

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        Notes:
        <select></select> <button>Add</button><br>
        <textarea style=" 100%"></textarea>

        <script>
            let list = document.querySelector("select");
            let note = document.querySelector("textarea");

            let state;

            function setState(newState) {
                list.textContent = "";
                for(let name of Object.keys(newState.notes)) {
                    let option = document.createElement("option");
                    option.textContent = name;
                    if(newState.selected == name) option.selected = true;
                    list.appendChild(option);
                }
                note.value = newState.notes[newState.selected];

                localStorage.setItem("Notes", JSON.stringify(newState));
                state = newState;
            }
            setState(JSON.parse(localStorage.getItem("Notes")) || {
                notes: {
                    "shopping list": "Carrots
Raisins"
                },
                selected: "shopping list"
            });

            list.addEventListener("change", () => {
                setState({
                    notes: state.notes,
                    selected: list.value
                });
            });
            note.addEventListener("change", () => {
                setState({
                    notes: Object.assign({}, state.notes, {
                        [state.selected]: note.value
                    }),
                    selected: state.selected
                });
            });
            document.querySelector("button")
                .addEventListener("click", () => {
                    let name = prompt("Note name");
                    if(name) setState({
                        notes: Object.assign({}, state.notes, {
                            [name]: ""
                        }),
                        selected: name
                    });
                });
        </script>
    </body>

</html>

Excercise

① Content negotiation

课本答案:

const url = "https://eloquentjavascript.net/author";
const types = ["text/plain",
               "text/html",
               "application/json",
               "application/rainbows+unicorns"];

async function showTypes() {
  for (let type of types) {
    let resp = await fetch(url, {headers: {accept: type}});
    console.log(`${type}: ${await resp.text()}
`);
  }
}

showTypes();

 ---------------------------

② A JavaScript workbench

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>

    <body>
        <textarea id="code">return "hi";</textarea>
        <button id="button">Run</button>
        <pre id="output"></pre>

        <script>
            // Your code here.
            let run = document.querySelector("#button");
            let outputNode = document.querySelector("#output");
            run.addEventListener("click", event => {
                let code = document.querySelector("#code").value;            
                let func = Function(code);
                let result;
                try {
                      result = func();
                } catch (error) {
                      result = error;
                }
                outputNode.innerText = String(result);                
            });
        </script>
    </body>

</html>

 ------------------- - -

③ Conway’s Game of Life

暂时省略

原文地址:https://www.cnblogs.com/xkxf/p/9634627.html