Removed jQuery 💃
This commit is contained in:
parent
1d7278d3d6
commit
785cf8f466
@ -22,7 +22,7 @@
|
|||||||
"it": true,
|
"it": true,
|
||||||
"expect": true,
|
"expect": true,
|
||||||
"sinon": true,
|
"sinon": true,
|
||||||
"$": true
|
"Clusterize": true
|
||||||
},
|
},
|
||||||
|
|
||||||
"parser": "babel-eslint",
|
"parser": "babel-eslint",
|
||||||
|
|||||||
@ -21,11 +21,11 @@
|
|||||||
<section style="width: 60%; font-size: 12px;">
|
<section style="width: 60%; font-size: 12px;">
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
<script src="./node_modules/jquery/dist/jquery.js"></script>
|
|
||||||
<script src="./node_modules/clusterize.js/clusterize.js"></script>
|
<script src="./node_modules/clusterize.js/clusterize.js"></script>
|
||||||
<script src="./lib/frappe-datatable.js"></script>
|
<script src="./lib/frappe-datatable.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(() => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
|
||||||
var data = {
|
var data = {
|
||||||
"columns": [
|
"columns": [
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1,23 +1,18 @@
|
|||||||
import { getCellContent, copyTextToClipboard } from './utils';
|
import { getCellContent, copyTextToClipboard } from './utils';
|
||||||
import keyboard from 'keyboard';
|
import keyboard from 'keyboard';
|
||||||
import perf from './performance';
|
import $ from './dom';
|
||||||
|
|
||||||
export default class CellManager {
|
export default class CellManager {
|
||||||
constructor(instance) {
|
constructor(instance) {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
|
this.wrapper = this.instance.wrapper;
|
||||||
this.options = this.instance.options;
|
this.options = this.instance.options;
|
||||||
this.style = this.instance.style;
|
this.style = this.instance.style;
|
||||||
this.bodyScrollable = this.instance.bodyScrollable;
|
this.bodyScrollable = this.instance.bodyScrollable;
|
||||||
|
|
||||||
this.prepare();
|
|
||||||
this.bindEvents();
|
this.bindEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare() {
|
|
||||||
this.$borderOutline = this.instance.$borders.find('.border-outline');
|
|
||||||
this.$borderBg = this.instance.$borders.find('.border-background');
|
|
||||||
}
|
|
||||||
|
|
||||||
bindEvents() {
|
bindEvents() {
|
||||||
this.bindFocusCell();
|
this.bindFocusCell();
|
||||||
this.bindEditCell();
|
this.bindEditCell();
|
||||||
@ -31,11 +26,10 @@ export default class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bindEditCell() {
|
bindEditCell() {
|
||||||
const self = this;
|
|
||||||
|
|
||||||
this.$editingCell = null;
|
this.$editingCell = null;
|
||||||
this.bodyScrollable.on('dblclick', '.data-table-col', function () {
|
|
||||||
self.activateEditing($(this));
|
$.on(this.bodyScrollable, 'dblclick', '.data-table-col', (e, cell) => {
|
||||||
|
this.activateEditing(cell);
|
||||||
});
|
});
|
||||||
|
|
||||||
keyboard.on('enter', (e) => {
|
keyboard.on('enter', (e) => {
|
||||||
@ -49,8 +43,8 @@ export default class CellManager {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$(document.body).on('click', e => {
|
$.on(document.body, 'click', e => {
|
||||||
if ($(e.target).is('.edit-cell, .edit-cell *')) return;
|
if (e.target.matches('.edit-cell, .edit-cell *')) return;
|
||||||
this.deactivateEditing();
|
this.deactivateEditing();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -161,23 +155,23 @@ export default class CellManager {
|
|||||||
bindMouseEvents() {
|
bindMouseEvents() {
|
||||||
let mouseDown = null;
|
let mouseDown = null;
|
||||||
|
|
||||||
this.bodyScrollable.on('mousedown', '.data-table-col', (e) => {
|
$.on(this.bodyScrollable, 'mousedown', '.data-table-col', (e) => {
|
||||||
mouseDown = true;
|
mouseDown = true;
|
||||||
this.focusCell($(e.currentTarget));
|
this.focusCell($(e.delegatedTarget));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.bodyScrollable.on('mouseup', () => {
|
$.on(this.bodyScrollable, 'mouseup', () => {
|
||||||
mouseDown = false;
|
mouseDown = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.bodyScrollable.on('mousemove', '.data-table-col', (e) => {
|
$.on(this.bodyScrollable, 'mousemove', '.data-table-col', (e) => {
|
||||||
if (!mouseDown) return;
|
if (!mouseDown) return;
|
||||||
this.selectArea($(e.currentTarget));
|
this.selectArea($(e.delegatedTarget));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
focusCell($cell) {
|
focusCell($cell) {
|
||||||
if (!$cell.length) return;
|
if (!$cell) return;
|
||||||
|
|
||||||
const { colIndex } = this.getCellAttr($cell);
|
const { colIndex } = this.getCellAttr($cell);
|
||||||
|
|
||||||
@ -193,11 +187,11 @@ export default class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.$focusedCell) {
|
if (this.$focusedCell) {
|
||||||
this.$focusedCell.removeClass('selected');
|
this.$focusedCell.classList.remove('selected');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$focusedCell = $cell;
|
this.$focusedCell = $cell;
|
||||||
$cell.addClass('selected');
|
$cell.classList.add('selected');
|
||||||
|
|
||||||
this.highlightRowColumnHeader($cell);
|
this.highlightRowColumnHeader($cell);
|
||||||
}
|
}
|
||||||
@ -209,13 +203,13 @@ export default class CellManager {
|
|||||||
const rowHeaderSelector = `.data-table-col[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
|
const rowHeaderSelector = `.data-table-col[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
|
||||||
|
|
||||||
if (this.lastHeaders) {
|
if (this.lastHeaders) {
|
||||||
this.style.unset(this.lastHeaders, 'backgroundColor');
|
$.removeStyle(this.lastHeaders, 'backgroundColor');
|
||||||
}
|
}
|
||||||
|
|
||||||
const colHeader = document.querySelector(colHeaderSelector);
|
const colHeader = $(colHeaderSelector, this.wrapper);
|
||||||
const rowHeader = document.querySelector(rowHeaderSelector);
|
const rowHeader = $(rowHeaderSelector, this.wrapper);
|
||||||
|
|
||||||
this.style.set([colHeader, rowHeader], {
|
$.style([colHeader, rowHeader], {
|
||||||
backgroundColor: 'var(--light-bg)'
|
backgroundColor: 'var(--light-bg)'
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -232,13 +226,11 @@ export default class CellManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
_selectArea($cell1, $cell2) {
|
_selectArea($cell1, $cell2) {
|
||||||
const cells = this.getCellsInRange(...arguments);
|
const cells = this.getCellsInRange($cell1, $cell2);
|
||||||
|
|
||||||
if (!cells) return false;
|
if (!cells) return false;
|
||||||
this.clearSelection();
|
|
||||||
const $cells = cells.map(([c, r]) => this.getCell$(r, c)[0]);
|
|
||||||
|
|
||||||
$($cells).addClass('highlight');
|
this.clearSelection();
|
||||||
|
cells.map(index => this.getCell$(...index)).map($cell => $cell.classList.add('highlight'));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +242,7 @@ export default class CellManager {
|
|||||||
} else
|
} else
|
||||||
if (typeof $cell1 === 'object') {
|
if (typeof $cell1 === 'object') {
|
||||||
|
|
||||||
if (!($cell1.length && $cell2.length)) {
|
if (!($cell1 && $cell2)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,7 +289,9 @@ export default class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clearSelection() {
|
clearSelection() {
|
||||||
this.bodyScrollable.find('.data-table-col.highlight').removeClass('highlight');
|
$.each('.data-table-col.highlight', this.bodyScrollable)
|
||||||
|
.map(cell => cell.classList.remove('highlight'));
|
||||||
|
|
||||||
this.$selectionCursor = null;
|
this.$selectionCursor = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,9 +317,11 @@ export default class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.$editingCell = $cell;
|
this.$editingCell = $cell;
|
||||||
$cell.addClass('editing');
|
$cell.classList.add('editing');
|
||||||
|
|
||||||
|
const $editCell = $('.edit-cell', $cell);
|
||||||
|
$editCell.innerHTML = '';
|
||||||
|
|
||||||
const $editCell = $cell.find('.edit-cell').empty();
|
|
||||||
const cell = this.getCell(colIndex, rowIndex);
|
const cell = this.getCell(colIndex, rowIndex);
|
||||||
const editing = this.getEditingObject(colIndex, rowIndex, cell.content, $editCell);
|
const editing = this.getEditingObject(colIndex, rowIndex, cell.content, $editCell);
|
||||||
|
|
||||||
@ -338,7 +334,7 @@ export default class CellManager {
|
|||||||
|
|
||||||
deactivateEditing() {
|
deactivateEditing() {
|
||||||
if (!this.$editingCell) return;
|
if (!this.$editingCell) return;
|
||||||
this.$editingCell.removeClass('editing');
|
this.$editingCell.classList.remove('editing');
|
||||||
this.$editingCell = null;
|
this.$editingCell = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,20 +344,21 @@ export default class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// editing fallback
|
// editing fallback
|
||||||
const $input = $('<input type="text" />');
|
const $input = $.create('input', {
|
||||||
|
type: 'text',
|
||||||
parent.append($input);
|
inside: parent
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
initValue(value) {
|
initValue(value) {
|
||||||
$input.focus();
|
$input.focus();
|
||||||
return $input.val(value);
|
$input.value = value;
|
||||||
},
|
},
|
||||||
getValue() {
|
getValue() {
|
||||||
return $input.val();
|
return $input.value;
|
||||||
},
|
},
|
||||||
setValue(value) {
|
setValue(value) {
|
||||||
return $input.val(value);
|
$input.value = value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -391,7 +388,7 @@ export default class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
copyCellContents($cell1, $cell2) {
|
copyCellContents($cell1, $cell2) {
|
||||||
const cells = this.getCellsInRange(...arguments);
|
const cells = this.getCellsInRange($cell1, $cell2);
|
||||||
|
|
||||||
if (!cells) return;
|
if (!cells) return;
|
||||||
|
|
||||||
@ -424,9 +421,9 @@ export default class CellManager {
|
|||||||
|
|
||||||
refreshCell(cell) {
|
refreshCell(cell) {
|
||||||
const selector = `.data-table-col[data-row-index="${cell.rowIndex}"][data-col-index="${cell.colIndex}"]`;
|
const selector = `.data-table-col[data-row-index="${cell.rowIndex}"][data-col-index="${cell.colIndex}"]`;
|
||||||
const $cell = this.bodyScrollable.find(selector);
|
const $cell = $(selector, this.bodyScrollable);
|
||||||
|
|
||||||
$cell.html(getCellContent(cell));
|
$cell.innerHTML = getCellContent(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
isStandardCell(colIndex) {
|
isStandardCell(colIndex) {
|
||||||
@ -434,30 +431,30 @@ export default class CellManager {
|
|||||||
return colIndex < this.instance.getFirstColumnIndex();
|
return colIndex < this.instance.getFirstColumnIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
getCell$(rowIndex, colIndex) {
|
getCell$(colIndex, rowIndex) {
|
||||||
return this.bodyScrollable.find(`.data-table-col[data-row-index="${rowIndex}"][data-col-index="${colIndex}"]`);
|
return $(`.data-table-col[data-row-index="${rowIndex}"][data-col-index="${colIndex}"]`, this.bodyScrollable);
|
||||||
}
|
}
|
||||||
|
|
||||||
getAboveCell$($cell) {
|
getAboveCell$($cell) {
|
||||||
const { colIndex } = this.getCellAttr($cell);
|
const { colIndex } = this.getCellAttr($cell);
|
||||||
const $aboveRow = $cell.parent().prev();
|
const $aboveRow = $cell.parentElement.previousElementSibling;
|
||||||
|
|
||||||
return $aboveRow.find(`[data-col-index="${colIndex}"]`);
|
return $(`[data-col-index="${colIndex}"]`, $aboveRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
getBelowCell$($cell) {
|
getBelowCell$($cell) {
|
||||||
const { colIndex } = this.getCellAttr($cell);
|
const { colIndex } = this.getCellAttr($cell);
|
||||||
const $belowRow = $cell.parent().next();
|
const $belowRow = $cell.parentElement.nextElementSibling;
|
||||||
|
|
||||||
return $belowRow.find(`[data-col-index="${colIndex}"]`);
|
return $(`[data-col-index="${colIndex}"]`, $belowRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLeftCell$($cell) {
|
getLeftCell$($cell) {
|
||||||
return $cell.prev();
|
return $cell.previousElementSibling;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRightCell$($cell) {
|
getRightCell$($cell) {
|
||||||
return $cell.next();
|
return $cell.nextElementSibling;
|
||||||
}
|
}
|
||||||
|
|
||||||
getLeftMostCell$(rowIndex) {
|
getLeftMostCell$(rowIndex) {
|
||||||
@ -481,11 +478,11 @@ export default class CellManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getCellAttr($cell) {
|
getCellAttr($cell) {
|
||||||
return $cell.data();
|
return this.instance.getCellAttr($cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
getRowHeight() {
|
getRowHeight() {
|
||||||
return this.bodyScrollable.find('.data-table-row:first').height();
|
return $.style($('.data-table-row', this.bodyScrollable), 'height');
|
||||||
}
|
}
|
||||||
|
|
||||||
inViewport($cell) {
|
inViewport($cell) {
|
||||||
@ -504,7 +501,7 @@ export default class CellManager {
|
|||||||
const rowHeight = this.getRowHeight();
|
const rowHeight = this.getRowHeight();
|
||||||
const rowOffset = rowIndex * rowHeight;
|
const rowOffset = rowIndex * rowHeight;
|
||||||
|
|
||||||
const scrollTopOffset = this.bodyScrollable[0].scrollTop;
|
const scrollTopOffset = this.bodyScrollable.scrollTop;
|
||||||
|
|
||||||
if (rowOffset - scrollTopOffset + rowHeight < viewportHeight) {
|
if (rowOffset - scrollTopOffset + rowHeight < viewportHeight) {
|
||||||
return true;
|
return true;
|
||||||
@ -526,7 +523,7 @@ export default class CellManager {
|
|||||||
scrollToRow(rowIndex) {
|
scrollToRow(rowIndex) {
|
||||||
const offset = rowIndex * this.getRowHeight();
|
const offset = rowIndex * this.getRowHeight();
|
||||||
|
|
||||||
this.bodyScrollable[0].scrollTop = offset;
|
this.bodyScrollable.scrollTop = offset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -36,7 +36,8 @@ export default class DataManager {
|
|||||||
const val = {
|
const val = {
|
||||||
content: '<input type="checkbox" />',
|
content: '<input type="checkbox" />',
|
||||||
editable: false,
|
editable: false,
|
||||||
resizable: false
|
resizable: false,
|
||||||
|
sortable: false
|
||||||
};
|
};
|
||||||
|
|
||||||
columns = [val].concat(columns);
|
columns = [val].concat(columns);
|
||||||
|
|||||||
185
src/datatable.js
185
src/datatable.js
@ -1,4 +1,3 @@
|
|||||||
/* globals $, Clusterize */
|
|
||||||
import {
|
import {
|
||||||
getHeaderHTML,
|
getHeaderHTML,
|
||||||
getBodyHTML,
|
getBodyHTML,
|
||||||
@ -6,6 +5,8 @@ import {
|
|||||||
getDefault
|
getDefault
|
||||||
} from './utils';
|
} from './utils';
|
||||||
|
|
||||||
|
import $ from './dom';
|
||||||
|
|
||||||
import DataManager from './datamanager';
|
import DataManager from './datamanager';
|
||||||
import CellManager from './cellmanager';
|
import CellManager from './cellmanager';
|
||||||
import Style from './style';
|
import Style from './style';
|
||||||
@ -29,8 +30,8 @@ const DEFAULT_OPTIONS = {
|
|||||||
export default class DataTable {
|
export default class DataTable {
|
||||||
constructor(wrapper, options) {
|
constructor(wrapper, options) {
|
||||||
|
|
||||||
this.wrapper = $(wrapper);
|
this.wrapper = wrapper;
|
||||||
if (this.wrapper.length === 0) {
|
if (!this.wrapper) {
|
||||||
throw new Error('Invalid argument given for `wrapper`');
|
throw new Error('Invalid argument given for `wrapper`');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,15 +53,13 @@ export default class DataTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
make() {
|
make() {
|
||||||
if (this.wrapper.find('.data-table').length === 0) {
|
this.makeDom();
|
||||||
this.makeDom();
|
this.makeStyle();
|
||||||
this.makeStyle();
|
this.bindEvents();
|
||||||
this.bindEvents();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
makeDom() {
|
makeDom() {
|
||||||
this.wrapper.html(`
|
this.wrapper.innerHTML = `
|
||||||
<div class="data-table">
|
<div class="data-table">
|
||||||
<table class="data-table-header">
|
<table class="data-table-header">
|
||||||
</table>
|
</table>
|
||||||
@ -73,13 +72,10 @@ export default class DataTable {
|
|||||||
<div class="border-background"></div>
|
<div class="border-background"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`;
|
||||||
|
|
||||||
this.header = this.wrapper.find('.data-table-header');
|
this.header = $('.data-table-header', this.wrapper);
|
||||||
this.bodyScrollable = this.wrapper.find('.body-scrollable');
|
this.bodyScrollable = $('.body-scrollable', this.wrapper);
|
||||||
// this.body = this.wrapper.find('.data-table-body');
|
|
||||||
this.footer = this.wrapper.find('.data-table-footer');
|
|
||||||
this.$borders = this.wrapper.find('.data-table-borders');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh(data) {
|
refresh(data) {
|
||||||
@ -101,7 +97,7 @@ export default class DataTable {
|
|||||||
renderHeader() {
|
renderHeader() {
|
||||||
const columns = this.datamanager.getColumns();
|
const columns = this.datamanager.getColumns();
|
||||||
|
|
||||||
this.header.html(getHeaderHTML(columns));
|
this.header.innerHTML = getHeaderHTML(columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBody() {
|
renderBody() {
|
||||||
@ -115,22 +111,22 @@ export default class DataTable {
|
|||||||
renderBodyHTML() {
|
renderBodyHTML() {
|
||||||
const rows = this.datamanager.getRows();
|
const rows = this.datamanager.getRows();
|
||||||
|
|
||||||
this.bodyScrollable.html(`
|
this.bodyScrollable.innerHTML = `
|
||||||
<table class="data-table-body table table-bordered">
|
<table class="data-table-body">
|
||||||
${getBodyHTML(rows)}
|
${getBodyHTML(rows)}
|
||||||
</table>
|
</table>
|
||||||
`);
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBodyWithClusterize() {
|
renderBodyWithClusterize() {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
// empty body
|
// empty body
|
||||||
this.bodyScrollable.html(`
|
this.bodyScrollable.innerHTML = `
|
||||||
<table class="data-table-body table table-bordered">
|
<table class="data-table-body">
|
||||||
${getBodyHTML([])}
|
${getBodyHTML([])}
|
||||||
</table>
|
</table>
|
||||||
`);
|
`;
|
||||||
|
|
||||||
this.start = 0;
|
this.start = 0;
|
||||||
this.pageLength = 1000;
|
this.pageLength = 1000;
|
||||||
@ -143,8 +139,8 @@ export default class DataTable {
|
|||||||
|
|
||||||
this.clusterize = new Clusterize({
|
this.clusterize = new Clusterize({
|
||||||
rows: initialData,
|
rows: initialData,
|
||||||
scrollElem: this.bodyScrollable.get(0),
|
scrollElem: this.bodyScrollable,
|
||||||
contentElem: this.bodyScrollable.find('tbody').get(0),
|
contentElem: $('tbody', this.bodyScrollable),
|
||||||
callbacks: {
|
callbacks: {
|
||||||
clusterChanged() {
|
clusterChanged() {
|
||||||
self.highlightCheckedRows();
|
self.highlightCheckedRows();
|
||||||
@ -213,21 +209,21 @@ export default class DataTable {
|
|||||||
if (!this.options.takeAvailableSpace) {
|
if (!this.options.takeAvailableSpace) {
|
||||||
// setting width as 0 will ensure that the
|
// setting width as 0 will ensure that the
|
||||||
// header doesn't take the available space
|
// header doesn't take the available space
|
||||||
this.header.css({
|
$.style(this.header, {
|
||||||
width: 0
|
width: 0
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.header.css({
|
$.style(this.header, {
|
||||||
margin: 0
|
margin: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
// cache minWidth for each column
|
// cache minWidth for each column
|
||||||
this.minWidthMap = getDefault(this.minWidthMap, []);
|
this.minWidthMap = getDefault(this.minWidthMap, []);
|
||||||
this.header.find('.data-table-col').each(function () {
|
|
||||||
const col = $(this);
|
$.each('.data-table-col', this.header).map(col => {
|
||||||
const width = parseInt(col.find('.content').css('width'), 10);
|
const width = $.style($('.content', col), 'width');
|
||||||
const colIndex = col.attr('data-col-index');
|
const { colIndex } = $.data(col);
|
||||||
|
|
||||||
if (!self.minWidthMap[colIndex]) {
|
if (!self.minWidthMap[colIndex]) {
|
||||||
// only set this once
|
// only set this once
|
||||||
@ -236,10 +232,10 @@ export default class DataTable {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// set initial width as naturally calculated by table's first row
|
// set initial width as naturally calculated by table's first row
|
||||||
this.bodyScrollable.find('.data-table-row[data-row-index="0"] .data-table-col').each(function () {
|
$.each('.data-table-row[data-row-index="0"] .data-table-col', this.bodyScrollable).map($cell => {
|
||||||
const $cell = $(this);
|
|
||||||
let width = parseInt($cell.find('.content').css('width'), 10);
|
let width = $.style($('.content', $cell), 'width');
|
||||||
const height = parseInt($cell.find('.content').css('height'), 10);
|
const height = $.style($('.content', $cell), 'height');
|
||||||
const { colIndex } = self.getCellAttr($cell);
|
const { colIndex } = self.getCellAttr($cell);
|
||||||
const minWidth = self.getColumnMinWidth(colIndex);
|
const minWidth = self.getColumnMinWidth(colIndex);
|
||||||
|
|
||||||
@ -252,8 +248,8 @@ export default class DataTable {
|
|||||||
|
|
||||||
this.setBodyWidth();
|
this.setBodyWidth();
|
||||||
|
|
||||||
this.style.set(this.bodyScrollable[0], {
|
$.style(this.bodyScrollable, {
|
||||||
marginTop: this.header.height() + 'px'
|
marginTop: $.style(this.header, 'height') + 'px'
|
||||||
});
|
});
|
||||||
|
|
||||||
// center align Sr. No column
|
// center align Sr. No column
|
||||||
@ -265,7 +261,9 @@ export default class DataTable {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.bodyScrollable.find('.table').css('margin', 0);
|
$.style($('table', this.bodyScrollable), {
|
||||||
|
margin: 0
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bindResizeColumn() {
|
bindResizeColumn() {
|
||||||
@ -273,9 +271,9 @@ export default class DataTable {
|
|||||||
let isDragging = false;
|
let isDragging = false;
|
||||||
let $currCell, startWidth, startX;
|
let $currCell, startWidth, startX;
|
||||||
|
|
||||||
this.header.on('mousedown', '.data-table-col', function (e) {
|
$.on(this.header, 'mousedown', '.data-table-col', (e, cell) => {
|
||||||
$currCell = $(this);
|
$currCell = cell;
|
||||||
const colIndex = $currCell.attr('data-col-index');
|
const { colIndex } = this.getCellAttr($currCell);
|
||||||
const col = self.getColumn(colIndex);
|
const col = self.getColumn(colIndex);
|
||||||
|
|
||||||
if (col && col.resizable === false) {
|
if (col && col.resizable === false) {
|
||||||
@ -283,28 +281,26 @@ export default class DataTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isDragging = true;
|
isDragging = true;
|
||||||
startWidth = $currCell.find('.content').width();
|
startWidth = $.style($('.content', $currCell), 'width');
|
||||||
startX = e.pageX;
|
startX = e.pageX;
|
||||||
});
|
});
|
||||||
|
|
||||||
$('body').on('mouseup', function (e) {
|
$.on(document.body, 'mouseup', (e) => {
|
||||||
if (!$currCell) return;
|
if (!$currCell) return;
|
||||||
isDragging = false;
|
isDragging = false;
|
||||||
const colIndex = $currCell.attr('data-col-index');
|
|
||||||
|
|
||||||
if ($currCell) {
|
const { colIndex } = this.getCellAttr($currCell);
|
||||||
const width = parseInt($currCell.find('.content').css('width'), 10);
|
const width = $.style($('.content', $currCell), 'width');
|
||||||
|
|
||||||
self.setColumnWidth(colIndex, width);
|
self.setColumnWidth(colIndex, width);
|
||||||
self.setBodyWidth();
|
self.setBodyWidth();
|
||||||
$currCell = null;
|
$currCell = null;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$('body').on('mousemove', function (e) {
|
$.on(document.body, 'mousemove', (e) => {
|
||||||
if (!isDragging) return;
|
if (!isDragging) return;
|
||||||
const finalWidth = startWidth + (e.pageX - startX);
|
const finalWidth = startWidth + (e.pageX - startX);
|
||||||
const colIndex = $currCell.attr('data-col-index');
|
const { colIndex } = this.getCellAttr($currCell);
|
||||||
|
|
||||||
if (self.getColumnMinWidth(colIndex) > finalWidth) {
|
if (self.getColumnMinWidth(colIndex) > finalWidth) {
|
||||||
// don't resize past minWidth
|
// don't resize past minWidth
|
||||||
@ -318,10 +314,10 @@ export default class DataTable {
|
|||||||
bindSortColumn() {
|
bindSortColumn() {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
this.header.on('click', '.data-table-col .content span', function () {
|
$.on(this.header, 'click', '.data-table-col .content span', (e, span) => {
|
||||||
const $cell = $(this).closest('.data-table-col');
|
const $cell = span.closest('.data-table-col');
|
||||||
let sortOrder = getDefault($cell.attr('data-sort-order'), 'none');
|
let { colIndex, sortOrder } = this.getCellAttr($cell);
|
||||||
const colIndex = $cell.attr('data-col-index');
|
sortOrder = getDefault(sortOrder, 'none');
|
||||||
const col = self.getColumn(colIndex);
|
const col = self.getColumn(colIndex);
|
||||||
|
|
||||||
if (col && col.sortable === false) {
|
if (col && col.sortable === false) {
|
||||||
@ -329,22 +325,24 @@ export default class DataTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reset sort indicator
|
// reset sort indicator
|
||||||
self.header.find('.sort-indicator').text('');
|
$('.sort-indicator', this.header).textContent = '';
|
||||||
self.header.find('.data-table-col').attr('data-sort-order', 'none');
|
$.each('.data-table-col', this.header).map($cell => {
|
||||||
|
$cell.setAttribute('data-sort-order', 'none');
|
||||||
|
});
|
||||||
|
|
||||||
if (sortOrder === 'none') {
|
if (sortOrder === 'none') {
|
||||||
$cell.attr('data-sort-order', 'asc');
|
$cell.setAttribute('data-sort-order', 'asc');
|
||||||
$cell.find('.sort-indicator').text('▲');
|
$('.sort-indicator', $cell).textContent = '▲';
|
||||||
} else if (sortOrder === 'asc') {
|
} else if (sortOrder === 'asc') {
|
||||||
$cell.attr('data-sort-order', 'desc');
|
$cell.setAttribute('data-sort-order', 'desc');
|
||||||
$cell.find('.sort-indicator').text('▼');
|
$('.sort-indicator', $cell).textContent = '▼';
|
||||||
} else if (sortOrder === 'desc') {
|
} else if (sortOrder === 'desc') {
|
||||||
$cell.attr('data-sort-order', 'none');
|
$cell.setAttribute('data-sort-order', 'none');
|
||||||
$cell.find('.sort-indicator').text('');
|
$('.sort-indicator', $cell).textContent = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
// sortWith this action
|
// sortWith this action
|
||||||
sortOrder = $cell.attr('data-sort-order');
|
sortOrder = $cell.getAttribute('data-sort-order');
|
||||||
|
|
||||||
if (self.events && self.events.onSort) {
|
if (self.events && self.events.onSort) {
|
||||||
self.events.onSort(colIndex, sortOrder);
|
self.events.onSort(colIndex, sortOrder);
|
||||||
@ -361,24 +359,21 @@ export default class DataTable {
|
|||||||
|
|
||||||
bindCheckbox() {
|
bindCheckbox() {
|
||||||
if (!this.options.addCheckboxColumn) return;
|
if (!this.options.addCheckboxColumn) return;
|
||||||
const self = this;
|
|
||||||
|
|
||||||
this.wrapper.on('click', '.data-table-col[data-col-index="0"] [type="checkbox"]', function () {
|
$.on(this.wrapper, 'click', '.data-table-col[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
|
||||||
const $checkbox = $(this);
|
|
||||||
const $cell = $checkbox.closest('.data-table-col');
|
const $cell = $checkbox.closest('.data-table-col');
|
||||||
const { rowIndex, isHeader } = self.getCellAttr($cell);
|
const { rowIndex, isHeader } = this.getCellAttr($cell);
|
||||||
const checked = $checkbox.is(':checked');
|
const checked = $checkbox.checked;
|
||||||
|
|
||||||
if (isHeader) {
|
if (isHeader) {
|
||||||
self.checkAll(checked);
|
this.checkAll(checked);
|
||||||
} else {
|
} else {
|
||||||
self.checkRow(rowIndex, checked);
|
this.checkRow(rowIndex, checked);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getCheckedRows() {
|
getCheckedRows() {
|
||||||
|
|
||||||
return this.checkMap
|
return this.checkMap
|
||||||
.map((c, rowIndex) => {
|
.map((c, rowIndex) => {
|
||||||
if (c) {
|
if (c) {
|
||||||
@ -402,9 +397,10 @@ export default class DataTable {
|
|||||||
// update internal map
|
// update internal map
|
||||||
this.checkMap[rowIndex] = value;
|
this.checkMap[rowIndex] = value;
|
||||||
// set checkbox value explicitly
|
// set checkbox value explicitly
|
||||||
this.bodyScrollable
|
$.each(`.data-table-col[data-row-index="${rowIndex}"][data-col-index="0"] [type="checkbox"]`, this.bodyScrollable)
|
||||||
.find(`.data-table-col[data-row-index="${rowIndex}"][data-col-index="0"] [type="checkbox"]`)
|
.map(input => {
|
||||||
.prop('checked', toggle);
|
input.checked = toggle;
|
||||||
|
});
|
||||||
// highlight row
|
// highlight row
|
||||||
this.highlightRow(rowIndex, toggle);
|
this.highlightRow(rowIndex, toggle);
|
||||||
}
|
}
|
||||||
@ -419,28 +415,30 @@ export default class DataTable {
|
|||||||
this.checkMap = [];
|
this.checkMap = [];
|
||||||
}
|
}
|
||||||
// set checkbox value
|
// set checkbox value
|
||||||
this.bodyScrollable
|
$.each('.data-table-col[data-col-index="0"] [type="checkbox"]', this.bodyScrollable)
|
||||||
.find('.data-table-col[data-col-index="0"] [type="checkbox"]')
|
.map(input => {
|
||||||
.prop('checked', toggle);
|
input.checked = toggle;
|
||||||
|
});
|
||||||
// highlight all
|
// highlight all
|
||||||
this.highlightAll(toggle);
|
this.highlightAll(toggle);
|
||||||
}
|
}
|
||||||
|
|
||||||
highlightRow(rowIndex, toggle = true) {
|
highlightRow(rowIndex, toggle = true) {
|
||||||
const $row = this.bodyScrollable
|
const $row = $(`.data-table-row[data-row-index="${rowIndex}"]`, this.bodyScrollable);
|
||||||
.find(`.data-table-row[data-row-index="${rowIndex}"]`);
|
|
||||||
|
|
||||||
if (toggle) {
|
if (toggle) {
|
||||||
$row.addClass('row-highlight');
|
$row.classList.add('row-highlight');
|
||||||
} else {
|
} else {
|
||||||
$row.removeClass('row-highlight');
|
$row.classList.remove('row-highlight');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
highlightAll(toggle = true) {
|
highlightAll(toggle = true) {
|
||||||
this.bodyScrollable
|
if (toggle) {
|
||||||
.find('.data-table-row')
|
this.bodyScrollable.classList.add('row-highlight-all');
|
||||||
.toggleClass('row-highlight', toggle);
|
} else {
|
||||||
|
this.bodyScrollable.classList.remove('row-highlight-all');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setColumnWidth(colIndex, width) {
|
setColumnWidth(colIndex, width) {
|
||||||
@ -485,7 +483,7 @@ export default class DataTable {
|
|||||||
const deltaWidth = (availableWidth - headerWidth) / this.datamanager.getColumnCount();
|
const deltaWidth = (availableWidth - headerWidth) / this.datamanager.getColumnCount();
|
||||||
|
|
||||||
columns.map(col => {
|
columns.map(col => {
|
||||||
const width = this.getColumnHeaderElement(col.colIndex).width();
|
const width = $.style(this.getColumnHeaderElement(col.colIndex), 'width');
|
||||||
let finalWidth = width + deltaWidth - 16;
|
let finalWidth = width + deltaWidth - 16;
|
||||||
|
|
||||||
if (this.options.addSerialNoColumn && col.colIndex === 0) {
|
if (this.options.addSerialNoColumn && col.colIndex === 0) {
|
||||||
@ -499,10 +497,9 @@ export default class DataTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setBodyWidth() {
|
setBodyWidth() {
|
||||||
this.bodyScrollable.css(
|
const width = $.style(this.header, 'width');
|
||||||
'width',
|
|
||||||
parseInt(this.header.css('width'), 10)
|
$.style(this.bodyScrollable, { width });
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
makeStyle() {
|
makeStyle() {
|
||||||
@ -524,9 +521,7 @@ export default class DataTable {
|
|||||||
getColumnHeaderElement(colIndex) {
|
getColumnHeaderElement(colIndex) {
|
||||||
colIndex = +colIndex;
|
colIndex = +colIndex;
|
||||||
if (colIndex < 0) return null;
|
if (colIndex < 0) return null;
|
||||||
return this.wrapper.find(
|
return $(`.data-table-col[data-is-header][data-col-index="${colIndex}"]`, this.wrapper);
|
||||||
`.data-table-col[data-is-header][data-col-index="${colIndex}"]`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getColumnMinWidth(colIndex) {
|
getColumnMinWidth(colIndex) {
|
||||||
@ -535,7 +530,7 @@ export default class DataTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getCellAttr($cell) {
|
getCellAttr($cell) {
|
||||||
return $cell.data();
|
return $.data($cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTotalRows() {
|
getTotalRows() {
|
||||||
@ -570,7 +565,7 @@ export default class DataTable {
|
|||||||
|
|
||||||
getViewportHeight() {
|
getViewportHeight() {
|
||||||
if (!this.viewportHeight) {
|
if (!this.viewportHeight) {
|
||||||
this.viewportHeight = this.bodyScrollable.height();
|
this.viewportHeight = $.style(this.bodyScrollable, 'height');
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.viewportHeight;
|
return this.viewportHeight;
|
||||||
|
|||||||
139
src/dom.js
Normal file
139
src/dom.js
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
|
||||||
|
export default function $(expr, con) {
|
||||||
|
return typeof expr === 'string' ?
|
||||||
|
(con || document).querySelector(expr) :
|
||||||
|
expr || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.each = (expr, con) => {
|
||||||
|
return typeof expr === 'string' ?
|
||||||
|
Array.from((con || document).querySelectorAll(expr)) :
|
||||||
|
expr || null;
|
||||||
|
};
|
||||||
|
|
||||||
|
$.create = (tag, o) => {
|
||||||
|
let element = document.createElement(tag);
|
||||||
|
|
||||||
|
for (let i in o) {
|
||||||
|
let val = o[i];
|
||||||
|
|
||||||
|
if (i === 'inside') {
|
||||||
|
$(val).appendChild(element);
|
||||||
|
} else
|
||||||
|
if (i === 'around') {
|
||||||
|
let ref = $(val);
|
||||||
|
ref.parentNode.insertBefore(element, ref);
|
||||||
|
element.appendChild(ref);
|
||||||
|
} else
|
||||||
|
if (i === 'styles') {
|
||||||
|
if (typeof val === 'object') {
|
||||||
|
Object.keys(val).map(prop => {
|
||||||
|
element.style[prop] = val[prop];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
if (i in element) {
|
||||||
|
element[i] = val;
|
||||||
|
} else {
|
||||||
|
element.setAttribute(i, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
};
|
||||||
|
|
||||||
|
$.on = (element, event, selector, callback) => {
|
||||||
|
if (!callback) {
|
||||||
|
callback = selector;
|
||||||
|
$.bind(element, event, callback);
|
||||||
|
} else {
|
||||||
|
$.delegate(element, event, selector, callback);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$.bind = (element, event, callback) => {
|
||||||
|
event.split(/\s+/).forEach(function (event) {
|
||||||
|
element.addEventListener(event, callback);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$.delegate = (element, event, selector, callback) => {
|
||||||
|
element.addEventListener(event, function (e) {
|
||||||
|
const delegatedTarget = e.target.closest(selector);
|
||||||
|
if (delegatedTarget) {
|
||||||
|
e.delegatedTarget = delegatedTarget;
|
||||||
|
callback.call(this, e, delegatedTarget);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$.unbind = (element, o) => {
|
||||||
|
if (element) {
|
||||||
|
for (let event in o) {
|
||||||
|
let callback = o[event];
|
||||||
|
|
||||||
|
event.split(/\s+/).forEach(function (event) {
|
||||||
|
element.removeEventListener(event, callback);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$.fire = (target, type, properties) => {
|
||||||
|
let evt = document.createEvent('HTMLEvents');
|
||||||
|
|
||||||
|
evt.initEvent(type, true, true);
|
||||||
|
|
||||||
|
for (let j in properties) {
|
||||||
|
evt[j] = properties[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
return target.dispatchEvent(evt);
|
||||||
|
};
|
||||||
|
|
||||||
|
$.data = (element) => {
|
||||||
|
return element.dataset;
|
||||||
|
};
|
||||||
|
|
||||||
|
$.style = (elements, styleMap) => { // eslint-disable-line
|
||||||
|
|
||||||
|
if (typeof styleMap === 'string') {
|
||||||
|
return $.getStyle(elements, styleMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(elements)) {
|
||||||
|
elements = [elements];
|
||||||
|
}
|
||||||
|
|
||||||
|
elements.map(element => {
|
||||||
|
for (const prop in styleMap) {
|
||||||
|
element.style[prop] = styleMap[prop];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$.removeStyle = (elements, styleProps) => {
|
||||||
|
if (!Array.isArray(elements)) {
|
||||||
|
elements = [elements];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(styleProps)) {
|
||||||
|
styleProps = [styleProps];
|
||||||
|
}
|
||||||
|
|
||||||
|
elements.map(element => {
|
||||||
|
for (const prop of styleProps) {
|
||||||
|
element.style[prop] = '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$.getStyle = (element, prop) => {
|
||||||
|
let val = getComputedStyle(element)[prop];
|
||||||
|
|
||||||
|
if (['width', 'height'].includes(prop)) {
|
||||||
|
val = parseFloat(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
};
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
import $ from './dom';
|
||||||
|
|
||||||
const KEYCODES = {
|
const KEYCODES = {
|
||||||
13: 'enter',
|
13: 'enter',
|
||||||
91: 'meta',
|
91: 'meta',
|
||||||
@ -16,7 +18,7 @@ const KEYCODES = {
|
|||||||
const handlers = {};
|
const handlers = {};
|
||||||
|
|
||||||
function bind() {
|
function bind() {
|
||||||
$(document).on('keydown', handler);
|
$.on(document, 'keydown', handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handler(e) {
|
function handler(e) {
|
||||||
@ -37,12 +39,9 @@ function handler(e) {
|
|||||||
const preventBubbling = handler();
|
const preventBubbling = handler();
|
||||||
|
|
||||||
if (preventBubbling === undefined || preventBubbling === true) {
|
if (preventBubbling === undefined || preventBubbling === true) {
|
||||||
if (!e.isDefaultPrevented()) {
|
e.preventDefault();
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
src/style.js
28
src/style.js
@ -22,32 +22,4 @@ export default class Style {
|
|||||||
|
|
||||||
this.styleSheet.insertRule(ruleString, this.styleSheet.cssRules.length);
|
this.styleSheet.insertRule(ruleString, this.styleSheet.cssRules.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
set(elements, styleMap) {
|
|
||||||
if (!Array.isArray(elements)) {
|
|
||||||
elements = [elements];
|
|
||||||
}
|
|
||||||
|
|
||||||
elements.map(element => {
|
|
||||||
for (const prop in styleMap) {
|
|
||||||
element.style[prop] = styleMap[prop];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
unset(elements, styleProps) {
|
|
||||||
if (!Array.isArray(elements)) {
|
|
||||||
elements = [elements];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Array.isArray(styleProps)) {
|
|
||||||
styleProps = [styleProps];
|
|
||||||
}
|
|
||||||
|
|
||||||
elements.map(element => {
|
|
||||||
for (const prop of styleProps) {
|
|
||||||
element.style[prop] = '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,6 +48,10 @@ button, input {
|
|||||||
max-height: 500px;
|
max-height: 500px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
border-bottom: 1px solid var(--border-color);
|
border-bottom: 1px solid var(--border-color);
|
||||||
|
|
||||||
|
&.row-highlight-all .data-table-row {
|
||||||
|
background-color: var(--light-bg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table-header {
|
.data-table-header {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user