react-sticky-table
Advanced tools
Comparing version 1.0.3 to 1.0.4
(function (global, factory) { | ||
if (typeof define === "function" && define.amd) { | ||
define(['exports', 'react', './Table', './Row', './Cell', 'nodeproxy', 'element-resize-event'], factory); | ||
define(['exports', 'react', './Table', './Row', './Cell', 'underscore', 'nodeproxy', 'element-resize-event'], factory); | ||
} else if (typeof exports !== "undefined") { | ||
factory(exports, require('react'), require('./Table'), require('./Row'), require('./Cell'), require('nodeproxy'), require('element-resize-event')); | ||
factory(exports, require('react'), require('./Table'), require('./Row'), require('./Cell'), require('underscore'), require('nodeproxy'), require('element-resize-event')); | ||
} else { | ||
@@ -10,6 +10,6 @@ var mod = { | ||
}; | ||
factory(mod.exports, global.react, global.Table, global.Row, global.Cell, global.nodeproxy, global.elementResizeEvent); | ||
factory(mod.exports, global.react, global.Table, global.Row, global.Cell, global.underscore, global.nodeproxy, global.elementResizeEvent); | ||
global.index = mod.exports; | ||
} | ||
})(this, function (exports, _react, _Table, _Row, _Cell, proxy, elementResizeEvent) { | ||
})(this, function (exports, _react, _Table, _Row, _Cell, _, proxy, elementResizeEvent) { | ||
'use strict'; | ||
@@ -116,3 +116,5 @@ | ||
_this.onColumnResize = _this.onColumnResize.bind(_this); | ||
_this.onScroll = _this.onScroll.bind(_this); | ||
_this.onScrollX = _this.onScrollX.bind(_this); | ||
_this.scrollXScrollbar = _.debounce(_this.scrollXScrollbar.bind(_this), 100); | ||
_this.scrollYScrollbar = _.debounce(_this.scrollYScrollbar.bind(_this), 100); | ||
return _this; | ||
@@ -127,9 +129,17 @@ } | ||
if (this.table) { | ||
this.table.querySelector('#sticky-table-x-wrapper').addEventListener('scroll', this.onScroll); | ||
this.realTable = this.table.querySelector('#sticky-table-x-wrapper').firstChild; | ||
this.xScrollbar = this.table.querySelector('#x-scrollbar'); | ||
this.yScrollbar = this.table.querySelector('#y-scrollbar'); | ||
this.xWrapper = this.table.querySelector('#sticky-table-x-wrapper'); | ||
this.yWrapper = this.table.querySelector('#sticky-table-y-wrapper'); | ||
this.stickyHeader = this.table.querySelector('#sticky-header'); | ||
this.stickyColumn = this.table.querySelector('#sticky-column'); | ||
elementResizeEvent(this.table.querySelector('#sticky-column'), this.onColumnResize); | ||
elementResizeEvent(this.table.querySelector('#sticky-table-x-wrapper').firstChild, this.onResize); | ||
this.xWrapper.addEventListener('scroll', this.onScrollX); | ||
this.setRowHeights(); | ||
this.setColumnWidths(); | ||
elementResizeEvent(this.stickyColumn, this.onColumnResize); | ||
elementResizeEvent(this.realTable, this.onResize); | ||
this.onResize(); | ||
this.addScrollBarEventHandlers(); | ||
} | ||
@@ -141,13 +151,42 @@ } | ||
if (this.table) { | ||
this.table.querySelector('#sticky-table-x-wrapper').removeEventListener('scroll', this.handleScrollX); | ||
this.xWrapper.removeEventListener('scroll', this.onScrollX); | ||
} | ||
} | ||
}, { | ||
key: 'onScroll', | ||
value: function onScroll() { | ||
var scrollLeft = this.table.querySelector('#sticky-table-x-wrapper').scrollLeft; | ||
key: 'addScrollBarEventHandlers', | ||
value: function addScrollBarEventHandlers() { | ||
var _this2 = this; | ||
this.table.querySelector('#sticky-header').style.left = -1 * scrollLeft + 'px'; | ||
//X Scrollbars | ||
this.xScrollbar.addEventListener('scroll', proxy(function () { | ||
_this2.xWrapper.scrollLeft = _this2.xScrollbar.scrollLeft; | ||
}, this)); | ||
//Y Scrollbars | ||
this.yWrapper.addEventListener('scroll', this.scrollYScrollbar); | ||
this.yScrollbar.addEventListener('scroll', proxy(function () { | ||
_this2.yWrapper.scrollTop = _this2.yScrollbar.scrollTop; | ||
}, this)); | ||
} | ||
}, { | ||
key: 'onScrollX', | ||
value: function onScrollX() { | ||
//Sticky header | ||
var scrollLeft = this.xWrapper.scrollLeft; | ||
this.stickyHeader.style.transform = 'translate(' + -1 * scrollLeft + 'px, 0)'; | ||
//Custom Scrollbar | ||
this.scrollXScrollbar(); | ||
} | ||
}, { | ||
key: 'scrollXScrollbar', | ||
value: function scrollXScrollbar() { | ||
this.xScrollbar.scrollLeft = this.xWrapper.scrollLeft; | ||
} | ||
}, { | ||
key: 'scrollYScrollbar', | ||
value: function scrollYScrollbar() { | ||
this.yScrollbar.scrollTop = this.yWrapper.scrollTop; | ||
} | ||
}, { | ||
key: 'onResize', | ||
@@ -157,8 +196,15 @@ value: function onResize() { | ||
this.setColumnWidths(); | ||
this.setScrollBarDims(); | ||
} | ||
}, { | ||
key: 'setScrollBarDims', | ||
value: function setScrollBarDims() { | ||
this.table.querySelector('#x-scrollbar div').style.width = this.getSizeWithoutBoxSizing(this.realTable.firstChild).width + 'px'; | ||
this.table.querySelector('#y-scrollbar div').style.height = this.getSizeWithoutBoxSizing(this.realTable).height + 'px'; | ||
} | ||
}, { | ||
key: 'onColumnResize', | ||
value: function onColumnResize() { | ||
var columnCell = this.table.querySelector('#sticky-column').firstChild.firstChild.childNodes[0]; | ||
var cell = this.table.querySelector('#sticky-table-x-wrapper').firstChild.firstChild.firstChild; | ||
var columnCell = this.stickyColumn.firstChild.firstChild.childNodes[0]; | ||
var cell = this.realTable.firstChild.firstChild; | ||
var dims = this.getSizeWithoutBoxSizing(columnCell); | ||
@@ -182,3 +228,3 @@ | ||
for (r = 0; r < this.rowCount; r++) { | ||
cellToCopy = this.table.querySelector('#sticky-table-x-wrapper').firstChild.childNodes[r].firstChild; | ||
cellToCopy = this.realTable.childNodes[r].firstChild; | ||
@@ -188,3 +234,3 @@ if (cellToCopy) { | ||
this.table.querySelector('#sticky-column').firstChild.childNodes[r].firstChild.style.height = height + 'px'; | ||
this.stickyColumn.firstChild.childNodes[r].firstChild.style.height = height + 'px'; | ||
} | ||
@@ -201,3 +247,3 @@ } | ||
for (c = 0; c < this.columnCount; c++) { | ||
cellToCopy = this.table.querySelector('#sticky-table-x-wrapper').firstChild.firstChild.childNodes[c]; | ||
cellToCopy = this.realTable.firstChild.childNodes[c]; | ||
@@ -239,3 +285,3 @@ if (cellToCopy) { | ||
row.props.children.forEach(function (cell, c) { | ||
cells.push(_react2.default.cloneElement(cell, { id: 'sticky-header-cell-' + c, style: {} })); | ||
cells.push(_react2.default.cloneElement(cell, { id: 'sticky-header-cell-' + c, key: c })); | ||
}); | ||
@@ -289,2 +335,12 @@ | ||
'div', | ||
{ id: 'x-scrollbar' }, | ||
_react2.default.createElement('div', null) | ||
), | ||
_react2.default.createElement( | ||
'div', | ||
{ id: 'y-scrollbar' }, | ||
_react2.default.createElement('div', null) | ||
), | ||
_react2.default.createElement( | ||
'div', | ||
{ className: 'sticky-header', id: 'sticky-header' }, | ||
@@ -291,0 +347,0 @@ _react2.default.createElement( |
{ | ||
"name": "react-sticky-table", | ||
"version": "1.0.3", | ||
"version": "1.0.4", | ||
"description": "Dynamically sized fixed header and column for tables", | ||
@@ -68,4 +68,5 @@ "repository": { | ||
"element-resize-event": "^2.0.7", | ||
"nodeproxy": "^1.0.0" | ||
"nodeproxy": "^1.0.0", | ||
"underscore": "^1.8.3" | ||
} | ||
} |
# Sticky Table | ||
Responsive and dynamically-sized fixed headers and columns for tables. | ||
Responsive and dynamically-sized fixed headers and columns for tables inspired by [fixed-data-table](https://facebook.github.io/fixed-data-table/example-object-data.html)'s lack of responsiveness. | ||
Inspired by [fixed-data-table](https://facebook.github.io/fixed-data-table/example-object-data.html)'s lack of responsiveness. | ||
[Demo](https://we-flow.github.io/react-sticky-table/) | ||
@@ -16,3 +14,2 @@ | ||
- Custom cells (just make sure your custom cell has `display: table-cell` set) | ||
- Supports `overflow: scroll` on both axes | ||
- Multiple tables per page | ||
@@ -24,5 +21,7 @@ | ||
Install react-sticky-table using npm. | ||
Install `react-sticky-table` using `npm`. | ||
`npm install react-sticky-table --save` | ||
``` | ||
npm install react-sticky-table --save | ||
``` | ||
@@ -32,3 +31,3 @@ Add the default stylesheet `react-sticky-table/dist/react-sticky-table.css`, then import it into any module. | ||
## Example | ||
``` | ||
```javascript | ||
import React, { Component } from 'react'; | ||
@@ -61,2 +60,25 @@ | ||
## Options | ||
Default settings: | ||
```javascript | ||
{ | ||
stickyHeaderCount: 1, | ||
stickyColumnCount: 1 | ||
} | ||
``` | ||
Disable sticky header: | ||
```javascript | ||
<StickyTable stickyHeaderCount={0}> | ||
``` | ||
Disable sticky column: | ||
```javascript | ||
<StickyTable stickyColumnCount={0}> | ||
``` | ||
## License | ||
@@ -63,0 +85,0 @@ |
import React from 'react'; | ||
import {shallow, mount, render} from 'enzyme'; | ||
import {mount} from 'enzyme'; | ||
import {expect} from 'chai'; | ||
import sinon from 'sinon'; | ||
import StickyTable from '../index'; | ||
import Row from '../Row'; | ||
import Cell from '../Cell'; | ||
import {StickyTable, Row, Cell} from '../index'; | ||
describe('StickyTable', () => { | ||
it('should render the children properly', () => { | ||
it('should render the correct number of children', () => { | ||
const table = mount( | ||
<StickyTable rowCount={2} columnCount={2}> | ||
<StickyTable> | ||
<Row> | ||
<Cell>'header 1'</Cell> | ||
<Cell>'header 2'</Cell> | ||
<Cell>{'header 1'}</Cell> | ||
<Cell>{'header 2'}</Cell> | ||
</Row> | ||
<Row> | ||
<Cell>'column 1 cell'</Cell> | ||
<Cell>'column 2 cell'</Cell> | ||
<Cell>{'column 1 cell'}</Cell> | ||
<Cell>{'column 2 cell'}</Cell> | ||
</Row> | ||
@@ -26,4 +23,40 @@ </StickyTable> | ||
expect(table.find('.cell')).to.have.length(4); | ||
expect(table.find('.cell')).to.have.length(8); | ||
}); | ||
it('shouldn\'t render columns when opting out', () => { | ||
const table = mount( | ||
<StickyTable stickyColumnCount={0}> | ||
<Row> | ||
<Cell>{'header 1'}</Cell> | ||
<Cell>{'header 2'}</Cell> | ||
</Row> | ||
<Row> | ||
<Cell>{'column 1 cell'}</Cell> | ||
<Cell>{'column 2 cell'}</Cell> | ||
</Row> | ||
</StickyTable> | ||
); | ||
expect(table.find('.cell')).to.have.length(6); | ||
expect(table.find('#sticky-column .cell')).to.have.length(0); | ||
}); | ||
it('shouldn\'t render headers when opting out', () => { | ||
const table = mount( | ||
<StickyTable stickyHeaderCount={0}> | ||
<Row> | ||
<Cell>{'header 1'}</Cell> | ||
<Cell>{'header 2'}</Cell> | ||
</Row> | ||
<Row> | ||
<Cell>{'column 1 cell'}</Cell> | ||
<Cell>{'column 2 cell'}</Cell> | ||
</Row> | ||
</StickyTable> | ||
); | ||
expect(table.find('.cell')).to.have.length(6); | ||
expect(table.find('#sticky-header .cell')).to.have.length(0); | ||
}); | ||
}); |
import React, { Component, PropTypes } from 'react'; | ||
var _ = require('underscore'); | ||
var proxy = require('nodeproxy'); | ||
@@ -32,3 +33,5 @@ var elementResizeEvent = require('element-resize-event'); | ||
this.onColumnResize = this.onColumnResize.bind(this); | ||
this.onScroll = this.onScroll.bind(this); | ||
this.onScrollX = this.onScrollX.bind(this); | ||
this.scrollXScrollbar = _.debounce(this.scrollXScrollbar.bind(this), 100); | ||
this.scrollYScrollbar = _.debounce(this.scrollYScrollbar.bind(this), 100); | ||
} | ||
@@ -40,9 +43,17 @@ | ||
if (this.table) { | ||
this.table.querySelector('#sticky-table-x-wrapper').addEventListener('scroll', this.onScroll); | ||
this.realTable = this.table.querySelector('#sticky-table-x-wrapper').firstChild; | ||
this.xScrollbar = this.table.querySelector('#x-scrollbar'); | ||
this.yScrollbar = this.table.querySelector('#y-scrollbar'); | ||
this.xWrapper = this.table.querySelector('#sticky-table-x-wrapper'); | ||
this.yWrapper = this.table.querySelector('#sticky-table-y-wrapper'); | ||
this.stickyHeader = this.table.querySelector('#sticky-header'); | ||
this.stickyColumn = this.table.querySelector('#sticky-column'); | ||
elementResizeEvent(this.table.querySelector('#sticky-column'), this.onColumnResize); | ||
elementResizeEvent(this.table.querySelector('#sticky-table-x-wrapper').firstChild, this.onResize); | ||
this.xWrapper.addEventListener('scroll', this.onScrollX); | ||
this.setRowHeights(); | ||
this.setColumnWidths(); | ||
elementResizeEvent(this.stickyColumn, this.onColumnResize); | ||
elementResizeEvent(this.realTable, this.onResize); | ||
this.onResize(); | ||
this.addScrollBarEventHandlers(); | ||
} | ||
@@ -53,12 +64,39 @@ } | ||
if (this.table) { | ||
this.table.querySelector('#sticky-table-x-wrapper').removeEventListener('scroll', this.handleScrollX); | ||
this.xWrapper.removeEventListener('scroll', this.onScrollX); | ||
} | ||
} | ||
onScroll() { | ||
var scrollLeft = this.table.querySelector('#sticky-table-x-wrapper').scrollLeft; | ||
/** | ||
* Link scrolling on either axis to scrolling in the scrollbar elements | ||
* @returns {null} no return necessary | ||
*/ | ||
addScrollBarEventHandlers() { | ||
//X Scrollbars | ||
this.xScrollbar.addEventListener('scroll', proxy(() => { | ||
this.xWrapper.scrollLeft = this.xScrollbar.scrollLeft; | ||
}, this)); | ||
this.table.querySelector('#sticky-header').style.left = (-1 * scrollLeft) + 'px'; | ||
//Y Scrollbars | ||
this.yWrapper.addEventListener('scroll', this.scrollYScrollbar); | ||
this.yScrollbar.addEventListener('scroll', proxy(() => { | ||
this.yWrapper.scrollTop = this.yScrollbar.scrollTop; | ||
}, this)); | ||
} | ||
onScrollX() { | ||
//Sticky header | ||
var scrollLeft = this.xWrapper.scrollLeft; | ||
this.stickyHeader.style.transform = 'translate(' + (-1 * scrollLeft) + 'px, 0)'; | ||
//Custom Scrollbar | ||
this.scrollXScrollbar(); | ||
} | ||
scrollXScrollbar() { | ||
this.xScrollbar.scrollLeft = this.xWrapper.scrollLeft | ||
} | ||
scrollYScrollbar() { | ||
this.yScrollbar.scrollTop = this.yWrapper.scrollTop | ||
} | ||
/** | ||
@@ -71,4 +109,10 @@ * Handle real cell resize events | ||
this.setColumnWidths(); | ||
this.setScrollBarDims(); | ||
} | ||
setScrollBarDims() { | ||
this.table.querySelector('#x-scrollbar div').style.width = this.getSizeWithoutBoxSizing(this.realTable.firstChild).width + 'px'; | ||
this.table.querySelector('#y-scrollbar div').style.height = this.getSizeWithoutBoxSizing(this.realTable).height + 'px'; | ||
} | ||
/** | ||
@@ -79,4 +123,4 @@ * Handle sticky column resize events | ||
onColumnResize() { | ||
var columnCell = this.table.querySelector('#sticky-column').firstChild.firstChild.childNodes[0]; | ||
var cell = this.table.querySelector('#sticky-table-x-wrapper').firstChild.firstChild.firstChild; | ||
var columnCell = this.stickyColumn.firstChild.firstChild.childNodes[0]; | ||
var cell = this.realTable.firstChild.firstChild; | ||
var dims = this.getSizeWithoutBoxSizing(columnCell); | ||
@@ -103,3 +147,3 @@ | ||
for (r = 0; r < this.rowCount; r++) { | ||
cellToCopy = this.table.querySelector('#sticky-table-x-wrapper').firstChild.childNodes[r].firstChild; | ||
cellToCopy = this.realTable.childNodes[r].firstChild; | ||
@@ -109,3 +153,3 @@ if (cellToCopy) { | ||
this.table.querySelector('#sticky-column').firstChild.childNodes[r].firstChild.style.height = height + 'px'; | ||
this.stickyColumn.firstChild.childNodes[r].firstChild.style.height = height + 'px'; | ||
} | ||
@@ -125,3 +169,3 @@ } | ||
for (c = 0; c < this.columnCount; c++) { | ||
cellToCopy = this.table.querySelector('#sticky-table-x-wrapper').firstChild.firstChild.childNodes[c]; | ||
cellToCopy = this.realTable.firstChild.childNodes[c]; | ||
@@ -173,3 +217,3 @@ if (cellToCopy) { | ||
row.props.children.forEach((cell, c) => { | ||
cells.push(React.cloneElement(cell, {id: 'sticky-header-cell-' + c, style: {}})); | ||
cells.push(React.cloneElement(cell, {id: 'sticky-header-cell-' + c, key: c})); | ||
}); | ||
@@ -180,3 +224,4 @@ | ||
{cells} | ||
</Row>); | ||
</Row> | ||
); | ||
} | ||
@@ -235,6 +280,6 @@ | ||
<div className={'sticky-table ' + (this.props.className || '')} id={'sticky-table-' + this.id}> | ||
<div id='x-scrollbar'><div></div></div> | ||
<div id='y-scrollbar'><div></div></div> | ||
<div className='sticky-header' id='sticky-header'> | ||
<Table> | ||
{stickyHeader} | ||
</Table> | ||
<Table>{stickyHeader}</Table> | ||
</div> | ||
@@ -241,0 +286,0 @@ <div className='sticky-table-y-wrapper' id='sticky-table-y-wrapper'> |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
45204
24
1155
91
6
+ Addedunderscore@^1.8.3
+ Addedunderscore@1.13.7(transitive)