Demo - Multi-Range Selection

HTML

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdn.grapecity.com/wijmo/5.latest/styles/wijmo.min.css">
<script src="https://cdn.grapecity.com/wijmo/5.latest/controls/wijmo.min.js"></script>
<script src="https://cdn.grapecity.com/wijmo/5.latest/controls/wijmo.grid.min.js"></script>
<div class="container">

  <h1>
    Multi-Range Selection</h1>
  <p>
    The FlexGrid has a <b>ListBox</b> selection mode that
    allows users to select non-contiguous ranges of rows.
    But it does not have a built-in selection mode that 
    allows user to select multiple, non-contiguous ranges
    of cells.</p>
  <p>
    You can add multi-range selection support by handling
    a few events.
    For example, press the control key while selecting ranges
    with the mouse on the grid below (the console will show 
    the list of selected ranges as the selection changes):</p>
  <div id="theGrid"></div>
  <button id="theBtn" class="btn btn-primary">
    List Selected Cells
  </button>

</div>

CSS

.wj-flexgrid {
  max-height: 300px;
}

.wj-state-extend-selected {
  color: white;
  background: #a47aff;
}

body {
  margin-bottom: 20px;
}

JavaScript

onload = function() {

  // create some random data
  var data = [];
  var countries = 'Austria,Belgium,Chile,Denmark,Finland,Japan,UK'.split(',');
  for (var i = 0; i < 300; i++) {
    data.push({
      id: i,
      from: countries[i % countries.length],
      to: countries[(i + 1) % countries.length],
      sales: Math.random() * 10000,
      expenses: Math.random() * 5000,
      amount: Math.random() * 10000,
      extra: Math.random() * 10000,
    });
  }

  // show the data in a grid
  var theGrid = new wijmo.grid.FlexGrid('#theGrid', {
    alternatingRowStep: 0,
    itemsSource: data
  });

  // add an extended selection manager to the grid
  var xsm = new ExtendedSelectionManager(theGrid);

  // show selected ranges on the console
  document.getElementById('theBtn').addEventListener('click', function() {
  
    console.log('selection:');
    console.log(wijmo.format('  ({row},{col})-({row2},{col2})', theGrid.selection));
  
    var arr = xsm.selectedRanges;
    console.log('extended selection: ' + arr.length);
    arr.forEach(function(rng, index) {
      console.log('  ' + index +
      	wijmo.format(': ({row},{col})-({row2},{col2})', rng)
			);
    })
  });
}

// ** ExtendedSelectionManager (transpiled from TypeScript)

var ExtendedSelectionManager = (function() {
  function ExtendedSelectionManager(flex) {
    var _this = this;
    this._selRanges = new wijmo.collections.ObservableArray();
    this._extending = false;

    // start/end extended selection mode
    flex.addEventListener(flex.hostElement, 'mousedown', function(e) {
      _this._extending = (e.button == 0) && (e.ctrlKey || e.metaKey);
      e.preventDefault(); /// << needed on Macs?
    });

    // end extended selection mode
    flex.addEventListener(flex.hostElement, 'mouseup', function(e) {
      _this._extending = false;
    });

    // extend selection when selection is changing
    flex.selectionChanging.addHandler(function(s, e) {
      if (_this._extending) {
        var oldRange =...