我试图让以下javascript计时器执行两个功能,只需单击一个按钮 - 一旦计时器启动就单击;再次点击;它停了再次点击它再次启动,依此类推。我在这里做错了什么?非常感谢你提前。
<html>
<head>
<script type="text/javascript">
var c=0;
var t;
var timer_is_on=0;
function timedCount()
{
document.getElementById('txt').value=c;
c=c+1;
t=setTimeout("timedCount()",1000);
}
function doTimer()
{
if (!timer_is_on)
{
timer_is_on=1;
timedCount();
}
}
function stopCount()
{
clearTimeout(t);
timer_is_on=0;
}
function both(){
doTimer();
stopCount();
}
</script>
</head>
<body>
<form>
<input type="button" value="Start count!" onclick="doTimer" />
<input type="text" id="txt" />
<input type="button" value="Stop count!" onclick="stopCount()" />
</form>
<p>
Click on the "Start count!" button above to start the timer. The input field will count forever, starting at 0. Click on the "Stop count!" button to stop the counting. Click on the "Start count!" button to start the timer again.
</p>
</body>
</html>
答案 0 :(得分:6)
您没有描述实际问题,因此我不太清楚应该采取什么措施,但这里有一些可能有用的注意事项。
timedCount函数是准时间递归的。如果你进入continuation passing style这很酷,但它没有必要,可能比它需要的JavaScript更令人困惑,并且会浪费一些没有尾部的语言的资源(堆栈帧)递归堆栈清理(不知道JS是否具有此功能)。
由于这是一个重复的函数执行,你可以使用setInterval
而不是setTimeout
,并且有一个重复的函数调用,它会检查它是否应该递增并重新显示计数。这样的事情:
var c=0;
var timer_is_on=false;
function displayCount() {
document.getElementById('txt').value=c;
}
function count() {
if(timer_is_on) {
c=c+1;
displayCount();
}
}
var interval = setInterval(count,1000);
现在,解决问题的单键部分。假设只有一个按钮:
<input type="button" value="Start count!" onclick="toggle" />
当我们点击它时,我们希望“value”属性发生变化,我们希望它翻转timer_is_on
变量。让我们创建一个完成所有这些事情的函数:
function toggle() {
if(timer_is_on) {
timer_is_on = false;
this.value = "Start count!"; // `toggle` is invoked by the button's event handler, so `this` is the button
} else {
timer_is_on = true;
this.value = "Stop count!";
}
}
所以...计数总是每1000毫秒执行一次,但只有当timer_is_on,以及timer_is_on是真还是假是由toggle
控制时,它只会执行任何操作,它连接到我们的按钮。我想,有点简单。
<强>更新强>
如果我们想不让函数count
始终在后台运行,该怎么办?正如Tom Tu所指出的,这可能代表CPU开销。我不确定它是一个可衡量的(或它代表浏览器可能运行以执行其自己的UI更新的计时器之外的任何开销),但它在某些平台上可能很重要,因此它可能值得解决。
虽然我们正在抛光,但我不太喜欢自己通过标签属性附加事件处理程序,或者如果我可以避免将变量放在全局/窗口范围内,那么我可能会包装所有相关的计数器设置/在一个大的setupCounter
函数中处理JavaScript,并使用DOM选择和JavaScript将toggle
函数附加到输入按钮的onclick
事件。我可能只尝试每次运行document.getElementById
次查找。
因此,假设按钮输入具有标识startstop
,但是否则采用类似的标记。我可能会做这样的事情:
function setupCounter() {
var c=0,
interval,
counter_display = document.getElementById('txt'),
button = document.getElementById('startstop');
function display_count() {
counter_display.value = c;
}
function count() {
c=c+1;
display_count();
}
function toggle() {
if(!interval)
interval = setInterval(count,1000);
button.value = "Stop count!";
else {
clearInterval(interval);
interval = false;
button.value = "Start count!";
}
}
button.onclick = toggle;
}
然后,在声明了counter_display和startstop元素之后,您可以在文档中的某个时间调用setupCounter
,或者将其分配给window.onload
事件或将其传递给类似jQuery的{{1} }}。
答案 1 :(得分:3)
试试这个
<form name="f1">
<input type="text" id="but" />
<input type="button" value="start" onclick="timer()" />
<input type="button" value="stop" onclick="stoptimer()" />
</form>
<script type="text/javascript">
var count=0;
var x;
function timer(){
x=setTimeout("timer()",1000);
count=count+1;
document.getElementById("but").value=count;
}
function stoptimer(){
clearTimeout(x);
}
</script>
答案 2 :(得分:1)
你在doTimer之后忘了括号:
<input type="button" value="Start count!" onclick="doTimer" />
答案 3 :(得分:1)
试试这段代码:
var c=0;
var t;
var timer_is_on= false;
function timedCount() {
document.getElementById('txt').value=c;
c++;
if (timer_is_on) {
t= setTimeout(timedCount,1000);
}
}
function doTimer() {
if (!timer_is_on) {
timer_is_on=true;
timedCount();
}
else {
clearTimeout(t);
timer_is_on=false;
}
}
将doTimer()
fn附加到每个按钮上。
我所做的更改:使用true / false而不是1/0。
答案 4 :(得分:0)
JavaScript
请注意使用true
和false
代替1
和0
。
var timer_is_on=false;
//..
function doTimer()
{
if (!timer_is_on)
{
timer_is_on=true;
timedCount();
}
else
{
timer_is_on=false;
stopCount();
}
}
HTML
我看到您的按钮已设置为致电doTimer()
onclick
(但请注意,您错过了括号):
<input type="button" value="Start count!" onclick="doTimer()" />
更改按钮的文字
首先,为按钮分配id
:
<input type="button" id="toggleTimer" value="Start count!" onclick="doTimer()" />
接下来,修改JS:
function doTimer()
{
if (!timer_is_on)
{
timer_is_on=true;
document.getElementById("toggleTimer").value="Stop count!";
timedCount();
}
else
{
timer_is_on=false;
document.getElementById("toggleTimer").value="Start count!";
stopCount();
}
}
答案 5 :(得分:0)
具有历史记录,数据存储和通知的计时器:
实时演示:https://codepen.io/4m6/pen/yLJBXxV (通知无法在演示中正常运行,因为它在Codepen内部)
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>EZ Timer</title>
<style>
* {
box-sizing: border-box;
}
html {
line-height: 1.15;
-webkit-text-size-adjust: 100%;
}
body {
margin: 0;
}
main {
display: block;
}
h1 {
font-size: 2em;
margin: 0.67em 0;
}
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
pre {
font-family: monospace, monospace;
font-size: 1em;
}
a {
background-color: transparent;
}
abbr[title] {
border-bottom: none;
text-decoration: underline;
text-decoration: underline dotted;
}
b,
strong {
font-weight: bolder;
}
code,
kbd,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
small {
font-size: 80%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
img {
border-style: none;
}
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
font-size: 100%;
line-height: 1.15;
margin: 0;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
fieldset {
padding: 0.35em 0.75em 0.625em;
}
legend {
box-sizing: border-box;
color: inherit;
display: table;
max-width: 100%;
padding: 0;
white-space: normal;
}
progress {
vertical-align: baseline;
}
textarea {
overflow: auto;
}
[type="checkbox"],
[type="radio"] {
box-sizing: border-box;
padding: 0;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit;
}
details {
display: block;
}
summary {
display: list-item;
}
template {
display: none;
}
[hidden] {
display: none;
}
body {
background-color: #333;
font-family: sans-serif;
display: flex;
flex-wrap: wrap;
justify-content: center;
height: 100vh;
}
#notif-container {
text-align: center;
min-width: 400px;
background-color: red;
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: center;
align-items: center;
border-radius: 4px;
position: relative;
color: #fff;
font-size: 20px;
padding: 10px 20px;
margin: 10px;
display: none;
}
.clock-container {
min-width: 400px;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
background-color: #1e5f74;
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: center;
align-items: center;
border-radius: 4px;
position: relative;
}
.clock-container--running {
background-color: #009400;
}
h1 {
color: #fff;
margin: 16px;
}
.clock {
display: flex;
font-size: 50px;
padding: 0 20px;
}
#reset-timer {
cursor: pointer;
display: inline-block;
position: absolute;
right: 18px;
top: 18px;
font-size: 22px;
font-weight: 600;
color: #fff;
background-color: red;
padding: 2px 6px;
border-radius: 4px;
}
.buttons {
padding: 10px;
display: flex;
}
.time {
font-size: 50px;
display: inline-block;
border: 0;
border-radius: 4px;
padding-left: 10px;
width: 90px;
background-color: #222;
color: #fff;
}
.time:disabled {
color: #c1ffd1;
background: #052400;
}
.time-head {
font-size: 22px;
color: #fff;
text-align: center;
}
.colon {
color: #fff;
padding-top: 20px;
}
.btn {
display: inline-block;
font-size: 28px;
font-weight: 600;
background: #888;
padding: 10px 16px;
margin: 10px;
border-radius: 4px;
color: #555;
border: 0;
}
.btn--active {
background: #ffd06a;
cursor: pointer;
color: #000;
}
.history-title {
margin: 10px;
}
.history-container {
background: #333;
border: 2px solid #222;
padding: 10px;
margin: 5px 10px;
color: #fff;
border-radius: 4px;
width: 350px;
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
.history {
line-height: 1.5;
padding: 10px;
margin: 2px;
background: #222;
border-radius: 4px;
}
</style>
</head>
<body>
<div style="display: flex; flex-direction: column; align-items: center;">
<div id="notif-container">
</div>
<div class="clock-container">
<h1>EZ Timer</h1>
<div id="reset-timer">X</div>
<div class="clock">
<div>
<div class="time-head">Hours</div>
<input min="0" max="99" type="number" value="0" class="time" id="hours" contenteditable="true" />
</div>
<div class="colon">:</div>
<div>
<div class="time-head">Minutes</div><input min="0" max="60" type="number" value="0" class="time"
id="minutes" contenteditable="true" />
</div>
<div class="colon">:</div>
<div>
<div class="time-head">Seconds</div><input min="0" max="60" type="number" value="0" class="time"
id="seconds" contenteditable="true" />
</div>
</div>
<div class="buttons">
<input type="submit" value="START" class="btn btn--active" id="start-timer" />
<div class="btn" id="pause-timer">PAUSE</div>
</div>
</div>
</div>
<div style="display: flex; flex-direction: column; align-items: center; height:100vh; overflow: auto;">
<h1 class="history-title">History</h1>
<div class="history-container">
</div>
</div>
<script>
// To make use single domain/protocol local storage - To avoid multiple storage
if (location.protocol !== "http:") {
location.protocol = "http:";
}
if (document.domain.substring(0, 4).toLowerCase() == 'www.') {
window.location = document.URL.replace('//www.', '//');
}
// EZ TIMER SELECTORS & FUNCTIONS
window.ezTimer = {};
window.ezTimer.isTimerRunning = 'no';
window.ezTimer.timerH1 = document.querySelector('h1');
window.ezTimer.clockContainer = document.querySelector('.clock-container');
window.ezTimer.hrContainer = document.getElementById('hours');
window.ezTimer.minContainer = document.getElementById('minutes');
window.ezTimer.secContainer = document.getElementById('seconds');
window.ezTimer.pauseTimerBtn = document.getElementById('pause-timer');
window.ezTimer.startTimerBtn = document.getElementById('start-timer');
window.ezTimer.resetTimerBtn = document.getElementById('reset-timer');
window.ezTimer.notifContainer = document.getElementById('notif-container');
window.ezTimer.validateInput = (e) => {
// prevent: "e", "=", ",", "-", "."
if ([69, 187, 188, 189, 190].includes(e.keyCode)) { e.preventDefault(); }
}
window.ezTimer.validateInput2 = (e) => {
if (e.target.value.length >= 2) {
e.target.value = e.target.value.slice(0, 2);
}
if (e.target.value > 60) {
e.target.value = 60;
}
}
window.ezTimer.resetTimer = () => {
window.ezTimer.updateHistoryArray('BEFORE RESETTING');
window.ezTimer.showHistoryOnPage();
window.ezTimer.setHistoryOnStorage();
window.ezTimer.hrContainer.value = 0;
window.ezTimer.minContainer.value = 0;
window.ezTimer.secContainer.value = 0;
localStorage.setItem('hrContainer', 0);
localStorage.setItem('minContainer', 0);
localStorage.setItem('secContainer', 0);
}
window.ezTimer.timerEndNotify = () => {
var date = new Date();
var monthNames = ["Jan", "Feb", "Mar", "April", "May", "June", "July", "Aug", "Sep", "Oct", "Nov", "Dec"];
var monthName = monthNames[date.getMonth()];
var today = `${date.getDate()} - ${monthName} - ${date.getFullYear()}`;
var hour = date.getHours();
var min = date.getMinutes();
var sec = date.getSeconds();
var time = hour + ":" + min + ":" + sec;
var title = 'TIMER DONE';
var desc = `(${time}) (${today})`;
if (!window.Notification) {
console.log('Browser does not support notifications.');
} else {
// check if permission is already granted
if (Notification.permission === 'granted') {
// show notification here
var notify = new Notification(title, {
body: desc,
requireInteraction: 'shouldRequireInteraction'
});
} else {
// request permission from user
Notification.requestPermission().then(function (p) {
if (p === 'granted') {
// show notification here
var notify = new Notification(title, {
body: desc,
requireInteraction: 'shouldRequireInteraction'
});
} else {
console.log('User blocked notifications.');
}
}).catch(function (err) {
console.error(err);
});
}
}
}
window.ezTimer.getHistoryArrayFromStorage = () => {
if (localStorage.getItem('history') != null) { window.ezTimer.history = JSON.parse(localStorage.getItem('history')); }
else { window.ezTimer.history = []; }
}
window.ezTimer.updateHistoryArray = (when) => {
window.ezTimer.updateStorageTime();
var date = new Date();
var monthNames = ["Jan", "Feb", "Mar", "April", "May", "June", "July", "Aug", "Sep", "Oct", "Nov", "Dec"];
var monthName = monthNames[date.getMonth()];
window.ezTimer.history.unshift(`WHEN: ${when} <br/> TIMER TIME LEFT: ${localStorage.getItem('hrContainer')}:${localStorage.getItem('minContainer')}:${localStorage.getItem('secContainer')} <br/> TIME: ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()} ( ${date.getDate()} - ${monthName} - ${date.getFullYear()} )`);
if (window.ezTimer.history.length > 150) { window.ezTimer.history.length = 150; }
}
window.ezTimer.showHistoryOnPage = () => {
document.querySelector('.history-container').innerHTML = '';
for (let a of window.ezTimer.history) {
document.querySelector('.history-container').insertAdjacentHTML('beforeend', `<div class="history">${a}</div>`);
}
}
window.ezTimer.setHistoryOnStorage = () => {
localStorage.setItem('history', JSON.stringify(window.ezTimer.history));
}
window.ezTimer.updatePageTime = () => {
if (window.ezTimer.secContainer.value >= 1) {
const x = window.ezTimer.secContainer.value - 1;
window.ezTimer.secContainer.value = x;
}
else {
if (window.ezTimer.minContainer.value >= 1) {
const x = window.ezTimer.minContainer.value - 1;
window.ezTimer.minContainer.value = x;
window.ezTimer.secContainer.value = 59;
}
else {
if (window.ezTimer.hrContainer.value >= 1) {
const x = window.ezTimer.hrContainer.value - 1;
window.ezTimer.hrContainer.value = x;
window.ezTimer.secContainer.value = 59;
window.ezTimer.minContainer.value = 59;
}
else {
window.ezTimer.pauseTimer('ON TIMER END');
window.ezTimer.timerEndNotify();
window.ezTimer.pauseTimerBtn.removeEventListener('click', window.ezTimer.runPauseTimer)
}
}
}
}
window.ezTimer.updateStorageTime = () => {
localStorage.setItem('secContainer', window.ezTimer.secContainer.value);
localStorage.setItem('minContainer', window.ezTimer.minContainer.value);
localStorage.setItem('hrContainer', window.ezTimer.hrContainer.value);
}
// EZ TIMER LOGIC
if (!window.Notification) {
window.ezTimer.notifContainer.textContent += 'Browser does not support notifications .';
window.ezTimer.notifContainer.style.display = 'block';
}
else {
if (Notification.permission === 'granted') {
window.ezTimer.notifContainer.textContent += 'Notification Permission Granted. ';
window.ezTimer.notifContainer.style.display = 'block';
window.ezTimer.notifContainer.style.backgroundColor = '#009400';
}
else {
window.ezTimer.notifContainer.textContent += 'Site Notification Permission Blocked. ';
window.ezTimer.notifContainer.style.display = 'block';
}
}
window.ezTimer.startTimerBtn.addEventListener('click', () => { window.ezTimer.startTimer() }, { once: true });
window.ezTimer.resetTimerBtn.addEventListener('click', () => { window.ezTimer.resetTimer() });
if (localStorage.getItem('hrContainer') != null) {
window.ezTimer.hrContainer.value = localStorage.getItem('hrContainer');
}
if (localStorage.getItem('minContainer') != null) {
window.ezTimer.minContainer.value = localStorage.getItem('minContainer');
}
if (localStorage.getItem('secContainer') != null) {
window.ezTimer.secContainer.value = localStorage.getItem('secContainer');
}
window.ezTimer.getHistoryArrayFromStorage();
window.ezTimer.showHistoryOnPage();
window.ezTimer.hrContainer.addEventListener('keydown', (e) => { window.ezTimer.validateInput(e) })
window.ezTimer.minContainer.addEventListener('keydown', (e) => { window.ezTimer.validateInput(e) })
window.ezTimer.secContainer.addEventListener('keydown', (e) => { window.ezTimer.validateInput(e) })
window.ezTimer.hrContainer.addEventListener('input', (e) => { window.ezTimer.validateInput2(e) })
window.ezTimer.minContainer.addEventListener('input', (e) => { window.ezTimer.validateInput2(e) })
window.ezTimer.secContainer.addEventListener('input', (e) => { window.ezTimer.validateInput2(e) })
window.ezTimer.startTimer = () => {
if (window.ezTimer.isTimerRunning == 'no') {
for (let inpt of document.querySelectorAll('.clock .time')) {
inpt.disabled = true;
}
window.ezTimer.updatePageTimeEverySec = window.setInterval(() => { window.ezTimer.updatePageTime() }, 1000);
window.ezTimer.updateStorageTimeEveryMinute = window.setInterval(() => { window.ezTimer.updateStorageTime() }, 60000);
window.ezTimer.updateHistoryArray('ON START');
window.ezTimer.showHistoryOnPage();
window.ezTimer.setHistoryOnStorage();
window.ezTimer.trackHistory = window.setInterval(() => { window.ezTimer.updateHistoryArray('AUTO'); window.ezTimer.showHistoryOnPage(); window.ezTimer.setHistoryOnStorage(); }
, 300000);
window.ezTimer.timerH1.innerText = 'EZ Timer - Running..';
window.ezTimer.clockContainer.classList.add('clock-container--running');
window.ezTimer.startTimerBtn.classList.remove('btn--active');
window.ezTimer.pauseTimerBtn.classList.add('btn--active');
window.ezTimer.resetTimerBtn.style.display = 'none';
window.ezTimer.isTimerRunning = 'yes';
window.ezTimer.pauseTimerBtn.addEventListener('click', window.ezTimer.runPauseTimer = () => { window.ezTimer.pauseTimer('ON PAUSE') } , { once: true })
}
}
window.ezTimer.pauseTimer = (when) => {
for (let inpt of document.querySelectorAll('.clock .time')) {
inpt.disabled = false;
}
clearInterval(window.ezTimer.updatePageTimeEverySec);
clearInterval(window.ezTimer.updateStorageTimeEveryMinute);
clearInterval(window.ezTimer.trackHistory);
window.ezTimer.updateHistoryArray(when);
window.ezTimer.showHistoryOnPage();
window.ezTimer.setHistoryOnStorage();
window.ezTimer.timerH1.innerText = 'EZ Timer';
window.ezTimer.clockContainer.classList.remove('clock-container--running');
window.ezTimer.pauseTimerBtn.classList.remove('btn--active');
window.ezTimer.startTimerBtn.classList.add('btn--active');
window.ezTimer.resetTimerBtn.style.display = 'inline-block';
window.ezTimer.isTimerRunning = 'no';
window.ezTimer.startTimerBtn.addEventListener('click', () => { window.ezTimer.startTimer() }, { once: true })
}
</script>
</body>
</html>