Refactor CSS to use BEM style

This commit is contained in:
Faris Ansari 2018-04-21 19:07:11 +05:30
parent 1f6174b232
commit fde1b7bcc9
9 changed files with 306 additions and 375 deletions

View File

@ -23,7 +23,7 @@
<input type="checkbox" id="input-large-data" />
<span>Large Data</span>
</label>
<section style="font-size: 12px; width: 60%">
<section style="font-size: 12px; width: 60%; margin: 0 auto;">
</section>

View File

@ -88,13 +88,13 @@ const prodCSS = merge(devCSS, {
// docs
const docJS = merge(devIIFE, {
output: {
file: 'docs/assets/frappe-datatable.js'
file: 'docs/assets/js/frappe-datatable.js'
}
});
const docCSS = merge(devCSS, {
output: {
file: 'docs/assets/frappe-datatable.css'
file: 'docs/assets/css/frappe-datatable.css'
}
});

View File

@ -26,7 +26,7 @@ export default class BodyRenderer {
const rows = this.datamanager.getRowsForView();
this.bodyScrollable.innerHTML = `
<table class="data-table-body">
<table class="dt-body">
${this.getBodyHTML(rows)}
</table>
`;
@ -40,13 +40,13 @@ export default class BodyRenderer {
let initialData = this.getDataForClusterize(rows);
if (initialData.length === 0) {
initialData = [`<tr class="no-data"><td>${this.options.noDataMessage}</td></tr>`];
initialData = [`<div class="dt-scrollable__no-data">${this.options.noDataMessage}</div>`];
}
if (!this.clusterize) {
// empty body
this.bodyScrollable.innerHTML = `
<table class="data-table-body">
<table class="dt-body">
${this.getBodyHTML([])}
</table>
`;
@ -87,7 +87,7 @@ export default class BodyRenderer {
}
showToastMessage(message) {
this.instance.toastMessage.innerHTML = `<span>${message}</span>`;
this.instance.toastMessage.innerHTML = `<span class="dt-toast__message">${message}</span>`;
}
clearToastMessage() {

View File

@ -5,7 +5,6 @@ import {
linkProperties
} from './utils';
import $ from './dom';
import { getDropdownHTML } from './columnmanager';
export default class CellManager {
constructor(instance) {
@ -40,7 +39,7 @@ export default class CellManager {
bindEditCell() {
this.$editingCell = null;
$.on(this.bodyScrollable, 'dblclick', '.data-table-cell', (e, cell) => {
$.on(this.bodyScrollable, 'dblclick', '.dt-cell', (e, cell) => {
this.activateEditing(cell);
});
@ -115,7 +114,7 @@ export default class CellManager {
if (this.options.inlineFilters) {
this.keyboard.on('ctrl+f', (e) => {
const $cell = $.closest('.data-table-cell', e.target);
const $cell = $.closest('.dt-cell', e.target);
const { colIndex } = $.data($cell);
this.activateFilter(colIndex);
@ -155,7 +154,7 @@ export default class CellManager {
bindMouseEvents() {
let mouseDown = null;
$.on(this.bodyScrollable, 'mousedown', '.data-table-cell', (e) => {
$.on(this.bodyScrollable, 'mousedown', '.dt-cell', (e) => {
mouseDown = true;
this.focusCell($(e.delegatedTarget));
});
@ -169,15 +168,15 @@ export default class CellManager {
this.selectArea($(e.delegatedTarget));
};
$.on(this.bodyScrollable, 'mousemove', '.data-table-cell', throttle(selectArea, 50));
$.on(this.bodyScrollable, 'mousemove', '.dt-cell', throttle(selectArea, 50));
}
bindTreeEvents() {
$.on(this.bodyScrollable, 'click', '.toggle', (e, $toggle) => {
const $cell = $.closest('.data-table-cell', $toggle);
$.on(this.bodyScrollable, 'click', '.dt-tree-node__toggle', (e, $toggle) => {
const $cell = $.closest('.dt-cell', $toggle);
const { rowIndex } = $.data($cell);
if ($cell.classList.contains('tree-close')) {
if ($cell.classList.contains('dt-cell--tree-close')) {
this.rowmanager.openSingleNode(rowIndex);
} else {
this.rowmanager.closeSingleNode(rowIndex);
@ -214,11 +213,11 @@ export default class CellManager {
}
if (this.$focusedCell) {
this.$focusedCell.classList.remove('selected');
this.$focusedCell.classList.remove('dt-cell--focus');
}
this.$focusedCell = $cell;
$cell.classList.add('selected');
$cell.classList.add('dt-cell--focus');
// so that keyboard nav works
$cell.focus();
@ -232,8 +231,8 @@ export default class CellManager {
rowIndex
} = $.data($cell);
const _colIndex = this.datamanager.getColumnIndexById('_rowIndex');
const colHeaderSelector = `.data-table-header .data-table-cell[data-col-index="${colIndex}"]`;
const rowHeaderSelector = `.data-table-cell[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
const colHeaderSelector = `.dt-header .dt-cell[data-col-index="${colIndex}"]`;
const rowHeaderSelector = `.dt-cell[data-row-index="${rowIndex}"][data-col-index="${_colIndex}"]`;
if (this.lastHeaders) {
$.removeStyle(this.lastHeaders, 'backgroundColor');
@ -300,7 +299,7 @@ export default class CellManager {
if (!cells) return false;
this.clearSelection();
cells.map(index => this.getCell$(...index)).map($cell => $cell.classList.add('highlight'));
cells.map(index => this.getCell$(...index)).map($cell => $cell.classList.add('dt-cell--highlight'));
return true;
}
@ -358,8 +357,8 @@ export default class CellManager {
}
clearSelection() {
$.each('.data-table-cell.highlight', this.bodyScrollable)
.map(cell => cell.classList.remove('highlight'));
$.each('.dt-cell--highlight', this.bodyScrollable)
.map(cell => cell.classList.remove('dt-cell--highlight'));
this.$selectionCursor = null;
}
@ -398,9 +397,9 @@ export default class CellManager {
}
this.$editingCell = $cell;
$cell.classList.add('editing');
$cell.classList.add('dt-cell--editing');
const $editCell = $('.edit-cell', $cell);
const $editCell = $('.dt-cell__edit', $cell);
$editCell.innerHTML = '';
const editor = this.getEditor(colIndex, rowIndex, cell.content, $editCell);
@ -417,7 +416,7 @@ export default class CellManager {
if (this.$focusedCell) this.$focusedCell.focus();
if (!this.$editingCell) return;
this.$editingCell.classList.remove('editing');
this.$editingCell.classList.remove('dt-cell--editing');
this.$editingCell = null;
}
@ -443,7 +442,7 @@ export default class CellManager {
getDefaultEditor(parent) {
const $input = $.create('input', {
class: 'input-style',
class: 'dt-input',
type: 'text',
inside: parent
});
@ -557,7 +556,7 @@ export default class CellManager {
const colIndex = this.columnmanager.getFirstColumnIndex();
const $cell = this.getCell$(colIndex, rowIndex);
if ($cell) {
$cell.classList[flag ? 'remove' : 'add']('tree-close');
$cell.classList[flag ? 'remove' : 'add']('dt-cell--tree-close');
}
}
@ -576,7 +575,7 @@ export default class CellManager {
} = $.data($cell);
let $aboveRow = $cell.parentElement.previousElementSibling;
while ($aboveRow && $aboveRow.classList.contains('hide')) {
while ($aboveRow && $aboveRow.classList.contains('dt-row--hide')) {
$aboveRow = $aboveRow.previousElementSibling;
}
@ -590,7 +589,7 @@ export default class CellManager {
} = $.data($cell);
let $belowRow = $cell.parentElement.nextElementSibling;
while ($belowRow && $belowRow.classList.contains('hide')) {
while ($belowRow && $belowRow.classList.contains('dt-row--hide')) {
$belowRow = $belowRow.nextElementSibling;
}
@ -631,7 +630,7 @@ export default class CellManager {
}
getRowHeight() {
return $.style($('.data-table-row', this.bodyScrollable), 'height');
return $.style($('.dt-row', this.bodyScrollable), 'height');
}
scrollToCell($cell) {
@ -662,8 +661,13 @@ export default class CellManager {
isFilter
});
const className = [
'dt-cell',
isHeader ? 'dt-cell--header' : ''
].join(' ');
return `
<td class="data-table-cell noselect" ${dataAttr} tabindex="0">
<td class="${className}" ${dataAttr} tabindex="0">
${this.getCellContent(cell)}
</td>
`;
@ -682,10 +686,10 @@ export default class CellManager {
const sortIndicator = sortable ? '<span class="sort-indicator"></span>' : '';
const resizable = isHeader && cell.resizable !== false;
const resizeColumn = resizable ? '<span class="column-resizer"></span>' : '';
const resizeColumn = resizable ? '<span class="dt-cell__resize-handle"></span>' : '';
const hasDropdown = isHeader && cell.dropdown !== false;
const dropdown = hasDropdown ? `<div class="data-table-dropdown">${getDropdownHTML()}</div>` : '';
const dropdown = hasDropdown ? this.columnmanager.getDropdownHTML() : '';
const customFormatter = cell.format || (cell.column && cell.column.format) || null;
@ -706,14 +710,15 @@ export default class CellManager {
const firstColumnIndex = this.datamanager.getColumnIndexById('_rowIndex') + 1;
if (firstColumnIndex === cell.colIndex) {
const padding = ((cell.indent || 0) + 1) * 1.5;
const toggleHTML = addToggle ? `<span class="toggle" style="left: ${padding - 1.5}rem"></span>` : '';
contentHTML = `<span class="tree-node" style="padding-left: ${padding}rem">
const toggleHTML = addToggle ?
`<span class="dt-tree-node__toggle" style="left: ${padding - 1.5}rem"></span>` : '';
contentHTML = `<span class="dt-tree-node" style="padding-left: ${padding}rem">
${toggleHTML}${contentHTML}</span>`;
}
}
return `
<div class="content ellipsis">
<div class="dt-cell__content">
${contentHTML}
${sortIndicator}
${resizeColumn}
@ -724,12 +729,10 @@ export default class CellManager {
}
getEditCellHTML() {
return `
<div class="edit-cell"></div>
`;
return '<div class="dt-cell__edit"></div>';
}
selector(colIndex, rowIndex) {
return `.data-table-cell[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`;
return `.dt-cell[data-col-index="${colIndex}"][data-row-index="${rowIndex}"]`;
}
}

View File

@ -21,7 +21,6 @@ export default class ColumnManager {
]);
this.bindEvents();
getDropdownHTML = getDropdownHTML.bind(this, this.options.dropdownButton);
}
renderHeader() {
@ -31,11 +30,11 @@ export default class ColumnManager {
refreshHeader() {
const columns = this.datamanager.getColumns();
const $cols = $.each('.data-table-cell[data-is-header]', this.header);
const $cols = $.each('.dt-cell[data-is-header]', this.header);
const refreshHTML =
// first init
!$('.data-table-cell', this.header) ||
!$('.dt-cell', this.header) ||
// deleted column
columns.length < $cols.length;
@ -43,7 +42,7 @@ export default class ColumnManager {
// refresh html
$('thead', this.header).innerHTML = this.getHeaderHTML(columns);
this.$filterRow = $('.data-table-row[data-is-filter]', this.header);
this.$filterRow = $('.dt-row[data-is-filter]', this.header);
if (this.$filterRow) {
$.style(this.$filterRow, { display: 'none' });
}
@ -89,12 +88,15 @@ export default class ColumnManager {
bindDropdown() {
let $activeDropdown;
$.on(this.header, 'click', '.data-table-dropdown-toggle', (e, $button) => {
const $dropdown = $.closest('.data-table-dropdown', $button);
let activeClass = 'dt-dropdown--active';
let toggleClass = '.dt-dropdown__toggle';
if (!$dropdown.classList.contains('is-active')) {
$.on(this.header, 'click', toggleClass, (e, $button) => {
const $dropdown = $.closest('.dt-dropdown', $button);
if (!$dropdown.classList.contains(activeClass)) {
deactivateDropdown();
$dropdown.classList.add('is-active');
$dropdown.classList.add(activeClass);
$activeDropdown = $dropdown;
} else {
deactivateDropdown();
@ -102,14 +104,14 @@ export default class ColumnManager {
});
$.on(document.body, 'click', (e) => {
if (e.target.matches('.data-table-dropdown-toggle')) return;
if (e.target.matches(toggleClass)) return;
deactivateDropdown();
});
const dropdownItems = this.options.headerDropdown;
$.on(this.header, 'click', '.data-table-dropdown-list > div', (e, $item) => {
const $col = $.closest('.data-table-cell', $item);
$.on(this.header, 'click', '.dt-dropdown__list-item', (e, $item) => {
const $col = $.closest('.dt-cell', $item);
const {
index
} = $.data($item);
@ -122,7 +124,7 @@ export default class ColumnManager {
});
function deactivateDropdown(e) {
$activeDropdown && $activeDropdown.classList.remove('is-active');
$activeDropdown && $activeDropdown.classList.remove(activeClass);
$activeDropdown = null;
}
}
@ -131,8 +133,8 @@ export default class ColumnManager {
let isDragging = false;
let $resizingCell, startWidth, startX;
$.on(this.header, 'mousedown', '.data-table-cell .column-resizer', (e, $handle) => {
document.body.classList.add('data-table-resize');
$.on(this.header, 'mousedown', '.dt-cell .dt-cell__resize-handle', (e, $handle) => {
document.body.classList.add('dt-resize');
const $cell = $handle.parentNode.parentNode;
$resizingCell = $cell;
const {
@ -145,12 +147,12 @@ export default class ColumnManager {
}
isDragging = true;
startWidth = $.style($('.content', $resizingCell), 'width');
startWidth = $.style($('.dt-cell__content', $resizingCell), 'width');
startX = e.pageX;
});
$.on(document.body, 'mouseup', (e) => {
document.body.classList.remove('data-table-resize');
document.body.classList.remove('dt-resize');
if (!$resizingCell) return;
isDragging = false;
@ -188,10 +190,10 @@ export default class ColumnManager {
$.off(document.body, 'mousemove', initialize);
return;
}
const ready = $('.data-table-cell', this.header);
const ready = $('.dt-cell', this.header);
if (!ready) return;
const $parent = $('.data-table-row', this.header);
const $parent = $('.dt-row', this.header);
this.sortable = Sortable.create($parent, {
onEnd: (e) => {
@ -208,7 +210,8 @@ export default class ColumnManager {
this.switchColumn(oldIndex, newIndex);
},
preventOnFilter: false,
filter: '.column-resizer, .data-table-dropdown',
filter: '.dt-cell__resize-handle, .dt-dropdown',
chosenClass: 'dt-cell--dragging',
animation: 150
});
};
@ -216,49 +219,6 @@ export default class ColumnManager {
$.on(document.body, 'mousemove', initialize);
}
bindSortColumn() {
$.on(this.header, 'click', '.data-table-cell .column-title', (e, span) => {
const $cell = span.closest('.data-table-cell');
let {
colIndex,
sortOrder = 'none'
} = $.data($cell);
const col = this.getColumn(colIndex);
if (col && col.sortable === false) {
return;
}
// reset sort indicator
$('.sort-indicator', this.header).textContent = '';
$.each('.data-table-cell', this.header).map($cell => {
$.data($cell, {
sortOrder: 'none'
});
});
let nextSortOrder, textContent;
if (sortOrder === 'none') {
nextSortOrder = 'asc';
textContent = '▲';
} else if (sortOrder === 'asc') {
nextSortOrder = 'desc';
textContent = '▼';
} else if (sortOrder === 'desc') {
nextSortOrder = 'none';
textContent = '';
}
$.data($cell, {
sortOrder: nextSortOrder
});
$('.sort-indicator', $cell).textContent = textContent;
this.sortColumn(colIndex, nextSortOrder);
});
}
sortColumn(colIndex, nextSortOrder) {
this.instance.freeze();
this.sortRows(colIndex, nextSortOrder)
@ -326,14 +286,14 @@ export default class ColumnManager {
focusFilter(colIndex) {
if (!this.isFilterShown) return;
const $filterInput = $(`[data-col-index="${colIndex}"] .data-table-filter`, this.$filterRow);
const $filterInput = $(`[data-col-index="${colIndex}"] .dt-filter`, this.$filterRow);
$filterInput.focus();
}
bindFilter() {
if (!this.options.inlineFilters) return;
const handler = e => {
const $filterCell = $.closest('.data-table-cell', e.target);
const $filterCell = $.closest('.dt-cell', e.target);
const {
colIndex
} = $.data($filterCell);
@ -348,7 +308,7 @@ export default class ColumnManager {
this.rowmanager.showRows(rowsToShow);
});
};
$.on(this.header, 'keydown', '.data-table-filter', debounce(handler, 300));
$.on(this.header, 'keydown', '.dt-filter', debounce(handler, 300));
}
sortRows(colIndex, sortOrder) {
@ -370,7 +330,11 @@ export default class ColumnManager {
let columnWidth = width || this.getColumn(colIndex).width;
let index = this._columnWidthMap[colIndex];
const selector = `[data-col-index="${colIndex}"] .content, [data-col-index="${colIndex}"] .edit-cell`;
const selector = [
`[data-col-index="${colIndex}"] .dt-cell__content`,
`[data-col-index="${colIndex}"] .dt-cell__edit`
].join(', ');
const styles = {
width: columnWidth + 'px'
};
@ -385,7 +349,7 @@ export default class ColumnManager {
setColumnHeaderWidth(colIndex) {
colIndex = +colIndex;
this.$columnMap = this.$columnMap || [];
const selector = `.data-table-header [data-col-index="${colIndex}"] .content`;
const selector = `.dt-header [data-col-index="${colIndex}"] .dt-cell__content`;
const {
width
} = this.getColumn(colIndex);
@ -409,7 +373,7 @@ export default class ColumnManager {
}
getHeaderCell$(colIndex) {
return $(`.data-table-cell[data-col-index="${colIndex}"]`, this.header);
return $(`.dt-cell[data-col-index="${colIndex}"]`, this.header);
}
getLastColumnIndex() {
@ -421,20 +385,19 @@ export default class ColumnManager {
return columns.findIndex(column => column.content.includes('Sr. No'));
}
getDropdownHTML() {
const { dropdownButton, headerDropdown: dropdownItems } = this.options;
return `
<div class="dt-dropdown">
<div class="dt-dropdown__toggle">${dropdownButton}</div>
<div class="dt-dropdown__list">
${dropdownItems.map((d, i) => `
<div class="dt-dropdown__list-item" data-index="${i}">${d.label}</div>
`).join('')}
</div>
</div>
`;
};
}
// eslint-disable-next-line
var getDropdownHTML = function getDropdownHTML(dropdownButton = 'v') {
// add dropdown buttons
const dropdownItems = this.options.headerDropdown;
return `<div class="data-table-dropdown-toggle">${dropdownButton}</div>
<div class="data-table-dropdown-list">
${dropdownItems.map((d, i) => `<div data-index="${i}">${d.label}</div>`).join('')}
</div>
`;
};
export {
getDropdownHTML
};

View File

@ -64,25 +64,25 @@ class DataTable {
prepareDom() {
this.wrapper.innerHTML = `
<div class="data-table">
<table class="data-table-header">
<div class="datatable">
<table class="dt-header">
</table>
<div class="body-scrollable">
<div class="dt-scrollable">
</div>
<div class="freeze-container">
<span>${this.options.freezeMessage}</span>
<div class="dt-freeze">
<span class="dt-freeze__message">
${this.options.freezeMessage}
</span>
</div>
<div class="data-table-footer">
</div>
<div class="toast-message"></div>
<div class="dt-toast"></div>
</div>
`;
this.datatableWrapper = $('.data-table', this.wrapper);
this.header = $('.data-table-header', this.wrapper);
this.bodyScrollable = $('.body-scrollable', this.wrapper);
this.freezeContainer = $('.freeze-container', this.wrapper);
this.toastMessage = $('.toast-message', this.wrapper);
this.datatableWrapper = $('.datatable', this.wrapper);
this.header = $('.dt-header', this.wrapper);
this.bodyScrollable = $('.dt-scrollable', this.wrapper);
this.freezeContainer = $('.dt-freeze', this.wrapper);
this.toastMessage = $('.dt-toast', this.wrapper);
}
refresh(data, columns) {

View File

@ -39,8 +39,8 @@ export default class RowManager {
// map of checked rows
this.checkMap = [];
$.on(this.wrapper, 'click', '.data-table-cell[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
const $cell = $checkbox.closest('.data-table-cell');
$.on(this.wrapper, 'click', '.dt-cell[data-col-index="0"] [type="checkbox"]', (e, $checkbox) => {
const $cell = $checkbox.closest('.dt-cell');
const {
rowIndex,
isHeader
@ -92,7 +92,7 @@ export default class RowManager {
checkRow(rowIndex, toggle) {
const value = toggle ? 1 : 0;
const selector = rowIndex =>
`.data-table-cell[data-row-index="${rowIndex}"][data-col-index="0"] [type="checkbox"]`;
`.dt-cell[data-row-index="${rowIndex}"][data-col-index="0"] [type="checkbox"]`;
// update internal map
this.checkMap[rowIndex] = value;
// set checkbox value explicitly
@ -116,7 +116,7 @@ export default class RowManager {
this.checkMap = [];
}
// set checkbox value
$.each('.data-table-cell[data-col-index="0"] [type="checkbox"]', this.bodyScrollable)
$.each('.dt-cell[data-col-index="0"] [type="checkbox"]', this.bodyScrollable)
.map(input => {
input.checked = toggle;
});
@ -140,34 +140,34 @@ export default class RowManager {
const $row = this.getRow$(rowIndex);
if (!$row) return;
if (!toggle && this.bodyScrollable.classList.contains('row-highlight-all')) {
$row.classList.add('row-unhighlight');
if (!toggle && this.bodyScrollable.classList.contains('dt-scrollable--highlight-all')) {
$row.classList.add('dt-row--unhighlight');
return;
}
if (toggle && $row.classList.contains('row-unhighlight')) {
$row.classList.remove('row-unhighlight');
if (toggle && $row.classList.contains('dt-row--unhighlight')) {
$row.classList.remove('dt-row--unhighlight');
}
this._highlightedRows = this._highlightedRows || {};
if (toggle) {
$row.classList.add('row-highlight');
$row.classList.add('dt-row--highlight');
this._highlightedRows[rowIndex] = $row;
} else {
$row.classList.remove('row-highlight');
$row.classList.remove('dt-row--highlight');
delete this._highlightedRows[rowIndex];
}
}
highlightAll(toggle = true) {
if (toggle) {
this.bodyScrollable.classList.add('row-highlight-all');
this.bodyScrollable.classList.add('dt-scrollable--highlight-all');
} else {
this.bodyScrollable.classList.remove('row-highlight-all');
this.bodyScrollable.classList.remove('dt-scrollable--highlight-all');
for (const rowIndex in this._highlightedRows) {
const $row = this._highlightedRows[rowIndex];
$row.classList.remove('row-highlight');
$row.classList.remove('dt-row--highlight');
}
this._highlightedRows = {};
}
@ -177,7 +177,7 @@ export default class RowManager {
rowIndices = ensureArray(rowIndices);
rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex);
$tr.classList.add('hide');
$tr.classList.add('dt-row--hide');
});
}
@ -185,7 +185,7 @@ export default class RowManager {
rowIndices = ensureArray(rowIndices);
rowIndices.map(rowIndex => {
const $tr = this.getRow$(rowIndex);
$tr.classList.remove('hide');
$tr.classList.remove('dt-row--hide');
});
}
@ -268,7 +268,7 @@ export default class RowManager {
}
return `
<tr class="data-table-row" ${dataAttr}>
<tr class="dt-row" ${dataAttr}>
${row.map(cell => this.cellmanager.getCellHTML(cell)).join('')}
</tr>
`;
@ -276,10 +276,10 @@ export default class RowManager {
getFilterInput(props) {
const dataAttr = makeDataAttributeString(props);
return `<input class="data-table-filter input-style" type="text" ${dataAttr} />`;
return `<input class="dt-filter dt-input" type="text" ${dataAttr} />`;
}
selector(rowIndex) {
return `.data-table-row[data-row-index="${rowIndex}"]`;
return `.dt-row[data-row-index="${rowIndex}"]`;
}
}

View File

@ -1,11 +1,9 @@
/* This file is processed by postcss */
/* variables */
:root {
--border-color: #d1d8dd;
--primary-color: rgb(82, 146, 247);
--light-bg: #f5f7fa;
--light-red: #FD8B8B;
--light-yellow: #fffce7;
--orange: rgb(255, 160, 10);
--text-color: #000000;
--text-light: #dfe2e5;
@ -15,275 +13,242 @@
--spacer-3: 1rem;
--border-radius: 3px;
--cell-bg: #fff;
}
.data-table {
/* resets */
*, *::after, *::before {
.datatable {
*, *::after, *::before {
box-sizing: border-box;
}
}
button, input {
overflow: visible;
font-family: inherit;
font-size: inherit;
line-height: inherit;
margin: 0;
padding: 0;
}
.input-style {
outline: none;
width: 100%;
border: none;
}
*, *:focus {
outline: none;
border-radius: 0px;
box-shadow: none;
}
/* styling */
.datatable {
position: relative;
overflow: auto;
table {
border-collapse: collapse;
}
table td {
padding: 0;
border: 1px solid var(--border-color);
}
thead td {
border-bottom-width: 1px;
}
.freeze-container {
display: flex;
justify-content: center;
align-content: center;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: var(--light-bg);
opacity: 0.5;
font-size: 2em;
span {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
}
.hide {
display: none;
}
.toast-message {
position: absolute;
bottom: var(--spacer-3);
left: 50%;
transform: translateX(-50%);
span {
display: inline-block;
background-color: rgba(0, 0, 0, 0.8);
color: var(--text-light);
border-radius: var(--border-radius);
padding: var(--spacer-2) var(--spacer-3);
}
}
}
.body-scrollable {
max-height: 500px;
overflow: auto;
.dt-header {
border-collapse: collapse;
border-bottom: 1px solid var(--border-color);
&.row-highlight-all .data-table-row:not(.row-unhighlight) {
background-color: var(--light-bg);
}
.no-data td {
text-align: center;
padding: var(--spacer-2);
}
}
.data-table-header {
position: absolute;
top: 0;
left: 0;
background-color: white;
font-weight: bold;
background-color: var(--cell-bg);
}
.content span:not(.column-resizer) {
cursor: pointer;
.dt-body {
border-collapse: collapse;
}
.dt-scrollable {
max-height: 40vw;
overflow: auto;
border-bottom: 1px solid var(--border-color);
&--highlight-all {
background-color: var(--light-yellow);
}
.column-resizer {
&__no-data {
text-align: center;
padding: var(--spacer-3);
border-left: 1px solid var(--border-color);
border-right: 1px solid var(--border-color);
}
}
.dt-row {
&--highlight {
background-color: var(--light-yellow);
}
&--unhighlight {
background-color: var(--cell-bg);
}
&--hide {
display: none;
position: absolute;
right: 0;
top: 0;
width: var(--spacer-1);
}
}
.dt-cell {
border: 1px solid var(--border-color);
position: relative;
outline: none;
padding: 0;
&__content {
padding: var(--spacer-2);
border: 2px solid transparent;
height: 100%;
background-color: var(--primary-color);
cursor: col-resize;
user-select: none;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
.data-table-dropdown {
&__edit {
display: none;
padding: var(--spacer-2);
background-color: var(--cell-bg);
border: 2px solid var(--orange);
z-index: 1;
height: 100%;
}
&__resize-handle {
opacity: 0;
position: absolute;
right: 10px;
display: inline-flex;
vertical-align: top;
text-align: left;
right: -3px;
top: 0;
width: 5px;
height: 100%;
cursor: col-resize;
z-index: 1;
}
&.is-active {
.data-table-dropdown-list {
display: block;
}
&--editing &__content {
display: none;
}
.data-table-dropdown-toggle {
display: block;
}
&--editing &__edit {
display: block;
}
&--focus &__content {
border-color: var(--primary-color);
}
&--highlight {
background-color: var(--light-bg);
}
&--dragging {
background-color: var(--light-bg);
}
&--header &__content {
padding-right: var(--spacer-3);
font-weight: bold;
}
&--header:hover .dt-dropdown__toggle {
opacity: 1;
}
&--tree-close {
.dt-tree-node__toggle:before {
content: '►';
}
}
}
.data-table-dropdown-toggle {
display: none;
background-color: transparent;
border: none;
.dt-dropdown {
position: absolute;
right: 10px;
display: inline-flex;
vertical-align: top;
text-align: left;
font-weight: normal;
cursor: pointer;
&__toggle {
opacity: 0;
}
.data-table-dropdown-list {
&__list {
display: none;
font-weight: normal;
position: absolute;
min-width: 8rem;
top: 100%;
right: 0;
z-index: 1;
background-color: white;
background-color: var(--cell-bg);
border-radius: var(--border-radius);
padding: var(--spacer-2) 0;
box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1);
padding-bottom: var(--spacer-2);
padding-top: var(--spacer-2);
}
&> div {
padding: var(--spacer-2) var(--spacer-3);
&__list-item {
padding: var(--spacer-2) var(--spacer-3);
&:hover {
background-color: var(--light-bg);
}
&:hover {
background-color: var(--light-bg);
}
}
.data-table-cell.remove-column {
background-color: var(--light-red);
transition: 300ms background-color ease-in-out;
}
.data-table-cell.sortable-chosen {
background-color: var(--light-bg);
&--active &__list {
display: block;
}
}
.data-table-cell {
.dt-tree-node {
display: inline-block;
position: relative;
.content {
padding: var(--spacer-2);
border: 2px solid transparent;
height: 100%;
&.ellipsis {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
}
.edit-cell {
display: none;
padding: var(--spacer-2);
background-color: #fff;
z-index: 1;
height: 100%;
}
&.selected .content {
border: 2px solid var(--primary-color);
}
&.editing {
.content {
display: none;
}
.edit-cell {
border: 2px solid var(--orange);
display: block;
}
}
&.highlight {
background-color: var(--light-bg);
}
&:hover .column-resizer {
display: inline-block;
}
&:hover .data-table-dropdown-toggle {
display: block;
}
.tree-node {
display: inline-block;
position: relative;
}
.toggle {
&__toggle {
display: inline-block;
position: absolute;
font-size: 10px;
padding: 0 4px;
cursor: pointer;
}
.toggle:before {
&__toggle:before {
content: '▼';
}
}
.data-table-cell.tree-close {
.toggle:before {
content: '►';
.dt-toast {
position: absolute;
bottom: var(--spacer-3);
left: 50%;
transform: translateX(-50%);
&__message {
display: inline-block;
background-color: rgba(0, 0, 0, 0.8);
color: var(--text-light);
border-radius: var(--border-radius);
padding: var(--spacer-2) var(--spacer-3);
}
}
.data-table-row {
&.row-highlight {
background-color: var(--light-bg);
}
.dt-input {
outline: none;
width: 100%;
border: none;
overflow: visible;
font-family: inherit;
font-size: inherit;
line-height: inherit;
margin: 0;
padding: 0;
}
.noselect {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
.dt-freeze {
display: flex;
justify-content: center;
align-content: center;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
background-color: var(--light-bg);
opacity: 0.5;
font-size: 2em;
&__message {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
}
body.data-table-resize {
body.dt-resize {
cursor: col-resize;
}

View File

@ -15,7 +15,7 @@ export default class Style {
'getColumn'
]);
this.scopeClass = 'datatable-instance-' + instance.constructor.instances;
this.scopeClass = 'dt-instance-' + instance.constructor.instances;
instance.datatableWrapper.classList.add(this.scopeClass);
const styleEl = document.createElement('style');
@ -103,7 +103,7 @@ export default class Style {
const nonResizableColumnsSelector = this.datamanager.getColumns()
.filter(col => col.resizable === false)
.map(col => col.colIndex)
.map(i => `.data-table-header [data-col-index="${i}"]`)
.map(i => `.dt-header [data-col-index="${i}"]`)
.join();
this.setStyle(nonResizableColumnsSelector, {
@ -112,8 +112,8 @@ export default class Style {
}
setupMinWidth() {
$.each('.data-table-cell[data-is-header]', this.header).map(col => {
const width = $.style($('.content', col), 'width');
$.each('.dt-cell[data-is-header]', this.header).map(col => {
const width = $.style($('.dt-cell__content', col), 'width');
const {
colIndex
} = $.data(col);
@ -127,16 +127,16 @@ export default class Style {
}
setupNaturalColumnWidth() {
if (!$('.data-table-row')) return;
if (!$('.dt-row')) return;
// set initial width as naturally calculated by table's first row
$.each('.data-table-row[data-row-index="0"] .data-table-cell', this.bodyScrollable).map($cell => {
$.each('.dt-row[data-row-index="0"] .dt-cell', this.bodyScrollable).map($cell => {
const {
colIndex
} = $.data($cell);
const column = this.datamanager.getColumn(colIndex);
let naturalWidth = $.style($('.content', $cell), 'width');
let naturalWidth = $.style($('.dt-cell__content', $cell), 'width');
if (column.id === '_rowIndex') {
naturalWidth = this.getRowIndexColumnWidth(naturalWidth);
@ -222,7 +222,7 @@ export default class Style {
setDefaultCellHeight() {
if (this.options.dynamicRowHeight) return;
if (this.__cellHeightSet) return;
const $firstCell = $('.data-table-cell[data-is-header]', this.instance.header);
const $firstCell = $('.dt-cell[data-is-header]', this.instance.header);
if (!$firstCell) return;
const height = this.options.cellHeight || $.style($firstCell, 'height');
@ -233,10 +233,10 @@ export default class Style {
}
setCellHeight(height) {
this.setStyle('.data-table-cell .content', {
this.setStyle('.dt-cell .dt-cell__content', {
height: height + 'px'
});
this.setStyle('.data-table-cell .edit-cell', {
this.setStyle('.dt-cell .dt-cell__edit', {
height: height + 'px'
});
}
@ -273,7 +273,7 @@ export default class Style {
width: width + 'px'
});
const $body = $('.data-table-body', this.bodyScrollable);
const $body = $('.dt-body', this.bodyScrollable);
if ($body) {
$.style($body, {
@ -294,7 +294,7 @@ export default class Style {
getColumnHeaderElement(colIndex) {
colIndex = +colIndex;
if (colIndex < 0) return null;
return $(`.data-table-cell[data-col-index="${colIndex}"]`, this.header);
return $(`.dt-cell[data-col-index="${colIndex}"]`, this.header);
}
getRowIndexColumnWidth(baseWidth) {