Я пытаюсь построить таймер обратного отсчета, который имеет 3 кнопки, управляющие таймером. Три кнопки: запуск, отмена и пауза. Таймер - это просто поле ввода текста, в которое можно ввести положительное целое число.

Мне нужно использовать основной JavaScript, а не jQuery

Кнопка Пуск: начать обратный отсчет до 0

Кнопка отмены: повторно отобразить значение ввода по умолчанию.

Кнопка паузы: удерживайте таймер на текущем значении до тех пор, пока не будет нажата кнопка «Пуск», чтобы вернуться в нормальный режим работы.

Я использую метод addEventListener для этих трех кнопок отправки, но все они срабатывают одновременно, когда я нажимаю на любую из кнопок. Я попытался разместить e.preventDefault и e.stopImmediatePropagation, но это не очень помогает.

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Countdown</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        ul {
            list-style-type: none;
            background-color: #03f72c;
        }

        .invalid {
            background-color: #c71f1f;
        }
    </style>
</head>

<body>
    <div>
        <h1>Countdown</h1>
        <form id="myForm">
            <div>
                <label for="posint">Timer:</label>
                <input type="text" id="input" name="posint">
            </div>
            <div class="controller">
                <div class="button">
                    <input id="start" type="submit" value="Start"></input>
                </div>
                <div class="button">
                    <input id="pause" type="submit" value="Pause"></input>
                </div>
                <div class="button">
                    <input id="cancel" type="submit" value="Cancel"></input>
                </div>
            </div>
            <div id="errormsgs">
                <ul id="warning">
                    <h3>Checklist</h3>
                    <li id="posint_err"></li>
                </ul>
            </div>
        </form>
    </div>
    <script>
        function formControl() {
            // getting input value
            var input = document.getElementById("input");
            var myForm = document.getElementById("myForm");
            myForm.addEventListener("submit", start);
            myForm.addEventListener("submit", cancel);
            myForm.addEventListener("submit", pause);
            // regex validate
            var containInt = /^-?[0-9]\d*$/;
            // ======== UI text ========
            var posint_err = "It must contain only an integer greater than 0";
            var expiredMsg = "expired";

            function render(target, content, attributes) {
                for (const key in attributes) {
                    target.setAttribute(key, attributes[key]);
                }
                target.value = content;
            }
            // Select All function
            function selectAll() {
                input.focus();
                input.setSelectionRange(0, input.value.length);
            }
            // UI state
            const state = {
                defaultValue: "",
                failed() {
                    document.getElementById("warning").classList.add("invalid");
                    document.getElementById("posint_err").innerHTML = posint_err;
                    document.getElementById("posint_err").style.display = "block";
                },
                success() {
                    document.getElementById("errormsgs").style.display = "none";
                },
                clear() {
                    document.getElementById("posint_err").style.display = "none";
                },
            }
            // start function
            function start(e) {
                if (parseInt(input.value) <= 0 || (!(input.value.match(containInt)))) {
                    state.clear()
                    state.failed();
                    selectAll();
                    e.preventDefault();
                    e.stopImmediatePropagation();
                    return false
                } else {
                    // success case
                    var inputValue = parseInt(input.value);
                    state.defaultValue = inputValue;
                    e.preventDefault();
                    e.stopImmediatePropagation();
                    state.success();
                    input = setInterval(countdown, 1000);
                    // Countdown function()
                    function countdown() {
                        inputValue--;
                        render(document.getElementById("input"), inputValue)
                        if (inputValue <= 0) {
                            clearInterval(input);
                            render(document.getElementById("input"), expiredMsg)
                        }
                    }
                    return false
                }
            }
            // cancel function
            function cancel(e) {
                // e.stopImmediatePropagation();
                // console.log(state.defaultValue)
                e.preventDefault();
                e.stopImmediatePropagation();
                clearInterval(input);
                render(input, state.defaultValue);
                return false
            }
            // cancel function
            function pause(e) {
                e.preventDefault();
                e.stopImmediatePropagation();
                console.log('pause')
                return false
            }
        }
        window.onload = function () {
            formControl();
        };
    </script>
</body>

</html>
1
Huy Le 2 Май 2018 в 06:58

1 ответ

Лучший ответ

Не прикрепляйте слушателей к form - вместо этого прикрепляйте их к input. (Также удалите type="submit" из этих входов - используйте вместо этого type="button", чтобы он отображался так, как вы хотите)

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Countdown</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
        ul {
            list-style-type: none;
            background-color: #03f72c;
        }

        .invalid {
            background-color: #c71f1f;
        }
    </style>
</head>

<body>
    <div>
        <h1>Countdown</h1>
        <form id="myForm">
            <div>
                <label for="posint">Timer:</label>
                <input type="text" id="input" name="posint">
            </div>
            <div class="controller">
                <div class="button">
                    <input type="button" id="start" value="Start"></input>
                </div>
                <div class="button">
                    <input type="button" id="pause" value="Pause"></input>
                </div>
                <div class="button">
                    <input type="button" id="cancel" value="Cancel"></input>
                </div>
            </div>
            <div id="errormsgs">
                <ul id="warning">
                    <h3>Checklist</h3>
                    <li id="posint_err"></li>
                </ul>
            </div>
        </form>
    </div>
    <script>
        function formControl() {
            // getting input value
            var input = document.getElementById("input");
            var myForm = document.getElementById("myForm");
            document.querySelector('#start').addEventListener("click", start);
            document.querySelector('#cancel').addEventListener("click", cancel);
            document.querySelector('#pause').addEventListener("click", pause);
            // regex validate
            var containInt = /^-?[0-9]\d*$/;
            // ======== UI text ========
            var posint_err = "It must contain only an integer greater than 0";
            var expiredMsg = "expired";

            function render(target, content, attributes) {
                for (const key in attributes) {
                    target.setAttribute(key, attributes[key]);
                }
                target.value = content;
            }
            // Select All function
            function selectAll() {
                input.focus();
                input.setSelectionRange(0, input.value.length);
            }
            // UI state
            const state = {
                defaultValue: "",
                failed() {
                    document.getElementById("warning").classList.add("invalid");
                    document.getElementById("posint_err").innerHTML = posint_err;
                    document.getElementById("posint_err").style.display = "block";
                },
                success() {
                    document.getElementById("errormsgs").style.display = "none";
                },
                clear() {
                    document.getElementById("posint_err").style.display = "none";
                },
            }
            // start function
            function start(e) {
                if (parseInt(input.value) <= 0 || (!(input.value.match(containInt)))) {
                    state.clear()
                    state.failed();
                    selectAll();
                    e.preventDefault();
                    e.stopImmediatePropagation();
                    return false
                } else {
                    // success case
                    var inputValue = parseInt(input.value);
                    state.defaultValue = inputValue;
                    e.preventDefault();
                    e.stopImmediatePropagation();
                    state.success();
                    input = setInterval(countdown, 1000);
                    // Countdown function()
                    function countdown() {
                        inputValue--;
                        render(document.getElementById("input"), inputValue)
                        if (inputValue <= 0) {
                            clearInterval(input);
                            render(document.getElementById("input"), expiredMsg)
                        }
                    }
                    return false
                }
            }
            // cancel function
            function cancel(e) {
              console.log('cancel');
                // e.stopImmediatePropagation();
                // console.log(state.defaultValue)
                e.preventDefault();
                e.stopImmediatePropagation();
                clearInterval(input);
                render(input, state.defaultValue);
                return false
            }
            // cancel function
            function pause(e) {
                e.preventDefault();
                e.stopImmediatePropagation();
                console.log('pause')
                return false
            }
        }
        window.onload = function () {
            formControl();
        };
    </script>
</body>

</html>
1
CertainPerformance 2 Май 2018 в 04:04