Copy cell contents
This commit is contained in:
parent
4316c5834e
commit
89dfaa13ed
@ -116,10 +116,16 @@ function getColumnHTML(column) {
|
||||
isHeader: isHeader
|
||||
});
|
||||
|
||||
return '\n <td class="data-table-col noselect" ' + dataAttr + '>\n ' + getCellContent(column) + '\n </td>\n ';
|
||||
}
|
||||
|
||||
function getCellContent(column) {
|
||||
var isHeader = column.isHeader;
|
||||
|
||||
var editCellHTML = isHeader ? '' : getEditCellHTML();
|
||||
var sortIndicator = isHeader ? '<span class="sort-indicator"></span>' : '';
|
||||
|
||||
return '\n <td class="data-table-col noselect" ' + dataAttr + '>\n <div class="content ellipsis">\n ' + (column.format ? column.format(column.content) : column.content) + '\n ' + sortIndicator + '\n </div>\n ' + editCellHTML + '\n </td>\n ';
|
||||
return '\n <div class="content ellipsis">\n ' + (column.format ? column.format(column.content) : column.content) + '\n ' + sortIndicator + '\n </div>\n ' + editCellHTML + '\n ';
|
||||
}
|
||||
|
||||
function getRowHTML(columns, props) {
|
||||
@ -273,6 +279,64 @@ function removeCSSRule(rule) {
|
||||
return output.trim();
|
||||
}
|
||||
|
||||
function copyTextToClipboard(text) {
|
||||
// https://stackoverflow.com/a/30810322/5353542
|
||||
var textArea = document.createElement('textarea');
|
||||
|
||||
//
|
||||
// *** This styling is an extra step which is likely not required. ***
|
||||
//
|
||||
// Why is it here? To ensure:
|
||||
// 1. the element is able to have focus and selection.
|
||||
// 2. if element was to flash render it has minimal visual impact.
|
||||
// 3. less flakyness with selection and copying which **might** occur if
|
||||
// the textarea element is not visible.
|
||||
//
|
||||
// The likelihood is the element won't even render, not even a flash,
|
||||
// so some of these are just precautions. However in IE the element
|
||||
// is visible whilst the popup box asking the user for permission for
|
||||
// the web page to copy to the clipboard.
|
||||
//
|
||||
|
||||
// Place in top-left corner of screen regardless of scroll position.
|
||||
textArea.style.position = 'fixed';
|
||||
textArea.style.top = 0;
|
||||
textArea.style.left = 0;
|
||||
|
||||
// Ensure it has a small width and height. Setting to 1px / 1em
|
||||
// doesn't work as this gives a negative w/h on some browsers.
|
||||
textArea.style.width = '2em';
|
||||
textArea.style.height = '2em';
|
||||
|
||||
// We don't need padding, reducing the size if it does flash render.
|
||||
textArea.style.padding = 0;
|
||||
|
||||
// Clean up any borders.
|
||||
textArea.style.border = 'none';
|
||||
textArea.style.outline = 'none';
|
||||
textArea.style.boxShadow = 'none';
|
||||
|
||||
// Avoid flash of white box if rendered for any reason.
|
||||
textArea.style.background = 'transparent';
|
||||
|
||||
textArea.value = text;
|
||||
|
||||
document.body.appendChild(textArea);
|
||||
|
||||
textArea.select();
|
||||
|
||||
try {
|
||||
var successful = document.execCommand('copy');
|
||||
var msg = successful ? 'successful' : 'unsuccessful';
|
||||
|
||||
console.log('Copying text command was ' + msg);
|
||||
} catch (err) {
|
||||
console.log('Oops, unable to copy');
|
||||
}
|
||||
|
||||
document.body.removeChild(textArea);
|
||||
}
|
||||
|
||||
exports.default = {
|
||||
getHeaderHTML: getHeaderHTML,
|
||||
getBodyHTML: getBodyHTML,
|
||||
@ -287,7 +351,9 @@ exports.default = {
|
||||
removeCSSRule: removeCSSRule,
|
||||
makeDataAttributeString: makeDataAttributeString,
|
||||
getDefault: getDefault,
|
||||
escapeRegExp: escapeRegExp
|
||||
escapeRegExp: escapeRegExp,
|
||||
getCellContent: getCellContent,
|
||||
copyTextToClipboard: copyTextToClipboard
|
||||
};
|
||||
module.exports = exports['default'];
|
||||
|
||||
@ -896,8 +962,8 @@ var DataTable = function () {
|
||||
}
|
||||
}, {
|
||||
key: 'getCell',
|
||||
value: function getCell(rowIndex, colIndex) {
|
||||
return this.datamanager.getCell(rowIndex, colIndex);
|
||||
value: function getCell(colIndex, rowIndex) {
|
||||
return this.datamanager.getCell(colIndex, rowIndex);
|
||||
}
|
||||
}, {
|
||||
key: 'getColumnHeaderElement',
|
||||
@ -1182,7 +1248,7 @@ var DataManager = function () {
|
||||
}
|
||||
}, {
|
||||
key: 'getCell',
|
||||
value: function getCell(rowIndex, colIndex) {
|
||||
value: function getCell(colIndex, rowIndex) {
|
||||
rowIndex = +rowIndex;
|
||||
colIndex = +colIndex;
|
||||
return this.rows.find(function (row) {
|
||||
@ -1244,10 +1310,10 @@ Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
|
||||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
||||
|
||||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
||||
|
||||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
|
||||
|
||||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
|
||||
|
||||
var _utils = __webpack_require__(0);
|
||||
@ -1258,6 +1324,8 @@ var _keyboard2 = _interopRequireDefault(_keyboard);
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
var CellManager = function () {
|
||||
@ -1285,6 +1353,7 @@ var CellManager = function () {
|
||||
this.bindEditCell();
|
||||
this.bindKeyboardNav();
|
||||
this.bindKeyboardSelection();
|
||||
this.bindCopyCellContents();
|
||||
}
|
||||
}, {
|
||||
key: 'bindFocusCell',
|
||||
@ -1298,63 +1367,6 @@ var CellManager = function () {
|
||||
_this.focusCell($(e.currentTarget));
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: 'focusCell',
|
||||
value: function focusCell($cell) {
|
||||
if (!$cell.length) return;
|
||||
|
||||
var _getCellAttr = this.getCellAttr($cell),
|
||||
colIndex = _getCellAttr.colIndex;
|
||||
|
||||
if (colIndex < this.instance.getFirstColumnIndex()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.deactivateEditing();
|
||||
this.clearSelection();
|
||||
|
||||
if (this.options.addCheckboxColumn && colIndex === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.$focusedCell) {
|
||||
this.$focusedCell.removeClass('selected');
|
||||
}
|
||||
|
||||
this.$focusedCell = $cell;
|
||||
$cell.addClass('selected');
|
||||
|
||||
this.highlightRowColumnHeader($cell);
|
||||
}
|
||||
}, {
|
||||
key: 'highlightRowColumnHeader',
|
||||
value: function highlightRowColumnHeader($cell) {
|
||||
var _getCellAttr2 = this.getCellAttr($cell),
|
||||
colIndex = _getCellAttr2.colIndex,
|
||||
rowIndex = _getCellAttr2.rowIndex;
|
||||
|
||||
var _colIndex = this.instance.getSerialColumnIndex();
|
||||
var colHeaderSelector = '.data-table-header .data-table-col[data-col-index="' + colIndex + '"]';
|
||||
var rowHeaderSelector = '.data-table-col[data-row-index="' + rowIndex + '"][data-col-index="' + _colIndex + '"]';
|
||||
|
||||
if (this.lastSelectors) {
|
||||
this.instance.removeStyle(this.lastSelectors.colHeaderSelector);
|
||||
this.instance.removeStyle(this.lastSelectors.rowHeaderSelector);
|
||||
}
|
||||
|
||||
this.instance.setStyle(colHeaderSelector, {
|
||||
'background-color': 'var(--light-bg)'
|
||||
});
|
||||
|
||||
this.instance.setStyle(rowHeaderSelector, {
|
||||
'background-color': 'var(--light-bg)'
|
||||
});
|
||||
|
||||
this.lastSelectors = {
|
||||
colHeaderSelector: colHeaderSelector,
|
||||
rowHeaderSelector: rowHeaderSelector
|
||||
};
|
||||
}
|
||||
}, {
|
||||
key: 'bindEditCell',
|
||||
value: function bindEditCell() {
|
||||
@ -1374,6 +1386,7 @@ var CellManager = function () {
|
||||
} else if (_this2.$editingCell) {
|
||||
// enter keypress on editing cell
|
||||
_this2.submitEditing(_this2.$editingCell);
|
||||
_this2.deactivateEditing();
|
||||
}
|
||||
});
|
||||
|
||||
@ -1451,15 +1464,114 @@ var CellManager = function () {
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: 'selectArea',
|
||||
value: function selectArea(colIndex1, rowIndex1, colIndex2, rowIndex2) {
|
||||
key: 'bindCopyCellContents',
|
||||
value: function bindCopyCellContents() {
|
||||
var _this5 = this;
|
||||
|
||||
if ((typeof colIndex1 === 'undefined' ? 'undefined' : _typeof(colIndex1)) === 'object') {
|
||||
if (!(colIndex1.length && rowIndex1.length)) return false;
|
||||
_keyboard2.default.on('ctrl+c', function () {
|
||||
_this5.copyCellContents(_this5.$focusedCell, _this5.$selectionCursor);
|
||||
});
|
||||
}
|
||||
}, {
|
||||
key: 'focusCell',
|
||||
value: function focusCell($cell) {
|
||||
if (!$cell.length) return;
|
||||
|
||||
var cell1 = this.getCellAttr(colIndex1);
|
||||
var cell2 = this.getCellAttr(rowIndex1);
|
||||
var _getCellAttr = this.getCellAttr($cell),
|
||||
colIndex = _getCellAttr.colIndex;
|
||||
|
||||
if (colIndex < this.instance.getFirstColumnIndex()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.deactivateEditing();
|
||||
this.clearSelection();
|
||||
|
||||
if (this.options.addCheckboxColumn && colIndex === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.$focusedCell) {
|
||||
this.$focusedCell.removeClass('selected');
|
||||
}
|
||||
|
||||
this.$focusedCell = $cell;
|
||||
$cell.addClass('selected');
|
||||
|
||||
this.highlightRowColumnHeader($cell);
|
||||
}
|
||||
}, {
|
||||
key: 'highlightRowColumnHeader',
|
||||
value: function highlightRowColumnHeader($cell) {
|
||||
var _getCellAttr2 = this.getCellAttr($cell),
|
||||
colIndex = _getCellAttr2.colIndex,
|
||||
rowIndex = _getCellAttr2.rowIndex;
|
||||
|
||||
var _colIndex = this.instance.getSerialColumnIndex();
|
||||
var colHeaderSelector = '.data-table-header .data-table-col[data-col-index="' + colIndex + '"]';
|
||||
var rowHeaderSelector = '.data-table-col[data-row-index="' + rowIndex + '"][data-col-index="' + _colIndex + '"]';
|
||||
|
||||
if (this.lastSelectors) {
|
||||
this.instance.removeStyle(this.lastSelectors.colHeaderSelector);
|
||||
this.instance.removeStyle(this.lastSelectors.rowHeaderSelector);
|
||||
}
|
||||
|
||||
this.instance.setStyle(colHeaderSelector, {
|
||||
'background-color': 'var(--light-bg)'
|
||||
});
|
||||
|
||||
this.instance.setStyle(rowHeaderSelector, {
|
||||
'background-color': 'var(--light-bg)'
|
||||
});
|
||||
|
||||
this.lastSelectors = {
|
||||
colHeaderSelector: colHeaderSelector,
|
||||
rowHeaderSelector: rowHeaderSelector
|
||||
};
|
||||
}
|
||||
}, {
|
||||
key: 'selectArea',
|
||||
value: function selectArea($cell1, $cell2) {
|
||||
var _this6 = this;
|
||||
|
||||
var cells = this.getCellsInRange.apply(this, arguments);
|
||||
|
||||
if (!cells) return false;
|
||||
this.clearSelection();
|
||||
var $cells = cells.map(function (_ref) {
|
||||
var _ref2 = _slicedToArray(_ref, 2),
|
||||
c = _ref2[0],
|
||||
r = _ref2[1];
|
||||
|
||||
return _this6.getCell$(r, c)[0];
|
||||
});
|
||||
|
||||
$($cells).addClass('highlight');
|
||||
return true;
|
||||
}
|
||||
}, {
|
||||
key: 'getCellsInRange',
|
||||
value: function getCellsInRange($cell1, $cell2) {
|
||||
var colIndex1 = void 0,
|
||||
rowIndex1 = void 0,
|
||||
colIndex2 = void 0,
|
||||
rowIndex2 = void 0;
|
||||
|
||||
if (typeof $cell1 === 'number') {
|
||||
var _arguments = Array.prototype.slice.call(arguments);
|
||||
|
||||
colIndex1 = _arguments[0];
|
||||
rowIndex1 = _arguments[1];
|
||||
colIndex2 = _arguments[2];
|
||||
rowIndex2 = _arguments[3];
|
||||
} else if ((typeof $cell1 === 'undefined' ? 'undefined' : _typeof($cell1)) === 'object') {
|
||||
|
||||
if (!($cell1.length && $cell2.length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var cell1 = this.getCellAttr($cell1);
|
||||
var cell2 = this.getCellAttr($cell2);
|
||||
|
||||
colIndex1 = cell1.colIndex;
|
||||
rowIndex1 = cell1.rowIndex;
|
||||
@ -1468,19 +1580,17 @@ var CellManager = function () {
|
||||
}
|
||||
|
||||
if (rowIndex1 > rowIndex2) {
|
||||
var _ref = [rowIndex2, rowIndex1];
|
||||
rowIndex1 = _ref[0];
|
||||
rowIndex2 = _ref[1];
|
||||
var _ref3 = [rowIndex2, rowIndex1];
|
||||
rowIndex1 = _ref3[0];
|
||||
rowIndex2 = _ref3[1];
|
||||
}
|
||||
|
||||
if (colIndex1 > colIndex2) {
|
||||
var _ref2 = [colIndex2, colIndex1];
|
||||
colIndex1 = _ref2[0];
|
||||
colIndex2 = _ref2[1];
|
||||
var _ref4 = [colIndex2, colIndex1];
|
||||
colIndex1 = _ref4[0];
|
||||
colIndex2 = _ref4[1];
|
||||
}
|
||||
|
||||
this.clearSelection();
|
||||
|
||||
var cells = [];
|
||||
var colIndex = colIndex1;
|
||||
var rowIndex = rowIndex1;
|
||||
@ -1499,17 +1609,7 @@ var CellManager = function () {
|
||||
colIndex = colIndex1;
|
||||
});
|
||||
|
||||
var $cells = cells.map(function (_ref3) {
|
||||
var _ref4 = _slicedToArray(_ref3, 2),
|
||||
c = _ref4[0],
|
||||
r = _ref4[1];
|
||||
|
||||
return _this5.getCell$(r, c)[0];
|
||||
});
|
||||
|
||||
$($cells).addClass('highlight');
|
||||
|
||||
return true;
|
||||
return cells;
|
||||
}
|
||||
}, {
|
||||
key: 'clearSelection',
|
||||
@ -1550,7 +1650,7 @@ var CellManager = function () {
|
||||
$cell.addClass('editing');
|
||||
|
||||
var $editCell = $cell.find('.edit-cell').empty();
|
||||
var cell = this.instance.getCell(rowIndex, colIndex);
|
||||
var cell = this.getCell(colIndex, rowIndex);
|
||||
var editing = this.getEditingObject(colIndex, rowIndex, cell.content, $editCell);
|
||||
|
||||
if (editing) {
|
||||
@ -1594,7 +1694,7 @@ var CellManager = function () {
|
||||
}, {
|
||||
key: 'submitEditing',
|
||||
value: function submitEditing($cell) {
|
||||
var _this6 = this;
|
||||
var _this7 = this;
|
||||
|
||||
var _getCellAttr5 = this.getCellAttr($cell),
|
||||
rowIndex = _getCellAttr5.rowIndex,
|
||||
@ -1610,7 +1710,7 @@ var CellManager = function () {
|
||||
if (done && done.then) {
|
||||
// wait for promise then update internal state
|
||||
done.then(function () {
|
||||
return _this6.updateCell(rowIndex, colIndex, value);
|
||||
return _this7.updateCell(rowIndex, colIndex, value);
|
||||
});
|
||||
} else {
|
||||
this.updateCell(rowIndex, colIndex, value);
|
||||
@ -1620,10 +1720,34 @@ var CellManager = function () {
|
||||
|
||||
this.currentCellEditing = null;
|
||||
}
|
||||
}, {
|
||||
key: 'copyCellContents',
|
||||
value: function copyCellContents($cell1, $cell2) {
|
||||
var _this8 = this;
|
||||
|
||||
var cells = this.getCellsInRange.apply(this, arguments);
|
||||
|
||||
if (!cells) return;
|
||||
|
||||
var values = cells.map(function (index) {
|
||||
return _this8.getCell.apply(_this8, _toConsumableArray(index));
|
||||
}).reduce(function (acc, curr) {
|
||||
var rowIndex = curr.rowIndex;
|
||||
|
||||
acc[rowIndex] = acc[rowIndex] || [];
|
||||
acc[rowIndex].push(curr.content);
|
||||
|
||||
return acc;
|
||||
}, []).map(function (row) {
|
||||
return row.join('\t');
|
||||
}).join('\n');
|
||||
|
||||
(0, _utils.copyTextToClipboard)(values);
|
||||
}
|
||||
}, {
|
||||
key: 'updateCell',
|
||||
value: function updateCell(rowIndex, colIndex, value) {
|
||||
var cell = this.getCell(rowIndex, colIndex);
|
||||
var cell = this.getCell(colIndex, rowIndex);
|
||||
|
||||
cell.content = value;
|
||||
this.refreshCell(cell);
|
||||
@ -1632,11 +1756,9 @@ var CellManager = function () {
|
||||
key: 'refreshCell',
|
||||
value: function refreshCell(cell) {
|
||||
var selector = '.data-table-col[data-row-index="' + cell.rowIndex + '"][data-col-index="' + cell.colIndex + '"]';
|
||||
var bodyScrollable = this.instance.bodyScrollable;
|
||||
var $cell = bodyScrollable.find(selector);
|
||||
var $newCell = $((0, _utils.getColumnHTML)(cell));
|
||||
var $cell = this.bodyScrollable.find(selector);
|
||||
|
||||
$cell.replaceWith($newCell);
|
||||
$cell.html((0, _utils.getCellContent)(cell));
|
||||
}
|
||||
}, {
|
||||
key: 'getCell$',
|
||||
@ -1675,8 +1797,8 @@ var CellManager = function () {
|
||||
}
|
||||
}, {
|
||||
key: 'getCell',
|
||||
value: function getCell(rowIndex, colIndex) {
|
||||
return this.instance.datamanager.getCell(rowIndex, colIndex);
|
||||
value: function getCell(colIndex, rowIndex) {
|
||||
return this.instance.datamanager.getCell(colIndex, rowIndex);
|
||||
}
|
||||
}, {
|
||||
key: 'getCellAttr',
|
||||
@ -1712,7 +1834,8 @@ var KEYCODES = {
|
||||
39: 'right',
|
||||
40: 'down',
|
||||
9: 'tab',
|
||||
27: 'esc'
|
||||
27: 'esc',
|
||||
67: 'c'
|
||||
};
|
||||
|
||||
var handlers = {};
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
||||
import { getColumnHTML } from './utils';
|
||||
import { getCellContent, copyTextToClipboard } from './utils';
|
||||
import keyboard from 'keyboard';
|
||||
|
||||
export default class CellManager {
|
||||
@ -21,6 +21,7 @@ export default class CellManager {
|
||||
this.bindEditCell();
|
||||
this.bindKeyboardNav();
|
||||
this.bindKeyboardSelection();
|
||||
this.bindCopyCellContents();
|
||||
}
|
||||
|
||||
bindFocusCell() {
|
||||
@ -32,56 +33,6 @@ export default class CellManager {
|
||||
});
|
||||
}
|
||||
|
||||
focusCell($cell) {
|
||||
if (!$cell.length) return;
|
||||
const { colIndex } = this.getCellAttr($cell);
|
||||
|
||||
if (colIndex < this.instance.getFirstColumnIndex()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.deactivateEditing();
|
||||
this.clearSelection();
|
||||
|
||||
if (this.options.addCheckboxColumn && colIndex === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.$focusedCell) {
|
||||
this.$focusedCell.removeClass('selected');
|
||||
}
|
||||
|
||||
this.$focusedCell = $cell;
|
||||
$cell.addClass('selected');
|
||||
|
||||
this.highlightRowColumnHeader($cell);
|
||||
}
|
||||
|
||||
highlightRowColumnHeader($cell) {
|
||||
const { colIndex, rowIndex } = this.getCellAttr($cell);
|
||||
const _colIndex = this.instance.getSerialColumnIndex();
|
||||
const colHeaderSelector = `.data-table-header .data-table-col[data-col-index="${colIndex}"]`;
|
||||
const rowHeaderSelector = `.data-table-col[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
|
||||
|
||||
if (this.lastSelectors) {
|
||||
this.instance.removeStyle(this.lastSelectors.colHeaderSelector);
|
||||
this.instance.removeStyle(this.lastSelectors.rowHeaderSelector);
|
||||
}
|
||||
|
||||
this.instance.setStyle(colHeaderSelector, {
|
||||
'background-color': 'var(--light-bg)'
|
||||
});
|
||||
|
||||
this.instance.setStyle(rowHeaderSelector, {
|
||||
'background-color': 'var(--light-bg)'
|
||||
});
|
||||
|
||||
this.lastSelectors = {
|
||||
colHeaderSelector,
|
||||
rowHeaderSelector
|
||||
};
|
||||
}
|
||||
|
||||
bindEditCell() {
|
||||
const self = this;
|
||||
|
||||
@ -97,6 +48,7 @@ export default class CellManager {
|
||||
} else if (this.$editingCell) {
|
||||
// enter keypress on editing cell
|
||||
this.submitEditing(this.$editingCell);
|
||||
this.deactivateEditing();
|
||||
}
|
||||
});
|
||||
|
||||
@ -165,13 +117,87 @@ export default class CellManager {
|
||||
);
|
||||
}
|
||||
|
||||
selectArea(colIndex1, rowIndex1, colIndex2, rowIndex2) {
|
||||
bindCopyCellContents() {
|
||||
keyboard.on('ctrl+c', () => {
|
||||
this.copyCellContents(this.$focusedCell, this.$selectionCursor);
|
||||
});
|
||||
}
|
||||
|
||||
if (typeof colIndex1 === 'object') {
|
||||
if (!(colIndex1.length && rowIndex1.length)) return false;
|
||||
focusCell($cell) {
|
||||
if (!$cell.length) return;
|
||||
const { colIndex } = this.getCellAttr($cell);
|
||||
|
||||
const cell1 = this.getCellAttr(colIndex1);
|
||||
const cell2 = this.getCellAttr(rowIndex1);
|
||||
if (colIndex < this.instance.getFirstColumnIndex()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.deactivateEditing();
|
||||
this.clearSelection();
|
||||
|
||||
if (this.options.addCheckboxColumn && colIndex === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.$focusedCell) {
|
||||
this.$focusedCell.removeClass('selected');
|
||||
}
|
||||
|
||||
this.$focusedCell = $cell;
|
||||
$cell.addClass('selected');
|
||||
|
||||
this.highlightRowColumnHeader($cell);
|
||||
}
|
||||
|
||||
highlightRowColumnHeader($cell) {
|
||||
const { colIndex, rowIndex } = this.getCellAttr($cell);
|
||||
const _colIndex = this.instance.getSerialColumnIndex();
|
||||
const colHeaderSelector = `.data-table-header .data-table-col[data-col-index="${colIndex}"]`;
|
||||
const rowHeaderSelector = `.data-table-col[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
|
||||
|
||||
if (this.lastSelectors) {
|
||||
this.instance.removeStyle(this.lastSelectors.colHeaderSelector);
|
||||
this.instance.removeStyle(this.lastSelectors.rowHeaderSelector);
|
||||
}
|
||||
|
||||
this.instance.setStyle(colHeaderSelector, {
|
||||
'background-color': 'var(--light-bg)'
|
||||
});
|
||||
|
||||
this.instance.setStyle(rowHeaderSelector, {
|
||||
'background-color': 'var(--light-bg)'
|
||||
});
|
||||
|
||||
this.lastSelectors = {
|
||||
colHeaderSelector,
|
||||
rowHeaderSelector
|
||||
};
|
||||
}
|
||||
|
||||
selectArea($cell1, $cell2) {
|
||||
const cells = this.getCellsInRange(...arguments);
|
||||
|
||||
if (!cells) return false;
|
||||
this.clearSelection();
|
||||
const $cells = cells.map(([c, r]) => this.getCell$(r, c)[0]);
|
||||
|
||||
$($cells).addClass('highlight');
|
||||
return true;
|
||||
}
|
||||
|
||||
getCellsInRange($cell1, $cell2) {
|
||||
let colIndex1, rowIndex1, colIndex2, rowIndex2;
|
||||
|
||||
if (typeof $cell1 === 'number') {
|
||||
[colIndex1, rowIndex1, colIndex2, rowIndex2] = arguments;
|
||||
} else
|
||||
if (typeof $cell1 === 'object') {
|
||||
|
||||
if (!($cell1.length && $cell2.length)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const cell1 = this.getCellAttr($cell1);
|
||||
const cell2 = this.getCellAttr($cell2);
|
||||
|
||||
colIndex1 = cell1.colIndex;
|
||||
rowIndex1 = cell1.rowIndex;
|
||||
@ -187,8 +213,6 @@ export default class CellManager {
|
||||
[colIndex1, colIndex2] = [colIndex2, colIndex1];
|
||||
}
|
||||
|
||||
this.clearSelection();
|
||||
|
||||
let cells = [];
|
||||
let colIndex = colIndex1;
|
||||
let rowIndex = rowIndex1;
|
||||
@ -207,11 +231,7 @@ export default class CellManager {
|
||||
colIndex = colIndex1;
|
||||
});
|
||||
|
||||
const $cells = cells.map(([c, r]) => this.getCell$(r, c)[0]);
|
||||
|
||||
$($cells).addClass('highlight');
|
||||
|
||||
return true;
|
||||
return cells;
|
||||
}
|
||||
|
||||
clearSelection() {
|
||||
@ -244,7 +264,7 @@ export default class CellManager {
|
||||
$cell.addClass('editing');
|
||||
|
||||
const $editCell = $cell.find('.edit-cell').empty();
|
||||
const cell = this.instance.getCell(rowIndex, colIndex);
|
||||
const cell = this.getCell(colIndex, rowIndex);
|
||||
const editing = this.getEditingObject(colIndex, rowIndex, cell.content, $editCell);
|
||||
|
||||
if (editing) {
|
||||
@ -308,8 +328,29 @@ export default class CellManager {
|
||||
this.currentCellEditing = null;
|
||||
}
|
||||
|
||||
copyCellContents($cell1, $cell2) {
|
||||
const cells = this.getCellsInRange(...arguments);
|
||||
|
||||
if (!cells) return;
|
||||
|
||||
const values = cells
|
||||
.map(index => this.getCell(...index))
|
||||
.reduce((acc, curr) => {
|
||||
const rowIndex = curr.rowIndex;
|
||||
|
||||
acc[rowIndex] = acc[rowIndex] || [];
|
||||
acc[rowIndex].push(curr.content);
|
||||
|
||||
return acc;
|
||||
}, [])
|
||||
.map(row => row.join('\t'))
|
||||
.join('\n');
|
||||
|
||||
copyTextToClipboard(values);
|
||||
}
|
||||
|
||||
updateCell(rowIndex, colIndex, value) {
|
||||
const cell = this.getCell(rowIndex, colIndex);
|
||||
const cell = this.getCell(colIndex, rowIndex);
|
||||
|
||||
cell.content = value;
|
||||
this.refreshCell(cell);
|
||||
@ -317,11 +358,9 @@ export default class CellManager {
|
||||
|
||||
refreshCell(cell) {
|
||||
const selector = `.data-table-col[data-row-index="${cell.rowIndex}"][data-col-index="${cell.colIndex}"]`;
|
||||
const bodyScrollable = this.instance.bodyScrollable;
|
||||
const $cell = bodyScrollable.find(selector);
|
||||
const $newCell = $(getColumnHTML(cell));
|
||||
const $cell = this.bodyScrollable.find(selector);
|
||||
|
||||
$cell.replaceWith($newCell);
|
||||
$cell.html(getCellContent(cell));
|
||||
}
|
||||
|
||||
getCell$(rowIndex, colIndex) {
|
||||
@ -350,8 +389,8 @@ export default class CellManager {
|
||||
return $cell.next();
|
||||
}
|
||||
|
||||
getCell(rowIndex, colIndex) {
|
||||
return this.instance.datamanager.getCell(rowIndex, colIndex);
|
||||
getCell(colIndex, rowIndex) {
|
||||
return this.instance.datamanager.getCell(colIndex, rowIndex);
|
||||
}
|
||||
|
||||
getCellAttr($cell) {
|
||||
|
||||
@ -181,7 +181,7 @@ export default class DataManager {
|
||||
return this.rows.find(row => row[0].rowIndex === rowIndex);
|
||||
}
|
||||
|
||||
getCell(rowIndex, colIndex) {
|
||||
getCell(colIndex, rowIndex) {
|
||||
rowIndex = +rowIndex;
|
||||
colIndex = +colIndex;
|
||||
return this.rows.find(row => row[0].rowIndex === rowIndex)[colIndex];
|
||||
|
||||
@ -533,8 +533,8 @@ export default class DataTable {
|
||||
return this.datamanager.getRow(rowIndex);
|
||||
}
|
||||
|
||||
getCell(rowIndex, colIndex) {
|
||||
return this.datamanager.getCell(rowIndex, colIndex);
|
||||
getCell(colIndex, rowIndex) {
|
||||
return this.datamanager.getCell(colIndex, rowIndex);
|
||||
}
|
||||
|
||||
getColumnHeaderElement(colIndex) {
|
||||
|
||||
@ -9,7 +9,8 @@ const KEYCODES = {
|
||||
39: 'right',
|
||||
40: 'down',
|
||||
9: 'tab',
|
||||
27: 'esc'
|
||||
27: 'esc',
|
||||
67: 'c'
|
||||
};
|
||||
|
||||
const handlers = {};
|
||||
|
||||
83
src/utils.js
83
src/utils.js
@ -31,17 +31,24 @@ function getColumnHTML(column) {
|
||||
isHeader
|
||||
});
|
||||
|
||||
return `
|
||||
<td class="data-table-col noselect" ${dataAttr}>
|
||||
${getCellContent(column)}
|
||||
</td>
|
||||
`;
|
||||
}
|
||||
|
||||
function getCellContent(column) {
|
||||
const { isHeader } = column;
|
||||
const editCellHTML = isHeader ? '' : getEditCellHTML();
|
||||
const sortIndicator = isHeader ? '<span class="sort-indicator"></span>' : '';
|
||||
|
||||
return `
|
||||
<td class="data-table-col noselect" ${dataAttr}>
|
||||
<div class="content ellipsis">
|
||||
${column.format ? column.format(column.content) : column.content}
|
||||
${sortIndicator}
|
||||
</div>
|
||||
${editCellHTML}
|
||||
</td>
|
||||
<div class="content ellipsis">
|
||||
${column.format ? column.format(column.content) : column.content}
|
||||
${sortIndicator}
|
||||
</div>
|
||||
${editCellHTML}
|
||||
`;
|
||||
}
|
||||
|
||||
@ -193,6 +200,64 @@ function removeCSSRule(rule, cssRulesString = '') {
|
||||
return output.trim();
|
||||
}
|
||||
|
||||
function copyTextToClipboard(text) {
|
||||
// https://stackoverflow.com/a/30810322/5353542
|
||||
var textArea = document.createElement('textarea');
|
||||
|
||||
//
|
||||
// *** This styling is an extra step which is likely not required. ***
|
||||
//
|
||||
// Why is it here? To ensure:
|
||||
// 1. the element is able to have focus and selection.
|
||||
// 2. if element was to flash render it has minimal visual impact.
|
||||
// 3. less flakyness with selection and copying which **might** occur if
|
||||
// the textarea element is not visible.
|
||||
//
|
||||
// The likelihood is the element won't even render, not even a flash,
|
||||
// so some of these are just precautions. However in IE the element
|
||||
// is visible whilst the popup box asking the user for permission for
|
||||
// the web page to copy to the clipboard.
|
||||
//
|
||||
|
||||
// Place in top-left corner of screen regardless of scroll position.
|
||||
textArea.style.position = 'fixed';
|
||||
textArea.style.top = 0;
|
||||
textArea.style.left = 0;
|
||||
|
||||
// Ensure it has a small width and height. Setting to 1px / 1em
|
||||
// doesn't work as this gives a negative w/h on some browsers.
|
||||
textArea.style.width = '2em';
|
||||
textArea.style.height = '2em';
|
||||
|
||||
// We don't need padding, reducing the size if it does flash render.
|
||||
textArea.style.padding = 0;
|
||||
|
||||
// Clean up any borders.
|
||||
textArea.style.border = 'none';
|
||||
textArea.style.outline = 'none';
|
||||
textArea.style.boxShadow = 'none';
|
||||
|
||||
// Avoid flash of white box if rendered for any reason.
|
||||
textArea.style.background = 'transparent';
|
||||
|
||||
textArea.value = text;
|
||||
|
||||
document.body.appendChild(textArea);
|
||||
|
||||
textArea.select();
|
||||
|
||||
try {
|
||||
const successful = document.execCommand('copy');
|
||||
const msg = successful ? 'successful' : 'unsuccessful';
|
||||
|
||||
console.log('Copying text command was ' + msg);
|
||||
} catch (err) {
|
||||
console.log('Oops, unable to copy');
|
||||
}
|
||||
|
||||
document.body.removeChild(textArea);
|
||||
}
|
||||
|
||||
export default {
|
||||
getHeaderHTML,
|
||||
getBodyHTML,
|
||||
@ -207,5 +272,7 @@ export default {
|
||||
removeCSSRule,
|
||||
makeDataAttributeString,
|
||||
getDefault,
|
||||
escapeRegExp
|
||||
escapeRegExp,
|
||||
getCellContent,
|
||||
copyTextToClipboard
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user