Skip to content Skip to sidebar Skip to footer

Javascript Stop TR Click Event On Dropdown Selection

I want to capture what option has been selected from dropdown. Here the problem is when option is being clicked TR click event is called because select doesn't have click event. H

Solution 1:

You need to capture click event on <select> and prevent its propagation:

function onSelectClick(ev) {
  ev.stopPropagation();
}
<select onclick="onSelectClick">

or you can try to simply return false for click event for <select>:

<select onclick="return false;">

Solution 2:

You can just check what element triggered the click, and if it was the drop down, ignore the event:

function check1(e) {
    if (typeof e == "undefined")
        e = window.event;
    if (e.srcElement.id != "drop_down") {
        alert("TR clicked");
    }
}

jsfiddle sample


If you want the JS to be more generic and not check for specific ID of elements, you can also change its logic to look for elements having a custom attribute defined:

function check1(e) {
    if (typeof e == "undefined")
        e = window.event;
    if (e) {
        var sourceElement = e.srcElement || e.target;
        if (sourceElement) {
            if (sourceElement.getAttribute("data-stop-propagation")) {
                //element being clicked asked to ignore the event, abort
                return;
            }
        }
    }
    alert("TR clicked");
}

To make it work with your code, change the HTML to this: (the value of the attribute doesn't matter)

<select name="" id="drop_down" onchange="check2();" data-stop-propagation="1">

updated fiddle


Solution 3:

one more thing you can do is get event target,

  function check1() {
   if(this.event.target.nodeName!=='SELECT'){
    alert("TR clicked");
   }
}

to support in all browsers just capture event and pass it as param

<tr onclick=check1(event)>....</tr>
//in js
function check1(event) {
   if(event.target.nodeName!=='SELECT'){
    alert("TR clicked");
   }
}

Solution 4:

Use addEventListener() instead of inline attribute eventHandlers. At the end of the eventListener(), or at the end of callback, add e.stopPropagation() so the event never bubbles thereby never reaching <tr>.

<tr> will need to be referenced as it is relative to another table component such as <table> or <td>. Although inline attribute events stick to anything (including a <tr> tag), it will become detrimental to maintaining such a layout (as I suspect it is already occurring). This is why it has been strongly suggested that addEventListener() be used instead of inline events.

In the following demo:

  • If <select> is clicked the console logs its value.

  • If a <td> is clicked then it logs a generic 'click'

  • It will not log both at click event

All modern browsers are supported

Details commented in demo

Demo

var table = document.querySelector('table');

function chk() {
  var drop = document.getElementById('drop');
  var val = drop.value
  console.log(val);
}

function rowLog() {
  console.log('Clicked');
}

table.addEventListener('click', function(e) {
  /* if the clicked element (e.target) is NOT
  || the element registered to listen for
  || click event (table) then...
  */
  if (e.target !== e.currentTarget) {

    /* if clicked element's #id is drop
    || call function chk()
    */
    if (e.target.id === 'drop') {
      chk();
      
      /* Stop the event from bubbling (thereby 
      || event never reaches TR if #drop is clicked)
      */
      e.stopPropagation();
    }
    /* TR is tightly integrated with TD so
    || target TD or spicify TBODY or TABLE
    || to reference TR.
    || Note e.stopPropagation() is not invoked
    || in this function so click event will
    || bubble to <tr>
    */
    else if(e.target.tagName === 'TD') {
      rowLog();
    }
  }
  
}, false);
<table border=1>
  <tr>
    <td>My Options</td>
    <td>
      <select name="" id="drop">
              <option></option>
              <option value="A">A</option>
              <option value="B">B</option>  
            </select>
    </td>
  </tr>
</table>

Solution 5:

I found this solution to work best for me:

<html>
<script>
    function check1(event) {
        // check if the event path contains the select element
        // Not checking null values for simplicity
        var preventFlag = event.path.filter(obj => 
                            obj.id.include('select')).length > 0
        if(!preventFlag) {
          // triggered only when preventFlag is false
          alert("TR clicked");
        }
    }

    function check2() {
        alert("drop_down clicked");
    }
</script>
<table border=1>
    <tr onclick="check1(event);">
        <td>My Options</td>
        <td>        
            <select name="" id="drop_down" onchange="check2();">
              <option value="A">A</option>
              <option value="B">B</option>  
            </select>           
        </td>
    </tr>
</table>

The good thing about this solution is that it works for all child elements inside the desired target element. For e.g, this logic works when a select element is clicked and it also works when any of the options inside the select element are clicked.

Downside: the path array needs to be looped through.


Post a Comment for "Javascript Stop TR Click Event On Dropdown Selection"