0

I use javascript to make a table that have rows and columns based on the number of cells of a matrix. I'll try to use a function, but it doesn't recognize the ID that was be created.

<!DOCTYPE html>
<html lang="en">
  <head >
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="src/style.css">
  </head>
  <body onload="tableCreate()">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>

    <script src="src/script.js"></script>
  </body>
</html>

the first part creates the table, the second part when enter key was released increment the cursor, the third is if the table doesn't contain other rows and the enter key was pressed in the last cell it created a new row

var c = [
  ['casa', 'casa1', 'casa2'],
  ['casa3', 'casa4', 'casa5'],
  ['casa6', 'casa7', 'casa8'],
  ['casa9', 'casa10', 'casa11'],
];
function tableCreate() {
  const body = document.body,
    tbl = document.createElement('table');
  tbl.setAttribute('id', 'tab_1');
  tbl.style.width = '100px';
  tbl.style.border = '1px solid red';

  for (let i = 0; i < c.length; i++) {
    const tr = tbl.insertRow();
    for (let j = 0; j < 3; j++) {
      const td = tr.insertCell();
      var x = document.createElement('INPUT');
      x.setAttribute('type', 'number');
      x.setAttribute('class', 'username');
      td.appendChild(x);
      td.style.border = '2px solid yellow';
    }
  }
  document.body.appendChild(tbl);
}


$('.username').focus(function (event) {
  console.log('gd');
});



var currentBoxNumber = 0;
$('.username').keyup(function (event) {
  if (event.keyCode == 13) {
    textboxes = $('input.username'); 
    console.log('o');
    currentBoxNumber = textboxes.index(this);
    if (textboxes[currentBoxNumber + 1] != null) {
      nextBox = textboxes[currentBoxNumber + 1];
      nextBox.focus();
      nextBox.select();
      event.preventDefault();
    } else {
     
      const bd = document.body,
      tbl = document.getElementById('tab_1');
      
      const tr = tbl.insertRow();
      for (let j = 0; j < 3; j++) {
        const td = tr.insertCell();
      var x = document.createElement('INPUT');
        x.setAttribute('type', 'number');
        x.setAttribute('class', 'username');
        td.style.border = '2px solid green';
        td.appendChild(x); 
      }
      bd.appendChild(tbl);
    }
    return false;
  }
});

anyone can help me? thanks

i try to use the function whit some keys, but not recognized the ID

1 Answers1

1

The problem here isn't that getElementById isn't finding the element by the ID, it's that your event binding is occurring before the elements it's binding to exist.

The order of events you have in your script is:

  1. Create tableCreate function.
  2. Bind focus event to .username elements.
  3. Bind keyup event to .username elements.
  4. On document onload execute tableCreate()

The .username elements are created in the tableCreate function which is executed after the events are bound.

When binding events, you're basically saying (to jQuery): get me all the .username elements, and bind this event to them. But because those elements don't exist yet, nothing is bound.

There's two ways to fix this in your script, either:

  1. Execute tableCreate() before binding your events.

    • This will ensure the elements are created first.
  2. Bind the event listeners to the document and use jQuery's context to filter the events to just .username elements (preferred)

Point #2 would be simpler to use as you're binding a single event listener, and it will handle events to elements added to the DOM after the listener is bound (since document is always there).

Example:

// Bind Target  Context
// |            |   
// v            v
$(document, '.username').focus(...);

$(document, '.username').keyup(...);

Update 2023-01-15

As in the original answer, when you are binding the keyup handler, you binding to the .username elements available at the time the binding occurred.

Any new .username elements which are added after that statement will not have the bindings.

Per my #2 suggestion above, you can bind the event listener to document and provide jQuery a context filter for which to execute the listener for.

For completeness, I've taken your code and updated it with this context filter, and also simplified your listener to allow it to shift the focus to the next row even after it has been added.

// Bind listener to document and filter by `.username`.
$(document, '.username').keyup(function (event) {
  if (event.keyCode !== 13) return; // Quick exit if not Enter key

  event.preventDefault(); // Prevent default straight away

  let textboxes = $('.username'); // Use `let` as we'll re-assign if we add more rows
  console.log('Current textboxes.length', textboxes.length);

  const currentBoxNumber = textboxes.index(event.target); // Search using `event.target` because `this` is the `document` as it's the element the listener is bound to, but the event's target is sourced from the `.username` element

  const nextBoxIndex = currentBoxNumber + 1;
  const hasNextCell = Boolean(textboxes[nextBoxIndex]); // false if no cell found

  if (!hasNextCell) {
    add_row(); // Create the next row if there isn't the next cell
    textboxes = $('.username'); // Query for textboxes again since we've added some more
    console.log('Updated textboxes.length', textboxes.length);
  }

  const nextBox = textboxes[nextBoxIndex];
  nextBox.focus();
});

// Bind to document and filter to `.username`
$(document, '.username').focus(function (event) {
  console.log('on_focus');
}); 
justrhysism
  • 1,125
  • 10
  • 16
  • i've tried to do some things: i put tableCreate() after the function, the function of enter presskey works, but, when i create a new row whit function add_row, never work. there is the code: https://playcode.io/1058010 – Emilio Pantanali Jan 13 '23 at 12:10
  • @EmilioPantanali have updated the answer with an example code snippet based on the code you linked. – justrhysism Jan 15 '23 at 05:14
  • @EmilioPantanali how did you go? If I have helped you find your answer, please mark the answer as correct. – justrhysism Jan 17 '23 at 23:59
  • Hi! i was busy at work, just tried, it works and understand the mistake! thanks! – Emilio Pantanali Jan 19 '23 at 18:18