4

I adopted the code from this post and made this fiddle. Try clicking the first row, then shift-clicking the last row. If you notice this code does very well, except the last row, the row that you click on, does not get selected. I have been scratching my head on this one. Can anyone help me alter the code so that the multiselect selects the last row too?

Thanks!

Community
  • 1
  • 1
jeffery_the_wind
  • 17,048
  • 34
  • 98
  • 160

5 Answers5

6

try replacing this: if ((shouldSelectRow = id == startID || shouldSelectRow)) { with this:

if ((shouldSelectRow = id == startID || shouldSelectRow) && (id != rowid)){
Michael Gendin
  • 3,285
  • 2
  • 18
  • 23
6

I agree with Michael Gendin that you should not select the row with the id equal to rowid. It's your main error. Nevertheless I would rewrite the most code of the demo to use rowIndex of DOM elements of the rows instead of enumerating of all rows of the grid. Additionally the selection of the text in IE is uncomfortable in your current code, so I would suggest removing it. The modified demo which you find here I used the following code of beforeSelectRow callback:

beforeSelectRow: function (rowid, e) {
    var $this = $(this), rows = this.rows,
        // get id of the previous selected row
        startId = $this.jqGrid('getGridParam', 'selrow'),
        startRow, endRow, iStart, iEnd, i, rowidIndex;

    if (!e.ctrlKey && !e.shiftKey) {
        $this.jqGrid('resetSelection');
    } else if (startId && e.shiftKey) {
        $this.jqGrid('resetSelection');

        // get DOM elements of the previous selected and the currect selected rows
        startRow = rows.namedItem(startId);
        endRow = rows.namedItem(rowid);
        if (startRow && endRow) {
            // get min and max from the indexes of the previous selected
            // and the currect selected rows 
            iStart = Math.min(startRow.rowIndex, endRow.rowIndex);
            rowidIndex = endRow.rowIndex;
            iEnd = Math.max(startRow.rowIndex, rowidIndex);
            for (i = iStart; i <= iEnd; i++) {
                // the row with rowid will be selected by jqGrid, so:
                if (i != rowidIndex) {
                    $this.jqGrid('setSelection', rows[i].id, false);
                }
            }
        }

        // clear text selection
        if(document.selection && document.selection.empty) {
            document.selection.empty();
        } else if(window.getSelection) {
            window.getSelection().removeAllRanges();
        }
    }
    return true;
}
Jason Jones
  • 319
  • 2
  • 12
Oleg
  • 220,925
  • 34
  • 403
  • 798
  • Oleg's solution works great on my Safari and IE8 setup. In case other people are looking at this for the same reason I am, here are the adjustments needed if you want to have appended selections (shift selecting one block, then another doesn't clear the selection): 1) Remove both calls to $this.jqGrid('resetSelection') to not clear the existing selections. 2) Call $this.jqGrid('getGridParam','selarrrow'); to get the array of selected indicies, and in the test to toggle selection, also check that the rows[i].id is not in your array of existing selections. – Kelly Dec 18 '12 at 16:39
  • @Kelly: It would be good if you just add your code in your answer. I can imagine that the problem could be interesting for other people. Call of `$this.jqGrid('resetSelection')` seems to me required to simulate the same behavior which the users know. If you would select some items for example in Windows and then click on one more with pressed Shift or without Shift and without Ctrl you will see that the selection will be reset. In any way sharing the code is good and I can imagine different implementation of selection. – Oleg Dec 18 '12 at 17:39
1

Add $('#grid').disableSelection(); to remove the annoying text selection

Paul
  • 588
  • 1
  • 4
  • 16
0

As discussed in Oleg's answer, here is an adjusted beforeSelectRow that does appended selections.

In my case, our users are selecting a bunch of rows for export, so additional selections does not usually mean they want to start a new selection.

 beforeSelectRow: function(rowid, e) {
      var $this = $(this), rows = this.rows,

      // get id of the previous selected row
      startId = $this.jqGrid('getGridParam', 'selrow'),
      startRow, endRow, iStart, iEnd, i, rowidIndex;

      if (!e.ctrlKey && !e.shiftKey) {
          //intentionally left here to show differences with
          //Oleg's solution. Just have normal behavior instead.
          //$this.jqGrid('resetSelection');
      } else if (startId && e.shiftKey) {
          //Do not clear existing selections
          //$this.jqGrid('resetSelection');

          // get DOM elements of the previous selected and
          // the currect selected rows
          startRow = rows.namedItem(startId);
          endRow = rows.namedItem(rowid);

          if (startRow && endRow) {
              // get min and max from the indexes of the previous selected
              // and the currect selected rows
              iStart = Math.min(startRow.rowIndex, endRow.rowIndex);
              rowidIndex = endRow.rowIndex;
              iEnd = Math.max(startRow.rowIndex, rowidIndex);

              // get the rowids of selected rows
              var selected = $this.jqGrid('getGridParam','selarrrow');

              for (i = iStart; i <= iEnd; i++) {
                  // if this row isn't selected, then toggle it.
                  // jqgrid will select the clicked on row, so just ingore it.
                  // note that we still go <= iEnd because we don't know which is start or end.
                  if(selected.indexOf(rows[i].id) < 0 && i != rowidIndex) {
                    // true is to trigger onSelectRow event, which you may not need
                    $this.jqGrid('setSelection', rows[i].id, true);
                  }
              }
          }

          // clear text selection (needed in IE)
          if(document.selection && document.selection.empty) {
              document.selection.empty();
          } else if(window.getSelection) {
              window.getSelection().removeAllRanges();
          }
      }
      return true;
  }
Kelly
  • 1,096
  • 12
  • 22
0

The solution of Oleg is not working in all selection mode (up/down). Thanks to him for the partial solution.

I correct this with this code:

You need 2 variables for stored the current start row Id and end row Id. And an other one to store the side of the selection.

var _currentStartSelectRow, _currentEndSelectRow, _isSideDown = null;

Code call by the beforeSelectRow callback:

beforeSelectRow: function (rowid, e) {
                var $this = $(this), rows = this.rows,
                // get id of the previous selected row
                previousId = $this.jqGrid('getGridParam', 'selrow'),
                previousRow, currentRow;

                if (!e.ctrlKey && !e.shiftKey) {
                    _isSideDown = null;                       
                        $this.jqGrid('resetSelection');                       

                } else if (previousId && e.shiftKey) {
                    $this.jqGrid('resetSelection');


                    // get DOM elements of the previous selected and the currect selected rows
                    previousRow = rows.namedItem(previousId);
                    currentRow = rows.namedItem(rowid);
                    if (previousRow && currentRow) {
                        //Increment
                        if (previousRow.rowIndex < currentRow.rowIndex) {
                            if (_isSideDown == false || _isSideDown == null) {
                                _currentStartSelectRow = previousRow.rowIndex;
                                _currentEndSelectRow = currentRow.rowIndex;
                            }
                            else {
                                _currentEndSelectRow = currentRow.rowIndex;
                            }
                            _isSideDown = true;
                        }
                        //Decrement
                        else {
                            if (_isSideDown == null) {
                                _currentStartSelectRow = currentRow.rowIndex;
                                _currentEndSelectRow = previousRow.rowIndex;
                                _isSideDown = false;
                            }
                            else if (_isSideDown == true) {
                                if (currentRow.rowIndex < _currentStartSelectRow) {
                                    _currentStartSelectRow = currentRow.rowIndex;
                                    _isSideDown = false;
                                }
                                else {
                                    _currentEndSelectRow = currentRow.rowIndex;
                                }
                            }
                            else {
                                _currentStartSelectRow = currentRow.rowIndex;
                            }

                        }

                        for (i = _currentStartSelectRow; i <= _currentEndSelectRow; i++) {
                            // the row with rowid will be selected by jqGrid, so we don't need to select him:
                            if (i != currentRow.rowIndex) {
                                $this.jqGrid('setSelection', rows[i].id, false);
                            }
                        }
                    }

                }
                return true;
            },