单击时禁用按钮一分钟
Disable Button for one minute when it's clicked
我正在尝试制作一个按钮,当您单击它时将禁用 1 分钟。
仅当启用该按钮并单击它时,才应将 25 点添加到 div(div 从 0 开始)。
每次点击后,按钮将被禁用,计时器将启动 运行.
这里有一些图片可以让整个事情更容易理解:
类似于:
const button = document.getElementById("myBtn")
function freeze () {
button.disabled = true
setTimeout(function() {
button.disabled = false
}, 60000);
}
button.onclick = function () {
if(button.disabled) { // Avoid user removing disable in the html
// Add 25 to whatever
freeze()
}
}
另一种可能是:
这是你的按钮:
<button id="MyBtn" onclick="disable_button_3_secs(); return false;">Disabled me for 3 seconds</button>
这是你的脚本:
var timeout_lenght = 3000;
var myBtn = document.getElementById("MyBtn");
function disable_button_3_secs() {
myBtn.disabled = true;
Enable_at_timer_out();
}
function Enable_at_timer_out() {
setTimeout(function () {myBtn.disabled = false; }, timeout_lenght);
}
我个人喜欢对我的代码有更多的控制权,所以我总是尽可能地使用变量。我已将计时器设置为 3 秒,但您可以根据需要更改它。
大卫
Here is your code
$('#btn').prop('disabled',true);
startCountDown();
function getCounter(){
return parseInt($('#counter').html());
}
function setCounter(count) {
$('#counter').html(count);
}
$("#btn").click(function() {
setCounter(getCounter()+25);
$('#btn').prop('disabled',true);
startCountDown();
});
function startCountDown() {
var minutes = 0,
seconds = 59;
$("#countdown").html(minutes + ":" + seconds);
var count = setInterval(function() {
if (parseInt(minutes) < 0 || parseInt(seconds) <=0 ) {
$("#countdown").html(minutes + ":" + seconds);
clearInterval(count);
$('#btn').prop('disabled',false);
} else {
$("#countdown").html(minutes + ":" + seconds);
seconds--;
if (seconds < 10) seconds = "0" + seconds;
}
}, 1000);
}
#counter{
font-size: 25px;
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="counter">0</div>
<button id="btn">
<span id="countdown">0:00</span>
</button>
可以创建 Custom Element.
这需要了解以下主题:
- Event Listener
- JavaScript Class-syntax
- Inheritance
- 计时机制,例如
setInterval()
and clearInterval()
- 可选:Shadow Root and its Shadow DOM
基本结构
定义一个 自定义元素 需要一个 JS class 扩展 HTMLElement(或其子元素之一-classes).
此 class 然后通过使用其 HTML 元素名称调用 customElements.define()
注册为 HTML 元素(必须包含 -
(连字符) 在它的名字,例如“example-element”)和它关联的class。
我决定调用 class CounterElement
和 HTML 元素 <counter-instance>
:
class CounterElement extends HTMLElement {
constructor() {
super(); // Required since we are extending a class
}
}
customElements.define('counter-instance', CounterElement);
设置影子根
设置影子根是这样完成的:
- 通过调用
Element.attachShadow()
创建影子根
- 创建并附加其 HTML-元素
- 为影子根添加样式
由于一些评论提到访问元素仍然很容易,我决定使用 {mode: 'closed'}
来防止不知情的用户访问它们。但是,并非无法访问。这将需要一个 MutationObserver,但此答案中未包含它以使其(有点)简短,heh.
使用{mode: 'closed'}
时,需要手动保留对影子根的引用。我决定使用私有成员变量 #shadow
.
现在,需要创建和追加影子根的元素。同样,我保留了“重要”元素的私人参考:#samp
和 #button
.
我还添加了一些样式。
class CounterElement extends HTMLElement {
#shadow;
#samp;
#button;
constructor() {
super();
// Shadow Root
this.#shadow = this.attachShadow({mode: 'closed'});
let div = document.createElement('div');
let style = document.createElement('style');
style.innerHTML = 'div{padding:0.2rem;border:1px solid black}'
+ 'samp{display:block}button{font-family:monospace}';
this.#samp = document.createElement('samp');
this.#button = document.createElement('button');
div.append(this.#samp, this.#button);
this.#shadow.append(style, div);
}
}
customElements.define('counter-instance', CounterElement);
设置元素
既然所有重要元素都存在,我们需要正确设置它们。那样的话,我的意思是添加他们应该有的文本。
由于我们将跟踪计数器和秒数,因此将它们声明为成员变量是有意义的。
为了将秒格式化为 mm:ss
格式,我编写了一个实用函数 formatTime()
。好像还蛮好用的,所以可以在全局范围内。
注意您应该尽量不要用太多变量使全局范围混乱。您可以使用 IIFEs 将它们保存在本地。
现在,添加文本就像使用 HTMLElement.innerText
一样简单。
在评论中,您要求在秒数达到 0 时让按钮显示“收集”。这可以使用 if-else 语句来完成,但为了简洁起见,我使用了 Ternary Operator.
function formatTime(seconds) {
var min = new String(Math.floor(seconds / 60));
var sec = new String(seconds % 60);
while (min.length < 2) min = '0' + min;
while (sec.length < 2) sec = '0' + sec;
return min + ':' + sec;
};
class CounterElement extends HTMLElement {
counter = 0;
seconds = 0;
#shadow;
#samp;
#button;
constructor() {
super();
// Shadow Root
// ...
this.updateText();
}
updateText() {
this.#samp.innerText = this.counter;
this.#button.innerText = this.seconds ? formatTime(this.seconds) : 'Collect';
}
}
customElements.define('counter-instance', CounterElement);
添加(计时器)功能
现在的最后一步是添加计时器和 onclick
-listener。
由于我们想在点击#button
时开始计时,并在seconds
达到0
后停止计时,我们可以使用setInterval()
和clearInterval()
分别。
前者函数returns区间的ID,后者用区间ID清除。要按预期使用这些函数,我们需要保留对间隔 ID 的引用。
单击 #button
时,应该:
- 重置
seconds
并增加counter
- 启动我们的计时器
- 在我们的计时器持续时间内被禁用
- 更新关于现在重置值的文本
这是我们实现它的(缩短的)代码:
// function formatTime(seconds) () { ... }
class CounterElement extends HTMLElement {
counter = 0;
seconds = 0;
#shadow;
#samp;
#button;
constructor() {
super();
// Shadow Root
// ...
let intervalId;
let intervalStep = () => { // Will be called every second
this.updateText();
if (--this.seconds <= 0) {
clearInterval(this.#intervalId);
this.#button.disabled = false;
}
};
this.#button.addEventListener('click', () => {
this.seconds = 60;
this.counter += 25;
this.#intervalId = setInterval(intervalStep, 1000);
this.#button.disabled = true;
this.updateText();
});
this.updateText();
}
// Member-functions ...
}
customElements.define('counter-instance', CounterElement);
结论
如前所述,仍然可以使用开发人员工具访问影子根的元素。完全禁用更改按钮的 disabled
-属性 的能力可以使用 MutationObserver 来实现,保持 属性 不被更改,具体取决于 seconds
当前拥有的数字。
这里是 Stack-Snippet 的完整代码,您可以自己尝试一下:
function formatTime(seconds) {
var min = new String(Math.floor(seconds / 60));
var sec = new String(seconds % 60);
while (min.length < 2) min = '0' + min;
while (sec.length < 2) sec = '0' + sec;
return min + ':' + sec;
};
class CounterElement extends HTMLElement {
counter = 0;
seconds = 0;
#shadow;
#samp;
#button;
constructor() {
super();
// Shadow Root
this.#shadow = this.attachShadow({mode: 'closed'});
let div = document.createElement('div');
let style = document.createElement('style');
style.innerHTML = 'div{padding:0.2rem;border:1px solid black}'
+ 'samp{display:block}button{font-family:monospace}';
this.#samp = document.createElement('samp');
this.#button = document.createElement('button');
div.append(this.#samp, this.#button);
this.#shadow.append(style, div);
let intervalId;
let intervalStep = () => { // Will be called every second
if (--this.seconds <= 0) {
clearInterval(intervalId);
this.#button.disabled = false;
}
this.updateText();
};
this.#button.addEventListener('click', () => {
this.seconds = 60;
this.counter += 25;
intervalId = setInterval(intervalStep, 1000);
this.#button.disabled = true;
this.updateText();
});
this.updateText();
}
updateText() {
this.#samp.innerText = this.counter;
this.#button.innerText = this.seconds ? formatTime(this.seconds) : 'Collect';
}
}
customElements.define('counter-instance', CounterElement);
/* Ignore; only for styling purposes */
body {
display: flex;
gap: 0.6rem;
}
<!-- Works with multiple elements -->
<counter-instance></counter-instance>
<counter-instance></counter-instance>
我正在尝试制作一个按钮,当您单击它时将禁用 1 分钟。 仅当启用该按钮并单击它时,才应将 25 点添加到 div(div 从 0 开始)。 每次点击后,按钮将被禁用,计时器将启动 运行.
这里有一些图片可以让整个事情更容易理解:
类似于:
const button = document.getElementById("myBtn")
function freeze () {
button.disabled = true
setTimeout(function() {
button.disabled = false
}, 60000);
}
button.onclick = function () {
if(button.disabled) { // Avoid user removing disable in the html
// Add 25 to whatever
freeze()
}
}
另一种可能是:
这是你的按钮:
<button id="MyBtn" onclick="disable_button_3_secs(); return false;">Disabled me for 3 seconds</button>
这是你的脚本:
var timeout_lenght = 3000;
var myBtn = document.getElementById("MyBtn");
function disable_button_3_secs() {
myBtn.disabled = true;
Enable_at_timer_out();
}
function Enable_at_timer_out() {
setTimeout(function () {myBtn.disabled = false; }, timeout_lenght);
}
我个人喜欢对我的代码有更多的控制权,所以我总是尽可能地使用变量。我已将计时器设置为 3 秒,但您可以根据需要更改它。
大卫
Here is your code
$('#btn').prop('disabled',true);
startCountDown();
function getCounter(){
return parseInt($('#counter').html());
}
function setCounter(count) {
$('#counter').html(count);
}
$("#btn").click(function() {
setCounter(getCounter()+25);
$('#btn').prop('disabled',true);
startCountDown();
});
function startCountDown() {
var minutes = 0,
seconds = 59;
$("#countdown").html(minutes + ":" + seconds);
var count = setInterval(function() {
if (parseInt(minutes) < 0 || parseInt(seconds) <=0 ) {
$("#countdown").html(minutes + ":" + seconds);
clearInterval(count);
$('#btn').prop('disabled',false);
} else {
$("#countdown").html(minutes + ":" + seconds);
seconds--;
if (seconds < 10) seconds = "0" + seconds;
}
}, 1000);
}
#counter{
font-size: 25px;
color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="counter">0</div>
<button id="btn">
<span id="countdown">0:00</span>
</button>
可以创建 Custom Element.
这需要了解以下主题:
- Event Listener
- JavaScript Class-syntax
- Inheritance
- 计时机制,例如
setInterval()
andclearInterval()
- 可选:Shadow Root and its Shadow DOM
基本结构
定义一个 自定义元素 需要一个 JS class 扩展 HTMLElement(或其子元素之一-classes).
此 class 然后通过使用其 HTML 元素名称调用 customElements.define()
注册为 HTML 元素(必须包含 -
(连字符) 在它的名字,例如“example-element”)和它关联的class。
我决定调用 class CounterElement
和 HTML 元素 <counter-instance>
:
class CounterElement extends HTMLElement {
constructor() {
super(); // Required since we are extending a class
}
}
customElements.define('counter-instance', CounterElement);
设置影子根
设置影子根是这样完成的:
- 通过调用
Element.attachShadow()
创建影子根
- 创建并附加其 HTML-元素
- 为影子根添加样式
由于一些评论提到访问元素仍然很容易,我决定使用 {mode: 'closed'}
来防止不知情的用户访问它们。但是,并非无法访问。这将需要一个 MutationObserver,但此答案中未包含它以使其(有点)简短,heh.
使用{mode: 'closed'}
时,需要手动保留对影子根的引用。我决定使用私有成员变量 #shadow
.
现在,需要创建和追加影子根的元素。同样,我保留了“重要”元素的私人参考:#samp
和 #button
.
我还添加了一些样式。
class CounterElement extends HTMLElement {
#shadow;
#samp;
#button;
constructor() {
super();
// Shadow Root
this.#shadow = this.attachShadow({mode: 'closed'});
let div = document.createElement('div');
let style = document.createElement('style');
style.innerHTML = 'div{padding:0.2rem;border:1px solid black}'
+ 'samp{display:block}button{font-family:monospace}';
this.#samp = document.createElement('samp');
this.#button = document.createElement('button');
div.append(this.#samp, this.#button);
this.#shadow.append(style, div);
}
}
customElements.define('counter-instance', CounterElement);
设置元素
既然所有重要元素都存在,我们需要正确设置它们。那样的话,我的意思是添加他们应该有的文本。
由于我们将跟踪计数器和秒数,因此将它们声明为成员变量是有意义的。
为了将秒格式化为 mm:ss
格式,我编写了一个实用函数 formatTime()
。好像还蛮好用的,所以可以在全局范围内。
注意您应该尽量不要用太多变量使全局范围混乱。您可以使用 IIFEs 将它们保存在本地。
现在,添加文本就像使用 HTMLElement.innerText
一样简单。
在评论中,您要求在秒数达到 0 时让按钮显示“收集”。这可以使用 if-else 语句来完成,但为了简洁起见,我使用了 Ternary Operator.
function formatTime(seconds) {
var min = new String(Math.floor(seconds / 60));
var sec = new String(seconds % 60);
while (min.length < 2) min = '0' + min;
while (sec.length < 2) sec = '0' + sec;
return min + ':' + sec;
};
class CounterElement extends HTMLElement {
counter = 0;
seconds = 0;
#shadow;
#samp;
#button;
constructor() {
super();
// Shadow Root
// ...
this.updateText();
}
updateText() {
this.#samp.innerText = this.counter;
this.#button.innerText = this.seconds ? formatTime(this.seconds) : 'Collect';
}
}
customElements.define('counter-instance', CounterElement);
添加(计时器)功能
现在的最后一步是添加计时器和 onclick
-listener。
由于我们想在点击#button
时开始计时,并在seconds
达到0
后停止计时,我们可以使用setInterval()
和clearInterval()
分别。
前者函数returns区间的ID,后者用区间ID清除。要按预期使用这些函数,我们需要保留对间隔 ID 的引用。
单击 #button
时,应该:
- 重置
seconds
并增加counter
- 启动我们的计时器
- 在我们的计时器持续时间内被禁用
- 更新关于现在重置值的文本
这是我们实现它的(缩短的)代码:
// function formatTime(seconds) () { ... }
class CounterElement extends HTMLElement {
counter = 0;
seconds = 0;
#shadow;
#samp;
#button;
constructor() {
super();
// Shadow Root
// ...
let intervalId;
let intervalStep = () => { // Will be called every second
this.updateText();
if (--this.seconds <= 0) {
clearInterval(this.#intervalId);
this.#button.disabled = false;
}
};
this.#button.addEventListener('click', () => {
this.seconds = 60;
this.counter += 25;
this.#intervalId = setInterval(intervalStep, 1000);
this.#button.disabled = true;
this.updateText();
});
this.updateText();
}
// Member-functions ...
}
customElements.define('counter-instance', CounterElement);
结论
如前所述,仍然可以使用开发人员工具访问影子根的元素。完全禁用更改按钮的 disabled
-属性 的能力可以使用 MutationObserver 来实现,保持 属性 不被更改,具体取决于 seconds
当前拥有的数字。
这里是 Stack-Snippet 的完整代码,您可以自己尝试一下:
function formatTime(seconds) {
var min = new String(Math.floor(seconds / 60));
var sec = new String(seconds % 60);
while (min.length < 2) min = '0' + min;
while (sec.length < 2) sec = '0' + sec;
return min + ':' + sec;
};
class CounterElement extends HTMLElement {
counter = 0;
seconds = 0;
#shadow;
#samp;
#button;
constructor() {
super();
// Shadow Root
this.#shadow = this.attachShadow({mode: 'closed'});
let div = document.createElement('div');
let style = document.createElement('style');
style.innerHTML = 'div{padding:0.2rem;border:1px solid black}'
+ 'samp{display:block}button{font-family:monospace}';
this.#samp = document.createElement('samp');
this.#button = document.createElement('button');
div.append(this.#samp, this.#button);
this.#shadow.append(style, div);
let intervalId;
let intervalStep = () => { // Will be called every second
if (--this.seconds <= 0) {
clearInterval(intervalId);
this.#button.disabled = false;
}
this.updateText();
};
this.#button.addEventListener('click', () => {
this.seconds = 60;
this.counter += 25;
intervalId = setInterval(intervalStep, 1000);
this.#button.disabled = true;
this.updateText();
});
this.updateText();
}
updateText() {
this.#samp.innerText = this.counter;
this.#button.innerText = this.seconds ? formatTime(this.seconds) : 'Collect';
}
}
customElements.define('counter-instance', CounterElement);
/* Ignore; only for styling purposes */
body {
display: flex;
gap: 0.6rem;
}
<!-- Works with multiple elements -->
<counter-instance></counter-instance>
<counter-instance></counter-instance>