Как запретить нажатие кнопки HTML, если уже запущен JS

#javascript #html #button #boolean #progress-bar

#javascript #HTML #кнопка #логическое #индикатор выполнения

Вопрос:

Мне интересно, как я мог бы остановить нажатие кнопки, если функция, которую она выполняет, запущена. Вот мой JS-код:

 let money = 0;
let running = false;

function start(time, val) {
  if (running == false) {
    running = true;
    console.log(running)
    let bar = document.getElementById('progressBar1');
    bar.value = time;
    time  ;
    let sim = setTimeout("start("   time   ")", 30);
    if (time == 100) {
      bar.value = 0;
      let id = val;
      money  ;
      document.getElementById("moneyValue").innerHTML = money;
      clearTimeout(sim);
      running = false;
    }
  } else if (running == true) {
      console.log("Already Growing!");
  };
} 
 <progress id="progressBar1" value="0" max="100" style="width:150px;"></progress>
<button id="restart-button" class="plantBtn" onclick="start(0, this.id)">Plant Seed</button> 

Что он делает, так это запускает индикатор выполнения (progress div). Я хочу, чтобы кнопка предупреждала о сообщении, в котором говорится, что оно уже запущено или что-то в этом роде.

Проблема, с которой я сталкиваюсь, заключается в том, что он переходит к оператору else if и ничего не запускает. Странно то, что если я добавлю a console.log в середину оператора if, это сработает.

Я думаю, это связано с тем, что для заполнения панели требуется время, она никогда не будет заполнена, если пользователь нажмет на нее, потому что она перейдет к оператору else if и отменит функцию if. (Он снова становится false только после того, как панель достигает 100%)

Кто-нибудь может помочь? Я открыт для JS или Jquery (немного ржавый на этом).

Спасибо

Комментарии:

1. У вас есть дополнительная фигурная скобка; вместо } else if (running == true) { того, чтобы вам просто нужно else if (running == true) {

2. Нет, эта фигурная скобка связана с другим оператором if (внутри первого)

3. Почему вы вызываете ту же функцию? Код после тайм-аута должен вызываться с тайм-аутом, а не вызывать логику, которая его запускает

4. что? Это происходит каждый раз, когда нажимается кнопка. Таким образом, кнопка будет нажата несколько раз, но я не хочу, чтобы она выполняла действие до завершения предыдущего

5. @epascarello не могли бы вы продемонстрировать?

Ответ №1:

Вам нужно запретить нажатие кнопки, а не фактическую start функцию, из которой вам нужно вызвать ее по таймеру. Поэтому лучше разделить эти функции:

 let money = 0;
let running = false;

// when clicking the button
function onClickButton(time, val) {
  if(running) {
    console.log("Already Growing!");
  } else {
    running = true;
    start(time, val);
  }
}

// timer function
function start(time, val) {
  let bar = document.getElementById('progressBar1');
  bar.value = time;
  time  ;
  let sim = setTimeout(() => start(time), 30);
  if (time == 100) {
    bar.value = 0;
    let id = val;
    money  ;
    document.getElementById("moneyValue").innerHTML = money;
    clearTimeout(sim);
    running = false;
  }
} 
 #moneyValue::before {
  content: 'Money: ';
} 
 <div id="moneyValue">0</div>
<progress id="progressBar1" value="0" max="100" style="width:150px;"></progress>
<button id="restart-button" class="plantBtn" onclick="onClickButton(0, this.id)">Plant Seed</button> 

Ответ №2:

Выделите логику в другую функцию, которая выполняет обновление. Кнопка, которая запускает ее в одном методе, и логика, которая обновляет пользовательский интерфейс в другом.

 let money = 0;
let running = false;

function start(time, val) {
  if (running == false) {
    running = true;
    console.log(running)
    runIt(time, val);
  } else if (running == true) {
    console.log("Already Growing!");
  };
}

function runIt(time, val) {
  let bar = document.getElementById('progressBar1');
  bar.value = time;
  time  ;
  let sim = setTimeout(function () {runIt(time); }, 30);
  if (time == 100) {
    bar.value = 0;
    let id = val;
    money  ;
    document.getElementById("moneyValue").innerHTML = money;
    running = false;
  }
} 
 <progress id="progressBar1" value="0" max="100" style="width:150px;"></progress>
<button id="restart-button" class="plantBtn" onclick="start(0, this.id)">Plant Seed</button>

<div id="moneyValue"></div> 

Ответ №3:

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

 let money = 0;
let running = false;

function start(time, val, isFromTimer) {
  if (running == false || isFromTimer == true) { // add check
    running = true;
    console.log(running)
    let bar = document.getElementById('progressBar1');
    bar.value = time;
    time  ;
    let sim = setTimeout(() => start(time, val, true), 30); // tell function it's from the timer
    if (time >= 100) { // use more than or equal to instead
      bar.value = 0;
      let id = val;
      money  ;
      //document.getElementById("moneyValue").innerHTML = money;
      clearTimeout(sim);
      running = false;
    }
  } else if (running == true) {
      console.log("Already Growing!");
  };
} 
 <progress id="progressBar1" value="0" max="100" style="width:150px;"></progress>
<button id="restart-button" class="plantBtn" onclick="start(0, this.id)">Plant Seed</button> 

Ответ №4:

Почему бы вам просто не использовать некоторые манипуляции с CSS в своей функции после нажатия на нее?

document.getElementById('restart-button').disabled = true;

Затем в конце вашей функции:

document.getElementById('restart-button').disabled = false;