0

I am creating an app that has multiple tables, one has the customer and their location, while another has the customer with their inventory items and item IDs. I am having trouble creating a function that can be used for multiple tables, the function allows the user to create new rows for a table, and I have working code, but with that code I have to copy it for each unique table.

What I want is to use (this) so that one single function will work for multiple tables, I have attempted using (this) but it obviously failed to work, the first problem is that it cannot read the property 'length' for the table, but I am sure I will run into many more problems.

Any help would be appreciated.

Desired Outcome: use (this) to use one single function on multiple tables.

function appendRow() {
        var table = document.getElementsByTagName('table'); // table reference
        length = this.length, 
        row = this.insertRow(this.rows.length),      // append table row
        i;
    // insert table cells to the new row
    for (i = 0; i < this.rows[0].cells.length; i++) {
        createCell(row.insertCell(i), i, 'row');
    }
}


// this works, but if I want it for multiple tables, I must copy it for each table....
/*
function appendRow() {
    var custList = document.getElementById('custList'), // table reference
        row = custList.insertRow(custList.rows.length),      // append table row
        i;
    // insert table cells to the new row
    for (i = 0; i < custList.rows[0].cells.length; i++) {
        createCell(row.insertCell(i), i, 'row');
    }
}
*/ 


function createCell(cell, text, style) {
    var div = document.createElement('div'), // create DIV element
        txt = document.createTextNode('_'); // create text node
    div.appendChild(txt);               // append text node to the DIV
    div.setAttribute('id', style);        // set DIV class attribute
    div.setAttribute('idName', style);    // set DIV class attribute for IE (?!)
    cell.appendChild(div);                   // append DIV to the table cell
}
<div id="custDiv">
  <div class="addBtns">
    <input id="searchName" onkeyup="custSearchName()" type="text" placeholder="search name"></input>
  </div>
  <div style="width: 355px; margin: 0 auto; height: 50px;">
    <button id="addCust" onclick="appendRow(this)">add customer</button>
  </div>

  <div class="custScroll">
    <table id="custListTop" contenteditable="false">
      <tr>
        <td style="border-top-left-radius: 5px;">Customers</td>
        <td style="border-top-right-radius: 5px;">Main Location</td>
      </tr>
    </table>
    <table id="custList" contenteditable="true">
      <tr>
        <td>Someone</td>
        <td>something</td>
      </tr>
    </table>
  </div>
</div>
hannacreed
  • 639
  • 3
  • 15
  • 34
  • 4
    Why not define a generic `function appendRow(id) { var custList = document.getElementById(id)... }`? – msanford Nov 10 '17 at 16:18
  • In `length = this.length`, why do you use `this` (which is `window`) when you actually want the number of tables in `table`? ([What do querySelectorAll, getElementsByClassName and other getElementsBy* methods return?](https://stackoverflow.com/questions/10693845/what-do-queryselectorall-getelementsbyclassname-and-other-getelementsby-method)) – Andreas Nov 10 '17 at 16:23
  • On a sidenote: `` is a self-closing tag, so it should be written as `` instead of `` - or you can omit the closing slash completely when using the correct HTML doctype. – Constantin Groß Nov 10 '17 at 16:25
  • if you really want to use this function with `this`, you can start to remove this line `var table = document.getElementsByTagName('table');` which will be useless. Then you have to retreive the table before the call and bind it to the function's this with `call`, like that : `var table1 = document.getElementById('custList'); appendRow.call(table1);` – Kaddath Nov 10 '17 at 16:26

2 Answers2

1

I question why you want to use the 'this' keyword. Saying 'this' in the button is meaningless unless you tell it somehow what 'this' is. Otherwise it has no way to know that 'this' is actually a table called custList. Somehow you need to make that connection and I have opted in the snippet below to pass the table name as a parameter in the js function.

You also had an issue in your code where the i variable was not declared.

function appendRow(id) {
        var table = document.getElementById(id); // table reference
        length = table.length, 
        row = table.insertRow(table.rows.length);      // append table row
        var i;
    // insert table cells to the new row
    for (i = 0; i < table.rows[0].cells.length; i++) {
        createCell(row.insertCell(i), i, 'row');
    }
}

function createCell(cell, text, style) {
    var div = document.createElement('div'), // create DIV element
        txt = document.createTextNode('_'); // create text node
    div.appendChild(txt);               // append text node to the DIV
    div.setAttribute('id', style);        // set DIV class attribute
    div.setAttribute('idName', style);    // set DIV class attribute for IE (?!)
    cell.appendChild(div);                   // append DIV to the table cell
}
<div id="custDiv">
  <div class="addBtns">
    <input id="searchName" onkeyup="custSearchName()" type="text" placeholder="search name"></input>
  </div>
  <div style="width: 355px; margin: 0 auto; height: 50px;">
    <button id="addCust" onclick="appendRow('custList')">add customer</button>
  </div>

  <div class="custScroll">
    <table id="custListTop" contenteditable="false">
      <tr>
        <td style="border-top-left-radius: 5px;">Customers</td>
        <td style="border-top-right-radius: 5px;">Main Location</td>
      </tr>
    </table>
    <table id="custList" contenteditable="true">
      <tr>
        <td>Someone</td>
        <td>something</td>
      </tr>
    </table>
  </div>
</div>
Bijan Rafraf
  • 393
  • 1
  • 7
0

Don't worry about this, just define a generic function from the one that works:

function appendRow(id) {
    var custList = document.getElementById(id),
        row = custList.insertRow(custList.rows.length),
        i;
    for (i = 0; i < custList.rows[0].cells.length; i++) {
        createCell(row.insertCell(i), i, 'row');
    }
}
msanford
  • 11,803
  • 11
  • 66
  • 93