Removed jQuery 💃

This commit is contained in:
Faris Ansari 2017-11-05 21:31:20 +05:30
parent 1d7278d3d6
commit 785cf8f466
11 changed files with 644 additions and 426 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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] = '';
}
});
}
} }

View File

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