2

When a SlickGrid is set up with:

enableAddRow: false,
enableCellNavigation: true,
autoEdit: true

and the last column in that SlickGrid is configured with:

editor: null,
focusable: false,
selectable: false

When attempting to tab out of the SlickGrid by tabbing out of the second to last column in the last row, I would expect the focus to be moved to the next focusable element outside of the grid, but it does not.

See this example, and try to tab out of the grid from the last row. I would expect the focus to shift to the textboxes below the grid, but it does not and instead focus is lost while the active cell in the grid is not reset.

Is there a way to fix this? To ensure, when tabbing out of an editable cell that is followed by an uneditable unfocusable cell, that focus is moved out of the grid?

A workaround would be to make the last column focusable: true, but that is not an option since it breaks the user experience forcing the user to tab through an uneditable cell before reaching an editable cell.

kavun
  • 3,358
  • 3
  • 25
  • 45

3 Answers3

5

Can you try below if it works for you.

yourGrid.onKeyDown.subscribe(function(event) {
  if (event.keyCode === 9 && event.shiftKey === false) { // check its only tab not shift tab
    if (yourGrid.getActiveCell().cell === lastCol) { // check if the current cell is the last editable column 
      $("#b").trigger('focus'); // this or below line should work for focus, "b" is your text input
      document.getElementById("b").focus(); // either this or above line
      event.stopImmediatePropagation();
    }
  }
});

UPDATE

Fixed it by changing the code in the plugin. The issue were coming and I think its a bug in the Slickgrid. After the change in below function your example is working in my local. Please replace the below function code and let me know if this is working for you.

function setActiveCellInternal(newCell, opt_editMode) {
      var lastActiveCell = null;
      var lastActiveRow = null;
      if (activeCellNode !== null) {
        makeActiveCellNormal();
        $(activeCellNode).removeClass("active");
        if (rowsCache[activeRow]) {
          $(rowsCache[activeRow].rowNode).removeClass("active");
        }
        var lastActiveCell = getCellFromNode(activeCellNode); // my added
        lastActiveRow = activeRow;
      }

      var activeCellChanged = (activeCellNode !== newCell);


      activeCellNode = newCell;

      if (activeCellNode != null) {
          //alert('1-3')
        activeRow = getRowFromNode(activeCellNode.parentNode);
        activeCell = activePosX = getCellFromNode(activeCellNode);

        if (opt_editMode == null) {
          opt_editMode = (activeRow == getDataLength()) || options.autoEdit;
        }

        $(activeCellNode).addClass("active");
        $(rowsCache[activeRow].rowNode).addClass("active");
        //alert(options.editable +' - '+ opt_editMode);
        if (options.editable && opt_editMode && isCellPotentiallyEditable(activeRow, activeCell) && ((lastActiveCell !== activeCell || lastActiveRow !== activeRow) ) ) { // not sure if need acheck on row also
          clearTimeout(h_editorLoader);

          if (options.asyncEditorLoading) {
            h_editorLoader = setTimeout(function () {
              makeActiveCellEditable();
            }, options.asyncEditorLoadDelay);
          } else {
            makeActiveCellEditable();
          }
          //alert('1-4')
        }
      } else {
        activeRow = activeCell = null;
        //alert('1-5')
      }

      if (activeCellChanged) {
          //alert('1-6')
        trigger(self.onActiveCellChanged, getActiveCell());
      }
    }
A Paul
  • 8,113
  • 3
  • 31
  • 61
  • Thanks for your answer, but this does not solve the root cause of the tabbing to outside the SlickGrid not working in my senario. I do not want to hard code the next focusable element outside of each grid. Also, how can I determine what `lastCol` should be if some rows have editing disabled (via `onBeforeCellEdit` or custom metadata) for specific columns while other rows do not? This is not the ideal solution. – kavun Jan 15 '14 at 22:47
  • Ok. You can use grid.getColumns()[cell.cell] to get the column I think you can also get if you are at last row. Then you know when to jump out of the table and regarding you can not use id not next focus item, just use jquery to find what is the next element after the table and shift the control there. It is possible. You can use $(this).next('input') – A Paul Jan 16 '14 at 07:30
  • There are [other elements other than `input` that are focusable](http://stackoverflow.com/questions/1599660/which-html-elements-can-receive-focus), and handling all of those for every browser would get very messy, especially if elements that are not normally focusable have a `tabindex`. Also, the editability of certain cells is changed via `onBeforeCellEdit` and/or `metadata` so getting the column definition at the same index every time will not always give me the last editable cell. I'm hoping to find a way to fix the bug that is causing the focus to stay in the grid when tabbing away. – kavun Jan 16 '14 at 15:15
  • [This seems to be working perfectly](http://jsbin.com/ukeDibAK/7/). Thank you very much. – kavun Jan 21 '14 at 14:07
  • The row check is necessary and it actually needs to be `(lastActiveCell !== activeCell || lastActiveRow !== activeRow)` so that if you try to navigate from one row to another but stay in the same column it will navigate correctly. If the check is not in place then `activeCell === lastActiveCell` when you change rows but stay in the same column. – kavun Feb 07 '14 at 16:08
  • Well, you had `(lastActiveCell !== activeCell && lastActiveRow = activeRow)`, but it should be `(lastActiveCell !== activeCell || lastActiveRow !== activeRow)`. – kavun Feb 08 '14 at 00:09
0

See the link below. https://github.com/mleibman/SlickGrid/issues/104

Since you cannot tab out of the last cell, you can try committing the change when you click on save changes

if (Slick.GlobalEditorLock.isActive() && !Slick.GlobalEditorLock.commitCurrentEdit()) return;

Will that work?

HappyKoder
  • 21
  • 4
  • That's the thing, you normally CAN tab out of the last cell if the last column is focusable - [see example](http://jsbin.com/ukeDibAK/3). It's just that when the last column has `focusable: false` tabbing out of the grid from the second to last column is not possible. The issue is not that the edit is not committed (it is committed in my example when tabbing out of the second to last column). The issue is that focus is not changed from inside the grid to outside the grid when tabbing out of the second to last column. – kavun Jan 16 '14 at 15:59
0

Can you try to replace the gotoRight function with below code in slick.grid.js file and try.

function gotoRight(row, cell, posX) {
  if (cell >= columns.length) {
    return null;
  }
  do {
    cell += getColspan(row, cell);
  }
  while (cell < columns.length && !canCellBeActive(row, cell));
  if(cell == columns.length && !canCellBeActive(row, cell)) {
    setActiveCell(row,cell-1)
  }
  if (cell < columns.length) {
    return {
      "row": row,
      "cell": cell,
      "posX": cell
    };
  }
  return null;
}
HeiN
  • 503
  • 3
  • 17
  • Thanks for your input, but this selects cells even if they are declared `selectable: false`. [See example](http://jsbin.com/ukeDibAK/6) that includes your `goToRight` function. Notice how when tabbing out of the last row, the last column is selected and the focus goes to the text box below the grid. – kavun Jan 21 '14 at 14:05