Home > other >  How could I apply a proper event handling or even event delegation to my example code?
How could I apply a proper event handling or even event delegation to my example code?

Time:09-23

I am trying to use the same function to change the color of three different divs, but it does not work. Please see below the code below:

const hours=document.getElementById('hours');
const minutes=document.getElementById('minutes');
const seconds=document.getElementById('seconds');

hours.addEventListener('click',changeColor);
minutes.addEventListener('click', changeColor);
seconds.addEventListener('click', changeColor);

function changeColor(obj){
        if(obj.style.backgroundColor==='seashell'){
            obj.style.backgroundColor='red';
        } else{
            obj.style.backgroundColor='seashell';
        }
    }


CodePudding user response:

The argument to an event listener is the Event object, not the target of the event. Use event.target to get the element that was clicked.

function changeColor(event) {
  let obj = event.target;
  if (obj.style.backgroundColor === 'seashell') {
    obj.style.backgroundColor = 'red';
  } else {
    obj.style.backgroundColor = 'seashell';
  }
}

CodePudding user response:

The handler function (callback) of a registered event listener gets passed an event object. If one wants to access the element where the listener has been registered at then one should use the event's currentTarget property and not target since the latter must not be identical to the former.

The OP's event handling example ...

function changeColor(evt) {
  const obj = evt.currentTarget;
  const objStyle = obj.style;

  const bgColor = (objStyle.backgroundColor === 'seashell')
    ? 'red'
    : 'seashell';

  objStyle.backgroundColor = bgColor;
}
document
  .querySelectorAll('[type="number"]')
  .forEach(elmNode =>
    elmNode.addEventListener('click' ,changeColor)
  );
<input id="hours" type="number" min="0" max="23" />
<input id="minutes" type="number" min="0" max="59" />
<input id="seconds" type="number" min="0" max="59" />

... turned into an event delegation based example ...

function handleColorChange(evt) {
  const inputRoot = evt.target?.closest('label');
  if (inputRoot) {
 
    const inputNode =
      inputRoot.querySelector('[type="number"]');
      
    const inputStyle = inputNode?.style;  
    if (inputStyle) {

      const bgColor = (inputStyle.backgroundColor === 'seashell')
        ? 'red'
        : 'seashell';

      inputStyle.backgroundColor = bgColor;
    }
  }
  console.log('evt.target ... ', evt.target);
}
document
  .querySelector('form')
  .addEventListener('click' , handleColorChange);
body { margin: -2px 0 0 0; }
.as-console-wrapper { max-height: 140px!important; }
<form>
  <fieldset>
    <legend>Time Settings</legend>
  
    <label>
      <span class="label">
        hours
      </span>
      <input name="hours" type="number" min="0" max="23" />
    </label>
  
    <label>
      <span class="label">
        minutes
      </span>
      <input name="minutes" type="number" min="0" max="59" />
    </label>
  
    <label>
      <span class="label">
        seconds
      </span>
      <input name="seconds" type="number" min="0" max="59" />
    </label>

  </fieldset>
</form>

  • Related