Copy cell contents

This commit is contained in:
Faris Ansari 2017-11-02 09:53:07 +05:30
parent 4316c5834e
commit 89dfaa13ed
7 changed files with 414 additions and 184 deletions

View File

@ -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

View File

@ -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) {

View File

@ -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];

View File

@ -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) {

View File

@ -9,7 +9,8 @@ const KEYCODES = {
39: 'right',
40: 'down',
9: 'tab',
27: 'esc'
27: 'esc',
67: 'c'
};
const handlers = {};

View File

@ -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
};