1

Is it possible to delegate blur event?

I have this code and want to add only one event listener to whole div where are my inputs:

const inputs = document.querySelectorAll('div.div input[type="number"]');

inputs.forEach(input => {
  input.addEventListener('blur', () => {
    const value = +input.value;
    const [min, max] = [+input.min, +input.max];
    
    if (!(value < min || value > max)) return;

    input.value = Math.max(min, Math.min(value, max));
    showRangeError(input);
  })
})

function showRangeError(input) {
  const error = document.createElement('p');

  error.className = "erorr-m";
  error.innerHTML = `Value must be between ${input.min} and ${input.max}`;

  input.after(error);

  setTimeout(() => error.remove(), 3000);
}
.div {
  display: flex;
  flex-wrap: nowrap;
  flex-direction: column;
  align-items: flex-start;
}

.erorr {
  border: solid 2px #e66565;
}

.erorr-m {
  margin-bottom: 10px;
  padding: 10px;
  color: #e66565;
  border-left: solid 2px #e66565;
  animation: 1s fadeIn;
}
<div class="div">
  <input name="one" type="number" min="10" max="24" placeholder="One">
  <input name="two" type="number" min="5" max="7" placeholder="Two">
</div>

I tried to add even listener to div but nothing happens when I click outside of div

const inputsDiv = document.querySelector('div.div');

inputsDiv.addEventListener('blur', console.log);
.div {
  display: flex;
  flex-wrap: nowrap;
  flex-direction: column;
  align-items: flex-start;
  outline: 1px solid black;
}

.erorr {
  border: solid 2px #e66565;
}

.erorr-m {
  margin-bottom: 10px;
  padding: 10px;
  color: #e66565;
  border-left: solid 2px #e66565;
  animation: 1s fadeIn;
}
<div class="div">
  <input name="one" type="number" min="10" max="24" placeholder="One">
  <input name="two" type="number" min="5" max="7" placeholder="Two">
</div>

Only if I add tabindex="0" attribute to div I can see event target but it always is div:

const inputsDiv = document.querySelector('div.div');

inputsDiv.addEventListener('blur', (e) => console.log(e.target, e.currentTarget));
.div {
  display: flex;
  flex-wrap: nowrap;
  flex-direction: column;
  align-items: flex-start;
  outline: 1px solid black;
}

.erorr {
  border: solid 2px #e66565;
}

.erorr-m {
  margin-bottom: 10px;
  padding: 10px;
  color: #e66565;
  border-left: solid 2px #e66565;
  animation: 1s fadeIn;
}
<div class="div" tabindex="0">
  <input name="one" type="number" min="10" max="24" placeholder="One">
  <input name="two" type="number" min="5" max="7" placeholder="Two">
</div>
EzioMercer
  • 1,502
  • 2
  • 7
  • 23
  • Is there a specific reason why you try to re-create the built-in validation function of a `
    ` and its input elements?
    – Andreas Jan 07 '23 at 14:54
  • @Andreas No, just playing with JS :) – EzioMercer Jan 07 '23 at 14:56
  • There's a specific event that would be way more appropriate to listen for (and that works): `input` – Andreas Jan 07 '23 at 15:00
  • @Andreas May be but I don't want to сhecking so many times – EzioMercer Jan 07 '23 at 15:07
  • @Andreas Thank you! It was so simple and I didn't guess :) – EzioMercer Jan 07 '23 at 15:12
  • @Andreas Why you deleted your comment it was the solution which I looking for – EzioMercer Jan 07 '23 at 15:14
  • Because `change` works the same way as `input` (in certain cases): [Difference between "change" and "input" event for an `input` element](https://stackoverflow.com/questions/17047497/difference-between-change-and-input-event-for-an-input-element) – Andreas Jan 07 '23 at 15:21
  • @Andreas In the accepted answer says that `onchange` for input is `change + lose focus`. And that is what I want :) So you can write answer and I will accept it. May be there are special cases where `change` event doesn't work as expected but it is not my case – EzioMercer Jan 07 '23 at 15:56

0 Answers0