diff --git a/dist/frappe-datatable.cjs.js b/dist/frappe-datatable.cjs.js index 17d8551..2cec045 100644 --- a/dist/frappe-datatable.cjs.js +++ b/dist/frappe-datatable.cjs.js @@ -315,6 +315,20 @@ function promisify(fn, context = null) { }; } + + +function linkProperties(target, source, properties) { + const props = properties.reduce((acc, prop) => { + acc[prop] = { + get() { + return source[prop]; + } + }; + return acc; + }, {}); + Object.defineProperties(target, props); +} + class DataManager { constructor(options) { this.options = options; @@ -406,6 +420,7 @@ class DataManager { resizable: true, focusable: true, dropdown: true, + width: null, format: (value) => { if (value === null || value === undefined) { return ''; @@ -429,8 +444,7 @@ class DataManager { align: 'left', sortOrder: 'none', colIndex: i, - column: this.columns[i], - width: 0 + column: this.columns[i] }; if (content !== null && typeof content === 'object') { @@ -475,6 +489,10 @@ class DataManager { } row = row.concat(d); + while (row.length < this.columns.length) { + row.push(''); + } + } else { // row is a dict for (let col of this.columns) { @@ -795,14 +813,17 @@ class DataError extends TypeError {} class ColumnManager { constructor(instance) { this.instance = instance; - this.options = this.instance.options; - this.fireEvent = this.instance.fireEvent; - this.header = this.instance.header; - this.datamanager = this.instance.datamanager; - this.style = this.instance.style; - this.wrapper = this.instance.wrapper; - this.rowmanager = this.instance.rowmanager; - this.bodyScrollable = this.instance.bodyScrollable; + + linkProperties(this, this.instance, [ + 'options', + 'fireEvent', + 'header', + 'datamanager', + 'style', + 'wrapper', + 'rowmanager', + 'bodyScrollable' + ]); this.bindEvents(); getDropdownHTML = getDropdownHTML.bind(this, this.options.dropdownButton); @@ -916,7 +937,7 @@ class ColumnManager { const { colIndex } = $.data($resizingCell); this.setColumnWidth(colIndex); - this.instance.setBodyWidth(); + this.style.setBodyStyle(); $resizingCell = null; }); @@ -1052,133 +1073,6 @@ class ColumnManager { }); } - setDimensions() { - this.setHeaderStyle(); - this.setupMinWidth(); - this.setupNaturalColumnWidth(); - this.distributeRemainingWidth(); - this.setColumnStyle(); - this.setDefaultCellHeight(); - } - - setHeaderStyle() { - if (!this.options.takeAvailableSpace) { - // setting width as 0 will ensure that the - // header doesn't take the available space - $.style(this.header, { - width: 0 - }); - } - - $.style(this.header, { - margin: 0 - }); - - // don't show resize cursor on nonResizable columns - const nonResizableColumnsSelector = this.datamanager.getColumns() - .filter(col => col.resizable === false) - .map(col => col.colIndex) - .map(i => `.data-table-header [data-col-index="${i}"]`) - .join(); - - this.style.setStyle(nonResizableColumnsSelector, { - cursor: 'pointer' - }); - } - - setupMinWidth() { - $.each('.data-table-col', this.header).map(col => { - const width = $.style($('.content', col), 'width'); - const { colIndex } = $.data(col); - const column = this.getColumn(colIndex); - - if (!column.minWidth) { - // only set this once - this.datamanager.updateColumn(colIndex, { minWidth: width }); - } - }); - } - - setupNaturalColumnWidth() { - // set initial width as naturally calculated by table's first row - $.each('.data-table-row[data-row-index="0"] .data-table-col', this.bodyScrollable).map($cell => { - const { colIndex } = $.data($cell); - if (this.getColumn(colIndex).width > 0) { - // already set - return; - } - - let width = $.style($('.content', $cell), 'width'); - const minWidth = this.getColumnMinWidth(colIndex); - - if (width < minWidth) { - width = minWidth; - } - this.datamanager.updateColumn(colIndex, { width }); - }); - } - - distributeRemainingWidth() { - if (!this.options.takeAvailableSpace) return; - - const wrapperWidth = $.style(this.instance.datatableWrapper, 'width'); - const headerWidth = $.style(this.header, 'width'); - - if (headerWidth >= wrapperWidth) { - // don't resize, horizontal scroll takes place - return; - } - - const resizableColumns = this.datamanager.getColumns().filter( - col => col.resizable === undefined || col.resizable - ); - - const deltaWidth = (wrapperWidth - headerWidth) / resizableColumns.length; - - resizableColumns.map(col => { - const width = $.style(this.getColumnHeaderElement(col.colIndex), 'width'); - let finalWidth = Math.min(width + deltaWidth) - 2; - - this.datamanager.updateColumn(col.colIndex, { width: finalWidth }); - }); - } - - setDefaultCellHeight() { - if (this.__cellHeightSet) return; - const height = $.style($('.data-table-col', this.instance.datatableWrapper), 'height'); - if (height) { - this.setCellHeight(height); - this.__cellHeightSet = true; - } - } - - setCellHeight(height) { - this.style.setStyle('.data-table-col .content', { - height: height + 'px' - }); - this.style.setStyle('.data-table-col .edit-cell', { - height: height + 'px' - }); - } - - setColumnStyle() { - // align columns - this.getColumns() - .map(column => { - // alignment - if (['left', 'center', 'right'].includes(column.align)) { - this.style.setStyle(`[data-col-index="${column.colIndex}"]`, { - 'text-align': column.align - }); - } - // width - this.setColumnHeaderWidth(column.colIndex); - this.setColumnWidth(column.colIndex); - }); - this.instance.setBodyWidth(); - - } - sortRows(colIndex, sortOrder) { return this.datamanager.sortRows(colIndex, sortOrder); } @@ -1247,12 +1141,6 @@ class ColumnManager { return this.datamanager.getColumnCount() - 1; } - getColumnHeaderElement(colIndex) { - colIndex = +colIndex; - if (colIndex < 0) return null; - return $(`.data-table-col[data-is-header][data-col-index="${colIndex}"]`, this.wrapper); - } - getSerialColumnIndex() { const columns = this.datamanager.getColumns(); @@ -1326,7 +1214,7 @@ class CellManager { let $cell = this.$focusedCell; - if (direction === 'left') { + if (direction === 'left' || direction === 'shift+tab') { $cell = this.getLeftCell$($cell); } else if (direction === 'right' || direction === 'tab') { $cell = this.getRightCell$($cell); @@ -1362,7 +1250,7 @@ class CellManager { return true; }; - ['left', 'right', 'up', 'down', 'tab'].map( + ['left', 'right', 'up', 'down', 'tab', 'shift+tab'].map( direction => this.keyboard.on(direction, () => focusCell(direction)) ); @@ -2114,7 +2002,7 @@ class BodyRenderer { } }, /* eslint-disable */ - no_data_text: this.options.loadingText, + no_data_text: this.options.noDataMessage, no_data_class: 'empty-state' /* eslint-enable */ }); @@ -2154,16 +2042,33 @@ function getBodyHTML(rows) { } class Style { + constructor(instance) { + this.instance = instance; - constructor(datatable) { - this.datatable = datatable; - this.scopeClass = 'datatable-instance-' + datatable.constructor.instances; - datatable.datatableWrapper.classList.add(this.scopeClass); + linkProperties(this, this.instance, [ + 'options', 'datamanager', 'columnmanager', + 'header', 'bodyScrollable', 'getColumn' + ]); + + this.scopeClass = 'datatable-instance-' + instance.constructor.instances; + instance.datatableWrapper.classList.add(this.scopeClass); const styleEl = document.createElement('style'); - datatable.wrapper.insertBefore(styleEl, datatable.datatableWrapper); + instance.wrapper.insertBefore(styleEl, instance.datatableWrapper); this.styleEl = styleEl; this.styleSheet = styleEl.sheet; + + this.bindResizeWindow(); + } + + bindResizeWindow() { + if (this.options.layout === 'fluid') { + $.on(window, 'resize', throttle(() => { + this.distributeRemainingWidth(); + this.refreshColumnWidth(); + this.setBodyStyle(); + }, 300)); + } } destroy() { @@ -2190,6 +2095,169 @@ class Style { this.styleSheet.insertRule(ruleString, _index); return _index; } + + setDimensions() { + this.setHeaderStyle(); + + this.setupMinWidth(); + this.setupNaturalColumnWidth(); + this.setupColumnWidth(); + + this.distributeRemainingWidth(); + this.setColumnStyle(); + this.setDefaultCellHeight(); + this.setBodyStyle(); + } + + setHeaderStyle() { + if (this.options.layout === 'fluid') { + // setting width as 0 will ensure that the + // header doesn't take the available space + $.style(this.header, { + width: 0 + }); + } + + $.style(this.header, { + margin: 0 + }); + + // don't show resize cursor on nonResizable columns + const nonResizableColumnsSelector = this.datamanager.getColumns() + .filter(col => col.resizable === false) + .map(col => col.colIndex) + .map(i => `.data-table-header [data-col-index="${i}"]`) + .join(); + + this.setStyle(nonResizableColumnsSelector, { + cursor: 'pointer' + }); + } + + setupMinWidth() { + $.each('.data-table-col', this.header).map(col => { + const width = $.style($('.content', col), 'width'); + const { + colIndex + } = $.data(col); + const column = this.getColumn(colIndex); + + if (!column.minWidth) { + // only set this once + column.minWidth = width; + } + }); + } + + setupNaturalColumnWidth() { + if (!$('.data-table-row')) return; + + // set initial width as naturally calculated by table's first row + $.each('.data-table-row[data-row-index="0"] .data-table-col', this.bodyScrollable).map($cell => { + const { + colIndex + } = $.data($cell); + const column = this.datamanager.getColumn(colIndex); + + let naturalWidth = $.style($('.content', $cell), 'width'); + column.naturalWidth = naturalWidth; + }); + } + + setupColumnWidth() { + this.datamanager.getColumns() + .map(column => { + if (column.width === null) { + column.width = column.naturalWidth; + } + if (column.width < column.minWidth) { + column.width = column.minWidth; + } + }); + } + + distributeRemainingWidth() { + if (this.options.layout !== 'fluid') return; + + const wrapperWidth = $.style(this.instance.datatableWrapper, 'width'); + const headerWidth = $.style(this.header, 'width'); + const resizableColumns = this.datamanager.getColumns().filter(col => col.resizable); + const deltaWidth = (wrapperWidth - headerWidth) / resizableColumns.length; + + resizableColumns.map(col => { + const width = $.style(this.getColumnHeaderElement(col.colIndex), 'width'); + let finalWidth = Math.floor(width + deltaWidth) - 2; + + this.datamanager.updateColumn(col.colIndex, { + width: finalWidth + }); + }); + } + + setDefaultCellHeight() { + if (this.__cellHeightSet) return; + const height = this.options.cellHeight || $.style($('.data-table-col', this.instance.datatableWrapper), 'height'); + if (height) { + this.setCellHeight(height); + this.__cellHeightSet = true; + } + } + + setCellHeight(height) { + this.setStyle('.data-table-col .content', { + height: height + 'px' + }); + this.setStyle('.data-table-col .edit-cell', { + height: height + 'px' + }); + } + + setColumnStyle() { + // align columns + this.datamanager.getColumns() + .map(column => { + // alignment + if (['left', 'center', 'right'].includes(column.align)) { + this.setStyle(`[data-col-index="${column.colIndex}"]`, { + 'text-align': column.align + }); + } + // width + this.columnmanager.setColumnHeaderWidth(column.colIndex); + this.columnmanager.setColumnWidth(column.colIndex); + }); + this.setBodyStyle(); + } + + refreshColumnWidth() { + this.datamanager.getColumns() + .map(column => { + this.columnmanager.setColumnHeaderWidth(column.colIndex); + this.columnmanager.setColumnWidth(column.colIndex); + }); + } + + setBodyStyle() { + const width = $.style(this.header, 'width'); + + $.style(this.bodyScrollable, { + width: width + 'px' + }); + + $.style(this.bodyScrollable, { + marginTop: $.style(this.header, 'height') + 'px' + }); + + $.style($('table', this.bodyScrollable), { + margin: 0 + }); + } + + getColumnHeaderElement(colIndex) { + colIndex = +colIndex; + if (colIndex < 0) return null; + return $(`.data-table-col[data-col-index="${colIndex}"]`, this.header); + } } const KEYCODES = { @@ -2292,8 +2360,9 @@ var DEFAULT_OPTIONS = { addCheckboxColumn: false, enableClusterize: true, enableLogs: false, - takeAvailableSpace: false, - loadingText: '' + layout: 'fixed', // fixed, fluid + noDataMessage: 'No Data', + cellHeight: null }; class DataTable { @@ -2394,29 +2463,21 @@ class DataTable { } setDimensions() { - this.columnmanager.setDimensions(); - - this.setBodyWidth(); - - $.style(this.bodyScrollable, { - marginTop: $.style(this.header, 'height') + 'px' - }); - - $.style($('table', this.bodyScrollable), { - margin: 0 - }); - } - - setBodyWidth() { - const width = $.style(this.header, 'width'); - - $.style(this.bodyScrollable, { width: width + 'px' }); + this.style.setDimensions(); } getColumn(colIndex) { return this.datamanager.getColumn(colIndex); } + getColumns() { + return this.datamanager.getColumns(); + } + + getRows() { + return this.datamanager.getRows(); + } + getCell(colIndex, rowIndex) { return this.datamanager.getCell(colIndex, rowIndex); } @@ -2471,13 +2532,13 @@ class DataTable { DataTable.instances = 0; var name = "frappe-datatable"; -var version = "0.0.1"; +var version = "0.0.2"; var description = "A modern datatable library for the web"; var main = "dist/frappe-datatable.cjs.js"; var scripts = {"start":"npm run dev","build":"rollup -c","dev":"rollup -c -w","test":"mocha --compilers js:babel-core/register --colors ./test/*.spec.js","test:watch":"mocha --compilers js:babel-core/register --colors -w ./test/*.spec.js"}; var devDependencies = {"chai":"3.5.0","cssnano":"^3.10.0","deepmerge":"^2.0.1","eslint":"3.19.0","eslint-loader":"1.7.1","mocha":"3.3.0","postcss-cssnext":"^3.1.0","postcss-nested":"^3.0.0","precss":"^3.1.0","rollup-plugin-json":"^2.3.0","rollup-plugin-postcss":"^1.2.8","rollup-plugin-uglify":"^3.0.0"}; var repository = {"type":"git","url":"https://github.com/frappe/datatable.git"}; -var keywords = ["webpack","es6","starter","library","universal","umd","commonjs"]; +var keywords = ["datatable","data","grid","table"]; var author = "Faris Ansari"; var license = "MIT"; var bugs = {"url":"https://github.com/frappe/datatable/issues"}; diff --git a/dist/frappe-datatable.css b/dist/frappe-datatable.css index 3d456a8..69ec17f 100644 --- a/dist/frappe-datatable.css +++ b/dist/frappe-datatable.css @@ -182,8 +182,8 @@ } .data-table-col .content { - padding: 4px; - padding: 0.25rem; + padding: 8px; + padding: 0.5rem; border: 2px solid transparent; } @@ -196,8 +196,8 @@ .data-table-col .edit-cell { display: none; // position: absolute; - padding: 4px; - padding: 0.25rem; + padding: 8px; + padding: 0.5rem; background: #fff; z-index: 1; height: 100%; diff --git a/dist/frappe-datatable.js b/dist/frappe-datatable.js index 537883e..06837ea 100644 --- a/dist/frappe-datatable.js +++ b/dist/frappe-datatable.js @@ -314,6 +314,20 @@ function promisify(fn, context = null) { }; } + + +function linkProperties(target, source, properties) { + const props = properties.reduce((acc, prop) => { + acc[prop] = { + get() { + return source[prop]; + } + }; + return acc; + }, {}); + Object.defineProperties(target, props); +} + class DataManager { constructor(options) { this.options = options; @@ -405,6 +419,7 @@ class DataManager { resizable: true, focusable: true, dropdown: true, + width: null, format: (value) => { if (value === null || value === undefined) { return ''; @@ -428,8 +443,7 @@ class DataManager { align: 'left', sortOrder: 'none', colIndex: i, - column: this.columns[i], - width: 0 + column: this.columns[i] }; if (content !== null && typeof content === 'object') { @@ -474,6 +488,10 @@ class DataManager { } row = row.concat(d); + while (row.length < this.columns.length) { + row.push(''); + } + } else { // row is a dict for (let col of this.columns) { @@ -794,14 +812,17 @@ class DataError extends TypeError {} class ColumnManager { constructor(instance) { this.instance = instance; - this.options = this.instance.options; - this.fireEvent = this.instance.fireEvent; - this.header = this.instance.header; - this.datamanager = this.instance.datamanager; - this.style = this.instance.style; - this.wrapper = this.instance.wrapper; - this.rowmanager = this.instance.rowmanager; - this.bodyScrollable = this.instance.bodyScrollable; + + linkProperties(this, this.instance, [ + 'options', + 'fireEvent', + 'header', + 'datamanager', + 'style', + 'wrapper', + 'rowmanager', + 'bodyScrollable' + ]); this.bindEvents(); getDropdownHTML = getDropdownHTML.bind(this, this.options.dropdownButton); @@ -915,7 +936,7 @@ class ColumnManager { const { colIndex } = $.data($resizingCell); this.setColumnWidth(colIndex); - this.instance.setBodyWidth(); + this.style.setBodyStyle(); $resizingCell = null; }); @@ -1051,133 +1072,6 @@ class ColumnManager { }); } - setDimensions() { - this.setHeaderStyle(); - this.setupMinWidth(); - this.setupNaturalColumnWidth(); - this.distributeRemainingWidth(); - this.setColumnStyle(); - this.setDefaultCellHeight(); - } - - setHeaderStyle() { - if (!this.options.takeAvailableSpace) { - // setting width as 0 will ensure that the - // header doesn't take the available space - $.style(this.header, { - width: 0 - }); - } - - $.style(this.header, { - margin: 0 - }); - - // don't show resize cursor on nonResizable columns - const nonResizableColumnsSelector = this.datamanager.getColumns() - .filter(col => col.resizable === false) - .map(col => col.colIndex) - .map(i => `.data-table-header [data-col-index="${i}"]`) - .join(); - - this.style.setStyle(nonResizableColumnsSelector, { - cursor: 'pointer' - }); - } - - setupMinWidth() { - $.each('.data-table-col', this.header).map(col => { - const width = $.style($('.content', col), 'width'); - const { colIndex } = $.data(col); - const column = this.getColumn(colIndex); - - if (!column.minWidth) { - // only set this once - this.datamanager.updateColumn(colIndex, { minWidth: width }); - } - }); - } - - setupNaturalColumnWidth() { - // set initial width as naturally calculated by table's first row - $.each('.data-table-row[data-row-index="0"] .data-table-col', this.bodyScrollable).map($cell => { - const { colIndex } = $.data($cell); - if (this.getColumn(colIndex).width > 0) { - // already set - return; - } - - let width = $.style($('.content', $cell), 'width'); - const minWidth = this.getColumnMinWidth(colIndex); - - if (width < minWidth) { - width = minWidth; - } - this.datamanager.updateColumn(colIndex, { width }); - }); - } - - distributeRemainingWidth() { - if (!this.options.takeAvailableSpace) return; - - const wrapperWidth = $.style(this.instance.datatableWrapper, 'width'); - const headerWidth = $.style(this.header, 'width'); - - if (headerWidth >= wrapperWidth) { - // don't resize, horizontal scroll takes place - return; - } - - const resizableColumns = this.datamanager.getColumns().filter( - col => col.resizable === undefined || col.resizable - ); - - const deltaWidth = (wrapperWidth - headerWidth) / resizableColumns.length; - - resizableColumns.map(col => { - const width = $.style(this.getColumnHeaderElement(col.colIndex), 'width'); - let finalWidth = Math.min(width + deltaWidth) - 2; - - this.datamanager.updateColumn(col.colIndex, { width: finalWidth }); - }); - } - - setDefaultCellHeight() { - if (this.__cellHeightSet) return; - const height = $.style($('.data-table-col', this.instance.datatableWrapper), 'height'); - if (height) { - this.setCellHeight(height); - this.__cellHeightSet = true; - } - } - - setCellHeight(height) { - this.style.setStyle('.data-table-col .content', { - height: height + 'px' - }); - this.style.setStyle('.data-table-col .edit-cell', { - height: height + 'px' - }); - } - - setColumnStyle() { - // align columns - this.getColumns() - .map(column => { - // alignment - if (['left', 'center', 'right'].includes(column.align)) { - this.style.setStyle(`[data-col-index="${column.colIndex}"]`, { - 'text-align': column.align - }); - } - // width - this.setColumnHeaderWidth(column.colIndex); - this.setColumnWidth(column.colIndex); - }); - this.instance.setBodyWidth(); - - } - sortRows(colIndex, sortOrder) { return this.datamanager.sortRows(colIndex, sortOrder); } @@ -1246,12 +1140,6 @@ class ColumnManager { return this.datamanager.getColumnCount() - 1; } - getColumnHeaderElement(colIndex) { - colIndex = +colIndex; - if (colIndex < 0) return null; - return $(`.data-table-col[data-is-header][data-col-index="${colIndex}"]`, this.wrapper); - } - getSerialColumnIndex() { const columns = this.datamanager.getColumns(); @@ -1325,7 +1213,7 @@ class CellManager { let $cell = this.$focusedCell; - if (direction === 'left') { + if (direction === 'left' || direction === 'shift+tab') { $cell = this.getLeftCell$($cell); } else if (direction === 'right' || direction === 'tab') { $cell = this.getRightCell$($cell); @@ -1361,7 +1249,7 @@ class CellManager { return true; }; - ['left', 'right', 'up', 'down', 'tab'].map( + ['left', 'right', 'up', 'down', 'tab', 'shift+tab'].map( direction => this.keyboard.on(direction, () => focusCell(direction)) ); @@ -2113,7 +2001,7 @@ class BodyRenderer { } }, /* eslint-disable */ - no_data_text: this.options.loadingText, + no_data_text: this.options.noDataMessage, no_data_class: 'empty-state' /* eslint-enable */ }); @@ -2153,16 +2041,33 @@ function getBodyHTML(rows) { } class Style { + constructor(instance) { + this.instance = instance; - constructor(datatable) { - this.datatable = datatable; - this.scopeClass = 'datatable-instance-' + datatable.constructor.instances; - datatable.datatableWrapper.classList.add(this.scopeClass); + linkProperties(this, this.instance, [ + 'options', 'datamanager', 'columnmanager', + 'header', 'bodyScrollable', 'getColumn' + ]); + + this.scopeClass = 'datatable-instance-' + instance.constructor.instances; + instance.datatableWrapper.classList.add(this.scopeClass); const styleEl = document.createElement('style'); - datatable.wrapper.insertBefore(styleEl, datatable.datatableWrapper); + instance.wrapper.insertBefore(styleEl, instance.datatableWrapper); this.styleEl = styleEl; this.styleSheet = styleEl.sheet; + + this.bindResizeWindow(); + } + + bindResizeWindow() { + if (this.options.layout === 'fluid') { + $.on(window, 'resize', throttle(() => { + this.distributeRemainingWidth(); + this.refreshColumnWidth(); + this.setBodyStyle(); + }, 300)); + } } destroy() { @@ -2189,6 +2094,169 @@ class Style { this.styleSheet.insertRule(ruleString, _index); return _index; } + + setDimensions() { + this.setHeaderStyle(); + + this.setupMinWidth(); + this.setupNaturalColumnWidth(); + this.setupColumnWidth(); + + this.distributeRemainingWidth(); + this.setColumnStyle(); + this.setDefaultCellHeight(); + this.setBodyStyle(); + } + + setHeaderStyle() { + if (this.options.layout === 'fluid') { + // setting width as 0 will ensure that the + // header doesn't take the available space + $.style(this.header, { + width: 0 + }); + } + + $.style(this.header, { + margin: 0 + }); + + // don't show resize cursor on nonResizable columns + const nonResizableColumnsSelector = this.datamanager.getColumns() + .filter(col => col.resizable === false) + .map(col => col.colIndex) + .map(i => `.data-table-header [data-col-index="${i}"]`) + .join(); + + this.setStyle(nonResizableColumnsSelector, { + cursor: 'pointer' + }); + } + + setupMinWidth() { + $.each('.data-table-col', this.header).map(col => { + const width = $.style($('.content', col), 'width'); + const { + colIndex + } = $.data(col); + const column = this.getColumn(colIndex); + + if (!column.minWidth) { + // only set this once + column.minWidth = width; + } + }); + } + + setupNaturalColumnWidth() { + if (!$('.data-table-row')) return; + + // set initial width as naturally calculated by table's first row + $.each('.data-table-row[data-row-index="0"] .data-table-col', this.bodyScrollable).map($cell => { + const { + colIndex + } = $.data($cell); + const column = this.datamanager.getColumn(colIndex); + + let naturalWidth = $.style($('.content', $cell), 'width'); + column.naturalWidth = naturalWidth; + }); + } + + setupColumnWidth() { + this.datamanager.getColumns() + .map(column => { + if (column.width === null) { + column.width = column.naturalWidth; + } + if (column.width < column.minWidth) { + column.width = column.minWidth; + } + }); + } + + distributeRemainingWidth() { + if (this.options.layout !== 'fluid') return; + + const wrapperWidth = $.style(this.instance.datatableWrapper, 'width'); + const headerWidth = $.style(this.header, 'width'); + const resizableColumns = this.datamanager.getColumns().filter(col => col.resizable); + const deltaWidth = (wrapperWidth - headerWidth) / resizableColumns.length; + + resizableColumns.map(col => { + const width = $.style(this.getColumnHeaderElement(col.colIndex), 'width'); + let finalWidth = Math.floor(width + deltaWidth) - 2; + + this.datamanager.updateColumn(col.colIndex, { + width: finalWidth + }); + }); + } + + setDefaultCellHeight() { + if (this.__cellHeightSet) return; + const height = this.options.cellHeight || $.style($('.data-table-col', this.instance.datatableWrapper), 'height'); + if (height) { + this.setCellHeight(height); + this.__cellHeightSet = true; + } + } + + setCellHeight(height) { + this.setStyle('.data-table-col .content', { + height: height + 'px' + }); + this.setStyle('.data-table-col .edit-cell', { + height: height + 'px' + }); + } + + setColumnStyle() { + // align columns + this.datamanager.getColumns() + .map(column => { + // alignment + if (['left', 'center', 'right'].includes(column.align)) { + this.setStyle(`[data-col-index="${column.colIndex}"]`, { + 'text-align': column.align + }); + } + // width + this.columnmanager.setColumnHeaderWidth(column.colIndex); + this.columnmanager.setColumnWidth(column.colIndex); + }); + this.setBodyStyle(); + } + + refreshColumnWidth() { + this.datamanager.getColumns() + .map(column => { + this.columnmanager.setColumnHeaderWidth(column.colIndex); + this.columnmanager.setColumnWidth(column.colIndex); + }); + } + + setBodyStyle() { + const width = $.style(this.header, 'width'); + + $.style(this.bodyScrollable, { + width: width + 'px' + }); + + $.style(this.bodyScrollable, { + marginTop: $.style(this.header, 'height') + 'px' + }); + + $.style($('table', this.bodyScrollable), { + margin: 0 + }); + } + + getColumnHeaderElement(colIndex) { + colIndex = +colIndex; + if (colIndex < 0) return null; + return $(`.data-table-col[data-col-index="${colIndex}"]`, this.header); + } } const KEYCODES = { @@ -2291,8 +2359,9 @@ var DEFAULT_OPTIONS = { addCheckboxColumn: false, enableClusterize: true, enableLogs: false, - takeAvailableSpace: false, - loadingText: '' + layout: 'fixed', // fixed, fluid + noDataMessage: 'No Data', + cellHeight: null }; class DataTable { @@ -2393,29 +2462,21 @@ class DataTable { } setDimensions() { - this.columnmanager.setDimensions(); - - this.setBodyWidth(); - - $.style(this.bodyScrollable, { - marginTop: $.style(this.header, 'height') + 'px' - }); - - $.style($('table', this.bodyScrollable), { - margin: 0 - }); - } - - setBodyWidth() { - const width = $.style(this.header, 'width'); - - $.style(this.bodyScrollable, { width: width + 'px' }); + this.style.setDimensions(); } getColumn(colIndex) { return this.datamanager.getColumn(colIndex); } + getColumns() { + return this.datamanager.getColumns(); + } + + getRows() { + return this.datamanager.getRows(); + } + getCell(colIndex, rowIndex) { return this.datamanager.getCell(colIndex, rowIndex); } @@ -2470,13 +2531,13 @@ class DataTable { DataTable.instances = 0; var name = "frappe-datatable"; -var version = "0.0.1"; +var version = "0.0.2"; var description = "A modern datatable library for the web"; var main = "dist/frappe-datatable.cjs.js"; var scripts = {"start":"npm run dev","build":"rollup -c","dev":"rollup -c -w","test":"mocha --compilers js:babel-core/register --colors ./test/*.spec.js","test:watch":"mocha --compilers js:babel-core/register --colors -w ./test/*.spec.js"}; var devDependencies = {"chai":"3.5.0","cssnano":"^3.10.0","deepmerge":"^2.0.1","eslint":"3.19.0","eslint-loader":"1.7.1","mocha":"3.3.0","postcss-cssnext":"^3.1.0","postcss-nested":"^3.0.0","precss":"^3.1.0","rollup-plugin-json":"^2.3.0","rollup-plugin-postcss":"^1.2.8","rollup-plugin-uglify":"^3.0.0"}; var repository = {"type":"git","url":"https://github.com/frappe/datatable.git"}; -var keywords = ["webpack","es6","starter","library","universal","umd","commonjs"]; +var keywords = ["datatable","data","grid","table"]; var author = "Faris Ansari"; var license = "MIT"; var bugs = {"url":"https://github.com/frappe/datatable/issues"}; diff --git a/package.json b/package.json index 7065ee1..f93bd5e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "frappe-datatable", - "version": "0.0.1", + "version": "0.0.2", "description": "A modern datatable library for the web", "main": "dist/frappe-datatable.cjs.js", "scripts": { @@ -29,13 +29,10 @@ "url": "https://github.com/frappe/datatable.git" }, "keywords": [ - "webpack", - "es6", - "starter", - "library", - "universal", - "umd", - "commonjs" + "datatable", + "data", + "grid", + "table" ], "author": "Faris Ansari", "license": "MIT", diff --git a/rollup.config.js b/rollup.config.js index 4456338..e006303 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -29,7 +29,7 @@ const dev = { external: ['sortablejs', 'clusterize.js'] }; -export default [dev, Object.assign(dev, { +export default [dev, Object.assign({}, dev, { output: { format: 'cjs', file: 'dist/frappe-datatable.cjs.js' diff --git a/src/defaults.js b/src/defaults.js index ffcf12f..e164c1e 100644 --- a/src/defaults.js +++ b/src/defaults.js @@ -45,5 +45,6 @@ export default { enableClusterize: true, enableLogs: false, layout: 'fixed', // fixed, fluid - noDataMessage: 'No Data' + noDataMessage: 'No Data', + cellHeight: null }; diff --git a/src/style.css b/src/style.css index e841e3b..121e544 100644 --- a/src/style.css +++ b/src/style.css @@ -176,7 +176,7 @@ position: relative; .content { - padding: var(--spacer-1); + padding: var(--spacer-2); border: 2px solid transparent; &.ellipsis { @@ -189,7 +189,7 @@ .edit-cell { display: none; // position: absolute; - padding: var(--spacer-1); + padding: var(--spacer-2); background: #fff; z-index: 1; height: 100%; diff --git a/src/style.js b/src/style.js index 25f715b..d4c7ab3 100644 --- a/src/style.js +++ b/src/style.js @@ -160,7 +160,7 @@ export default class Style { setDefaultCellHeight() { if (this.__cellHeightSet) return; - const height = $.style($('.data-table-col', this.instance.datatableWrapper), 'height'); + const height = this.options.cellHeight || $.style($('.data-table-col', this.instance.datatableWrapper), 'height'); if (height) { this.setCellHeight(height); this.__cellHeightSet = true;