Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Блокировка с таймаутом (обратным отсчётом) кнопки после её нажатия (https://javascript.ru/forum/misc/70820-blokirovka-s-tajjmautom-obratnym-otschjotom-knopki-posle-ejo-nazhatiya.html)

mxup 04.10.2017 19:36

Блокировка с таймаутом (обратным отсчётом) кнопки после её нажатия
 
Здравствуйте, на сайте имеется кнопка для того, чтобы при регистрации запросить СМС на телефон.
Так вот, хочу сделать, чтобы был какой то интервал между запросами СМС. Для этого думаю сделать, чтобы кнопка деактивировалась (то есть на неё нельзя было нажать) на 3 минуты и рядом появлялся таймер с обратным отсчётом.
Помогите плиз как это сделать средствами JavaScript
Код кнопки:
Код:

<input id="send_sms" name="send_sms" type="button" value="Получить код в СМС">

рони 04.10.2017 20:14

jquery timer отключение кнопки на несколько минут с индикацией и localStorage
 
mxup,

<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  </style>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script>
$(function() {
    $.fn.Timer = function Timer(obj) {
        var def = {
            from: 5E3,
            duration: 5E3,
            to: 0,
            callback: null,
            step: function(now, fx) {
                $(fx.elem).html(now | 0)
            }
        };
        var opt = $.extend({}, def, obj);
        return this.each(function(indx, el) {
            $(el).queue(function() {
                el.n = opt.from;
                $(el).dequeue()
            });
            $(el).animate({
                n: opt.to
            }, {
                easing: "linear",
                duration: opt.duration,
                step: opt.step,
                complete: opt.callback
            })
        })
    };
    var end = +localStorage.getItem("end")||0, duration = 180 * 1E3;
    $("#send_sms").on("click", function (event) {
    var time = (new Date).getTime(),
    d = duration;
    if (end && end > time) {
          event.stopPropagation();
          d = end - time;
        }
    else {
       localStorage.setItem("end", time + duration);
    }
    var f = d/1000|0;
        var text = this.defaultValue;
        $(this).prop({
            disabled: true
        }).Timer({
            step: function(now, fx) {
                var a = Math.trunc(now);
                var b = ['секунда','секунды','секунд'];
                a = `${a} ${b[1 == a % 10 && 11 != a % 100 ? 0 : 2 <= a % 10 && 4 >= a % 10 && (10 > a % 100 || 20 <= a % 100) ? 1 : 2]}`;
                fx.elem.value = `текст ${a} текст`;
            },
            from: f,
            duration: d,
            to: 0,
            callback: function() {
                localStorage.setItem("end", "0");
                $(this).prop({
                    disabled: false
                }).val(text)
            }
        })
    })
    if (end && end > (new Date).getTime()) $("#send_sms").click();

});
  </script>
</head>

<body>
<input id="send_sms" name="send_sms" type="button" value="Получить код в СМС" >
</body>
</html>

Rasy 04.10.2017 20:22

mxup,
/**

TODO:
- Клик на кнопку. Добавить атрибут disabled.
- Записать в локалсторэдж время в миллисекундах с 1 января 1970 года до текущего момента.
- Добавить 180000 миллисекунд. Записать в локалсторэдж сумму. (теперь есть две метки времени: начальная и конечная).
- Запустить таймер с задержкой равной разницы двух меток времени в миллисекундах, т.е 180000 миллисекунд (3 минуты). По окончанию таймера удалить атрибут disabled у кнопки... Удалить ключи из локального хранилища...
- При обновлении страницы переопределять метку в локалсторэдж время в миллисекундах с 1970 года до текущего момента. Снова вычислить разницу двух меток, передать аргумент разницы в функцию с таймером и запустить отсчет.

*/

mxup 04.10.2017 20:31

Ваш вариант для того чтобы при обновлении страницы таймер не сбрасывался на начальное значение?

Rasy 04.10.2017 20:34

mxup,
Мой? Ага, такая логика.

mxup 04.10.2017 20:51

Цитата:

Сообщение от Rasy (Сообщение 466568)
mxup,
Мой? Ага, такая логика.

Да, логика хорошая, только реализация небось сложноватая.

рони 04.10.2017 21:07

Rasy,
спасибо
:write: внесены изменения в пост №2

Rasy 04.10.2017 21:10

рони,
Не за что. Мне до твоего скилла еще пахать и пахать:)

Nexus 05.10.2017 10:59

рони, можете объяснить почему вы использовали побитовое ИЛИ?
step: function(now, fx) {
	$(fx.elem).html(now | 0)
}

PS. Я не понимаю как работаю побитовые операторы.

Alexandroppolus 05.10.2017 11:23

подозреваю, что здесь это округление до целого.

аналог Math.floor, но только если число не больше максимального int32

рони 05.10.2017 11:29

Цитата:

Сообщение от Alexandroppolus
это округление до целого.

Цитата:

Сообщение от Alexandroppolus
только если число не больше максимального int32

:yes:

Nexus 05.10.2017 11:36

Цитата:

Сообщение от Alexandroppolus
int32

Number.MAX_SAFE_INTEGER имеете ввиду?

Alexandroppolus 05.10.2017 12:00

Nexus,

int32 простирается от -2147483648 до 2147483647 включительно (от -(2**31) до 2**31-1). Все что в этих пределах, может нормально и без сюрпризов подвергаться побитовым действиям.

а всё потому, что поразрядные операции сначала приводят число к формату int32, потом что-то уже делают. X | 0 просто приводится, потому как "| 0" всегда ничего не меняет.

Nexus 05.10.2017 12:05

Alexandroppolus, благодарю за ответ.

рони 05.10.2017 12:38

Nexus,
Округление битовыми операторами
округление

Nexus 05.10.2017 13:06

рони, благодарю за ссылки.
В приведенных вами статьях описываются способы применения побитовых операторов (округление в том числе).
Великолепно знать, что округлить число можно еще и этим способом, однако лучше всего понять, как эти операторы работают.
Сегодня вечером еще раз попробую понять как они работают.
Еще раз спасибо.

mxup 11.10.2017 18:08

Кнопка отлично работает спасибо. А подскажите ещё пожалуйста вот что: можно ли ещё заблокировать на это время функцию JavaScript, которая вызывается нажатием этой кнопки? То есть чтобы клиент какими нибудь обходными путями (без кнопки) не мог её вызвать.

рони 11.10.2017 18:19

Цитата:

Сообщение от mxup
можно ли ещё заблокировать на это время функцию JavaScript

нет, клиент волен делать с JavaScript, что ему хочется, ограничение возможно только на сервере.

stewe7 08.05.2020 17:03

Никак не могу понять, как к счетчику добавить произвольный текст... Чтобы был не просто таймер с цифрами, а в виде "10 секунд".
Есть у кого мысли?

рони 08.05.2020 17:43

Цитата:

Сообщение от stewe7
как к счетчику добавить произвольный текст...

добавлено строка 58, пост #2, текст вокруг ${a} изменить или убрать.

sayman100 21.07.2023 15:46

Изменить количество кликов по кнопке
 
Цитата:

Сообщение от рони (Сообщение 466557)
mxup,

<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  </style>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script>
$(function() {
    $.fn.Timer = function Timer(obj) {
        var def = {
            from: 5E3,
            duration: 5E3,
            to: 0,
            callback: null,
            step: function(now, fx) {
                $(fx.elem).html(now | 0)
            }
        };
        var opt = $.extend({}, def, obj);
        return this.each(function(indx, el) {
            $(el).queue(function() {
                el.n = opt.from;
                $(el).dequeue()
            });
            $(el).animate({
                n: opt.to
            }, {
                easing: "linear",
                duration: opt.duration,
                step: opt.step,
                complete: opt.callback
            })
        })
    };
    var end = +localStorage.getItem("end")||0, duration = 180 * 1E3;
    $("#send_sms").on("click", function (event) {
    var time = (new Date).getTime(),
    d = duration;
    if (end && end > time) {
          event.stopPropagation();
          d = end - time;
        }
    else {
       localStorage.setItem("end", time + duration);
    }
    var f = d/1000|0;
        var text = this.defaultValue;
        $(this).prop({
            disabled: true
        }).Timer({
            step: function(now, fx) {
                var a = Math.trunc(now);
                var b = ['секунда','секунды','секунд'];
                a = `${a} ${b[1 == a % 10 && 11 != a % 100 ? 0 : 2 <= a % 10 && 4 >= a % 10 && (10 > a % 100 || 20 <= a % 100) ? 1 : 2]}`;
                fx.elem.value = `текст ${a} текст`;
            },
            from: f,
            duration: d,
            to: 0,
            callback: function() {
                localStorage.setItem("end", "0");
                $(this).prop({
                    disabled: false
                }).val(text)
            }
        })
    })
    if (end && end > (new Date).getTime()) $("#send_sms").click();

});
  </script>
</head>

<body>
<input id="send_sms" name="send_sms" type="button" value="Получить код в СМС" >
</body>
</html>

Народ как в этом скрипте сделать так, что бы был не один клик по кнопке, а предположим 10 нажатий, после чего срабатывал таймаут?

рони 21.07.2023 16:56

Цитата:

Сообщение от sayman100
10 нажатий, после чего срабатывал таймаут?

<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  </style>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script>
$(function() {
    $.fn.Timer = function Timer(obj) {
        var def = {
            from: 5E3,
            duration: 5E3,
            to: 0,
            callback: null,
            step: function(now, fx) {
                $(fx.elem).html(now | 0)
            }
        };
        var opt = $.extend({}, def, obj);
        return this.each(function(indx, el) {
            $(el).queue(function() {
                el.n = opt.from;
                $(el).dequeue()
            });
            $(el).animate({
                n: opt.to
            }, {
                easing: "linear",
                duration: opt.duration,
                step: opt.step,
                complete: opt.callback
            })
        })
    };
    var end = +localStorage.getItem("end")||0, duration = 180 * 1E3;
    var num = +localStorage.getItem("num")||0;
    $("#send_sms").on("click", function (event) {
    num++;
    localStorage.setItem("num", num);
    if(num < 10) return;
    var time = (new Date).getTime(),
    d = duration;
    if (end && end > time) {
          event.stopPropagation();
          d = end - time;
        }
    else {
       localStorage.setItem("end", time + duration);
    }
    var f = d/1000|0;
        var text = this.defaultValue;
        $(this).prop({
            disabled: true
        }).Timer({
            step: function(now, fx) {
                var a = Math.trunc(now);
                var b = ['секунда','секунды','секунд'];
                a = `${a} ${b[1 == a % 10 && 11 != a % 100 ? 0 : 2 <= a % 10 && 4 >= a % 10 && (10 > a % 100 || 20 <= a % 100) ? 1 : 2]}`;
                fx.elem.value = `текст ${a} текст`;
            },
            from: f,
            duration: d,
            to: 0,
            callback: function() {
                localStorage.setItem("end", "0");
                localStorage.setItem("num", "0");
                $(this).prop({
                    disabled: false
                }).val(text)
            }
        })
    })
    if (end && end > (new Date).getTime()) $("#send_sms").click();

});
  </script>
</head>

<body>
<input id="send_sms" name="send_sms" type="button" value="Получить код в СМС" >
</body>
</html>

sayman100 21.07.2023 17:28

Спасибо огромное то что надо :victory:

sayman100 21.07.2023 21:27

Лимит нажатий на кнопку
 
Цитата:

Сообщение от рони (Сообщение 552812)
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  </style>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script>
$(function() {
    $.fn.Timer = function Timer(obj) {
        var def = {
            from: 5E3,
            duration: 5E3,
            to: 0,
            callback: null,
            step: function(now, fx) {
                $(fx.elem).html(now | 0)
            }
        };
        var opt = $.extend({}, def, obj);
        return this.each(function(indx, el) {
            $(el).queue(function() {
                el.n = opt.from;
                $(el).dequeue()
            });
            $(el).animate({
                n: opt.to
            }, {
                easing: "linear",
                duration: opt.duration,
                step: opt.step,
                complete: opt.callback
            })
        })
    };
    var end = +localStorage.getItem("end")||0, duration = 180 * 1E3;
    var num = +localStorage.getItem("num")||0;
    $("#send_sms").on("click", function (event) {
    num++;
    localStorage.setItem("num", num);
    if(num < 10) return;
    var time = (new Date).getTime(),
    d = duration;
    if (end && end > time) {
          event.stopPropagation();
          d = end - time;
        }
    else {
       localStorage.setItem("end", time + duration);
    }
    var f = d/1000|0;
        var text = this.defaultValue;
        $(this).prop({
            disabled: true
        }).Timer({
            step: function(now, fx) {
                var a = Math.trunc(now);
                var b = ['секунда','секунды','секунд'];
                a = `${a} ${b[1 == a % 10 && 11 != a % 100 ? 0 : 2 <= a % 10 && 4 >= a % 10 && (10 > a % 100 || 20 <= a % 100) ? 1 : 2]}`;
                fx.elem.value = `текст ${a} текст`;
            },
            from: f,
            duration: d,
            to: 0,
            callback: function() {
                localStorage.setItem("end", "0");
                localStorage.setItem("num", "0");
                $(this).prop({
                    disabled: false
                }).val(text)
            }
        })
    })
    if (end && end > (new Date).getTime()) $("#send_sms").click();

});
  </script>
</head>

<body>
<input id="send_sms" name="send_sms" type="button" value="Получить код в СМС" >
</body>
</html>

Подскажите еще пожалуйста, данный скрипт немного не так отрабатывает, у него после того, как время ожидания прошло, кнопка нажимается только один раз, а мне нужно сделать так что бы когда лимит времени прошел, можно было нажимать еще 10 раз и так постоянно. И еще данный код при обновлении странице автоматически кликает по кнопке 1 раз (но только когда кнопка находится в режиме ожидания окончания лимита), получается что на сайте у меня срабатывает мой код к которому я подвязываю данную кнопку при каждом обновлении страницы (но повторю, это происходит только когда кнопка находится в режиме ожидания, как это поправить?

Вообще мне нужна просто кнопка с лимитом нажатий (желательно отобразить на кнопке сколько нажатий осталось), чтобы лимит при обновлении страницы не обнулялся, как выполнено в коде выше и надпись на ней в режиме ожидания, что то вроде "Лимит окончен подождите (таймер 20 мин)" . Можете помочь с такой кнопкой пожалуйста!

рони 21.07.2023 23:37

Цитата:

Сообщение от sayman100
можно было нажимать еще 10 раз

добавить
num = 0;
в строку 68.

рони 21.07.2023 23:54

sayman100,
<!DOCTYPE html>
<html>

<head>
    <title>Untitled</title>
    <meta charset="utf-8">
    <style type="text/css">
    </style>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script>
        $(function() {
            $.fn.Timer = function Timer(obj) {
                var def = {
                    from: 5E3,
                    duration: 5E3,
                    to: 0,
                    callback: null,
                    step: function(now, fx) {
                        $(fx.elem).html(now | 0)
                    }
                };
                var opt = $.extend({}, def, obj);
                return this.each(function(indx, el) {
                    $(el).queue(function() {
                        el.n = opt.from;
                        $(el).dequeue()
                    });
                    $(el).animate({
                        n: opt.to
                    }, {
                        easing: "linear",
                        duration: opt.duration,
                        step: opt.step,
                        complete: opt.callback
                    })
                })
            };
            var end = +localStorage.getItem("end") || 0,
                duration = 20 * 60 * 1E3;
            var num = +localStorage.getItem("num") || 0;
            var max = 20;

            $("#send_sms").on("click", function(event) {
                num++;
                localStorage.setItem("num", num);
                this.textContent = `Получить код в СМС, осталось ${max - num}`;
                if (num < max) return;
                var time = (new Date).getTime(),
                    d = duration;
                if (end && end > time) {
                    event.stopPropagation();
                    d = end - time;
                } else {
                    localStorage.setItem("end", time + duration);
                }
                var f = d / 1000 | 0;
                var text = this.defaultValue;
                $(this).prop({
                    disabled: true
                }).Timer({
                    step: function(now, fx) {
                        var a = Math.trunc(now);
                        var b = ['секунда', 'секунды', 'секунд'];
                        a = `${a} ${b[1 == a % 10 && 11 != a % 100 ? 0 : 2 <= a % 10 && 4 >= a % 10 && (10 > a % 100 || 20 <= a % 100) ? 1 : 2]}`;
                        fx.elem.textContent = `Подождите ${a}`;
                    },
                    from: f,
                    duration: d,
                    to: 0,
                    callback: function() {
                        localStorage.setItem("end", "0");
                        localStorage.setItem("num", "0");
                        num = 0;
                        $(this).prop({
                            disabled: false
                        }).val(text)
                    }
                })
            })
            if (num) $("#send_sms").click();

        });
    </script>
</head>

<body>
    <button id="send_sms" name="send_sms" type="button">Получить код в СМС</button>
</body>

</html>

sayman100 22.07.2023 00:46

Цены тебе нет, просто от души, идеально, мне бы твои знания, Спасибо!

sayman100 22.07.2023 01:15

Цитата:

Сообщение от рони (Сообщение 552816)
sayman100,
<!DOCTYPE html>
<html>

<head>
    <title>Untitled</title>
    <meta charset="utf-8">
    <style type="text/css">
    </style>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script>
        $(function() {
            $.fn.Timer = function Timer(obj) {
                var def = {
                    from: 5E3,
                    duration: 5E3,
                    to: 0,
                    callback: null,
                    step: function(now, fx) {
                        $(fx.elem).html(now | 0)
                    }
                };
                var opt = $.extend({}, def, obj);
                return this.each(function(indx, el) {
                    $(el).queue(function() {
                        el.n = opt.from;
                        $(el).dequeue()
                    });
                    $(el).animate({
                        n: opt.to
                    }, {
                        easing: "linear",
                        duration: opt.duration,
                        step: opt.step,
                        complete: opt.callback
                    })
                })
            };
            var end = +localStorage.getItem("end") || 0,
                duration = 20 * 60 * 1E3;
            var num = +localStorage.getItem("num") || 0;
            var max = 20;

            $("#send_sms").on("click", function(event) {
                num++;
                localStorage.setItem("num", num);
                this.textContent = `Получить код в СМС, осталось ${max - num}`;
                if (num < max) return;
                var time = (new Date).getTime(),
                    d = duration;
                if (end && end > time) {
                    event.stopPropagation();
                    d = end - time;
                } else {
                    localStorage.setItem("end", time + duration);
                }
                var f = d / 1000 | 0;
                var text = this.defaultValue;
                $(this).prop({
                    disabled: true
                }).Timer({
                    step: function(now, fx) {
                        var a = Math.trunc(now);
                        var b = ['секунда', 'секунды', 'секунд'];
                        a = `${a} ${b[1 == a % 10 && 11 != a % 100 ? 0 : 2 <= a % 10 && 4 >= a % 10 && (10 > a % 100 || 20 <= a % 100) ? 1 : 2]}`;
                        fx.elem.textContent = `Подождите ${a}`;
                    },
                    from: f,
                    duration: d,
                    to: 0,
                    callback: function() {
                        localStorage.setItem("end", "0");
                        localStorage.setItem("num", "0");
                        num = 0;
                        $(this).prop({
                            disabled: false
                        }).val(text)
                    }
                })
            })
            if (num) $("#send_sms").click();

        });
    </script>
</head>

<body>
    <button id="send_sms" name="send_sms" type="button">Получить код в СМС</button>
</body>

</html>

Блин, только название кнопки не возвращается, зависает на "осталось 0 секунд", а нужно вернуть на исходную "Получить код в СМС" после тайм аута где это исправить?

рони 22.07.2023 06:55

sayman100,
строку 76 заменить на
}).text("Получить код в СМС");


не копируйте сообщения целиком, без необходимости, и есть цитирование.


Часовой пояс GMT +3, время: 16:23.