1

I am writing a program that will generate a set of HTML tables, each with an (obviously) unique ID. Certain of the cells in each table have onClick handlers (and each also has a unique id). I want to be able to get the table id on clicking a cell to use it as a parameter in the function I'm calling onClick.

This question has been asked previously (and answered) specifically for JQuery, but I would prefer to do it in pure JavaScript. I assume it must be possible, but how?

Community
  • 1
  • 1
David
  • 1,018
  • 13
  • 22
  • I see this has immediately attracted two down-votes. A comment explaining why would be appreciated. – David Jul 01 '16 at 16:47
  • `this.id` contains the ID of the element the event handler is bound to. It's that simple. – Niet the Dark Absol Jul 01 '16 at 16:47
  • Since you're generating the table, why can't you just put the table id to the onclick handler at the same time? – JJJ Jul 01 '16 at 16:47
  • 1
    @NiettheDarkAbsol — Surely this.id gives me the id of the td cell, not that of the table? I use this in my event handler to send the td object to the function. – David Jul 01 '16 at 16:50
  • @Juhana — Yes, I could generate a compound id which included the table id and then parse it. But I wondered if... – David Jul 01 '16 at 16:51
  • Why a compound id? Just pass the id as it is to the function. (I'm not saying that it's the most elegant solution but if you're set on using inline event handlers it's as good as anything.) – JJJ Jul 01 '16 at 16:53
  • 2
    Make a generic function that accepts an element and a selector, and traverse up the `.parentElement`s until `el.matches(selector)`. –  Jul 01 '16 at 16:53
  • OK. I admit I have never heard of binding. Reference to Flanagan's JavaScript (6e) indicates it was only added in ECMAScript 5, so perhaps I can be excused. – David Jul 01 '16 at 16:55
  • @Juhana — Your comment suggests inline event handlers are a bad thing. What do you suggest instead? The first cell id determines the target row of the event (a border highlighting) in a second table with a different layout. – David Jul 01 '16 at 16:59
  • Possible duplicate of [jQuery: get table id by click in td](http://stackoverflow.com/q/20175970/1529630) and [Finding closest element without jQuery](http://stackoverflow.com/q/18663941/1529630) – Oriol Jul 01 '16 at 17:02
  • Some discussion here: http://stackoverflow.com/questions/11737873/why-is-inline-event-handler-attributes-a-bad-idea-in-modern-semantic-html, http://programmers.stackexchange.com/a/119022. Generally [`.addEventListener`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) is preferred. – JJJ Jul 01 '16 at 17:05
  • @Juhana — Thanks, I'll check that out. – David Jul 01 '16 at 17:07
  • @David: They're not "bad", but like anything they have their pros and cons. Depending upon how you're generating the tables, it may make more sense to manually bind the handler instead of using an attribute. Some people here tend to become absolutists on this topic for some reason but IMO, there's a time and place for everything. –  Jul 01 '16 at 17:07
  • So after a year and a half in which the question has been edited by a mod, received an answer that five people voted for and solved my problem (and one presumes that of others), someone has decided to down-vote my question without giving any indication why. You just wonder... – David Feb 08 '18 at 21:04

2 Answers2

6

Please try the following:

var tds = document.getElementsByTagName("td");

var getParentTableID = function() {
    var el = this;
    while ((el = el.parentElement) && el.nodeName.toUpperCase() !== 'TABLE');
    console.log(el.id);//Table id
};

for(var i = 0; i < tds.length; i++) {
  tds[i].onclick = getParentTableID;
};
<h4>Table1</h4>
<table id="tableID_1">
  <tr>
    <td>1</td>
    <td>2</td>
    <td>3</td>
  </tr>
  <tr>
    <td>4</td>
    <td>5</td>
    <td id="b3">6</td>
  </tr>
  <tr>
    <td>7</td>
    <td>8</td>
    <td>9</td>
  </tr>
</table>
<h4>Table2</h4>
<table id="tableID_2">
  <tr>
    <td>1</td>
    <td>2</td>
    <td>3</td>
  </tr>
  <tr>
    <td>4</td>
    <td>5</td>
    <td id="b3">6</td>
  </tr>
  <tr>
    <td>7</td>
    <td>8</td>
    <td>9</td>
  </tr>
</table>
Ismail RBOUH
  • 10,292
  • 2
  • 24
  • 36
  • 1
    Please use a `for` loop instead of `for-in`. Right now you'll be bumping into some non-elements in that loop. Harmless with the code you've provided, but still not altogether good. –  Jul 01 '16 at 16:56
  • ...and that function could be reused instead of creating a new one for each element. Not a big deal, but a little nicer IMO. –  Jul 01 '16 at 16:57
  • 1
    `.toUpperCase()` wouldn't hurt in HTML, and would be necessary in XHTML. – Oriol Jul 01 '16 at 17:04
  • Many thanks for the answer. I have now taken your getParentTableID() function and modified it to take the td as an argument and return the tableID. This works fine. Can I check that I understand the code (which is the point of doing it in pure JavaScript)? I assume that the (el = el.parentElement) of the while loop continually assigns a parent node to the variable el, until the node name of the element is "TABLE", at which point it has the table element and can access (and return) the ID. – David Jul 02 '16 at 11:11
0

Try it:

<table id="Test">
  <tr>
    <td onclick="test(this)">teste</td>
    <td>teste</td>
  </tr>
</table>

<table id="Test2">
  <tr>
    <td onclick="test(this)">teste</td>
    <td>teste</td>
  </tr>
</table>

<script>
function test(obj) {

  while(obj.tagName.toUpperCase() !== "TABLE") {
    obj = obj.parentNode;
  }

    console.log(obj.id);

}

</script>
msantos
  • 691
  • 5
  • 6