JSFiddle - React, Tailwind, and code Playground
HTML
<!-- normal form -->
<form id="normal" action="#">
<p>Обычный таймер</p>
<fieldset>
<label for="normal-ideal">
<span>Расчетное время:</span>
<input type="text" id="normal-ideal" name="ideal" />
</label>
<label for="normal-real">
<span>Реальное время:</span>
<input type="text" id="normal-real" name="real" />
</label>
<label for="normal-diff">
<span>Разница:</span>
<input type="text" id="normal-diff" name="diff" />
</label>
</fieldset>
<fieldset>
<button type="submit">Старт</button>
<button type="reset">Стоп</button>
</fieldset>
</form>
<!-- more work form -->
<form id="morework" action="#">
<p>Обычный таймер c дополнительной задачей</p>
<fieldset>
<label for="morework-ideal">
<span>Расчетное время:</span>
<input type="text" id="morework-ideal" name="ideal" />
</label>
<label for="morework-real">
<span>Реальное время:</span>
<input type="text" id="morework-real" name="real" />
</label>
<label for="morework-diff">
<span>Разница:</span>
<input type="text" id="morework-diff" name="diff" />
</label>
</fieldset>
<fieldset>
<button type="submit">Старт</button>
<button type="reset">Стоп</button>
</fieldset>
</form>
<!-- self-adjusting form -->
<form id="adjusting" action="#">
<p>Таймер с самокоррекцией</p>
<fieldset>
<label for="adjusting-ideal">
<span>Расчетное время:</span>
<input type="text" id="adjusting-ideal" name="ideal" />
</label>
<label for="adjusting-real">
<span>Реальное время:</span>
<input type="text" id="adjusting-real" name="real" />
</label>
<label for="adjusting-diff">
<span>Разница:</span>
<input type="text" id="adjusting-diff" name="diff" />
</label>
</fieldset>
<fieldset>
<button type="submit">Старт</button>
<button type="reset">Стоп</button>
</fieldset>
</form>
CSS
html, body
{
background:#fff;
color:#000;
font:normal normal normal 1em/1.4 verdana,sans-serif;
}
form
{
float:left;
border:1px solid #166;
background: #399;
width:240px;
margin:0 10px 10px 0;
}
form fieldset
{
border:none;
padding:10px 10px 0 10px;
text-align: center;
}
form label
{
display:block;
float:left;
clear:both;
width:210px;
margin:0 0 5px 0;
}
form label span
{
display:block;
float:left;
width:140px;
}
form input
{
width:60px;
font-size:0.88em;
border: 1px solid #177
}
form button
{
padding:2px 8px;
font-size:1em;
background:#ddd;
border:1px solid #177;
margin:0 0 10px 0;
}
form p {
padding-left: 30px;
}
JavaScript
//глобальная переменная со всеми таймерами для их управления
var timeouts = {};
//функция с обычным таймером
function timer(form, adjust, morework)
{
//создаем скорость таймера, счетчик итераций и задаем временной штамп для начала отсчета
var speed = 50,
counter = 0,
start = new Date().getTime();
//пример таймера
function instance()
{
//если флаг morework == true,
//выполняем некоторые вычисления для увеличения количества работы
if(morework)
{
for(var x=1, i=0; i<1000000; i++) { x *= (i + 1); }
}
//вычисляем идеальное и реальное время работы таймера
//судя по всему, в оригинале, автор изменил названия переменных, чтобы идентифицировать свой код при перепосте.
var real = (counter * speed),
ideal = (new Date().getTime() - start);
//увеличиваем счетчик
counter++;
//отображаем вычисленные значения
form.ideal.value = real;
form.real.value = ideal;
//вычисляем и отображаем разницу
var diff = (ideal - real);
form.diff.value = diff;
//если флаг adjust == true, будем вычитать разницу перед последующим вызовом (тем самым реализовав необходимое упреждение)
if(adjust)
{
timeouts[form.id] = window.setTimeout(function() { instance(); }, (speed - diff));
}
//и, если флага нет, просто вызываем следующую итерацию
else
{
timeouts[form.id] = window.setTimeout(function() { instance(); }, speed);
}
};
//далее, просто отбрасываем все прочь в случае обычного таймера
timeouts[form.id] = window.setTimeout(function() { instance(); }, speed);
}
//биндим управление таймеров на субмит форм
document.getElementById('normal').onsubmit = function()
{
//вызов нашей функции таймера без флагов (обычный таймер)
timer(this, false, false);
return false;
};
//биндим обработчик ресета таймера
document.getElementById('normal').onreset =...