New to Kendo UI for jQuery? Download free 30-day trial

Skip Non-Editable Cells When Tabbing

Environment

Product Progress® Kendo UI® Grid for jQuery
Operating System All
Browser All
Browser Version All

Description

How can I skip non-editable cells when tabbing in the Kendo UI Grid for jQuery?

Solution

Normally, tabbing in an editable Grid steps on each cell, no matter if it is editable or not.

The following examples demonstrate how to skip non-editable cells of a Grid during tabbing. They apply the following different scenarios:

  • Skip all cells from a specific column.
  • Skip specific cells from different columns and rows, based on custom criteria.

Both examples work only if navigatable is disabled and the locked (frozen) columns are not used.

Skipping Specific Columns

The following example demonstrates how to skip all cells from a given column.

  <p>The "gender" column is not editable and is skipped during tabbing:</p>
  <div id="grid"></div>
  <script>
    $("#grid").kendoGrid({
      columns: [
        { field: "name" },
        { field: "gender" },
        { field: "city" }
      ],
      dataSource: {
        data: [
          { id: 1, name: "Jane Doe", gender: "female", city: "Sofia" },
          { id: 2, name: "John Smith", gender: "male", city: "London" },
          { id: 3, name: "James Jones", gender: "male", city: "New York" },
          { id: 4, name: "Mary Johnson", gender: "female", city: "Paris" },
          { id: 5, name: "Robert Lee", gender: "male", city: "Berlin" }
        ],
        schema: {
          model: {
            id: "id",
            fields: {
              gender: {
                editable: false
              }
            }
          }
        }
      },
      editable: {
        mode: "incell"
      }
    });

    var grid = $('#grid').data('kendoGrid');

    grid.table.on('keydown', function(e) {
      if (e.keyCode === kendo.keys.TAB && $($(e.target).closest('.k-edit-cell'))[0]) {
        e.preventDefault();
        var currentNumberOfItems = grid.dataSource.view().length;
        var row = $(e.target).closest('tr').index();
        var col = grid.cellIndex($(e.target).closest('td'));

        var dataItem = grid.dataItem($(e.target).closest('tr'));
        var field = grid.columns[col].field;
        var value = $(e.target).val();
        dataItem.set(field, value);

        if (row >= 0 && row < currentNumberOfItems && col >= 0 && col < grid.columns.length) {
          var nextCellRow;
          var nextCellCol = col === 0 ? 2 : 0;
          if(e.shiftKey){
            nextCellRow = nextCellCol === 0 ? row : row - 1;
          } else {
            nextCellRow = nextCellCol === 0 ? row + 1 : row;
          }

          if(nextCellRow >= currentNumberOfItems || nextCellRow < 0){
            return;
          }

          // wait for cell to close and Grid to rebind when changes have been made
          setTimeout(function() {
            grid.editCell(grid.tbody.find("tr:eq(" + nextCellRow + ") td:eq(" + nextCellCol + ")"));
          });
        }
      }
    });
  </script>

Skipping Specific Cells

The following example demonstrates how to skip cells from different columns and rows based on custom criteria.

    <style>
      .noneditable {
        border: 1px solid red !important;
        opacity: 0.6;
      }
    </style>

    <p>The marked cells are not editable and are skipped during tabbing:</p>

    <div id="grid"></div>
    <script>
      $("#grid").kendoGrid({
        columns: [
          { field: "name" },
          { field: "gender" },
          { field: "city" }
        ],
        dataSource: {
          data: [
            { id: 1, name: "Jane Doe", gender: "female", city: "Sofia" },
            { id: 2, name: "John Smith", gender: "male", city: "London" },
            { id: 3, name: "James Jones", gender: "male", city: "New York" },
            { id: 4, name: "Mary Johnson", gender: "female", city: "Paris" },
            { id: 5, name: "Robert Lee", gender: "male", city: "Berlin" }
          ],
          schema: {
            model: {
              id: "id",
            }
          }
        },
        editable: {
          mode: "incell"
        },
        dataBound: function(e){
          var cells = e.sender.tbody.find('td');
          cells.each(function(idx, item){
            if(!((idx + 1)%4)){
              $(item).addClass('noneditable');
            }
          });
        }
      });

      var grid = $('#grid').data('kendoGrid');

      grid.table.on('click', function(ev){
        if($(ev.target).is('.noneditable')){
          ev.preventDefault();
          ev.stopImmediatePropagation();
        }
      });

      grid.table.on('keydown', function moveToNext(e) {
        if (e.keyCode === kendo.keys.TAB && $($(e.target).closest('.k-edit-cell'))[0]) {
          e.preventDefault();
          var currentNumberOfItems = grid.dataSource.view().length;
          var row = $(e.target).closest('tr').index();
          var col = grid.cellIndex($(e.target).closest('td'));

          var dataItem = grid.dataItem($(e.target).closest('tr'));
             var field = grid.columns[col].field;
             var value = $(e.target).val();
             dataItem.set(field, value);

          if (row >= 0 && row < currentNumberOfItems && col >= 0 && col < grid.columns.length) {
            var nextCellRow;
            var nextCellCol;

            if(!e.shiftKey){
              nextCellCol = (col + 1) === grid.columns.length ? 0 : col + 1;
            } else {
              nextCellCol = (col - 1) === -1 ?  grid.columns.length - 1: col - 1;
            }

            if(!e.shiftKey){
              nextCellRow = nextCellCol === 0 ? row + 1 : row;
            } else {
              nextCellRow = nextCellCol === grid.columns.length - 1 ? row - 1 : row;
            }

            if(nextCellRow >= currentNumberOfItems || nextCellRow < 0){
              return;
            }

            // wait for cell to close and Grid to rebind when changes have been made
            if(!grid.tbody.find("tr:eq(" + nextCellRow + ") td:eq(" + nextCellCol + ")").is('.noneditable')){
              setTimeout(function() {
                grid.editCell(grid.tbody.find("tr:eq(" + nextCellRow + ") td:eq(" + nextCellCol + ")"));
              });
            } else {
              while(grid.tbody.find("tr:eq(" + nextCellRow + ") td:eq(" + nextCellCol + ")").is('.noneditable')){
                !e.shiftKey ? nextCellCol++ : nextCellCol--;

                if(nextCellCol === grid.columns.length){
                  nextCellCol = 0;

                  nextCellRow++;
                }

                if(nextCellCol === -1){
                  nextCellCol = grid.columns.length - 1;

                  nextCellRow--;
                }

                if(nextCellRow >= currentNumberOfItems || nextCellRow < 0){
                  return;
                }
              }
              grid.editCell(grid.tbody.find("tr:eq(" + nextCellRow + ") td:eq(" + nextCellCol + ")"));
            }

          }
        }
      });
    </script>

See Also

In this article