Search code examples
javascriptjquerydatatabledatatables

How to make select cell focused in jquery datatable


Im using Jquery data table

im using 3 fixedColumn when i press shift+tab from end row its navigating each cell but some cell are not focusable its showing half field which difficult identify which field user are entering. how to make focusable input field jquery data table?

Please refer below shift+tab video issue enter image description here

$(document).ready(function() {
  let data = [];
  for (let i = 1; i <= 100; i++) {
    let row = [];
    for (let j = 1; j <= 20; j++) {
      row.push(`<input type='text' value='Row ${i} Col ${j}'>`);
    }
    data.push(row);
  }

  $('#example').DataTable({
    data: data,
    scrollX: true,
    scrollCollapse: true,
    paging: false,
    fixedColumns: {
      left: 3
    }
  });
});
<link rel="stylesheet" href="https://cdn.datatables.net/2.2.2/css/dataTables.dataTables.css">
<link rel="stylesheet" href="https://cdn.datatables.net/fixedcolumns/5.0.4/css/fixedColumns.dataTables.css">
<script src="https://code.jquery.com/jquery-3.7.1.js"></script>
<script src="https://cdn.datatables.net/2.2.2/js/dataTables.js"></script>
<script src="https://cdn.datatables.net/fixedcolumns/5.0.4/js/dataTables.fixedColumns.js"></script>

<table id="example" class="display nowrap" style="width:100%">
  <thead>
    <tr>
      <th>Fixed 1</th>
      <th>Fixed 2</th>
      <th>Fixed 3</th>
      <th>Column 4</th>
      <th>Column 5</th>
      <th>Column 6</th>
      <th>Column 7</th>
      <th>Column 8</th>
      <th>Column 9</th>
      <th>Column 10</th>
      <th>Column 11</th>
      <th>Column 12</th>
      <th>Column 13</th>
      <th>Column 14</th>
      <th>Column 15</th>
      <th>Column 16</th>
      <th>Column 17</th>
      <th>Column 18</th>
      <th>Column 19</th>
      <th>Column 20</th>
    </tr>
  </thead>
  <tbody>
  </tbody>
</table>


Solution

  • You can use a simple trick to scroll to the focused cell.

    • Calculate the boundary of the last fixed column.
    • On input focus event, check if the focused cell is behind the fixed columns (by comparing the getBoundingClientRect values) and if yes then scroll it back to the "view".

    Here is the script:

    let lastFixedTd = $('tr:first-child td.dtfc-fixed-start').last()[0];
    let leftPoint = lastFixedTd.getBoundingClientRect().left + lastFixedTd.getBoundingClientRect().width;
    
    $('input').on('focus', (e) => {
      if ($(e.target).closest('td').hasClass('dtfc-fixed-start')) return;
    
      let left = e.target.getBoundingClientRect().left;
      let width = e.target.getBoundingClientRect().width;
    
      if(Math.round(left) < Math.round(leftPoint)) {
        console.log('Not visible!')
    
        let scrollEl = document.getElementsByClassName('dt-scroll-body')[0];
        if(Math.round(left + width) > Math.round(leftPoint)) {
          // Handle the case when the cell is partly hidden
          scrollEl.scrollLeft = scrollEl.scrollLeft - (leftPoint - left);
        } else {
          scrollEl.scrollLeft = scrollEl.scrollLeft - (left + leftPoint) + width;
        }
      } else {
        console.log('Visible!')
      }
    })
    

    Full code snippet:

    $(document).ready(function() {
          let data = [];
          for (let i = 1; i <= 100; i++) {
            let row = [];
            for (let j = 1; j <= 20; j++) {
              row.push(`<input type='text' value='Row ${i} Col ${j}'>`);
            }
            data.push(row);
          }
    
          $('#example').DataTable({
            data: data,
            scrollX: true,
            scrollCollapse: true,
            paging: false,
            fixedColumns: {
              left: 3
            }
          });
    
          let lastFixedTd = $('tr:first-child td.dtfc-fixed-start').last()[0];
          let leftPoint = lastFixedTd.getBoundingClientRect().left + lastFixedTd.getBoundingClientRect().width;
    
          $('input').on('focus', (e) => {
            if ($(e.target).closest('td').hasClass('dtfc-fixed-start')) return;
    
            let left = e.target.getBoundingClientRect().left;
            let width = e.target.getBoundingClientRect().width;
    
    
            if(Math.round(left) < Math.round(leftPoint)) {
              console.log('Not visible!')
    
              let scrollEl = document.getElementsByClassName('dt-scroll-body')[0];
              if(Math.round(left + width) > Math.round(leftPoint)) {
                scrollEl.scrollLeft = scrollEl.scrollLeft - (leftPoint - left);
              } else {
                scrollEl.scrollLeft = scrollEl.scrollLeft - (left + leftPoint) + width;
              }
            } else {
              console.log('Visible!')
            }
          })
        });
    <link rel="stylesheet" href="https://cdn.datatables.net/2.2.2/css/dataTables.dataTables.css">
    <link rel="stylesheet" href="https://cdn.datatables.net/fixedcolumns/5.0.4/css/fixedColumns.dataTables.css">
    <script src="https://code.jquery.com/jquery-3.7.1.js"></script>
    <script src="https://cdn.datatables.net/2.2.2/js/dataTables.js"></script>
    <script src="https://cdn.datatables.net/fixedcolumns/5.0.4/js/dataTables.fixedColumns.js"></script>
    
    <table id="example" class="display nowrap" style="width:100%">
      <thead>
        <tr>
          <th>Fixed 1</th>
          <th>Fixed 2</th>
          <th>Fixed 3</th>
          <th>Column 4</th>
          <th>Column 5</th>
          <th>Column 6</th>
          <th>Column 7</th>
          <th>Column 8</th>
          <th>Column 9</th>
          <th>Column 10</th>
          <th>Column 11</th>
          <th>Column 12</th>
          <th>Column 13</th>
          <th>Column 14</th>
          <th>Column 15</th>
          <th>Column 16</th>
          <th>Column 17</th>
          <th>Column 18</th>
          <th>Column 19</th>
          <th>Column 20</th>
        </tr>
      </thead>
      <tbody>
      </tbody>
    </table>