0

I am searching for a solution to let an event fire on a radio group after some time delay.

Specifically, I need to ask users a question and want to submit their input without having the users click a separate button. At the same time, it shall be possible that the user clicks different radio buttons while considering the answer.

onInput and onChange are both fired immediately after a user click. However, is there another solution?

Here is small example:

<div class="form-check form-check-inline"> 
  <label> What is 17 * 21? </label>
  <br></br>      
  
  <input class="form-check-input" type="radio" id="MC_0" name="MC_first" value="1" oninput="console.log('here');">
  <label for="MC_0" class="form-check-label">263</label>

  <input class="form-check-input" type="radio" id="MC_1" name="MC_first" value="2" oninput="console.log('here');">
  <label for="MC_1" class="form-check-label">357</label>
</div>

I would love to have oninput only fire after, say, 5 seconds without activity in this radio group.

Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
max1993
  • 23
  • 5
  • Does this help: https://stackoverflow.com/questions/14226803/wait-5-seconds-before-executing-next-line? – Samball May 31 '22 at 09:34
  • @Samball: Thanks for your suggestion. I believe it won't, because setTimeout is also fired whenever any radio button is clicked. What I am looking for is a flow such as: "User clicks 1, user waits, user clicks 2, user waits 5 sec, event is fired". With setTimeout, it's "user click 1, event fired after X sec, user click 2, event fired after X sec", etc. – max1993 May 31 '22 at 09:44
  • If I understand correctly when the user clicks 1 it should start a timer of 5 seconds, but when user clicks 2 it should reset the timer and start again from 5 seconds? If that is the case you can stop `setTimeout` and reset it with `clearTimeout()`. – Samball May 31 '22 at 09:49
  • @Samball ... the matter/subject the OP is dealing with is not **sleep** / **wait** but is about the controlled handling of (constantly) incoming data in a **debounced** way. – Peter Seliger May 31 '22 at 11:12

2 Answers2

1

You can use setTimeout():

var timer;
function setTimer(time) {
  if (timer) {
    clearTimeout(timer);
  }
  timer = setTimeout(() => { console.log('abc'); }, time);
}
<button onclick="setTimer(2000)">Click Me</button>
sportzpikachu
  • 831
  • 5
  • 18
  • Thank you, @Ramesh Sarthi. I believe that setTimeout won't work well, because it will also be fired on any radio-button click and will thus be always executed upon user input (and thus show multiple feedbacks to the user if the user clicks several radio buttons). Won't it? – max1993 May 31 '22 at 09:40
  • 1
    @max1993 That's why we are clearing previous timer if there is any. I think this should work. – Ramesh Sarthi May 31 '22 at 09:47
  • 1
    @max1993 Here is how this will work - If user clicks 1, and then user clicks 2 before 5 sec. then it will clear previous timer and will run after user has clicked 2. – Ramesh Sarthi May 31 '22 at 09:48
  • You are absolutely right! Thank you! – max1993 May 31 '22 at 09:56
  • The OP will run into problems, if it comes to adapting the above presented approach to the OP's markup/DOM, especially for more than just one radio-group, but also in order to prevent interferences (timer resetting) by any other not related input events. – Peter Seliger May 31 '22 at 10:11
1

The OP needs to choose an approach which combines event-delegation and thedebounced handling of a callback-function.

The requirements are that a (or each in case of more than just one) radio-group needs to be entirely nested within a parent-structure where the event-delegation takes place. And each delegation-node of cause needs to have its own debounced event-handler registered to its related input-event.

Additionally a refactoring of the OP's markup is strongly recommended.

function handleRadioGroupInput(evt) {
  const { target } = evt;

  console.log({ target });
}

document
  .querySelectorAll('fieldset')
  .forEach(elmNode =>
    elmNode
      // each radio-group parent has to register its own debounced handler.
      .addEventListener('input', _.debounce(handleRadioGroupInput, 3000))
  );
body { margin: 0; }
fieldset { float: left; width: 40%; }
.as-console-wrapper { max-height: 140px!important; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

<fieldset class="form-check form-check-inline">
  <legend> What is 17 * 21? </legend>

  <input class="form-check-input" type="radio" id="MC_0" name="MC_first" value="1">
  <label for="MC_0" class="form-check-label">263</label>

  <input class="form-check-input" type="radio" id="MC_1" name="MC_first" value="2">
  <label for="MC_1" class="form-check-label">357</label>
</fieldset>

<fieldset class="form-check form-check-inline">
  <legend> What is 7 * 22? </legend>

  <input class="form-check-input" type="radio" id="MC_2" name="MC_second" value="1">
  <label for="MC_2" class="form-check-label">154</label>

  <input class="form-check-input" type="radio" id="MC_3" name="MC_second" value="2">
  <label for="MC_3" class="form-check-label">144</label>
</fieldset>
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37