canvas-datagrid 0.3.15 → 0.3.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,7 +7,31 @@ All notable changes to this project will be documented in this file.
7
7
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
8
8
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
9
9
 
10
- ## 0.3.14 - 2021-10-20
10
+ ## 0.3.19 - 2021-11-24
11
+
12
+ ### Fixed
13
+
14
+ - Fix copy when column name or cell value is number (faimaklg, #402)
15
+ - Fix moving multiple columns or rows (xianzhi3, #390)
16
+ - Fix position of scroll bar with frozen pane xianzhi3, (#393)
17
+
18
+ ## 0.3.18 - 2021-11-18
19
+
20
+ No changes; had to bump version number because race condition caused 0.3.16 to be published instead of 0.3.17.
21
+
22
+ ## 0.3.17 - 2021-11-18
23
+
24
+ ### Fixed
25
+
26
+ - Do not render row gaps when sorting (ndrsn, #391)
27
+
28
+ ## 0.3.16 - 2021-11-18
29
+
30
+ ### Fixed
31
+
32
+ - Fix string sort when value is null/undefined (faimaklg, #388)
33
+
34
+ ## 0.3.15 - 2021-11-18
11
35
 
12
36
  ### Fixed
13
37
 
@@ -2386,8 +2386,14 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
2386
2386
  m = self.style.scrollBarBoxMargin * 2;
2387
2387
  self.ctx.strokeStyle = self.style.scrollBarBorderColor;
2388
2388
  self.ctx.lineWidth = self.style.scrollBarBorderWidth;
2389
- en.horizontalBox.x = rowHeaderCellWidth + self.style.scrollBarBoxMargin + (en.horizontalBar.width - self.scrollBox.scrollBoxWidth) * (self.scrollBox.scrollLeft / self.scrollBox.scrollWidth);
2390
- en.verticalBox.y = columnHeaderCellHeight + self.style.scrollBarBoxMargin + (en.verticalBar.height - self.scrollBox.scrollBoxHeight) * (self.scrollBox.scrollTop / self.scrollBox.scrollHeight);
2389
+
2390
+ if (self.frozenColumn > 0) {
2391
+ en.horizontalBox.x = rowHeaderCellWidth + self.style.scrollBarBoxMargin + self.scrollCache.x[self.frozenColumn - 1] + (en.horizontalBar.width - self.scrollCache.x[self.frozenColumn - 1] - self.scrollBox.scrollBoxWidth) * (self.scrollBox.scrollLeft / self.scrollBox.scrollWidth);
2392
+ } else {
2393
+ en.horizontalBox.x = rowHeaderCellWidth + self.style.scrollBarBoxMargin + (en.horizontalBar.width - self.scrollBox.scrollBoxWidth) * (self.scrollBox.scrollLeft / self.scrollBox.scrollWidth);
2394
+ }
2395
+
2396
+ en.verticalBox.y = columnHeaderCellHeight + self.style.scrollBarBoxMargin + self.scrollCache.y[self.frozenRow] + (en.verticalBar.height - self.scrollBox.scrollBoxHeight - self.scrollCache.y[self.frozenRow]) * (self.scrollBox.scrollTop / self.scrollBox.scrollHeight);
2391
2397
 
2392
2398
  if (self.scrollBox.horizontalBarVisible) {
2393
2399
  self.ctx.fillStyle = self.style.scrollBarBackgroundColor;
@@ -2796,9 +2802,13 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
2796
2802
 
2797
2803
  self.ctx.restore(); // Gaps may occur in row numbers between consecutively rendered rows
2798
2804
  // when we are filtering. We draw attention to this by drawing a thick
2799
- // border overlapping the two consecutive row headers.
2805
+ // border overlapping the two consecutive row headers. If sorting, visible
2806
+ // row numbers stay the same (i.e. they don't correspond to the underlying
2807
+ // data's row number), so we do not show row gaps in that case.
2800
2808
 
2801
- if (isRowHeader && self.attributes.showRowNumbers && self.attributes.showRowNumberGaps) {
2809
+ var isSorting = self.orderings.columns && self.orderings.columns.length > 0;
2810
+
2811
+ if (isRowHeader && self.attributes.showRowNumbers && self.attributes.showRowNumberGaps && isSorting === false) {
2802
2812
  var previousRowNumber = self.getBoundRowIndexFromViewRowIndex(rowOrderIndex - 1);
2803
2813
  var hasRowGap = previousRowNumber !== undefined && cell.boundRowIndex > 0 && cell.boundRowIndex - previousRowNumber > 1;
2804
2814
 
@@ -3174,6 +3184,11 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3174
3184
  self.ctx.strokeStyle = self.style.reorderMarkerBorderColor;
3175
3185
 
3176
3186
  if (self.dragMode === 'row-reorder') {
3187
+ for (var k = 0; k < self.selections.length; k++) {
3188
+ if (!self.selections[k] || k == self.reorderObject.rowIndex) continue;
3189
+ b.height += self.getRowHeight(k);
3190
+ }
3191
+
3177
3192
  b.width = w;
3178
3193
  b.x = 0;
3179
3194
  m.width = w;
@@ -3188,6 +3203,12 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3188
3203
  addBorderLine(m, self.reorderTarget.sortRowIndex > self.reorderObject.sortRowIndex ? 'b' : 't');
3189
3204
  }
3190
3205
  } else if (self.dragMode === 'column-reorder' && self.reorderObject) {
3206
+ var selectedColumns = self.selections[0];
3207
+
3208
+ for (var k = 1; k < selectedColumns.length; k++) {
3209
+ b.width += self.getColumnWidth(self.orders.columns[selectedColumns[k]]);
3210
+ }
3211
+
3191
3212
  b.height = h;
3192
3213
  b.y = 0;
3193
3214
  m.height = h;
@@ -3805,14 +3826,20 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3805
3826
  setScrollBoxSize();
3806
3827
  self.scrollBox.scrollWidth = dataWidth - self.scrollBox.width;
3807
3828
  self.scrollBox.scrollHeight = dataHeight - self.scrollBox.height;
3808
- self.scrollBox.widthBoxRatio = self.scrollBox.width / dataWidth;
3829
+
3830
+ if (self.frozenColumn > 0) {
3831
+ self.scrollBox.widthBoxRatio = (self.scrollBox.width - self.scrollCache.x[self.frozenColumn - 1]) / dataWidth;
3832
+ } else {
3833
+ self.scrollBox.widthBoxRatio = self.scrollBox.width / dataWidth;
3834
+ }
3835
+
3809
3836
  self.scrollBox.scrollBoxWidth = self.scrollBox.width * self.scrollBox.widthBoxRatio - self.style.scrollBarWidth - b - d; // TODO: This heightBoxRatio number is terribly wrong.
3810
3837
  // They should be a result of the size of the grid/canvas?
3811
3838
  // it being off causes the scroll bar to "slide" under
3812
3839
  // the dragged mouse.
3813
3840
  // https://github.com/TonyGermaneri/canvas-datagrid/issues/97
3814
3841
 
3815
- self.scrollBox.heightBoxRatio = (self.scrollBox.height - columnHeaderCellHeight) / dataHeight;
3842
+ self.scrollBox.heightBoxRatio = (self.scrollBox.height - columnHeaderCellHeight - self.scrollCache.y[self.frozenRow]) / dataHeight;
3816
3843
  self.scrollBox.scrollBoxHeight = self.scrollBox.height * self.scrollBox.heightBoxRatio - self.style.scrollBarWidth - b - d;
3817
3844
  self.scrollBox.scrollBoxWidth = Math.max(self.scrollBox.scrollBoxWidth, self.style.scrollBarBoxMinSize);
3818
3845
  self.scrollBox.scrollBoxHeight = Math.max(self.scrollBox.scrollBoxHeight, self.style.scrollBarBoxMinSize); // horizontal
@@ -3827,11 +3854,12 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
3827
3854
  nb.height = self.style.scrollBarBoxWidth; // vertical
3828
3855
 
3829
3856
  v.x += self.width - self.style.scrollBarWidth - self.style.scrollBarBorderWidth - d;
3830
- v.y += columnHeaderCellHeight;
3857
+ v.y += columnHeaderCellHeight + self.scrollCache.y[self.frozenRow];
3831
3858
  v.width = self.style.scrollBarWidth + self.style.scrollBarBorderWidth + d;
3832
3859
  v.height = self.height - columnHeaderCellHeight - self.style.scrollBarWidth - d - m; // vertical box
3833
3860
 
3834
3861
  vb.x = v.x + self.style.scrollBarBoxMargin;
3862
+ vb.y += self.scrollCache.y[self.frozenRow];
3835
3863
  vb.width = self.style.scrollBarBoxWidth;
3836
3864
  vb.height = self.scrollBox.scrollBoxHeight; // corner
3837
3865
 
@@ -4060,6 +4088,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4060
4088
  }
4061
4089
  } else if (dragBounds.top !== -1) {
4062
4090
  self.selectArea(sBounds, true);
4091
+ if (sBounds.left == -1 && sBounds.top !== sBounds.bottom) self.isMultiRowsSelected = true;
4063
4092
  }
4064
4093
  }
4065
4094
 
@@ -4157,12 +4186,6 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4157
4186
  checkSelectionChange();
4158
4187
  return;
4159
4188
  }
4160
-
4161
- if (self.attributes.columnHeaderClickBehavior === 'select') {
4162
- self.selectColumn(i.header.index, ctrl, e.shiftKey);
4163
- self.draw();
4164
- return;
4165
- }
4166
4189
  }
4167
4190
 
4168
4191
  self.selections[i.rowIndex] = self.selections[i.rowIndex] || [];
@@ -4342,6 +4365,12 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4342
4365
  return;
4343
4366
  }
4344
4367
 
4368
+ if ((e.ctrlKey || e.metaKey || e.shiftKey) && self.reorderObject) {
4369
+ if (self.dragMode === 'column-reorder' && !self.isMultiColumnsSelected(self.draggingItem.header.index)) {
4370
+ self.selectColumn(self.draggingItem.header.index, false, false);
4371
+ }
4372
+ }
4373
+
4345
4374
  if (self.dispatchEvent('reordering', {
4346
4375
  NativeEvent: e,
4347
4376
  source: self.dragStartObject,
@@ -4353,6 +4382,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4353
4382
 
4354
4383
  if (Math.abs(x) > self.attributes.reorderDeadZone || Math.abs(y) > self.attributes.reorderDeadZone) {
4355
4384
  self.reorderObject = self.draggingItem;
4385
+ if (self.isMultiRowsSelected) self.reorderObject = self.getVisibleCellByIndex(-1, self.activeCell.rowIndex);
4356
4386
  self.reorderTarget = self.currentCell;
4357
4387
  self.reorderObject.dragOffset = {
4358
4388
  x: x,
@@ -4365,7 +4395,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4365
4395
  self.stopDragReorder = function (e) {
4366
4396
  var oIndex,
4367
4397
  tIndex,
4368
- odata,
4398
+ odata = [],
4369
4399
  cr = {
4370
4400
  'row-reorder': self.orders.rows,
4371
4401
  'column-reorder': self.orders.columns
@@ -4388,14 +4418,45 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4388
4418
  tIndex = cr[self.dragMode].indexOf(self.reorderTarget[i]);
4389
4419
 
4390
4420
  if (self.dragMode === 'column-reorder') {
4391
- cr[self.dragMode].splice(oIndex, 1);
4392
- cr[self.dragMode].splice(tIndex, 0, self.reorderObject[i]);
4421
+ var sortColumnIndices = [];
4422
+ var seletedColumnIndices = [];
4423
+
4424
+ if (self.selections[0]) {
4425
+ self.selections[0].forEach(function (value) {
4426
+ sortColumnIndices.push(self.orders.columns[value]);
4427
+ });
4428
+ }
4429
+
4430
+ var deleteCount = sortColumnIndices.length;
4431
+ cr[self.dragMode].splice(oIndex, deleteCount);
4432
+ if (tIndex > oIndex) tIndex = tIndex - (deleteCount - 1);
4433
+
4434
+ for (var i = 0; i < sortColumnIndices.length; i++) {
4435
+ seletedColumnIndices.push(tIndex + i);
4436
+ cr[self.dragMode].splice(tIndex + i, 0, sortColumnIndices[i]);
4437
+ }
4438
+
4393
4439
  self.orders.columns = cr[self.dragMode];
4440
+ self.viewData.forEach(function (row, rowIndex) {
4441
+ self.selections[rowIndex] = seletedColumnIndices;
4442
+ });
4394
4443
  } else {
4395
- // self.orders.rows = cr[self.dragMode];
4396
- odata = self.viewData[oIndex];
4397
- self.viewData[oIndex] = self.viewData[tIndex];
4398
- self.viewData[tIndex] = odata;
4444
+ var selectedRows = [];
4445
+ self.selections.forEach(function (row, rowIndex) {
4446
+ if (row) {
4447
+ selectedRows.push(row);
4448
+ odata.push(self.viewData[rowIndex]);
4449
+ }
4450
+ });
4451
+ self.viewData.splice(oIndex, odata.length);
4452
+ self.selections = [];
4453
+ if (tIndex > oIndex) tIndex = tIndex - (odata.length - 1);
4454
+ self.activeCell.rowIndex = tIndex;
4455
+
4456
+ for (var i = 0; i < odata.length; i++) {
4457
+ self.viewData.splice(tIndex + i, 0, odata[i]);
4458
+ self.selections[tIndex + i] = selectedRows[i];
4459
+ }
4399
4460
  }
4400
4461
 
4401
4462
  self.resize();
@@ -4461,18 +4522,36 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4461
4522
  return;
4462
4523
  }
4463
4524
 
4464
- var pos = self.getLayerPos(e);
4525
+ var pos = self.getLayerPos(e),
4526
+ bm = self.style.gridBorderCollapse === 'collapse' ? 1 : 2,
4527
+ columnHeaderCellBorder = self.style.columnHeaderCellBorderWidth * bm,
4528
+ columnHeaderCellHeight = self.getColumnHeaderCellHeight(),
4529
+ rowHeaderCellWidth = self.getRowHeaderCellWidth();
4465
4530
  self.ignoreNextClick = true;
4466
4531
  self.freezeMarkerPosition = pos;
4467
4532
 
4468
4533
  if (self.currentCell && self.currentCell.rowIndex !== undefined && self.dragMode === 'frozen-row-marker') {
4469
4534
  self.scrollBox.scrollTop = 0;
4470
4535
  self.frozenRow = self.currentCell.rowIndex + 1;
4536
+ self.scrollBox.bar.v.y = columnHeaderCellHeight + columnHeaderCellBorder + self.scrollCache.y[self.frozenRow];
4537
+ self.scrollBox.box.v.y = columnHeaderCellHeight + columnHeaderCellBorder + self.scrollCache.y[self.frozenRow];
4538
+ var dataHeight = self.scrollCache.y[self.scrollCache.y.length - 1];
4539
+ self.scrollBox.heightBoxRatio = (self.scrollBox.height - columnHeaderCellHeight - self.scrollCache.y[self.frozenRow]) / dataHeight;
4540
+ self.scrollBox.scrollBoxHeight = self.scrollBox.height * self.scrollBox.heightBoxRatio - self.style.scrollBarWidth;
4541
+ self.scrollBox.scrollBoxHeight = Math.max(self.scrollBox.scrollBoxHeight, self.style.scrollBarBoxMinSize);
4542
+ self.scrollBox.box.v.height = self.scrollBox.scrollBoxHeight;
4471
4543
  }
4472
4544
 
4473
4545
  if (self.currentCell && self.currentCell.columnIndex !== undefined && self.dragMode === 'frozen-column-marker') {
4474
4546
  self.scrollBox.scrollLeft = 0;
4475
4547
  self.frozenColumn = self.currentCell.columnIndex + 1;
4548
+ self.scrollBox.bar.h.x = rowHeaderCellWidth + self.scrollCache.x[self.frozenColumn - 1];
4549
+ self.scrollBox.box.h.x = rowHeaderCellWidth + self.scrollCache.x[self.frozenColumn - 1];
4550
+ var dataWidth = self.scrollCache.x[self.scrollCache.x.length - 1];
4551
+ self.scrollBox.widthBoxRatio = (self.scrollBox.width - self.scrollCache.x[self.frozenColumn - 1]) / dataWidth;
4552
+ self.scrollBox.scrollBoxWidth = self.scrollBox.width * self.scrollBox.widthBoxRatio - self.style.scrollBarWidth;
4553
+ self.scrollBox.scrollBoxWidth = Math.max(self.scrollBox.scrollBoxWidth, self.style.scrollBarBoxMinSize);
4554
+ self.scrollBox.box.h.width = self.scrollBox.scrollBoxWidth;
4476
4555
  }
4477
4556
 
4478
4557
  if (Math.abs(pos.x) > self.attributes.reorderDeadZone || Math.abs(pos.y) > self.attributes.reorderDeadZone) {
@@ -4531,7 +4610,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4531
4610
  self.dragAddToSelection = !self.dragStartObject.selected;
4532
4611
 
4533
4612
  if (!ctrl && !e.shiftKey && !/(vertical|horizontal)-scroll-(bar|box)/.test(self.dragStartObject.context) && self.currentCell && !self.currentCell.isColumnHeader && !move && !freeze && !resize) {
4534
- self.selections = [];
4613
+ if (!(self.dragMode == 'row-reorder' && self.isMultiRowsSelected)) self.selections = [];
4535
4614
  }
4536
4615
 
4537
4616
  if (self.dragStartObject.isGrid) {
@@ -4622,9 +4701,10 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4622
4701
  if (['row-reorder', 'column-reorder'].indexOf(self.dragMode) !== -1) {
4623
4702
  self.draggingItem = self.dragStartObject;
4624
4703
 
4625
- if (self.dragMode === 'column-reorder' && self.attributes.columnHeaderClickBehavior === 'select') {
4704
+ if (self.dragMode === 'column-reorder' && !self.isMultiColumnsSelected(self.currentCell.header.index)) {
4626
4705
  self.selectColumn(self.currentCell.header.index, ctrl, e.shiftKey);
4627
- self.draw();
4706
+ } else if (self.dragMode === 'row-reorder' && !self.isMultiRowsSelected) {
4707
+ self.selectRow(self.dragStartObject.rowIndex, ctrl, null);
4628
4708
  }
4629
4709
 
4630
4710
  document.body.addEventListener('mousemove', self.dragReorder, false);
@@ -4635,16 +4715,9 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
4635
4715
 
4636
4716
  self.mouseup = function (e) {
4637
4717
  clearTimeout(self.scrollTimer);
4638
- var ctrl = e.ctrlKey || e.metaKey;
4639
4718
  self.cellBoundaryCrossed = true;
4640
4719
  self.rowBoundaryCrossed = true;
4641
4720
  self.columnBoundaryCrossed = true;
4642
-
4643
- if (self.draggingItem) {
4644
- self.selectColumn(self.currentCell.header.index, ctrl, e.shiftKey);
4645
- self.draw();
4646
- }
4647
-
4648
4721
  self.selecting = undefined;
4649
4722
  self.draggingItem = undefined;
4650
4723
  self.dragStartObject = undefined;
@@ -5217,6 +5290,7 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
5217
5290
  isNeat = true; // Selected like [[0, 1], [0, 1]] of [[0, 3]] is neat; Selected like [[0, 1], [1, 2]] is untidy
5218
5291
 
5219
5292
  function htmlSafe(v) {
5293
+ if (typeof v === 'number') return v;
5220
5294
  return v.replace(/</g, '&lt;').replace(/>/g, '&gt;');
5221
5295
  }
5222
5296
 
@@ -5232,8 +5306,8 @@ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len
5232
5306
  if (!firstRowKeys) firstRowKeys = Object.keys(row);
5233
5307
  if (isNeat && rowKeys.length !== firstRowKeys.length) isNeat = false;
5234
5308
  sSorted.forEach(function (column, columnIndex) {
5235
- if (rowKeys.indexOf(column.name) < 0) {
5236
- if (firstRowKeys.indexOf(column.name) < 0) {
5309
+ if (rowKeys.indexOf(String(column.name)) < 0) {
5310
+ if (firstRowKeys.indexOf(String(column.name)) < 0) {
5237
5311
  return;
5238
5312
  } else if (isNeat) {
5239
5313
  isNeat = false;
@@ -7734,6 +7808,35 @@ __webpack_require__.r(__webpack_exports__);
7734
7808
 
7735
7809
  self.draw();
7736
7810
  };
7811
+ /**
7812
+ * Returns true if indices of columns next to the selected columnIndex is selected on every row.
7813
+ * @memberof canvasDatagrid
7814
+ * @name isMultiColumnsSelected
7815
+ * @method
7816
+ * @param {number} columnIndex The column index to check.
7817
+ */
7818
+
7819
+
7820
+ self.isMultiColumnsSelected = function (columnIndex) {
7821
+ var multiColIsSelected = true;
7822
+ self.viewData.forEach(function (row, rowIndex) {
7823
+ var columnIndices = self.selections[rowIndex];
7824
+
7825
+ if (!columnIndices || columnIndices.length <= 1 || columnIndices.indexOf(columnIndex) === -1) {
7826
+ multiColIsSelected = false;
7827
+ } else if (columnIndices.length > 1) {
7828
+ if (columnIndices[0] != columnIndex) multiColIsSelected = false;else {
7829
+ for (var i = 0; i < columnIndices.length - 1; i++) {
7830
+ if (columnIndices[i] + 1 != columnIndices[i + 1]) {
7831
+ multiColIsSelected = false;
7832
+ break;
7833
+ }
7834
+ }
7835
+ }
7836
+ }
7837
+ });
7838
+ return multiColIsSelected;
7839
+ };
7737
7840
  /**
7738
7841
  * Returns true if the selected columnIndex is selected on every row.
7739
7842
  * @memberof canvasDatagrid
@@ -7746,7 +7849,7 @@ __webpack_require__.r(__webpack_exports__);
7746
7849
  self.isColumnSelected = function (columnIndex) {
7747
7850
  var colIsSelected = true;
7748
7851
  self.viewData.forEach(function (row, rowIndex) {
7749
- if (!self.selections[rowIndex] || self.selections[rowIndex].indexOf(self.orders.columns[columnIndex]) === -1) {
7852
+ if (!self.selections[rowIndex] || self.selections[rowIndex].indexOf(columnIndex) === -1) {
7750
7853
  colIsSelected = false;
7751
7854
  }
7752
7855
  });
@@ -7874,6 +7977,7 @@ __webpack_require__.r(__webpack_exports__);
7874
7977
  st,
7875
7978
  en,
7876
7979
  s = self.getVisibleSchema();
7980
+ self.isMultiRowsSelected = false;
7877
7981
 
7878
7982
  function de() {
7879
7983
  if (supressEvent) {
@@ -8734,27 +8838,22 @@ __webpack_require__.r(__webpack_exports__);
8734
8838
  self.sorters.string = function (columnName, direction) {
8735
8839
  var asc = direction === 'asc';
8736
8840
  return function (a, b) {
8737
- if (a[columnName] === undefined || a[columnName] === null) {
8738
- return 1;
8739
- }
8740
-
8741
- if (b[columnName] === undefined || b[columnName] === null) {
8742
- return 0;
8743
- }
8841
+ var aValue = a[columnName] || '';
8842
+ var bValue = b[columnName] || '';
8744
8843
 
8745
8844
  if (asc) {
8746
- if (!a[columnName].localeCompare) {
8845
+ if (!aValue.localeCompare) {
8747
8846
  return 1;
8748
8847
  }
8749
8848
 
8750
- return a[columnName].localeCompare(b[columnName]);
8849
+ return aValue.localeCompare(bValue);
8751
8850
  }
8752
8851
 
8753
- if (!b[columnName].localeCompare) {
8852
+ if (!bValue.localeCompare) {
8754
8853
  return 1;
8755
8854
  }
8756
8855
 
8757
- return b[columnName].localeCompare(a[columnName]);
8856
+ return bValue.localeCompare(aValue);
8758
8857
  };
8759
8858
  };
8760
8859