Nick
Nick

Reputation: 21

EventListeners Fetching classes with label tags

I have an Event Listener that grabs an element by its class name, if the input tags name is the same as that class. It works for the first label but it doesn't work for the second label. Am I using event targeting incorrectly? See Below.

JS

let selected = true;
document.querySelector('label').addEventListener("click", function(e) {
  if (e.target.checked = selected) {
    let labelFor = document.querySelector('label').htmlFor;
    let inputId = document.getElementById(labelFor);
    let inputName = inputId.name;
    let path = document.getElementsByClassName(inputName)
    console.log(path);
  }
})

HTML

Formatted HTML:
<input type="radio" name="first" id="floor-1">
<label for="floor-1">first</label><br>
<input type="radio" name="second" id="floor-2">
<label for="floor-2">second</label>
<svg viewBox="0 0 300 300">
   <g class="first">
      <path d="M 10 10 H 90 V 90 H 10 L 10 10"/>
   </g>
   <g class="second">
      <path d="M 20 20 H 100 V 100 H 20 L 20 20" />
   </g>
</svg>

Any guidance would be extremely helpful.

Upvotes: 0

Views: 1179

Answers (2)

Marirs
Marirs

Reputation: 1

This is to be expected because document.querySelector('<CSS selector>') returns the first element within the document that matches with the <CSS selector> specified.

So in your case,

  • It encounters the #floor-1 input field's label
  • Then attaches the event listener to that field alone.

If you need to listen to all the labels in your HTML file, use

document.querySelectorAll('label').forEach(eachLabelElem => 
   eachLabelElem.addEventListener("click",<your function logic here>)
)

Note that the Event Listener will be applied to all the label present in your HTML.

Upvotes: 0

Peter Seliger
Peter Seliger

Reputation: 13417

// since the handler is going to be associated
// with more than one html element, provide it
// as separate function which reduces overhead.
function handleControlStateChange(evt) {

  const elmControl = evt.currentTarget;
  const svgRoot = document.body.querySelector('svg');

  if (svgRoot && elmControl && elmControl.checked) {

    const pathContainer = svgRoot.getElementsByClassName(elmControl.name)[0];

    const elmPath = pathContainer && pathContainer.children[0];
    const pathValue = elmPath && elmPath.getAttribute('d');

    console.log(pathValue);
  }
}

// initialize event listeners, but for the
// "change" event of each checkbox control.
document.body.querySelectorAll('[type="checkbox"]').forEach(elm =>
  elm.addEventListener("change", handleControlStateChange)
);
<label>
  <!--
    provide a simpler stucture and thus, reduced html overhead as with
    `for` and `id` attributes, as well as with the code which handles
    the state changes of a checkbox-control.
  //-->
  <span class="label">first</span>
  <!--
    make use of a checkbox- instead of a radio-control since differently
    named radio-controls do not make sense because there will be no radio-
    group that contains both controls; thus each radio could not be unchecked.
  /-->
  <input type="checkbox" name="first"/>
</label>

<label>
  <span class="label">second</span>
  <input type="checkbox" name="second"/>
</label>

<svg viewBox="0 0 300 300">
  <g class="first"> 
    <path d="M 10 10 H 90 V 90 H 10 L 10 10"/>
  </g>
  <g class="second"> 
    <path d="M 20 20 H 100 V 100 H 20 L 20 20"/>
  </g>
</svg>

Upvotes: 1

Related Questions