diff --git a/index.html b/index.html index ac55f93..36cee9e 100644 --- a/index.html +++ b/index.html @@ -23,7 +23,7 @@ Large Data -
+
diff --git a/rollup.config.js b/rollup.config.js index 266f395..2e9a558 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -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' } }); diff --git a/src/body-renderer.js b/src/body-renderer.js index db1e6be..0017133 100644 --- a/src/body-renderer.js +++ b/src/body-renderer.js @@ -26,7 +26,7 @@ export default class BodyRenderer { const rows = this.datamanager.getRowsForView(); this.bodyScrollable.innerHTML = ` - +
${this.getBodyHTML(rows)}
`; @@ -40,13 +40,13 @@ export default class BodyRenderer { let initialData = this.getDataForClusterize(rows); if (initialData.length === 0) { - initialData = [`${this.options.noDataMessage}`]; + initialData = [`
${this.options.noDataMessage}
`]; } if (!this.clusterize) { // empty body this.bodyScrollable.innerHTML = ` - +
${this.getBodyHTML([])}
`; @@ -87,7 +87,7 @@ export default class BodyRenderer { } showToastMessage(message) { - this.instance.toastMessage.innerHTML = `${message}`; + this.instance.toastMessage.innerHTML = `${message}`; } clearToastMessage() { diff --git a/src/cellmanager.js b/src/cellmanager.js index 3d9bfae..e0b9872 100644 --- a/src/cellmanager.js +++ b/src/cellmanager.js @@ -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 ` - + ${this.getCellContent(cell)} `; @@ -682,10 +686,10 @@ export default class CellManager { const sortIndicator = sortable ? '' : ''; const resizable = isHeader && cell.resizable !== false; - const resizeColumn = resizable ? '' : ''; + const resizeColumn = resizable ? '' : ''; const hasDropdown = isHeader && cell.dropdown !== false; - const dropdown = hasDropdown ? `
${getDropdownHTML()}
` : ''; + 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 ? `` : ''; - contentHTML = ` + const toggleHTML = addToggle ? + `` : ''; + contentHTML = ` ${toggleHTML}${contentHTML}`; } } return ` -
+
${contentHTML} ${sortIndicator} ${resizeColumn} @@ -724,12 +729,10 @@ export default class CellManager { } getEditCellHTML() { - return ` -
- `; + return '
'; } 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}"]`; } } diff --git a/src/columnmanager.js b/src/columnmanager.js index 030b337..168fa8c 100644 --- a/src/columnmanager.js +++ b/src/columnmanager.js @@ -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 ` +
+
${dropdownButton}
+
+ ${dropdownItems.map((d, i) => ` +
${d.label}
+ `).join('')} +
+
+ `; + }; } - -// eslint-disable-next-line -var getDropdownHTML = function getDropdownHTML(dropdownButton = 'v') { - // add dropdown buttons - const dropdownItems = this.options.headerDropdown; - - return `
${dropdownButton}
-
- ${dropdownItems.map((d, i) => `
${d.label}
`).join('')} -
- `; -}; - -export { - getDropdownHTML -}; diff --git a/src/datatable.js b/src/datatable.js index 7b6649f..b685bf0 100644 --- a/src/datatable.js +++ b/src/datatable.js @@ -64,25 +64,25 @@ class DataTable { prepareDom() { this.wrapper.innerHTML = ` -
- +
+
-
+
-
- ${this.options.freezeMessage} +
+ + ${this.options.freezeMessage} +
- -
+
`; - 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) { diff --git a/src/rowmanager.js b/src/rowmanager.js index 7381b7d..99de615 100644 --- a/src/rowmanager.js +++ b/src/rowmanager.js @@ -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 ` - + ${row.map(cell => this.cellmanager.getCellHTML(cell)).join('')} `; @@ -276,10 +276,10 @@ export default class RowManager { getFilterInput(props) { const dataAttr = makeDataAttributeString(props); - return ``; + return ``; } selector(rowIndex) { - return `.data-table-row[data-row-index="${rowIndex}"]`; + return `.dt-row[data-row-index="${rowIndex}"]`; } } diff --git a/src/style.css b/src/style.css index be01171..06ad597 100644 --- a/src/style.css +++ b/src/style.css @@ -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; } diff --git a/src/style.js b/src/style.js index 35767e1..12c7f0a 100644 --- a/src/style.js +++ b/src/style.js @@ -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) {