From 0b06a686c15c60bb40155da7e21801c9a566660e Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Wed, 2 Dec 2015 11:23:45 +0100 Subject: [PATCH 01/35] Add visibleItems() method returns an array of data objects that are currently visible, handy to implement item selection / mark as read etc --- src/reactable/table.jsx | 17 +++++++++ tests/reactable_test.jsx | 79 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index f011a6ff..f30548f1 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -300,6 +300,21 @@ export class Table extends React.Component { this.sortByCurrentSort(); } + visibleItems() { + return this.currentChildren.map(item => { + const {i, id} = item.props; + const iOrId = i != null ? i : id; + const idOrKey = iOrId != null ? iOrId : item.key; + const data = {id: idOrKey}; + + Object.keys(item.props.data).forEach(key => { + data[key] = item.props.data[key].value; + }); + + return data; + }) + } + render() { let children = []; let columns; @@ -422,6 +437,8 @@ export class Table extends React.Component { let noDataText = this.props.noDataText ? {this.props.noDataText} : null; + this.currentChildren = currentChildren; + return {columns && columns.length > 0 ? { + const {Table, Thead, Tr, Th, Td} = Reactable; + const data = [{name:"Lee SomeoneElse", age:18},{name:"Lee Salminen", age:23},{name:"No Age", age:null}]; + class Tester extends React.Component { + componentDidMount() { + this.props.run && this.props.run(this) + } + render() { + return ( +
+ + + + + {data.map((item, i) => + + + )} + + + + +
The NameThe Age
+ +
+ +
+ +
+ ) + } + } + const doTest = (runMe, options = {}) => ( + ReactDOM.render( + , + ReactableTestUtils.testNode() + ) + ) + + after(ReactableTestUtils.resetTestEnvironment); + + it('works', () => { + doTest(me => { + const items = me.refs.table.visibleItems() + expect(items.length).to.eql(5) + expect(items[0].Age).to.eql(18) + }) + }); + it('works when filtered', () => { + doTest(me => { + const items = me.refs.table.visibleItems() + expect(items.length).to.eql(2) + expect(items[1].Age).to.eql(23) + }, {filterBy: 'lee'}) + }); + it('works when paged', () => { + doTest(me => { + const items = me.refs.table.visibleItems() + expect(items.length).to.eql(1) + expect(items[0].Age).to.eql(18) + }, {itemsPerPage: 1}) + }); + it('has keys', () => { + doTest(me => { + const items = me.refs.table.visibleItems() + expect(items[1].id).to.eql(1) + // id is not defined and key is a string + expect(items[2].id).to.eql("2") + // Falsy ids still count + expect(items[0].id).to.eql(0) + expect(items[3].id).to.eql(true) + expect(items[4].id).to.eql("id") + }) + }); + }); + + }); From 477c1ec6a1cc502c2c06be3eb0fed2c96bdbbb04 Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Wed, 2 Dec 2015 15:24:33 +0100 Subject: [PATCH 02/35] Don't show pager if only one page --- src/reactable/table.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index f011a6ff..a186173b 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -410,7 +410,7 @@ export class Table extends React.Component { currentPage = numPages - 1; } - pagination = true; + pagination = numPages > 1; currentChildren = filteredChildren.slice( currentPage * itemsPerPage, (currentPage + 1) * itemsPerPage From 9adf60bfb95e65b421de3cdc0cc0694216cb266d Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Wed, 2 Dec 2015 15:25:33 +0100 Subject: [PATCH 03/35] Add built files --- build/reactable.js | 33 ++++- build/tests/reactable_test.js | 261 ++++++++++++++++++++++++++++++++++ lib/reactable/table.js | 33 ++++- 3 files changed, 325 insertions(+), 2 deletions(-) diff --git a/build/reactable.js b/build/reactable.js index 29772566..ce6bdd07 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -1284,6 +1284,25 @@ window.ReactDOM["default"] = window.ReactDOM; this.setState({ currentSort: currentSort }); this.sortByCurrentSort(); } + }, { + key: 'visibleItems', + value: function visibleItems() { + return this.currentChildren.map(function (item) { + var _item$props = item.props; + var i = _item$props.i; + var id = _item$props.id; + + var iOrId = i != null ? i : id; + var idOrKey = iOrId != null ? iOrId : item.key; + var data = { id: idOrKey }; + + Object.keys(item.props.data).forEach(function (key) { + data[key] = item.props.data[key].value; + }); + + return data; + }); + } }, { key: 'render', value: function render() { @@ -1391,6 +1410,18 @@ window.ReactDOM["default"] = window.ReactDOM; // Manually transfer props var props = (0, _libFilter_props_from.filterPropsFrom)(this.props); + var noDataText = this.props.noDataText ? _react['default'].createElement( + 'tr', + { className: 'reactable-no-data' }, + _react['default'].createElement( + 'td', + { colSpan: columns.length }, + this.props.noDataText + ) + ) : null; + + this.currentChildren = currentChildren; + return _react['default'].createElement( 'table', props, @@ -1408,7 +1439,7 @@ window.ReactDOM["default"] = window.ReactDOM; _react['default'].createElement( 'tbody', { className: 'reactable-data', key: 'tbody' }, - currentChildren + currentChildren.length > 0 ? currentChildren : noDataText ), pagination === true ? _react['default'].createElement(_paginator.Paginator, { colSpan: columns.length, pageButtonLimit: pageButtonLimit, diff --git a/build/tests/reactable_test.js b/build/tests/reactable_test.js index 785ab765..6f552f4a 100644 --- a/build/tests/reactable_test.js +++ b/build/tests/reactable_test.js @@ -13,6 +13,16 @@ })(this, function (exports) { 'use strict'; + var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; + + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + + function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + var ReactTestUtils = React.addons.TestUtils; var expect = chai.expect; @@ -2151,5 +2161,256 @@ expect(this.clicked).to.eq(true); }); }); + + describe('table with no data', function () { + context('when noDataText prop is null', function () { + before(function () { + this.component = ReactDOM.render(React.createElement(Reactable.Table, { data: [], columns: ['State', 'Description', 'Tag'] }), ReactableTestUtils.testNode()); + }); + + after(ReactableTestUtils.resetTestEnvironment); + + it('does not render the reactable-no-data element', function () { + expect($('.reactable-no-data').length).to.eq(0); + }); + }); + + context('when initialized without s', function () { + before(function () { + this.component = ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', columns: ['State', 'Description', 'Tag'], noDataText: 'No matching records found.' }), ReactableTestUtils.testNode()); + }); + + after(ReactableTestUtils.resetTestEnvironment); + + it('shows the "no data" message', function () { + var $text = $('.reactable-no-data').text(); + expect($text).to.eq('No matching records found.'); + }); + }); + + context('when filtered without any matches', function () { + before(function () { + this.component = ReactDOM.render(React.createElement( + Reactable.Table, + { className: 'table', id: 'table', + filterable: ['State', 'Tag'], + filterPlaceholder: 'Filter Results', + filterBy: 'xxxxx', + noDataText: 'No matching records found.', + columns: ['State', 'Description', 'Tag'] }, + React.createElement( + Reactable.Tr, + null, + React.createElement( + Reactable.Td, + { column: 'State' }, + 'New York' + ), + React.createElement( + Reactable.Td, + { column: 'Description' }, + 'this is some text' + ), + React.createElement( + Reactable.Td, + { column: 'Tag' }, + 'new' + ) + ), + React.createElement( + Reactable.Tr, + null, + React.createElement( + Reactable.Td, + { column: 'State' }, + 'New Mexico' + ), + React.createElement( + Reactable.Td, + { column: 'Description' }, + 'lorem ipsum' + ), + React.createElement( + Reactable.Td, + { column: 'Tag' }, + 'old' + ) + ), + React.createElement( + Reactable.Tr, + null, + React.createElement( + Reactable.Td, + { column: 'State' }, + 'Colorado' + ), + React.createElement( + Reactable.Td, + { column: 'Description' }, + 'new description that shouldnt match filter' + ), + React.createElement( + Reactable.Td, + { column: 'Tag' }, + 'old' + ) + ), + React.createElement( + Reactable.Tr, + null, + React.createElement( + Reactable.Td, + { column: 'State' }, + 'Alaska' + ), + React.createElement( + Reactable.Td, + { column: 'Description' }, + 'bacon' + ), + React.createElement( + Reactable.Td, + { column: 'Tag' }, + 'renewed' + ) + ) + ), ReactableTestUtils.testNode()); + }); + + after(ReactableTestUtils.resetTestEnvironment); + + it('shows the "no data" message', function () { + var text = $('.reactable-no-data').text(); + expect(text).to.eq('No matching records found.'); + }); + }); + + context('when initialized with an empty array for `data` prop', function () { + before(function () { + this.component = ReactDOM.render(React.createElement(Reactable.Table, { data: [], className: 'table', id: 'table', columns: ['State', 'Description', 'Tag'], noDataText: 'No matching records found.' }), ReactableTestUtils.testNode()); + }); + + after(ReactableTestUtils.resetTestEnvironment); + + it('shows the "no data" message', function () { + var $text = $('.reactable-no-data').text(); + expect($text).to.eq('No matching records found.'); + }); + }); + }); + + describe('visibleItems()', function () { + var _Reactable = Reactable; + var Table = _Reactable.Table; + var Thead = _Reactable.Thead; + var Tr = _Reactable.Tr; + var Th = _Reactable.Th; + var Td = _Reactable.Td; + + var data = [{ name: "Lee SomeoneElse", age: 18 }, { name: "Lee Salminen", age: 23 }, { name: "No Age", age: null }]; + + var Tester = (function (_React$Component) { + _inherits(Tester, _React$Component); + + function Tester() { + _classCallCheck(this, Tester); + + _get(Object.getPrototypeOf(Tester.prototype), 'constructor', this).apply(this, arguments); + } + + _createClass(Tester, [{ + key: 'componentDidMount', + value: function componentDidMount() { + this.props.run && this.props.run(this); + } + }, { + key: 'render', + value: function render() { + return React.createElement( + Table, + _extends({ ref: 'table', className: 'table', id: 'table', + filterable: ['Name', 'Age'] }, this.props), + React.createElement( + Thead, + null, + React.createElement( + Th, + { column: 'Name' }, + 'The Name' + ), + React.createElement( + Th, + { column: 'Age' }, + 'The Age' + ) + ), + data.map(function (item, i) { + return React.createElement( + Tr, + { key: i, i: i < 2 ? i : null }, + React.createElement(Td, { column: 'Name', data: item.name }), + React.createElement(Td, { column: 'Age', data: item.age }) + ); + }), + React.createElement( + Tr, + { i: true }, + React.createElement(Td, { column: 'Name', data: "hi" }), + React.createElement(Td, { column: 'Age', data: 5 }) + ), + React.createElement( + Tr, + { id: "id" }, + React.createElement(Td, { column: 'Name', data: "hi" }), + React.createElement(Td, { column: 'Age', data: 7 }) + ) + ); + } + }]); + + return Tester; + })(React.Component); + + var doTest = function doTest(runMe) { + var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + return ReactDOM.render(React.createElement(Tester, _extends({ run: runMe }, options)), ReactableTestUtils.testNode()); + }; + + after(ReactableTestUtils.resetTestEnvironment); + + it('works', function () { + doTest(function (me) { + var items = me.refs.table.visibleItems(); + expect(items.length).to.eql(5); + expect(items[0].Age).to.eql(18); + }); + }); + it('works when filtered', function () { + doTest(function (me) { + var items = me.refs.table.visibleItems(); + expect(items.length).to.eql(2); + expect(items[1].Age).to.eql(23); + }, { filterBy: 'lee' }); + }); + it('works when paged', function () { + doTest(function (me) { + var items = me.refs.table.visibleItems(); + expect(items.length).to.eql(1); + expect(items[0].Age).to.eql(18); + }, { itemsPerPage: 1 }); + }); + it('has keys', function () { + doTest(function (me) { + var items = me.refs.table.visibleItems(); + expect(items[1].id).to.eql(1); + // id is not defined and key is a string + expect(items[2].id).to.eql("2"); + // Falsy ids still count + expect(items[0].id).to.eql(0); + expect(items[3].id).to.eql(true); + expect(items[4].id).to.eql("id"); + }); + }); + }); }); }); diff --git a/lib/reactable/table.js b/lib/reactable/table.js index b2bf8519..26b117be 100644 --- a/lib/reactable/table.js +++ b/lib/reactable/table.js @@ -337,6 +337,25 @@ var Table = (function (_React$Component) { this.setState({ currentSort: currentSort }); this.sortByCurrentSort(); } + }, { + key: 'visibleItems', + value: function visibleItems() { + return this.currentChildren.map(function (item) { + var _item$props = item.props; + var i = _item$props.i; + var id = _item$props.id; + + var iOrId = i != null ? i : id; + var idOrKey = iOrId != null ? iOrId : item.key; + var data = { id: idOrKey }; + + Object.keys(item.props.data).forEach(function (key) { + data[key] = item.props.data[key].value; + }); + + return data; + }); + } }, { key: 'render', value: function render() { @@ -444,6 +463,18 @@ var Table = (function (_React$Component) { // Manually transfer props var props = (0, _libFilter_props_from.filterPropsFrom)(this.props); + var noDataText = this.props.noDataText ? _react2['default'].createElement( + 'tr', + { className: 'reactable-no-data' }, + _react2['default'].createElement( + 'td', + { colSpan: columns.length }, + this.props.noDataText + ) + ) : null; + + this.currentChildren = currentChildren; + return _react2['default'].createElement( 'table', props, @@ -461,7 +492,7 @@ var Table = (function (_React$Component) { _react2['default'].createElement( 'tbody', { className: 'reactable-data', key: 'tbody' }, - currentChildren + currentChildren.length > 0 ? currentChildren : noDataText ), pagination === true ? _react2['default'].createElement(_paginator.Paginator, { colSpan: columns.length, pageButtonLimit: pageButtonLimit, From f55f313d0db8d72e95b1fb1348ccb45b6a790149 Mon Sep 17 00:00:00 2001 From: Folly's Date: Thu, 7 Jan 2016 12:12:22 +0100 Subject: [PATCH 04/35] Don't reset filter on update --- src/reactable/table.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index f30548f1..b6cad39e 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -204,14 +204,14 @@ export class Table extends React.Component { componentWillMount() { this.initialize(this.props); this.sortByCurrentSort(); - this.filterBy(this.props.filterBy); + this.filterBy(this.props.filterBy != null ? this.props.filterBy : this.state.filter); } componentWillReceiveProps(nextProps) { this.initialize(nextProps); this.updateCurrentSort(nextProps.sortBy); this.sortByCurrentSort(); - this.filterBy(nextProps.filterBy); + this.filterBy(nextProps.filterBy != null ? nextProps.filterBy : this.state.filter); } applyFilter(filter, children) { From baa3c1e99c64c2571b4032885e1d4601c6df8600 Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Thu, 7 Jan 2016 12:51:25 +0100 Subject: [PATCH 05/35] build --- build/reactable.js | 6 +++--- lib/reactable/table.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/reactable.js b/build/reactable.js index ce6bdd07..ecac7356 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -1191,7 +1191,7 @@ window.ReactDOM["default"] = window.ReactDOM; value: function componentWillMount() { this.initialize(this.props); this.sortByCurrentSort(); - this.filterBy(this.props.filterBy); + this.filterBy(this.props.filterBy != null ? this.props.filterBy : this.state.filter); } }, { key: 'componentWillReceiveProps', @@ -1199,7 +1199,7 @@ window.ReactDOM["default"] = window.ReactDOM; this.initialize(nextProps); this.updateCurrentSort(nextProps.sortBy); this.sortByCurrentSort(); - this.filterBy(nextProps.filterBy); + this.filterBy(nextProps.filterBy != null ? nextProps.filterBy : this.state.filter); } }, { key: 'applyFilter', @@ -1403,7 +1403,7 @@ window.ReactDOM["default"] = window.ReactDOM; currentPage = numPages - 1; } - pagination = true; + pagination = numPages > 1; currentChildren = filteredChildren.slice(currentPage * itemsPerPage, (currentPage + 1) * itemsPerPage); } diff --git a/lib/reactable/table.js b/lib/reactable/table.js index 26b117be..477ed0f9 100644 --- a/lib/reactable/table.js +++ b/lib/reactable/table.js @@ -244,7 +244,7 @@ var Table = (function (_React$Component) { value: function componentWillMount() { this.initialize(this.props); this.sortByCurrentSort(); - this.filterBy(this.props.filterBy); + this.filterBy(this.props.filterBy != null ? this.props.filterBy : this.state.filter); } }, { key: 'componentWillReceiveProps', @@ -252,7 +252,7 @@ var Table = (function (_React$Component) { this.initialize(nextProps); this.updateCurrentSort(nextProps.sortBy); this.sortByCurrentSort(); - this.filterBy(nextProps.filterBy); + this.filterBy(nextProps.filterBy != null ? nextProps.filterBy : this.state.filter); } }, { key: 'applyFilter', @@ -456,7 +456,7 @@ var Table = (function (_React$Component) { currentPage = numPages - 1; } - pagination = true; + pagination = numPages > 1; currentChildren = filteredChildren.slice(currentPage * itemsPerPage, (currentPage + 1) * itemsPerPage); } From 12277be154ebd87248b1266a19acb5e87bd1df78 Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Thu, 7 Jan 2016 14:02:44 +0100 Subject: [PATCH 06/35] Don't provide default filterBy This made it impossible to see if filterBy was provided by the user --- src/reactable/table.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index 242b72ae..e45066d2 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -475,6 +475,5 @@ Table.defaultProps = { sortBy: false, defaultSort: false, itemsPerPage: 0, - filterBy: '', hideFilterInput: false }; From 688495a3f94c4af9cc759e2e4793dca2c8afc9c1 Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Thu, 7 Jan 2016 14:03:17 +0100 Subject: [PATCH 07/35] build --- build/reactable.js | 1 - lib/reactable/table.js | 1 - 2 files changed, 2 deletions(-) diff --git a/build/reactable.js b/build/reactable.js index ecac7356..87371ed1 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -1463,7 +1463,6 @@ window.ReactDOM["default"] = window.ReactDOM; sortBy: false, defaultSort: false, itemsPerPage: 0, - filterBy: '', hideFilterInput: false }; }); diff --git a/lib/reactable/table.js b/lib/reactable/table.js index 477ed0f9..264f79b0 100644 --- a/lib/reactable/table.js +++ b/lib/reactable/table.js @@ -516,6 +516,5 @@ Table.defaultProps = { sortBy: false, defaultSort: false, itemsPerPage: 0, - filterBy: '', hideFilterInput: false }; From 02b6a7cb4ad053ae9fdbf098ec2137efaf091e76 Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Thu, 7 Jan 2016 18:38:01 +0100 Subject: [PATCH 08/35] i18n --- src/reactable/filterer.jsx | 23 ++++++++++------------- src/reactable/paginator.jsx | 19 ++++++++++++++----- src/reactable/table.jsx | 5 +++-- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/reactable/filterer.jsx b/src/reactable/filterer.jsx index a21cdb19..b8e7c293 100644 --- a/src/reactable/filterer.jsx +++ b/src/reactable/filterer.jsx @@ -1,19 +1,15 @@ import React from 'react'; -import ReactDOM from 'react-dom'; export class FiltererInput extends React.Component { - onChange() { - this.props.onFilter(ReactDOM.findDOMNode(this).value); - } - render() { + const {onFilter, placeholder,value} = this.props return ( - + placeholder={placeholder} + value={value} + onChange={ev => onFilter(ev.target.value)} + /> ); } }; @@ -27,12 +23,13 @@ export class Filterer extends React.Component { return ( - + placeholder={this.props.placeholder} + /> ); } }; - diff --git a/src/reactable/paginator.jsx b/src/reactable/paginator.jsx index 5586c20a..07c3dd38 100644 --- a/src/reactable/paginator.jsx +++ b/src/reactable/paginator.jsx @@ -21,27 +21,38 @@ export class Paginator extends React.Component { } renderPrevious() { + const previousBtn = { + nl: "Vorige", + fr: "Précédente", + en: "Previous", + } + const {locale} = this.props if(this.props.currentPage > 0) { return - Previous + {previousBtn[locale]} } } renderNext() { + const nextBtn = { + nl: "Volgende", + fr: "Suivante", + en: "Next", + } + const {locale} = this.props if(this.props.currentPage < this.props.numPages - 1) { return - Next + {nextBtn[locale]} } } renderPageButton(className, pageNum) { - return upperHalf) { pageButtons.splice(pageButtonLimit, pageButtons.length - pageButtonLimit); } - return ( @@ -105,4 +115,3 @@ export class Paginator extends React.Component { ); } }; - diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index f7e08442..192a2987 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -461,7 +461,7 @@ export class Table extends React.Component { {currentChildren.length > 0 ? currentChildren : noDataText} {pagination === true ? - Date: Thu, 7 Jan 2016 20:05:54 +0100 Subject: [PATCH 09/35] Fallback when locale not available --- src/reactable/paginator.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reactable/paginator.jsx b/src/reactable/paginator.jsx index 07c3dd38..00ca31f8 100644 --- a/src/reactable/paginator.jsx +++ b/src/reactable/paginator.jsx @@ -31,7 +31,7 @@ export class Paginator extends React.Component { return - {previousBtn[locale]} + {previousBtn[locale] || previousBtn.en} } } @@ -47,7 +47,7 @@ export class Paginator extends React.Component { return - {nextBtn[locale]} + {nextBtn[locale] || nextBtn.en} } } From 16c6855eb214febb71a4204b610c5069257efcce Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Thu, 7 Jan 2016 20:07:05 +0100 Subject: [PATCH 10/35] build --- build/reactable.js | 129 +++++++++++++++++++++---------------- lib/reactable/filterer.js | 32 ++++----- lib/reactable/paginator.js | 84 +++++++++++++----------- lib/reactable/table.js | 5 +- 4 files changed, 140 insertions(+), 110 deletions(-) diff --git a/build/reactable.js b/build/reactable.js index 45624eb2..0f020ede 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -201,17 +201,17 @@ window.ReactDOM["default"] = window.ReactDOM; (function (global, factory) { if (typeof define === 'function' && define.amd) { - define(['exports', 'react', 'react-dom'], factory); + define(['exports', 'react'], factory); } else if (typeof exports !== 'undefined') { - factory(exports, require('react'), require('react-dom')); + factory(exports, require('react')); } else { var mod = { exports: {} }; - factory(mod.exports, global.React, global.ReactDOM); + factory(mod.exports, global.React); global.filterer = mod.exports; } -})(this, function (exports, _react, _reactDom) { +})(this, function (exports, _react) { 'use strict'; var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); @@ -232,19 +232,21 @@ window.ReactDOM["default"] = window.ReactDOM; } _createClass(FiltererInput, [{ - key: 'onChange', - value: function onChange() { - this.props.onFilter(_reactDom['default'].findDOMNode(this).value); - } - }, { key: 'render', value: function render() { - return _react['default'].createElement('input', { type: 'text', + var _props = this.props; + var onFilter = _props.onFilter; + var placeholder = _props.placeholder; + var value = _props.value; + + return _react['default'].createElement('input', { className: 'reactable-filter-input', - placeholder: this.props.placeholder, - value: this.props.value, - onKeyUp: this.onChange.bind(this), - onChange: this.onChange.bind(this) }); + placeholder: placeholder, + value: value, + onChange: function (ev) { + return onFilter(ev.target.value); + } + }); } }]); @@ -276,9 +278,11 @@ window.ReactDOM["default"] = window.ReactDOM; _react['default'].createElement( 'td', { colSpan: this.props.colSpan }, - _react['default'].createElement(FiltererInput, { onFilter: this.props.onFilter, + _react['default'].createElement(FiltererInput, { + onFilter: this.props.onFilter, value: this.props.value, - placeholder: this.props.placeholder }) + placeholder: this.props.placeholder + }) ) ); } @@ -797,10 +801,10 @@ window.ReactDOM["default"] = window.ReactDOM; }); (function (global, factory) { - if (typeof define === 'function' && define.amd) { - define(['exports', 'react'], factory); - } else if (typeof exports !== 'undefined') { - factory(exports, require('react')); + if (typeof define === "function" && define.amd) { + define(["exports", "react"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("react")); } else { var mod = { exports: {} @@ -809,18 +813,18 @@ window.ReactDOM["default"] = window.ReactDOM; global.paginator = mod.exports; } })(this, function (exports, _react) { - 'use strict'; + "use strict"; - var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; + var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function pageHref(num) { - return '#page-' + (num + 1); + return "#page-" + (num + 1); } var Paginator = (function (_React$Component) { @@ -829,59 +833,72 @@ window.ReactDOM["default"] = window.ReactDOM; function Paginator() { _classCallCheck(this, Paginator); - _get(Object.getPrototypeOf(Paginator.prototype), 'constructor', this).apply(this, arguments); + _get(Object.getPrototypeOf(Paginator.prototype), "constructor", this).apply(this, arguments); } _createClass(Paginator, [{ - key: 'handlePrevious', + key: "handlePrevious", value: function handlePrevious(e) { e.preventDefault(); this.props.onPageChange(this.props.currentPage - 1); } }, { - key: 'handleNext', + key: "handleNext", value: function handleNext(e) { e.preventDefault(); this.props.onPageChange(this.props.currentPage + 1); } }, { - key: 'handlePageButton', + key: "handlePageButton", value: function handlePageButton(page, e) { e.preventDefault(); this.props.onPageChange(page); } }, { - key: 'renderPrevious', + key: "renderPrevious", value: function renderPrevious() { + var previousBtn = { + nl: "Vorige", + fr: "Précédente", + en: "Previous" + }; + var locale = this.props.locale; + if (this.props.currentPage > 0) { - return _react['default'].createElement( - 'a', - { className: 'reactable-previous-page', + return _react["default"].createElement( + "a", + { className: "reactable-previous-page", href: pageHref(this.props.currentPage - 1), onClick: this.handlePrevious.bind(this) }, - 'Previous' + previousBtn[locale] || previousBtn.en ); } } }, { - key: 'renderNext', + key: "renderNext", value: function renderNext() { + var nextBtn = { + nl: "Volgende", + fr: "Suivante", + en: "Next" + }; + var locale = this.props.locale; + if (this.props.currentPage < this.props.numPages - 1) { - return _react['default'].createElement( - 'a', - { className: 'reactable-next-page', + return _react["default"].createElement( + "a", + { className: "reactable-next-page", href: pageHref(this.props.currentPage + 1), onClick: this.handleNext.bind(this) }, - 'Next' + nextBtn[locale] || nextBtn.en ); } } }, { - key: 'renderPageButton', + key: "renderPageButton", value: function renderPageButton(className, pageNum) { - - return _react['default'].createElement( - 'a', + return _react["default"].createElement( + "a", { className: className, key: pageNum, href: pageHref(pageNum), @@ -890,7 +907,7 @@ window.ReactDOM["default"] = window.ReactDOM; ); } }, { - key: 'render', + key: "render", value: function render() { if (typeof this.props.colSpan === 'undefined') { throw new TypeError('Must pass a colSpan argument to Paginator'); @@ -932,15 +949,14 @@ window.ReactDOM["default"] = window.ReactDOM; if (numPages - currentPage > upperHalf) { pageButtons.splice(pageButtonLimit, pageButtons.length - pageButtonLimit); } - - return _react['default'].createElement( - 'tbody', - { className: 'reactable-pagination' }, - _react['default'].createElement( - 'tr', + return _react["default"].createElement( + "tbody", + { className: "reactable-pagination" }, + _react["default"].createElement( + "tr", null, - _react['default'].createElement( - 'td', + _react["default"].createElement( + "td", { colSpan: this.props.colSpan }, this.renderPrevious(), pageButtons, @@ -952,7 +968,7 @@ window.ReactDOM["default"] = window.ReactDOM; }]); return Paginator; - })(_react['default'].Component); + })(_react["default"].Component); exports.Paginator = Paginator; ; @@ -1445,7 +1461,7 @@ window.ReactDOM["default"] = window.ReactDOM; { className: 'reactable-data', key: 'tbody' }, currentChildren.length > 0 ? currentChildren : noDataText ), - pagination === true ? _react['default'].createElement(_paginator.Paginator, { colSpan: columns.length, + pagination === true ? _react['default'].createElement(_paginator.Paginator, { locale: props.locale, colSpan: columns.length, pageButtonLimit: pageButtonLimit, numPages: numPages, currentPage: currentPage, @@ -1467,7 +1483,8 @@ window.ReactDOM["default"] = window.ReactDOM; sortBy: false, defaultSort: false, itemsPerPage: 0, - hideFilterInput: false + hideFilterInput: false, + locale: 'en' }; }); diff --git a/lib/reactable/filterer.js b/lib/reactable/filterer.js index b88f7f28..25448fda 100644 --- a/lib/reactable/filterer.js +++ b/lib/reactable/filterer.js @@ -18,10 +18,6 @@ var _react = require('react'); var _react2 = _interopRequireDefault(_react); -var _reactDom = require('react-dom'); - -var _reactDom2 = _interopRequireDefault(_reactDom); - var FiltererInput = (function (_React$Component) { _inherits(FiltererInput, _React$Component); @@ -32,19 +28,21 @@ var FiltererInput = (function (_React$Component) { } _createClass(FiltererInput, [{ - key: 'onChange', - value: function onChange() { - this.props.onFilter(_reactDom2['default'].findDOMNode(this).value); - } - }, { key: 'render', value: function render() { - return _react2['default'].createElement('input', { type: 'text', + var _props = this.props; + var onFilter = _props.onFilter; + var placeholder = _props.placeholder; + var value = _props.value; + + return _react2['default'].createElement('input', { className: 'reactable-filter-input', - placeholder: this.props.placeholder, - value: this.props.value, - onKeyUp: this.onChange.bind(this), - onChange: this.onChange.bind(this) }); + placeholder: placeholder, + value: value, + onChange: function (ev) { + return onFilter(ev.target.value); + } + }); } }]); @@ -76,9 +74,11 @@ var Filterer = (function (_React$Component2) { _react2['default'].createElement( 'td', { colSpan: this.props.colSpan }, - _react2['default'].createElement(FiltererInput, { onFilter: this.props.onFilter, + _react2['default'].createElement(FiltererInput, { + onFilter: this.props.onFilter, value: this.props.value, - placeholder: this.props.placeholder }) + placeholder: this.props.placeholder + }) ) ); } diff --git a/lib/reactable/paginator.js b/lib/reactable/paginator.js index 34b90839..08770615 100644 --- a/lib/reactable/paginator.js +++ b/lib/reactable/paginator.js @@ -1,25 +1,25 @@ -'use strict'; +"use strict"; -Object.defineProperty(exports, '__esModule', { +Object.defineProperty(exports, "__esModule", { value: true }); -var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); -var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; +var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _react = require('react'); var _react2 = _interopRequireDefault(_react); function pageHref(num) { - return '#page-' + (num + 1); + return "#page-" + (num + 1); } var Paginator = (function (_React$Component) { @@ -28,59 +28,72 @@ var Paginator = (function (_React$Component) { function Paginator() { _classCallCheck(this, Paginator); - _get(Object.getPrototypeOf(Paginator.prototype), 'constructor', this).apply(this, arguments); + _get(Object.getPrototypeOf(Paginator.prototype), "constructor", this).apply(this, arguments); } _createClass(Paginator, [{ - key: 'handlePrevious', + key: "handlePrevious", value: function handlePrevious(e) { e.preventDefault(); this.props.onPageChange(this.props.currentPage - 1); } }, { - key: 'handleNext', + key: "handleNext", value: function handleNext(e) { e.preventDefault(); this.props.onPageChange(this.props.currentPage + 1); } }, { - key: 'handlePageButton', + key: "handlePageButton", value: function handlePageButton(page, e) { e.preventDefault(); this.props.onPageChange(page); } }, { - key: 'renderPrevious', + key: "renderPrevious", value: function renderPrevious() { + var previousBtn = { + nl: "Vorige", + fr: "Précédente", + en: "Previous" + }; + var locale = this.props.locale; + if (this.props.currentPage > 0) { - return _react2['default'].createElement( - 'a', - { className: 'reactable-previous-page', + return _react2["default"].createElement( + "a", + { className: "reactable-previous-page", href: pageHref(this.props.currentPage - 1), onClick: this.handlePrevious.bind(this) }, - 'Previous' + previousBtn[locale] || previousBtn.en ); } } }, { - key: 'renderNext', + key: "renderNext", value: function renderNext() { + var nextBtn = { + nl: "Volgende", + fr: "Suivante", + en: "Next" + }; + var locale = this.props.locale; + if (this.props.currentPage < this.props.numPages - 1) { - return _react2['default'].createElement( - 'a', - { className: 'reactable-next-page', + return _react2["default"].createElement( + "a", + { className: "reactable-next-page", href: pageHref(this.props.currentPage + 1), onClick: this.handleNext.bind(this) }, - 'Next' + nextBtn[locale] || nextBtn.en ); } } }, { - key: 'renderPageButton', + key: "renderPageButton", value: function renderPageButton(className, pageNum) { - - return _react2['default'].createElement( - 'a', + return _react2["default"].createElement( + "a", { className: className, key: pageNum, href: pageHref(pageNum), @@ -89,7 +102,7 @@ var Paginator = (function (_React$Component) { ); } }, { - key: 'render', + key: "render", value: function render() { if (typeof this.props.colSpan === 'undefined') { throw new TypeError('Must pass a colSpan argument to Paginator'); @@ -131,15 +144,14 @@ var Paginator = (function (_React$Component) { if (numPages - currentPage > upperHalf) { pageButtons.splice(pageButtonLimit, pageButtons.length - pageButtonLimit); } - - return _react2['default'].createElement( - 'tbody', - { className: 'reactable-pagination' }, - _react2['default'].createElement( - 'tr', + return _react2["default"].createElement( + "tbody", + { className: "reactable-pagination" }, + _react2["default"].createElement( + "tr", null, - _react2['default'].createElement( - 'td', + _react2["default"].createElement( + "td", { colSpan: this.props.colSpan }, this.renderPrevious(), pageButtons, @@ -151,7 +163,7 @@ var Paginator = (function (_React$Component) { }]); return Paginator; -})(_react2['default'].Component); +})(_react2["default"].Component); exports.Paginator = Paginator; ; diff --git a/lib/reactable/table.js b/lib/reactable/table.js index e0e0c415..722f0939 100644 --- a/lib/reactable/table.js +++ b/lib/reactable/table.js @@ -498,7 +498,7 @@ var Table = (function (_React$Component) { { className: 'reactable-data', key: 'tbody' }, currentChildren.length > 0 ? currentChildren : noDataText ), - pagination === true ? _react2['default'].createElement(_paginator.Paginator, { colSpan: columns.length, + pagination === true ? _react2['default'].createElement(_paginator.Paginator, { locale: props.locale, colSpan: columns.length, pageButtonLimit: pageButtonLimit, numPages: numPages, currentPage: currentPage, @@ -520,5 +520,6 @@ Table.defaultProps = { sortBy: false, defaultSort: false, itemsPerPage: 0, - hideFilterInput: false + hideFilterInput: false, + locale: 'en' }; From ad2f0dd417393689c749cf3ec8540b78f9fb4cd0 Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Fri, 15 Jan 2016 16:40:50 +0100 Subject: [PATCH 11/35] WIL-1240 Implement top-side pagination. Done for the inbox. The dropdown is not gonna work though, because of the lack of flags --- src/reactable/paginatorInbox.jsx | 71 +++++++++++++++++++++++ src/reactable/table.jsx | 97 ++++++++++++++++++++++---------- 2 files changed, 138 insertions(+), 30 deletions(-) create mode 100644 src/reactable/paginatorInbox.jsx diff --git a/src/reactable/paginatorInbox.jsx b/src/reactable/paginatorInbox.jsx new file mode 100644 index 00000000..ed090b1a --- /dev/null +++ b/src/reactable/paginatorInbox.jsx @@ -0,0 +1,71 @@ +import React from 'react'; + +function pageHref(num) { + return `#page-${num + 1}` +} + +export class PaginatorInbox extends React.Component { + handlePrevious(e) { + e.preventDefault() + this.props.onPageChange(this.props.currentPage - 1) + } + + handleNext(e) { + e.preventDefault() + this.props.onPageChange(this.props.currentPage + 1); + } + + renderPrevious() { + return + + } + + renderNext() { + return + + } + + calcRange() { + const {currentPage, itemsNumber, itemsPerPage} = this.props + const fromVal = currentPage * itemsPerPage + 1 + const toValTmp = ((currentPage + 1) * itemsPerPage) + const toVal = toValTmp < itemsNumber ? toValTmp : itemsNumber + return `${fromVal} - ${toVal}` + } + + renderCounter() { + const {itemsNumber} = this.props + return
+ {this.calcRange()} + van + {itemsNumber} +
+ } + + render() { + if (typeof this.props.colSpan === 'undefined') { + throw new TypeError('Must pass a colSpan argument to Paginator'); + } + + if (typeof this.props.numPages === 'undefined') { + throw new TypeError('Must pass a non-zero numPages argument to Paginator'); + } + + if (typeof this.props.currentPage === 'undefined') { + throw new TypeError('Must pass a currentPage argument to Paginator'); + } + return ( +
+ {this.renderCounter()} +
+ {this.renderPrevious()} + {this.renderNext()} +
+
+ ); + } +}; diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index 192a2987..0602b1e6 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -7,6 +7,8 @@ import { Th } from './th'; import { Tr } from './tr'; import { Tfoot } from './tfoot'; import { Paginator } from './paginator'; +import { PaginatorInbox } from './PaginatorInbox'; +import { FiltererInput } from './filterer'; export class Table extends React.Component { constructor(props) { @@ -398,8 +400,10 @@ export class Table extends React.Component { // Determine if we render the filter box let filtering = false; + let filterType = "default"; if ( this.props.filterable && + this.props.filterType !== "top" && Array.isArray(this.props.filterable) && this.props.filterable.length > 0 && !this.props.hideFilterInput @@ -407,6 +411,10 @@ export class Table extends React.Component { filtering = true; } + if (this.props.filterType === "top") { + filterType = "top" + } + // Apply filters let filteredChildren = children; if (this.state.filter !== '') { @@ -415,6 +423,7 @@ export class Table extends React.Component { // Determine pagination properties and which columns to display let itemsPerPage = 0; + let pagiPosition = this.props.pagiPosition || 'bottom'; let pagination = false; let numPages; let currentPage = this.state.currentPage; @@ -442,36 +451,64 @@ export class Table extends React.Component { let noDataText = this.props.noDataText ? {this.props.noDataText} : null; this.currentChildren = currentChildren; - - return - {columns && columns.length > 0 ? - { - this.setState({ filter: filter }); - }} - filterPlaceholder={this.props.filterPlaceholder} - currentFilter={this.state.filter} - sort={this.state.currentSort} - sortableColumns={this._sortable} - onSort={this.onSort.bind(this)} - key="thead"/> - : null} - - {currentChildren.length > 0 ? currentChildren : noDataText} - - {pagination === true ? - { - this.setState({ currentPage: page }); - }} - key="paginator"/> - : null} - {this.tfoot} -
; + return
+
+ {this.props.customElemL} + {filterType === 'top' && + { + this.setState({ filter: filter }); + }} + placeholder={this.props.filterPlaceholder} + currentFilter={this.state.filter} + /> + } + {pagination && (pagiPosition === 'top') ? + { + this.setState({ currentPage: page }); + }} + key="paginator"/> : null + } + {this.props.customElemR} +
+ + {columns && columns.length > 0 ? + { + this.setState({ filter: filter }); + }} + filterPlaceholder={this.props.filterPlaceholder} + currentFilter={this.state.filter} + sort={this.state.currentSort} + sortableColumns={this._sortable} + onSort={this.onSort.bind(this)} + key="thead"/> + : null} + + {currentChildren.length > 0 ? currentChildren : noDataText} + + {pagination && (pagiPosition === 'bottom') ? + { + this.setState({ currentPage: page }); + }} + key="paginator"/> + : null} + {this.tfoot} +
+
} } From 5a20f18183f6af55261f913e39c43874777b92c2 Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Mon, 18 Jan 2016 14:35:22 +0100 Subject: [PATCH 12/35] WIL-1152 after click "next" to go to the next page it should scroll up the page --- src/reactable/table.jsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index 0602b1e6..d6f00223 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -321,6 +321,12 @@ export class Table extends React.Component { }) } + scrollToTop() { + if(document.querySelectorAll('table').length < 2) { + document.querySelector('table tr:first-child').scrollIntoView() + } + } + render() { let children = []; let columns; @@ -479,7 +485,6 @@ export class Table extends React.Component { } {this.props.customElemR} - {columns && columns.length > 0 ? { this.setState({ currentPage: page }); + this.scrollToTop() }} key="paginator"/> : null} From 86407964e6dec1bab78107de47a6b0b37bc0599e Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Tue, 26 Jan 2016 17:47:50 +0100 Subject: [PATCH 13/35] better API and add bottom pager --- Gruntfile.js | 4 +- .../{paginatorInbox.jsx => btnPaginator.jsx} | 49 ++++--- src/reactable/paginator.jsx | 38 ++++-- src/reactable/table.jsx | 128 ++++++++---------- src/reactable/thead.jsx | 31 ++++- 5 files changed, 146 insertions(+), 104 deletions(-) rename src/reactable/{paginatorInbox.jsx => btnPaginator.jsx} (52%) diff --git a/Gruntfile.js b/Gruntfile.js index 728df8df..dadd7a21 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -45,6 +45,7 @@ module.exports = function(grunt) { 'tmp/reactable/unsafe.js': 'src/reactable/unsafe.jsx', 'tmp/reactable/th.js': 'src/reactable/th.jsx', 'tmp/reactable/paginator.js': 'src/reactable/paginator.jsx', + 'tmp/reactable/btnPaginator.js': 'src/reactable/btnPaginator.jsx', 'tmp/reactable/table.js': 'src/reactable/table.jsx', 'tmp/reactable.js': 'src/reactable.jsx', @@ -69,6 +70,7 @@ module.exports = function(grunt) { 'lib/reactable/unsafe.js': 'src/reactable/unsafe.jsx', 'lib/reactable/th.js': 'src/reactable/th.jsx', 'lib/reactable/paginator.js': 'src/reactable/paginator.jsx', + 'lib/reactable/btnPaginator.js': 'src/reactable/btnPaginator.jsx', 'lib/reactable/table.js': 'src/reactable/table.jsx', 'lib/reactable.js': 'src/reactable.jsx', @@ -94,6 +96,7 @@ module.exports = function(grunt) { 'tmp/reactable/th.js', 'tmp/reactable/thead.js', 'tmp/reactable/tfoot.js', + 'tmp/reactable/btnPaginator.js', 'tmp/reactable/paginator.js', 'tmp/reactable/table.js', 'tmp/reactable.js' @@ -131,4 +134,3 @@ module.exports = function(grunt) { grunt.registerTask('build', ['babel:common', 'buildBrowser']); grunt.registerTask('default', ['build', 'watch:build']); }; - diff --git a/src/reactable/paginatorInbox.jsx b/src/reactable/btnPaginator.jsx similarity index 52% rename from src/reactable/paginatorInbox.jsx rename to src/reactable/btnPaginator.jsx index ed090b1a..64f1be32 100644 --- a/src/reactable/paginatorInbox.jsx +++ b/src/reactable/btnPaginator.jsx @@ -4,29 +4,43 @@ function pageHref(num) { return `#page-${num + 1}` } -export class PaginatorInbox extends React.Component { +const tr = { + of: { + nl: "van", + fr: "de", + de: "von", + en: "of", + } +} + +export class BtnPaginator extends React.Component { + constructor(props) { + super(props); + this.handlePrevious = this.handlePrevious.bind(this); + this.handleNext = this.handleNext.bind(this); + } handlePrevious(e) { - e.preventDefault() + e.preventDefault(); this.props.onPageChange(this.props.currentPage - 1) } handleNext(e) { - e.preventDefault() + e.preventDefault(); this.props.onPageChange(this.props.currentPage + 1); } renderPrevious() { - return - + onClick={this.handlePrevious}> + } renderNext() { - return - + onClick={this.handleNext}> + } calcRange() { @@ -38,30 +52,21 @@ export class PaginatorInbox extends React.Component { } renderCounter() { - const {itemsNumber} = this.props + const {itemsNumber, locale} = this.props return
- {this.calcRange()} - van - {itemsNumber} + {this.calcRange()} {tr.of[locale]} {itemsNumber}
} render() { - if (typeof this.props.colSpan === 'undefined') { - throw new TypeError('Must pass a colSpan argument to Paginator'); - } - - if (typeof this.props.numPages === 'undefined') { - throw new TypeError('Must pass a non-zero numPages argument to Paginator'); - } if (typeof this.props.currentPage === 'undefined') { throw new TypeError('Must pass a currentPage argument to Paginator'); } return ( -
+
{this.renderCounter()} -
+
{this.renderPrevious()} {this.renderNext()}
diff --git a/src/reactable/paginator.jsx b/src/reactable/paginator.jsx index 00ca31f8..0c863580 100644 --- a/src/reactable/paginator.jsx +++ b/src/reactable/paginator.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import { BtnPaginator } from './btnPaginator'; function pageHref(num) { return `#page-${num + 1}` @@ -75,9 +76,7 @@ export class Paginator extends React.Component { } let pageButtons = []; - let pageButtonLimit = this.props.pageButtonLimit; - let currentPage = this.props.currentPage; - let numPages = this.props.numPages; + const {locale, bottomPaginationElem, onPageChange, itemsNumber, itemsPerPage, bottomPagination, pageButtonLimit, currentPage, numPages} = this.props; let lowerHalf = Math.round( pageButtonLimit / 2 ); let upperHalf = (pageButtonLimit - lowerHalf); @@ -104,13 +103,32 @@ export class Paginator extends React.Component { } return (
- - - + {bottomPagination ? + + + : + + + + } ); } diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index d6f00223..41507931 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -7,8 +7,6 @@ import { Th } from './th'; import { Tr } from './tr'; import { Tfoot } from './tfoot'; import { Paginator } from './paginator'; -import { PaginatorInbox } from './PaginatorInbox'; -import { FiltererInput } from './filterer'; export class Table extends React.Component { constructor(props) { @@ -322,8 +320,8 @@ export class Table extends React.Component { } scrollToTop() { - if(document.querySelectorAll('table').length < 2) { - document.querySelector('table tr:first-child').scrollIntoView() + if (this.tableEl) { + this.tableEl.scrollIntoView(); } } @@ -406,10 +404,9 @@ export class Table extends React.Component { // Determine if we render the filter box let filtering = false; - let filterType = "default"; if ( this.props.filterable && - this.props.filterType !== "top" && + !this.props.topPagination && Array.isArray(this.props.filterable) && this.props.filterable.length > 0 && !this.props.hideFilterInput @@ -417,10 +414,6 @@ export class Table extends React.Component { filtering = true; } - if (this.props.filterType === "top") { - filterType = "top" - } - // Apply filters let filteredChildren = children; if (this.state.filter !== '') { @@ -429,8 +422,9 @@ export class Table extends React.Component { // Determine pagination properties and which columns to display let itemsPerPage = 0; - let pagiPosition = this.props.pagiPosition || 'bottom'; let pagination = false; + let topPagination = this.props.topPagination || false; + let bottomPagination = this.props.bottomPagination || false; let numPages; let currentPage = this.state.currentPage; let pageButtonLimit = this.props.pageButtonLimit || 10; @@ -457,64 +451,60 @@ export class Table extends React.Component { let noDataText = this.props.noDataText ? : null; this.currentChildren = currentChildren; - return
-
- {this.props.customElemL} - {filterType === 'top' && - { - this.setState({ filter: filter }); - }} - placeholder={this.props.filterPlaceholder} - currentFilter={this.state.filter} - /> - } - {pagination && (pagiPosition === 'top') ? - { - this.setState({ currentPage: page }); - }} - key="paginator"/> : null - } - {this.props.customElemR} -
- {columns && columns.length > 0 ? -
{ - this.setState({ filter: filter }); - }} - filterPlaceholder={this.props.filterPlaceholder} - currentFilter={this.state.filter} - sort={this.state.currentSort} - sortableColumns={this._sortable} - onSort={this.onSort.bind(this)} - key="thead"/> - : null} - - {currentChildren.length > 0 ? currentChildren : noDataText} - - {pagination && (pagiPosition === 'bottom') ? - { - this.setState({ currentPage: page }); - this.scrollToTop() - }} - key="paginator"/> - : null} - {this.tfoot} -
- {this.renderPrevious()} - {pageButtons} - {this.renderNext()} -
+
+ {bottomPaginationElem.left} + + {bottomPaginationElem.right} +
+
+ {this.renderPrevious()} + {pageButtons} + {this.renderNext()} +
{this.props.noDataText}
- + return this.tableEl = t}> + {columns && columns.length > 0 ? + { + this.setState({ filter: filter }); + }} + onPageChange={page => { + this.setState({ currentPage: page }); + this.scrollToTop(); + }} + filterPlaceholder={this.props.filterPlaceholder} + currentFilter={this.state.filter} + sort={this.state.currentSort} + sortableColumns={this._sortable} + onSort={this.onSort.bind(this)} + key="thead" + locale={props.locale} + /> : null + } + + {currentChildren.length > 0 ? currentChildren : noDataText} + + {pagination ? + { + this.setState({ currentPage: page }); + this.scrollToTop() + }} + key="paginator" + /> : null + } + {this.tfoot} +
} } diff --git a/src/reactable/thead.jsx b/src/reactable/thead.jsx index aba0226d..73403e63 100644 --- a/src/reactable/thead.jsx +++ b/src/reactable/thead.jsx @@ -3,6 +3,9 @@ import { Th } from './th'; import { Filterer } from './filterer'; import { filterPropsFrom } from './lib/filter_props_from'; +import { BtnPaginator } from './btnPaginator'; +import { FiltererInput } from './filterer'; + export class Thead extends React.Component { static getColumns(component) { // Can't use React.Children.map since that doesn't return a proper array @@ -77,7 +80,6 @@ export class Thead extends React.Component { // Manually transfer props var props = filterPropsFrom(this.props); - return ( {this.props.filtering === true ? @@ -86,7 +88,32 @@ export class Thead extends React.Component { onFilter={this.props.onFilter} placeholder={this.props.filterPlaceholder} value={this.props.currentFilter} - /> : null} + /> : null + } + {this.props.topPagination ? + + +
+ {this.props.topPaginationElem.left} + + + {this.props.topPaginationElem.right} +
+ + : null + } {Ths} ); From 9c0b46cdd25fc7c7f53c27d9ab106388fe22b6ba Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Tue, 26 Jan 2016 18:05:27 +0100 Subject: [PATCH 14/35] build --- build/reactable.js | 301 +++++++++++++++++++++++++++++----- lib/reactable/btnPaginator.js | 126 ++++++++++++++ lib/reactable/paginator.js | 102 ++++++++---- lib/reactable/table.js | 47 +++++- lib/reactable/thead.js | 31 +++- 5 files changed, 526 insertions(+), 81 deletions(-) create mode 100644 lib/reactable/btnPaginator.js diff --git a/build/reactable.js b/build/reactable.js index 0f020ede..c621d3dd 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -626,17 +626,17 @@ window.ReactDOM["default"] = window.ReactDOM; (function (global, factory) { if (typeof define === 'function' && define.amd) { - define(['exports', 'react', './th', './filterer', './lib/filter_props_from'], factory); + define(['exports', 'react', './th', './filterer', './lib/filter_props_from', './btnPaginator'], factory); } else if (typeof exports !== 'undefined') { - factory(exports, require('react'), require('./th'), require('./filterer'), require('./lib/filter_props_from')); + factory(exports, require('react'), require('./th'), require('./filterer'), require('./lib/filter_props_from'), require('./btnPaginator')); } else { var mod = { exports: {} }; - factory(mod.exports, global.React, global.th, global.filterer, global.filter_props_from); + factory(mod.exports, global.React, global.th, global.filterer, global.filter_props_from, global.btnPaginator); global.thead = mod.exports; } -})(this, function (exports, _react, _th, _filterer, _libFilter_props_from) { +})(this, function (exports, _react, _th, _filterer, _libFilter_props_from, _btnPaginator) { 'use strict'; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; @@ -708,7 +708,6 @@ window.ReactDOM["default"] = window.ReactDOM; // Manually transfer props var props = (0, _libFilter_props_from.filterPropsFrom)(this.props); - return _react['default'].createElement( 'thead', props, @@ -718,6 +717,34 @@ window.ReactDOM["default"] = window.ReactDOM; placeholder: this.props.filterPlaceholder, value: this.props.currentFilter }) : null, + this.props.topPagination ? _react['default'].createElement( + 'tr', + { className: 'reactable-btnPagination' }, + _react['default'].createElement( + 'td', + { colSpan: this.props.columns.length }, + _react['default'].createElement( + 'div', + { className: 'reactable-topDesign' }, + this.props.topPaginationElem.left, + _react['default'].createElement(_filterer.FiltererInput, { + onFilter: this.props.onFilter, + placeholder: this.props.filterPlaceholder, + value: this.props.currentFilter + }), + _react['default'].createElement(_btnPaginator.BtnPaginator, { + locale: this.props.locale, + itemsPerPage: this.props.itemsPerPage, + itemsNumber: this.props.itemsNumber, + numPages: this.props.numPages, + currentPage: this.props.currentPage, + onPageChange: this.props.onPageChange, + key: 'paginator' + }), + this.props.topPaginationElem.right + ) + ) + ) : null, _react['default'].createElement( 'tr', { className: 'reactable-column-header' }, @@ -810,7 +837,7 @@ window.ReactDOM["default"] = window.ReactDOM; exports: {} }; factory(mod.exports, global.React); - global.paginator = mod.exports; + global.btnPaginator = mod.exports; } })(this, function (exports, _react) { "use strict"; @@ -827,35 +854,166 @@ window.ReactDOM["default"] = window.ReactDOM; return "#page-" + (num + 1); } + var tr = { + of: { + nl: "van", + fr: "de", + de: "von", + en: "of" + } + }; + + var BtnPaginator = (function (_React$Component) { + _inherits(BtnPaginator, _React$Component); + + function BtnPaginator(props) { + _classCallCheck(this, BtnPaginator); + + _get(Object.getPrototypeOf(BtnPaginator.prototype), "constructor", this).call(this, props); + this.handlePrevious = this.handlePrevious.bind(this); + this.handleNext = this.handleNext.bind(this); + } + + _createClass(BtnPaginator, [{ + key: "handlePrevious", + value: function handlePrevious(e) { + e.preventDefault(); + this.props.onPageChange(this.props.currentPage - 1); + } + }, { + key: "handleNext", + value: function handleNext(e) { + e.preventDefault(); + this.props.onPageChange(this.props.currentPage + 1); + } + }, { + key: "renderPrevious", + value: function renderPrevious() { + return _react["default"].createElement("button", { className: "reactable-previous-page " + (this.props.currentPage === 0 ? "disabled" : null), + href: pageHref(this.props.currentPage - 1), + onClick: this.handlePrevious }); + } + }, { + key: "renderNext", + value: function renderNext() { + return _react["default"].createElement("button", { className: "reactable-next-page " + (this.props.currentPage + 1 === this.props.numPages ? "disabled" : null), + href: pageHref(this.props.currentPage + 1), + onClick: this.handleNext }); + } + }, { + key: "calcRange", + value: function calcRange() { + var _props = this.props; + var currentPage = _props.currentPage; + var itemsNumber = _props.itemsNumber; + var itemsPerPage = _props.itemsPerPage; + + var fromVal = currentPage * itemsPerPage + 1; + var toValTmp = (currentPage + 1) * itemsPerPage; + var toVal = toValTmp < itemsNumber ? toValTmp : itemsNumber; + return fromVal + " - " + toVal; + } + }, { + key: "renderCounter", + value: function renderCounter() { + var _props2 = this.props; + var itemsNumber = _props2.itemsNumber; + var locale = _props2.locale; + + return _react["default"].createElement( + "div", + { className: "counter" }, + this.calcRange(), + " ", + tr.of[locale], + " ", + itemsNumber + ); + } + }, { + key: "render", + value: function render() { + + if (typeof this.props.currentPage === 'undefined') { + throw new TypeError('Must pass a currentPage argument to Paginator'); + } + return _react["default"].createElement( + "div", + { className: "reactable-pagesSwitcher" }, + this.renderCounter(), + _react["default"].createElement( + "div", + { className: "reactable-pageBtns" }, + this.renderPrevious(), + this.renderNext() + ) + ); + } + }]); + + return BtnPaginator; + })(_react["default"].Component); + + exports.BtnPaginator = BtnPaginator; + ; +}); + +(function (global, factory) { + if (typeof define === 'function' && define.amd) { + define(['exports', 'react', './btnPaginator'], factory); + } else if (typeof exports !== 'undefined') { + factory(exports, require('react'), require('./btnPaginator')); + } else { + var mod = { + exports: {} + }; + factory(mod.exports, global.React, global.btnPaginator); + global.paginator = mod.exports; + } +})(this, function (exports, _react, _btnPaginator) { + 'use strict'; + + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + + var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; + + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + + function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + + function pageHref(num) { + return '#page-' + (num + 1); + } + var Paginator = (function (_React$Component) { _inherits(Paginator, _React$Component); function Paginator() { _classCallCheck(this, Paginator); - _get(Object.getPrototypeOf(Paginator.prototype), "constructor", this).apply(this, arguments); + _get(Object.getPrototypeOf(Paginator.prototype), 'constructor', this).apply(this, arguments); } _createClass(Paginator, [{ - key: "handlePrevious", + key: 'handlePrevious', value: function handlePrevious(e) { e.preventDefault(); this.props.onPageChange(this.props.currentPage - 1); } }, { - key: "handleNext", + key: 'handleNext', value: function handleNext(e) { e.preventDefault(); this.props.onPageChange(this.props.currentPage + 1); } }, { - key: "handlePageButton", + key: 'handlePageButton', value: function handlePageButton(page, e) { e.preventDefault(); this.props.onPageChange(page); } }, { - key: "renderPrevious", + key: 'renderPrevious', value: function renderPrevious() { var previousBtn = { nl: "Vorige", @@ -865,9 +1023,9 @@ window.ReactDOM["default"] = window.ReactDOM; var locale = this.props.locale; if (this.props.currentPage > 0) { - return _react["default"].createElement( - "a", - { className: "reactable-previous-page", + return _react['default'].createElement( + 'a', + { className: 'reactable-previous-page', href: pageHref(this.props.currentPage - 1), onClick: this.handlePrevious.bind(this) }, previousBtn[locale] || previousBtn.en @@ -875,7 +1033,7 @@ window.ReactDOM["default"] = window.ReactDOM; } } }, { - key: "renderNext", + key: 'renderNext', value: function renderNext() { var nextBtn = { nl: "Volgende", @@ -885,9 +1043,9 @@ window.ReactDOM["default"] = window.ReactDOM; var locale = this.props.locale; if (this.props.currentPage < this.props.numPages - 1) { - return _react["default"].createElement( - "a", - { className: "reactable-next-page", + return _react['default'].createElement( + 'a', + { className: 'reactable-next-page', href: pageHref(this.props.currentPage + 1), onClick: this.handleNext.bind(this) }, nextBtn[locale] || nextBtn.en @@ -895,10 +1053,10 @@ window.ReactDOM["default"] = window.ReactDOM; } } }, { - key: "renderPageButton", + key: 'renderPageButton', value: function renderPageButton(className, pageNum) { - return _react["default"].createElement( - "a", + return _react['default'].createElement( + 'a', { className: className, key: pageNum, href: pageHref(pageNum), @@ -907,7 +1065,7 @@ window.ReactDOM["default"] = window.ReactDOM; ); } }, { - key: "render", + key: 'render', value: function render() { if (typeof this.props.colSpan === 'undefined') { throw new TypeError('Must pass a colSpan argument to Paginator'); @@ -922,9 +1080,17 @@ window.ReactDOM["default"] = window.ReactDOM; } var pageButtons = []; - var pageButtonLimit = this.props.pageButtonLimit; - var currentPage = this.props.currentPage; - var numPages = this.props.numPages; + var _props = this.props; + var locale = _props.locale; + var bottomPaginationElem = _props.bottomPaginationElem; + var onPageChange = _props.onPageChange; + var itemsNumber = _props.itemsNumber; + var itemsPerPage = _props.itemsPerPage; + var bottomPagination = _props.bottomPagination; + var pageButtonLimit = _props.pageButtonLimit; + var currentPage = _props.currentPage; + var numPages = _props.numPages; + var lowerHalf = Math.round(pageButtonLimit / 2); var upperHalf = pageButtonLimit - lowerHalf; @@ -949,14 +1115,36 @@ window.ReactDOM["default"] = window.ReactDOM; if (numPages - currentPage > upperHalf) { pageButtons.splice(pageButtonLimit, pageButtons.length - pageButtonLimit); } - return _react["default"].createElement( - "tbody", - { className: "reactable-pagination" }, - _react["default"].createElement( - "tr", + return _react['default'].createElement( + 'tbody', + { className: 'reactable-pagination' }, + bottomPagination ? _react['default'].createElement( + 'tr', + { className: 'reactable-btnPagination' }, + _react['default'].createElement( + 'td', + { colSpan: this.props.colSpan }, + _react['default'].createElement( + 'div', + { className: 'reactable-bottomDesign' }, + bottomPaginationElem.left, + _react['default'].createElement(_btnPaginator.BtnPaginator, { + locale: locale, + itemsPerPage: itemsPerPage, + itemsNumber: itemsNumber, + numPages: numPages, + currentPage: currentPage, + onPageChange: onPageChange, + key: 'paginator' + }), + bottomPaginationElem.right + ) + ) + ) : _react['default'].createElement( + 'tr', null, - _react["default"].createElement( - "td", + _react['default'].createElement( + 'td', { colSpan: this.props.colSpan }, this.renderPrevious(), pageButtons, @@ -968,7 +1156,7 @@ window.ReactDOM["default"] = window.ReactDOM; }]); return Paginator; - })(_react["default"].Component); + })(_react['default'].Component); exports.Paginator = Paginator; ; @@ -1323,6 +1511,13 @@ window.ReactDOM["default"] = window.ReactDOM; return data; }); } + }, { + key: 'scrollToTop', + value: function scrollToTop() { + if (this.tableEl) { + this.tableEl.scrollIntoView(); + } + } }, { key: 'render', value: function render() { @@ -1397,7 +1592,7 @@ window.ReactDOM["default"] = window.ReactDOM; // Determine if we render the filter box var filtering = false; - if (this.props.filterable && Array.isArray(this.props.filterable) && this.props.filterable.length > 0 && !this.props.hideFilterInput) { + if (this.props.filterable && !this.props.topPagination && Array.isArray(this.props.filterable) && this.props.filterable.length > 0 && !this.props.hideFilterInput) { filtering = true; } @@ -1410,6 +1605,8 @@ window.ReactDOM["default"] = window.ReactDOM; // Determine pagination properties and which columns to display var itemsPerPage = 0; var pagination = false; + var topPagination = this.props.topPagination || false; + var bottomPagination = this.props.bottomPagination || false; var numPages = undefined; var currentPage = this.state.currentPage; var pageButtonLimit = this.props.pageButtonLimit || 10; @@ -1441,34 +1638,60 @@ window.ReactDOM["default"] = window.ReactDOM; ) : null; this.currentChildren = currentChildren; - return _react['default'].createElement( 'table', - props, + { ref: function (t) { + return _this.tableEl = t; + } }, columns && columns.length > 0 ? _react['default'].createElement(_thead.Thead, { columns: columns, + topPagination: topPagination, + itemsNumber: filteredChildren.length, + itemsPerPage: itemsPerPage, + numPages: numPages, + currentPage: currentPage, + topPaginationElem: { + left: this.props.topPaginationElemL, + right: this.props.topPaginationElemR + }, filtering: filtering, onFilter: function (filter) { _this.setState({ filter: filter }); }, + onPageChange: function (page) { + _this.setState({ currentPage: page }); + _this.scrollToTop(); + }, filterPlaceholder: this.props.filterPlaceholder, currentFilter: this.state.filter, sort: this.state.currentSort, sortableColumns: this._sortable, onSort: this.onSort.bind(this), - key: 'thead' }) : null, + key: 'thead', + locale: props.locale + }) : null, _react['default'].createElement( 'tbody', { className: 'reactable-data', key: 'tbody' }, currentChildren.length > 0 ? currentChildren : noDataText ), - pagination === true ? _react['default'].createElement(_paginator.Paginator, { locale: props.locale, colSpan: columns.length, + pagination ? _react['default'].createElement(_paginator.Paginator, { bottomPagination: bottomPagination, + itemsNumber: filteredChildren.length, + itemsPerPage: itemsPerPage, + locale: props.locale, + colSpan: columns.length, pageButtonLimit: pageButtonLimit, numPages: numPages, currentPage: currentPage, + bottomPaginationElem: { + left: this.props.bottomPaginationElemL, + right: this.props.bottomPaginationElemR + }, onPageChange: function (page) { _this.setState({ currentPage: page }); + _this.scrollToTop(); }, - key: 'paginator' }) : null, + key: 'paginator' + }) : null, this.tfoot ); } diff --git a/lib/reactable/btnPaginator.js b/lib/reactable/btnPaginator.js new file mode 100644 index 00000000..1eee10a1 --- /dev/null +++ b/lib/reactable/btnPaginator.js @@ -0,0 +1,126 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var _react = require('react'); + +var _react2 = _interopRequireDefault(_react); + +function pageHref(num) { + return "#page-" + (num + 1); +} + +var tr = { + of: { + nl: "van", + fr: "de", + de: "von", + en: "of" + } +}; + +var BtnPaginator = (function (_React$Component) { + _inherits(BtnPaginator, _React$Component); + + function BtnPaginator(props) { + _classCallCheck(this, BtnPaginator); + + _get(Object.getPrototypeOf(BtnPaginator.prototype), "constructor", this).call(this, props); + this.handlePrevious = this.handlePrevious.bind(this); + this.handleNext = this.handleNext.bind(this); + } + + _createClass(BtnPaginator, [{ + key: "handlePrevious", + value: function handlePrevious(e) { + e.preventDefault(); + this.props.onPageChange(this.props.currentPage - 1); + } + }, { + key: "handleNext", + value: function handleNext(e) { + e.preventDefault(); + this.props.onPageChange(this.props.currentPage + 1); + } + }, { + key: "renderPrevious", + value: function renderPrevious() { + return _react2["default"].createElement("button", { className: "reactable-previous-page " + (this.props.currentPage === 0 ? "disabled" : null), + href: pageHref(this.props.currentPage - 1), + onClick: this.handlePrevious }); + } + }, { + key: "renderNext", + value: function renderNext() { + return _react2["default"].createElement("button", { className: "reactable-next-page " + (this.props.currentPage + 1 === this.props.numPages ? "disabled" : null), + href: pageHref(this.props.currentPage + 1), + onClick: this.handleNext }); + } + }, { + key: "calcRange", + value: function calcRange() { + var _props = this.props; + var currentPage = _props.currentPage; + var itemsNumber = _props.itemsNumber; + var itemsPerPage = _props.itemsPerPage; + + var fromVal = currentPage * itemsPerPage + 1; + var toValTmp = (currentPage + 1) * itemsPerPage; + var toVal = toValTmp < itemsNumber ? toValTmp : itemsNumber; + return fromVal + " - " + toVal; + } + }, { + key: "renderCounter", + value: function renderCounter() { + var _props2 = this.props; + var itemsNumber = _props2.itemsNumber; + var locale = _props2.locale; + + return _react2["default"].createElement( + "div", + { className: "counter" }, + this.calcRange(), + " ", + tr.of[locale], + " ", + itemsNumber + ); + } + }, { + key: "render", + value: function render() { + + if (typeof this.props.currentPage === 'undefined') { + throw new TypeError('Must pass a currentPage argument to Paginator'); + } + return _react2["default"].createElement( + "div", + { className: "reactable-pagesSwitcher" }, + this.renderCounter(), + _react2["default"].createElement( + "div", + { className: "reactable-pageBtns" }, + this.renderPrevious(), + this.renderNext() + ) + ); + } + }]); + + return BtnPaginator; +})(_react2["default"].Component); + +exports.BtnPaginator = BtnPaginator; +; diff --git a/lib/reactable/paginator.js b/lib/reactable/paginator.js index 08770615..de71d4c1 100644 --- a/lib/reactable/paginator.js +++ b/lib/reactable/paginator.js @@ -1,25 +1,27 @@ -"use strict"; +'use strict'; -Object.defineProperty(exports, "__esModule", { +Object.defineProperty(exports, '__esModule', { value: true }); -var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); -var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; +var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _react = require('react'); var _react2 = _interopRequireDefault(_react); +var _btnPaginator = require('./btnPaginator'); + function pageHref(num) { - return "#page-" + (num + 1); + return '#page-' + (num + 1); } var Paginator = (function (_React$Component) { @@ -28,29 +30,29 @@ var Paginator = (function (_React$Component) { function Paginator() { _classCallCheck(this, Paginator); - _get(Object.getPrototypeOf(Paginator.prototype), "constructor", this).apply(this, arguments); + _get(Object.getPrototypeOf(Paginator.prototype), 'constructor', this).apply(this, arguments); } _createClass(Paginator, [{ - key: "handlePrevious", + key: 'handlePrevious', value: function handlePrevious(e) { e.preventDefault(); this.props.onPageChange(this.props.currentPage - 1); } }, { - key: "handleNext", + key: 'handleNext', value: function handleNext(e) { e.preventDefault(); this.props.onPageChange(this.props.currentPage + 1); } }, { - key: "handlePageButton", + key: 'handlePageButton', value: function handlePageButton(page, e) { e.preventDefault(); this.props.onPageChange(page); } }, { - key: "renderPrevious", + key: 'renderPrevious', value: function renderPrevious() { var previousBtn = { nl: "Vorige", @@ -60,9 +62,9 @@ var Paginator = (function (_React$Component) { var locale = this.props.locale; if (this.props.currentPage > 0) { - return _react2["default"].createElement( - "a", - { className: "reactable-previous-page", + return _react2['default'].createElement( + 'a', + { className: 'reactable-previous-page', href: pageHref(this.props.currentPage - 1), onClick: this.handlePrevious.bind(this) }, previousBtn[locale] || previousBtn.en @@ -70,7 +72,7 @@ var Paginator = (function (_React$Component) { } } }, { - key: "renderNext", + key: 'renderNext', value: function renderNext() { var nextBtn = { nl: "Volgende", @@ -80,9 +82,9 @@ var Paginator = (function (_React$Component) { var locale = this.props.locale; if (this.props.currentPage < this.props.numPages - 1) { - return _react2["default"].createElement( - "a", - { className: "reactable-next-page", + return _react2['default'].createElement( + 'a', + { className: 'reactable-next-page', href: pageHref(this.props.currentPage + 1), onClick: this.handleNext.bind(this) }, nextBtn[locale] || nextBtn.en @@ -90,10 +92,10 @@ var Paginator = (function (_React$Component) { } } }, { - key: "renderPageButton", + key: 'renderPageButton', value: function renderPageButton(className, pageNum) { - return _react2["default"].createElement( - "a", + return _react2['default'].createElement( + 'a', { className: className, key: pageNum, href: pageHref(pageNum), @@ -102,7 +104,7 @@ var Paginator = (function (_React$Component) { ); } }, { - key: "render", + key: 'render', value: function render() { if (typeof this.props.colSpan === 'undefined') { throw new TypeError('Must pass a colSpan argument to Paginator'); @@ -117,9 +119,17 @@ var Paginator = (function (_React$Component) { } var pageButtons = []; - var pageButtonLimit = this.props.pageButtonLimit; - var currentPage = this.props.currentPage; - var numPages = this.props.numPages; + var _props = this.props; + var locale = _props.locale; + var bottomPaginationElem = _props.bottomPaginationElem; + var onPageChange = _props.onPageChange; + var itemsNumber = _props.itemsNumber; + var itemsPerPage = _props.itemsPerPage; + var bottomPagination = _props.bottomPagination; + var pageButtonLimit = _props.pageButtonLimit; + var currentPage = _props.currentPage; + var numPages = _props.numPages; + var lowerHalf = Math.round(pageButtonLimit / 2); var upperHalf = pageButtonLimit - lowerHalf; @@ -144,14 +154,36 @@ var Paginator = (function (_React$Component) { if (numPages - currentPage > upperHalf) { pageButtons.splice(pageButtonLimit, pageButtons.length - pageButtonLimit); } - return _react2["default"].createElement( - "tbody", - { className: "reactable-pagination" }, - _react2["default"].createElement( - "tr", + return _react2['default'].createElement( + 'tbody', + { className: 'reactable-pagination' }, + bottomPagination ? _react2['default'].createElement( + 'tr', + { className: 'reactable-btnPagination' }, + _react2['default'].createElement( + 'td', + { colSpan: this.props.colSpan }, + _react2['default'].createElement( + 'div', + { className: 'reactable-bottomDesign' }, + bottomPaginationElem.left, + _react2['default'].createElement(_btnPaginator.BtnPaginator, { + locale: locale, + itemsPerPage: itemsPerPage, + itemsNumber: itemsNumber, + numPages: numPages, + currentPage: currentPage, + onPageChange: onPageChange, + key: 'paginator' + }), + bottomPaginationElem.right + ) + ) + ) : _react2['default'].createElement( + 'tr', null, - _react2["default"].createElement( - "td", + _react2['default'].createElement( + 'td', { colSpan: this.props.colSpan }, this.renderPrevious(), pageButtons, @@ -163,7 +195,7 @@ var Paginator = (function (_React$Component) { }]); return Paginator; -})(_react2["default"].Component); +})(_react2['default'].Component); exports.Paginator = Paginator; ; diff --git a/lib/reactable/table.js b/lib/reactable/table.js index 722f0939..99f1bce2 100644 --- a/lib/reactable/table.js +++ b/lib/reactable/table.js @@ -360,6 +360,13 @@ var Table = (function (_React$Component) { return data; }); } + }, { + key: 'scrollToTop', + value: function scrollToTop() { + if (this.tableEl) { + this.tableEl.scrollIntoView(); + } + } }, { key: 'render', value: function render() { @@ -434,7 +441,7 @@ var Table = (function (_React$Component) { // Determine if we render the filter box var filtering = false; - if (this.props.filterable && Array.isArray(this.props.filterable) && this.props.filterable.length > 0 && !this.props.hideFilterInput) { + if (this.props.filterable && !this.props.topPagination && Array.isArray(this.props.filterable) && this.props.filterable.length > 0 && !this.props.hideFilterInput) { filtering = true; } @@ -447,6 +454,8 @@ var Table = (function (_React$Component) { // Determine pagination properties and which columns to display var itemsPerPage = 0; var pagination = false; + var topPagination = this.props.topPagination || false; + var bottomPagination = this.props.bottomPagination || false; var numPages = undefined; var currentPage = this.state.currentPage; var pageButtonLimit = this.props.pageButtonLimit || 10; @@ -478,34 +487,60 @@ var Table = (function (_React$Component) { ) : null; this.currentChildren = currentChildren; - return _react2['default'].createElement( 'table', - props, + { ref: function (t) { + return _this.tableEl = t; + } }, columns && columns.length > 0 ? _react2['default'].createElement(_thead.Thead, { columns: columns, + topPagination: topPagination, + itemsNumber: filteredChildren.length, + itemsPerPage: itemsPerPage, + numPages: numPages, + currentPage: currentPage, + topPaginationElem: { + left: this.props.topPaginationElemL, + right: this.props.topPaginationElemR + }, filtering: filtering, onFilter: function (filter) { _this.setState({ filter: filter }); }, + onPageChange: function (page) { + _this.setState({ currentPage: page }); + _this.scrollToTop(); + }, filterPlaceholder: this.props.filterPlaceholder, currentFilter: this.state.filter, sort: this.state.currentSort, sortableColumns: this._sortable, onSort: this.onSort.bind(this), - key: 'thead' }) : null, + key: 'thead', + locale: props.locale + }) : null, _react2['default'].createElement( 'tbody', { className: 'reactable-data', key: 'tbody' }, currentChildren.length > 0 ? currentChildren : noDataText ), - pagination === true ? _react2['default'].createElement(_paginator.Paginator, { locale: props.locale, colSpan: columns.length, + pagination ? _react2['default'].createElement(_paginator.Paginator, { bottomPagination: bottomPagination, + itemsNumber: filteredChildren.length, + itemsPerPage: itemsPerPage, + locale: props.locale, + colSpan: columns.length, pageButtonLimit: pageButtonLimit, numPages: numPages, currentPage: currentPage, + bottomPaginationElem: { + left: this.props.bottomPaginationElemL, + right: this.props.bottomPaginationElemR + }, onPageChange: function (page) { _this.setState({ currentPage: page }); + _this.scrollToTop(); }, - key: 'paginator' }) : null, + key: 'paginator' + }) : null, this.tfoot ); } diff --git a/lib/reactable/thead.js b/lib/reactable/thead.js index 70a336bd..b83aeb57 100644 --- a/lib/reactable/thead.js +++ b/lib/reactable/thead.js @@ -26,6 +26,8 @@ var _filterer = require('./filterer'); var _libFilter_props_from = require('./lib/filter_props_from'); +var _btnPaginator = require('./btnPaginator'); + var Thead = (function (_React$Component) { _inherits(Thead, _React$Component); @@ -85,7 +87,6 @@ var Thead = (function (_React$Component) { // Manually transfer props var props = (0, _libFilter_props_from.filterPropsFrom)(this.props); - return _react2['default'].createElement( 'thead', props, @@ -95,6 +96,34 @@ var Thead = (function (_React$Component) { placeholder: this.props.filterPlaceholder, value: this.props.currentFilter }) : null, + this.props.topPagination ? _react2['default'].createElement( + 'tr', + { className: 'reactable-btnPagination' }, + _react2['default'].createElement( + 'td', + { colSpan: this.props.columns.length }, + _react2['default'].createElement( + 'div', + { className: 'reactable-topDesign' }, + this.props.topPaginationElem.left, + _react2['default'].createElement(_filterer.FiltererInput, { + onFilter: this.props.onFilter, + placeholder: this.props.filterPlaceholder, + value: this.props.currentFilter + }), + _react2['default'].createElement(_btnPaginator.BtnPaginator, { + locale: this.props.locale, + itemsPerPage: this.props.itemsPerPage, + itemsNumber: this.props.itemsNumber, + numPages: this.props.numPages, + currentPage: this.props.currentPage, + onPageChange: this.props.onPageChange, + key: 'paginator' + }), + this.props.topPaginationElem.right + ) + ) + ) : null, _react2['default'].createElement( 'tr', { className: 'reactable-column-header' }, From 6f658d11cda3edfc921cf6a034d688d5da3061de Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Mon, 1 Feb 2016 15:07:59 +0100 Subject: [PATCH 15/35] fixed the pagination for empty table --- build/reactable.js | 4 ++-- lib/reactable/btnPaginator.js | 4 ++-- src/reactable/btnPaginator.jsx | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/build/reactable.js b/build/reactable.js index c621d3dd..6aefbb82 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -889,7 +889,7 @@ window.ReactDOM["default"] = window.ReactDOM; }, { key: "renderPrevious", value: function renderPrevious() { - return _react["default"].createElement("button", { className: "reactable-previous-page " + (this.props.currentPage === 0 ? "disabled" : null), + return _react["default"].createElement("button", { className: "reactable-previous-page " + (this.props.currentPage <= 0 ? "disabled" : null), href: pageHref(this.props.currentPage - 1), onClick: this.handlePrevious }); } @@ -908,7 +908,7 @@ window.ReactDOM["default"] = window.ReactDOM; var itemsNumber = _props.itemsNumber; var itemsPerPage = _props.itemsPerPage; - var fromVal = currentPage * itemsPerPage + 1; + var fromVal = currentPage === -1 ? 0 : currentPage * itemsPerPage + 1; var toValTmp = (currentPage + 1) * itemsPerPage; var toVal = toValTmp < itemsNumber ? toValTmp : itemsNumber; return fromVal + " - " + toVal; diff --git a/lib/reactable/btnPaginator.js b/lib/reactable/btnPaginator.js index 1eee10a1..b6085508 100644 --- a/lib/reactable/btnPaginator.js +++ b/lib/reactable/btnPaginator.js @@ -57,7 +57,7 @@ var BtnPaginator = (function (_React$Component) { }, { key: "renderPrevious", value: function renderPrevious() { - return _react2["default"].createElement("button", { className: "reactable-previous-page " + (this.props.currentPage === 0 ? "disabled" : null), + return _react2["default"].createElement("button", { className: "reactable-previous-page " + (this.props.currentPage <= 0 ? "disabled" : null), href: pageHref(this.props.currentPage - 1), onClick: this.handlePrevious }); } @@ -76,7 +76,7 @@ var BtnPaginator = (function (_React$Component) { var itemsNumber = _props.itemsNumber; var itemsPerPage = _props.itemsPerPage; - var fromVal = currentPage * itemsPerPage + 1; + var fromVal = currentPage === -1 ? 0 : currentPage * itemsPerPage + 1; var toValTmp = (currentPage + 1) * itemsPerPage; var toVal = toValTmp < itemsNumber ? toValTmp : itemsNumber; return fromVal + " - " + toVal; diff --git a/src/reactable/btnPaginator.jsx b/src/reactable/btnPaginator.jsx index 64f1be32..2cc9de1d 100644 --- a/src/reactable/btnPaginator.jsx +++ b/src/reactable/btnPaginator.jsx @@ -30,7 +30,7 @@ export class BtnPaginator extends React.Component { } renderPrevious() { - return @@ -45,7 +45,7 @@ export class BtnPaginator extends React.Component { calcRange() { const {currentPage, itemsNumber, itemsPerPage} = this.props - const fromVal = currentPage * itemsPerPage + 1 + const fromVal = currentPage === -1 ? 0 : currentPage * itemsPerPage + 1 const toValTmp = ((currentPage + 1) * itemsPerPage) const toVal = toValTmp < itemsNumber ? toValTmp : itemsNumber return `${fromVal} - ${toVal}` From 5050ba58d853aaa76dd3d05a2384e5e069d1cfd5 Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Tue, 2 Feb 2016 16:04:43 +0100 Subject: [PATCH 16/35] Remove useless empty Td warning it was making devtools unhappy with big datasets --- src/reactable/table.jsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index 41507931..ea679aa0 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -89,9 +89,6 @@ export class Table extends React.Component { } else if (typeof(descendant.props.children) !== 'undefined') { value = descendant.props.children; } else { - console.warn('exports.Td specified without ' + - 'a `data` property or children, ' + - 'ignoring'); return; } From f88f3b0d1d2ea2837da99c6cdcad7bbc5bd59128 Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Tue, 2 Feb 2016 16:05:13 +0100 Subject: [PATCH 17/35] build --- build/reactable.js | 1 - lib/reactable/table.js | 1 - 2 files changed, 2 deletions(-) diff --git a/build/reactable.js b/build/reactable.js index c621d3dd..62223327 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -1274,7 +1274,6 @@ window.ReactDOM["default"] = window.ReactDOM; } else if (typeof descendant.props.children !== 'undefined') { value = descendant.props.children; } else { - console.warn('exports.Td specified without ' + 'a `data` property or children, ' + 'ignoring'); return; } diff --git a/lib/reactable/table.js b/lib/reactable/table.js index 99f1bce2..c3c4cb51 100644 --- a/lib/reactable/table.js +++ b/lib/reactable/table.js @@ -123,7 +123,6 @@ var Table = (function (_React$Component) { } else if (typeof descendant.props.children !== 'undefined') { value = descendant.props.children; } else { - console.warn('exports.Td specified without ' + 'a `data` property or children, ' + 'ignoring'); return; } From bfb8d3f60e57aa33506804544a9960140fd075fd Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Fri, 5 Feb 2016 17:24:15 +0100 Subject: [PATCH 18/35] improved the 'disabled' button state for renderNext and renderPrevious --- build/reactable.js | 30 +++++++++++++++++++----------- lib/reactable/btnPaginator.js | 30 +++++++++++++++++++----------- src/reactable/btnPaginator.jsx | 12 ++++++++---- 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/build/reactable.js b/build/reactable.js index 6aefbb82..a090dde3 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -889,24 +889,32 @@ window.ReactDOM["default"] = window.ReactDOM; }, { key: "renderPrevious", value: function renderPrevious() { - return _react["default"].createElement("button", { className: "reactable-previous-page " + (this.props.currentPage <= 0 ? "disabled" : null), + var currentPage = this.props.currentPage; + + var canPage = currentPage > 0; + return _react["default"].createElement("button", { className: "reactable-previous-page " + (canPage ? "" : "disabled"), href: pageHref(this.props.currentPage - 1), - onClick: this.handlePrevious }); + onClick: canPage && this.handlePrevious }); } }, { key: "renderNext", value: function renderNext() { - return _react["default"].createElement("button", { className: "reactable-next-page " + (this.props.currentPage + 1 === this.props.numPages ? "disabled" : null), + var _props = this.props; + var currentPage = _props.currentPage; + var numPages = _props.numPages; + + var canPage = currentPage + 1 !== numPages; + return _react["default"].createElement("button", { className: "reactable-next-page " + (canPage ? "" : "disabled"), href: pageHref(this.props.currentPage + 1), - onClick: this.handleNext }); + onClick: canPage && this.handleNext }); } }, { key: "calcRange", value: function calcRange() { - var _props = this.props; - var currentPage = _props.currentPage; - var itemsNumber = _props.itemsNumber; - var itemsPerPage = _props.itemsPerPage; + var _props2 = this.props; + var currentPage = _props2.currentPage; + var itemsNumber = _props2.itemsNumber; + var itemsPerPage = _props2.itemsPerPage; var fromVal = currentPage === -1 ? 0 : currentPage * itemsPerPage + 1; var toValTmp = (currentPage + 1) * itemsPerPage; @@ -916,9 +924,9 @@ window.ReactDOM["default"] = window.ReactDOM; }, { key: "renderCounter", value: function renderCounter() { - var _props2 = this.props; - var itemsNumber = _props2.itemsNumber; - var locale = _props2.locale; + var _props3 = this.props; + var itemsNumber = _props3.itemsNumber; + var locale = _props3.locale; return _react["default"].createElement( "div", diff --git a/lib/reactable/btnPaginator.js b/lib/reactable/btnPaginator.js index b6085508..b1d11977 100644 --- a/lib/reactable/btnPaginator.js +++ b/lib/reactable/btnPaginator.js @@ -57,24 +57,32 @@ var BtnPaginator = (function (_React$Component) { }, { key: "renderPrevious", value: function renderPrevious() { - return _react2["default"].createElement("button", { className: "reactable-previous-page " + (this.props.currentPage <= 0 ? "disabled" : null), + var currentPage = this.props.currentPage; + + var canPage = currentPage > 0; + return _react2["default"].createElement("button", { className: "reactable-previous-page " + (canPage ? "" : "disabled"), href: pageHref(this.props.currentPage - 1), - onClick: this.handlePrevious }); + onClick: canPage && this.handlePrevious }); } }, { key: "renderNext", value: function renderNext() { - return _react2["default"].createElement("button", { className: "reactable-next-page " + (this.props.currentPage + 1 === this.props.numPages ? "disabled" : null), + var _props = this.props; + var currentPage = _props.currentPage; + var numPages = _props.numPages; + + var canPage = currentPage + 1 !== numPages; + return _react2["default"].createElement("button", { className: "reactable-next-page " + (canPage ? "" : "disabled"), href: pageHref(this.props.currentPage + 1), - onClick: this.handleNext }); + onClick: canPage && this.handleNext }); } }, { key: "calcRange", value: function calcRange() { - var _props = this.props; - var currentPage = _props.currentPage; - var itemsNumber = _props.itemsNumber; - var itemsPerPage = _props.itemsPerPage; + var _props2 = this.props; + var currentPage = _props2.currentPage; + var itemsNumber = _props2.itemsNumber; + var itemsPerPage = _props2.itemsPerPage; var fromVal = currentPage === -1 ? 0 : currentPage * itemsPerPage + 1; var toValTmp = (currentPage + 1) * itemsPerPage; @@ -84,9 +92,9 @@ var BtnPaginator = (function (_React$Component) { }, { key: "renderCounter", value: function renderCounter() { - var _props2 = this.props; - var itemsNumber = _props2.itemsNumber; - var locale = _props2.locale; + var _props3 = this.props; + var itemsNumber = _props3.itemsNumber; + var locale = _props3.locale; return _react2["default"].createElement( "div", diff --git a/src/reactable/btnPaginator.jsx b/src/reactable/btnPaginator.jsx index 2cc9de1d..dbe1bfeb 100644 --- a/src/reactable/btnPaginator.jsx +++ b/src/reactable/btnPaginator.jsx @@ -30,16 +30,20 @@ export class BtnPaginator extends React.Component { } renderPrevious() { - return } renderNext() { - return } From 6465d833a410ccc33f425bb6cdbea5cf604d2a8c Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Tue, 9 Feb 2016 15:40:25 +0100 Subject: [PATCH 19/35] encapsulation of the btnPaginators --- build/reactable.js | 78 ++++++++++++++++++++++++------------- lib/reactable/paginator.js | 34 ++++++++++------ lib/reactable/thead.js | 44 +++++++++++++-------- src/reactable/paginator.jsx | 28 +++++++------ src/reactable/thead.jsx | 38 ++++++++++-------- 5 files changed, 141 insertions(+), 81 deletions(-) diff --git a/build/reactable.js b/build/reactable.js index a090dde3..e7db7bab 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -726,22 +726,34 @@ window.ReactDOM["default"] = window.ReactDOM; _react['default'].createElement( 'div', { className: 'reactable-topDesign' }, - this.props.topPaginationElem.left, - _react['default'].createElement(_filterer.FiltererInput, { - onFilter: this.props.onFilter, - placeholder: this.props.filterPlaceholder, - value: this.props.currentFilter - }), - _react['default'].createElement(_btnPaginator.BtnPaginator, { - locale: this.props.locale, - itemsPerPage: this.props.itemsPerPage, - itemsNumber: this.props.itemsNumber, - numPages: this.props.numPages, - currentPage: this.props.currentPage, - onPageChange: this.props.onPageChange, - key: 'paginator' - }), - this.props.topPaginationElem.right + _react['default'].createElement( + 'div', + { className: 'reactable-leftElem' }, + this.props.topPaginationElem.left + ), + _react['default'].createElement( + 'div', + { className: 'reactable-mainElem' }, + _react['default'].createElement(_filterer.FiltererInput, { + onFilter: this.props.onFilter, + placeholder: this.props.filterPlaceholder, + value: this.props.currentFilter + }), + _react['default'].createElement(_btnPaginator.BtnPaginator, { + locale: this.props.locale, + itemsPerPage: this.props.itemsPerPage, + itemsNumber: this.props.itemsNumber, + numPages: this.props.numPages, + currentPage: this.props.currentPage, + onPageChange: this.props.onPageChange, + key: 'paginator' + }) + ), + _react['default'].createElement( + 'div', + { className: 'reactable-rightElem' }, + this.props.topPaginationElem.right + ) ) ) ) : null, @@ -1135,17 +1147,29 @@ window.ReactDOM["default"] = window.ReactDOM; _react['default'].createElement( 'div', { className: 'reactable-bottomDesign' }, - bottomPaginationElem.left, - _react['default'].createElement(_btnPaginator.BtnPaginator, { - locale: locale, - itemsPerPage: itemsPerPage, - itemsNumber: itemsNumber, - numPages: numPages, - currentPage: currentPage, - onPageChange: onPageChange, - key: 'paginator' - }), - bottomPaginationElem.right + _react['default'].createElement( + 'div', + { className: 'reactable-leftElem' }, + bottomPaginationElem.left + ), + _react['default'].createElement( + 'div', + { className: 'reactable-mainElem' }, + _react['default'].createElement(_btnPaginator.BtnPaginator, { + locale: locale, + itemsPerPage: itemsPerPage, + itemsNumber: itemsNumber, + numPages: numPages, + currentPage: currentPage, + onPageChange: onPageChange, + key: 'paginator' + }) + ), + _react['default'].createElement( + 'div', + { className: 'reactable-rightElem' }, + bottomPaginationElem.right + ) ) ) ) : _react['default'].createElement( diff --git a/lib/reactable/paginator.js b/lib/reactable/paginator.js index de71d4c1..8af72425 100644 --- a/lib/reactable/paginator.js +++ b/lib/reactable/paginator.js @@ -166,17 +166,29 @@ var Paginator = (function (_React$Component) { _react2['default'].createElement( 'div', { className: 'reactable-bottomDesign' }, - bottomPaginationElem.left, - _react2['default'].createElement(_btnPaginator.BtnPaginator, { - locale: locale, - itemsPerPage: itemsPerPage, - itemsNumber: itemsNumber, - numPages: numPages, - currentPage: currentPage, - onPageChange: onPageChange, - key: 'paginator' - }), - bottomPaginationElem.right + _react2['default'].createElement( + 'div', + { className: 'reactable-leftElem' }, + bottomPaginationElem.left + ), + _react2['default'].createElement( + 'div', + { className: 'reactable-mainElem' }, + _react2['default'].createElement(_btnPaginator.BtnPaginator, { + locale: locale, + itemsPerPage: itemsPerPage, + itemsNumber: itemsNumber, + numPages: numPages, + currentPage: currentPage, + onPageChange: onPageChange, + key: 'paginator' + }) + ), + _react2['default'].createElement( + 'div', + { className: 'reactable-rightElem' }, + bottomPaginationElem.right + ) ) ) ) : _react2['default'].createElement( diff --git a/lib/reactable/thead.js b/lib/reactable/thead.js index b83aeb57..3b04d1d3 100644 --- a/lib/reactable/thead.js +++ b/lib/reactable/thead.js @@ -105,22 +105,34 @@ var Thead = (function (_React$Component) { _react2['default'].createElement( 'div', { className: 'reactable-topDesign' }, - this.props.topPaginationElem.left, - _react2['default'].createElement(_filterer.FiltererInput, { - onFilter: this.props.onFilter, - placeholder: this.props.filterPlaceholder, - value: this.props.currentFilter - }), - _react2['default'].createElement(_btnPaginator.BtnPaginator, { - locale: this.props.locale, - itemsPerPage: this.props.itemsPerPage, - itemsNumber: this.props.itemsNumber, - numPages: this.props.numPages, - currentPage: this.props.currentPage, - onPageChange: this.props.onPageChange, - key: 'paginator' - }), - this.props.topPaginationElem.right + _react2['default'].createElement( + 'div', + { className: 'reactable-leftElem' }, + this.props.topPaginationElem.left + ), + _react2['default'].createElement( + 'div', + { className: 'reactable-mainElem' }, + _react2['default'].createElement(_filterer.FiltererInput, { + onFilter: this.props.onFilter, + placeholder: this.props.filterPlaceholder, + value: this.props.currentFilter + }), + _react2['default'].createElement(_btnPaginator.BtnPaginator, { + locale: this.props.locale, + itemsPerPage: this.props.itemsPerPage, + itemsNumber: this.props.itemsNumber, + numPages: this.props.numPages, + currentPage: this.props.currentPage, + onPageChange: this.props.onPageChange, + key: 'paginator' + }) + ), + _react2['default'].createElement( + 'div', + { className: 'reactable-rightElem' }, + this.props.topPaginationElem.right + ) ) ) ) : null, diff --git a/src/reactable/paginator.jsx b/src/reactable/paginator.jsx index 0c863580..96c083f1 100644 --- a/src/reactable/paginator.jsx +++ b/src/reactable/paginator.jsx @@ -107,17 +107,23 @@ export class Paginator extends React.Component {
- {bottomPaginationElem.left} - - {bottomPaginationElem.right} +
+ {bottomPaginationElem.left} +
+
+ +
+
+ {bottomPaginationElem.right} +
: diff --git a/src/reactable/thead.jsx b/src/reactable/thead.jsx index 73403e63..12ad992d 100644 --- a/src/reactable/thead.jsx +++ b/src/reactable/thead.jsx @@ -94,22 +94,28 @@ export class Thead extends React.Component {
- {this.props.topPaginationElem.left} - - - {this.props.topPaginationElem.right} +
+ {this.props.topPaginationElem.left} +
+
+ + +
+
+ {this.props.topPaginationElem.right} +
: null From 3602f0d407302aab042530dc65339dc9b3d12021 Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Fri, 12 Feb 2016 15:55:10 +0100 Subject: [PATCH 20/35] WIL-1053 Input fields should have "IE cross" to clear them added it to the reactable inputs --- build/reactable.js | 147 ++++++++++++++++++++++++------------- lib/reactable/filterer.js | 70 +++++++++++------- lib/reactable/table.js | 5 ++ lib/reactable/thead.js | 67 +++++++++++------ src/reactable/filterer.jsx | 23 ++++-- src/reactable/table.jsx | 5 ++ src/reactable/thead.jsx | 50 +++++++------ 7 files changed, 233 insertions(+), 134 deletions(-) diff --git a/build/reactable.js b/build/reactable.js index e7db7bab..6d371ac7 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -200,10 +200,10 @@ window.ReactDOM["default"] = window.ReactDOM; }); (function (global, factory) { - if (typeof define === 'function' && define.amd) { - define(['exports', 'react'], factory); - } else if (typeof exports !== 'undefined') { - factory(exports, require('react')); + if (typeof define === "function" && define.amd) { + define(["exports", "react"], factory); + } else if (typeof exports !== "undefined") { + factory(exports, require("react")); } else { var mod = { exports: {} @@ -212,15 +212,15 @@ window.ReactDOM["default"] = window.ReactDOM; global.filterer = mod.exports; } })(this, function (exports, _react) { - 'use strict'; + "use strict"; - var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; + var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var FiltererInput = (function (_React$Component) { _inherits(FiltererInput, _React$Component); @@ -228,30 +228,43 @@ window.ReactDOM["default"] = window.ReactDOM; function FiltererInput() { _classCallCheck(this, FiltererInput); - _get(Object.getPrototypeOf(FiltererInput.prototype), 'constructor', this).apply(this, arguments); + _get(Object.getPrototypeOf(FiltererInput.prototype), "constructor", this).apply(this, arguments); } _createClass(FiltererInput, [{ - key: 'render', + key: "render", value: function render() { var _props = this.props; var onFilter = _props.onFilter; + var onClean = _props.onClean; + var filterCleanBtn = _props.filterCleanBtn; var placeholder = _props.placeholder; var value = _props.value; - return _react['default'].createElement('input', { - className: 'reactable-filter-input', - placeholder: placeholder, - value: value, - onChange: function (ev) { - return onFilter(ev.target.value); - } - }); + return _react["default"].createElement( + "div", + { className: "reactable-filter-input-container" }, + _react["default"].createElement("input", { + className: "reactable-filter-input", + placeholder: placeholder, + value: value, + onChange: function (ev) { + return onFilter(ev.target.value); + } + }), + filterCleanBtn && _react["default"].createElement( + "div", + { onClick: function () { + return onClean(); + }, className: "reactable-btn-clean" }, + "×" + ) + ); } }]); return FiltererInput; - })(_react['default'].Component); + })(_react["default"].Component); exports.FiltererInput = FiltererInput; ; @@ -262,23 +275,24 @@ window.ReactDOM["default"] = window.ReactDOM; function Filterer() { _classCallCheck(this, Filterer); - _get(Object.getPrototypeOf(Filterer.prototype), 'constructor', this).apply(this, arguments); + _get(Object.getPrototypeOf(Filterer.prototype), "constructor", this).apply(this, arguments); } _createClass(Filterer, [{ - key: 'render', + key: "render", value: function render() { if (typeof this.props.colSpan === 'undefined') { throw new TypeError('Must pass a colSpan argument to Filterer'); } - - return _react['default'].createElement( - 'tr', - { className: 'reactable-filterer' }, - _react['default'].createElement( - 'td', + return _react["default"].createElement( + "tr", + { className: "reactable-filterer" }, + _react["default"].createElement( + "td", { colSpan: this.props.colSpan }, - _react['default'].createElement(FiltererInput, { + _react["default"].createElement(FiltererInput, { + filterCleanBtn: this.props.filterCleanBtn, + onClean: this.props.onClean, onFilter: this.props.onFilter, value: this.props.value, placeholder: this.props.placeholder @@ -289,7 +303,7 @@ window.ReactDOM["default"] = window.ReactDOM; }]); return Filterer; - })(_react['default'].Component); + })(_react["default"].Component); exports.Filterer = Filterer; ; @@ -666,20 +680,39 @@ window.ReactDOM["default"] = window.ReactDOM; }, { key: 'render', value: function render() { + var _props = this.props; + var sort = _props.sort; + var sortableColumns = _props.sortableColumns; + var filtering = _props.filtering; + var columns = _props.columns; + var onFilter = _props.onFilter; + var onClean = _props.onClean; + var filterPlaceholder = _props.filterPlaceholder; + var currentFilter = _props.currentFilter; + var topPagination = _props.topPagination; + var filterCleanBtn = _props.filterCleanBtn; + var locale = _props.locale; + var itemsPerPage = _props.itemsPerPage; + var itemsNumber = _props.itemsNumber; + var numPages = _props.numPages; + var currentPage = _props.currentPage; + var onPageChange = _props.onPageChange; + var topPaginationElem = _props.topPaginationElem; + // Declare the list of Ths var Ths = []; - for (var index = 0; index < this.props.columns.length; index++) { - var column = this.props.columns[index]; + for (var index = 0; index < columns.length; index++) { + var column = columns[index]; var thClass = 'reactable-th-' + column.key.replace(/\s+/g, '-').toLowerCase(); var sortClass = ''; - if (this.props.sortableColumns[column.key]) { + if (sortableColumns[column.key]) { sortClass += 'reactable-header-sortable '; } - if (this.props.sort.column === column.key) { + if (sort.column === column.key) { sortClass += 'reactable-header-sort'; - if (this.props.sort.direction === 1) { + if (sort.direction === 1) { sortClass += '-asc'; } else { sortClass += '-desc'; @@ -708,51 +741,54 @@ window.ReactDOM["default"] = window.ReactDOM; // Manually transfer props var props = (0, _libFilter_props_from.filterPropsFrom)(this.props); + return _react['default'].createElement( 'thead', props, - this.props.filtering === true ? _react['default'].createElement(_filterer.Filterer, { - colSpan: this.props.columns.length, - onFilter: this.props.onFilter, - placeholder: this.props.filterPlaceholder, - value: this.props.currentFilter + filtering === true ? _react['default'].createElement(_filterer.Filterer, { + colSpan: columns.length, + onFilter: onFilter, + placeholder: filterPlaceholder, + value: currentFilter }) : null, - this.props.topPagination ? _react['default'].createElement( + topPagination ? _react['default'].createElement( 'tr', { className: 'reactable-btnPagination' }, _react['default'].createElement( 'td', - { colSpan: this.props.columns.length }, + { colSpan: columns.length }, _react['default'].createElement( 'div', { className: 'reactable-topDesign' }, _react['default'].createElement( 'div', { className: 'reactable-leftElem' }, - this.props.topPaginationElem.left + topPaginationElem.left ), _react['default'].createElement( 'div', { className: 'reactable-mainElem' }, _react['default'].createElement(_filterer.FiltererInput, { - onFilter: this.props.onFilter, - placeholder: this.props.filterPlaceholder, - value: this.props.currentFilter + filterCleanBtn: filterCleanBtn, + onClean: onClean, + onFilter: onFilter, + placeholder: filterPlaceholder, + value: currentFilter }), _react['default'].createElement(_btnPaginator.BtnPaginator, { - locale: this.props.locale, - itemsPerPage: this.props.itemsPerPage, - itemsNumber: this.props.itemsNumber, - numPages: this.props.numPages, - currentPage: this.props.currentPage, - onPageChange: this.props.onPageChange, + locale: locale, + itemsPerPage: itemsPerPage, + itemsNumber: itemsNumber, + numPages: numPages, + currentPage: currentPage, + onPageChange: onPageChange, key: 'paginator' }) ), _react['default'].createElement( 'div', { className: 'reactable-rightElem' }, - this.props.topPaginationElem.right + topPaginationElem.right ) ) ) @@ -1629,6 +1665,7 @@ window.ReactDOM["default"] = window.ReactDOM; } // Apply filters + var filterCleanBtn = this.props.filterCleanBtn && this.state.filter; var filteredChildren = children; if (this.state.filter !== '') { filteredChildren = this.applyFilter(this.state.filter, filteredChildren); @@ -1689,6 +1726,10 @@ window.ReactDOM["default"] = window.ReactDOM; onFilter: function (filter) { _this.setState({ filter: filter }); }, + filterCleanBtn: filterCleanBtn, + onClean: function (filter) { + _this.setState({ filter: '' }); + }, onPageChange: function (page) { _this.setState({ currentPage: page }); _this.scrollToTop(); diff --git a/lib/reactable/filterer.js b/lib/reactable/filterer.js index 25448fda..30aa6dd3 100644 --- a/lib/reactable/filterer.js +++ b/lib/reactable/filterer.js @@ -1,18 +1,18 @@ -'use strict'; +"use strict"; -Object.defineProperty(exports, '__esModule', { +Object.defineProperty(exports, "__esModule", { value: true }); -var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); -var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; +var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } var _react = require('react'); @@ -24,30 +24,43 @@ var FiltererInput = (function (_React$Component) { function FiltererInput() { _classCallCheck(this, FiltererInput); - _get(Object.getPrototypeOf(FiltererInput.prototype), 'constructor', this).apply(this, arguments); + _get(Object.getPrototypeOf(FiltererInput.prototype), "constructor", this).apply(this, arguments); } _createClass(FiltererInput, [{ - key: 'render', + key: "render", value: function render() { var _props = this.props; var onFilter = _props.onFilter; + var onClean = _props.onClean; + var filterCleanBtn = _props.filterCleanBtn; var placeholder = _props.placeholder; var value = _props.value; - return _react2['default'].createElement('input', { - className: 'reactable-filter-input', - placeholder: placeholder, - value: value, - onChange: function (ev) { - return onFilter(ev.target.value); - } - }); + return _react2["default"].createElement( + "div", + { className: "reactable-filter-input-container" }, + _react2["default"].createElement("input", { + className: "reactable-filter-input", + placeholder: placeholder, + value: value, + onChange: function (ev) { + return onFilter(ev.target.value); + } + }), + filterCleanBtn && _react2["default"].createElement( + "div", + { onClick: function () { + return onClean(); + }, className: "reactable-btn-clean" }, + "×" + ) + ); } }]); return FiltererInput; -})(_react2['default'].Component); +})(_react2["default"].Component); exports.FiltererInput = FiltererInput; ; @@ -58,23 +71,24 @@ var Filterer = (function (_React$Component2) { function Filterer() { _classCallCheck(this, Filterer); - _get(Object.getPrototypeOf(Filterer.prototype), 'constructor', this).apply(this, arguments); + _get(Object.getPrototypeOf(Filterer.prototype), "constructor", this).apply(this, arguments); } _createClass(Filterer, [{ - key: 'render', + key: "render", value: function render() { if (typeof this.props.colSpan === 'undefined') { throw new TypeError('Must pass a colSpan argument to Filterer'); } - - return _react2['default'].createElement( - 'tr', - { className: 'reactable-filterer' }, - _react2['default'].createElement( - 'td', + return _react2["default"].createElement( + "tr", + { className: "reactable-filterer" }, + _react2["default"].createElement( + "td", { colSpan: this.props.colSpan }, - _react2['default'].createElement(FiltererInput, { + _react2["default"].createElement(FiltererInput, { + filterCleanBtn: this.props.filterCleanBtn, + onClean: this.props.onClean, onFilter: this.props.onFilter, value: this.props.value, placeholder: this.props.placeholder @@ -85,7 +99,7 @@ var Filterer = (function (_React$Component2) { }]); return Filterer; -})(_react2['default'].Component); +})(_react2["default"].Component); exports.Filterer = Filterer; ; diff --git a/lib/reactable/table.js b/lib/reactable/table.js index 99f1bce2..d41630b9 100644 --- a/lib/reactable/table.js +++ b/lib/reactable/table.js @@ -446,6 +446,7 @@ var Table = (function (_React$Component) { } // Apply filters + var filterCleanBtn = this.props.filterCleanBtn && this.state.filter; var filteredChildren = children; if (this.state.filter !== '') { filteredChildren = this.applyFilter(this.state.filter, filteredChildren); @@ -506,6 +507,10 @@ var Table = (function (_React$Component) { onFilter: function (filter) { _this.setState({ filter: filter }); }, + filterCleanBtn: filterCleanBtn, + onClean: function (filter) { + _this.setState({ filter: '' }); + }, onPageChange: function (page) { _this.setState({ currentPage: page }); _this.scrollToTop(); diff --git a/lib/reactable/thead.js b/lib/reactable/thead.js index 3b04d1d3..4e4d2b49 100644 --- a/lib/reactable/thead.js +++ b/lib/reactable/thead.js @@ -45,20 +45,39 @@ var Thead = (function (_React$Component) { }, { key: 'render', value: function render() { + var _props = this.props; + var sort = _props.sort; + var sortableColumns = _props.sortableColumns; + var filtering = _props.filtering; + var columns = _props.columns; + var onFilter = _props.onFilter; + var onClean = _props.onClean; + var filterPlaceholder = _props.filterPlaceholder; + var currentFilter = _props.currentFilter; + var topPagination = _props.topPagination; + var filterCleanBtn = _props.filterCleanBtn; + var locale = _props.locale; + var itemsPerPage = _props.itemsPerPage; + var itemsNumber = _props.itemsNumber; + var numPages = _props.numPages; + var currentPage = _props.currentPage; + var onPageChange = _props.onPageChange; + var topPaginationElem = _props.topPaginationElem; + // Declare the list of Ths var Ths = []; - for (var index = 0; index < this.props.columns.length; index++) { - var column = this.props.columns[index]; + for (var index = 0; index < columns.length; index++) { + var column = columns[index]; var thClass = 'reactable-th-' + column.key.replace(/\s+/g, '-').toLowerCase(); var sortClass = ''; - if (this.props.sortableColumns[column.key]) { + if (sortableColumns[column.key]) { sortClass += 'reactable-header-sortable '; } - if (this.props.sort.column === column.key) { + if (sort.column === column.key) { sortClass += 'reactable-header-sort'; - if (this.props.sort.direction === 1) { + if (sort.direction === 1) { sortClass += '-asc'; } else { sortClass += '-desc'; @@ -90,48 +109,50 @@ var Thead = (function (_React$Component) { return _react2['default'].createElement( 'thead', props, - this.props.filtering === true ? _react2['default'].createElement(_filterer.Filterer, { - colSpan: this.props.columns.length, - onFilter: this.props.onFilter, - placeholder: this.props.filterPlaceholder, - value: this.props.currentFilter + filtering === true ? _react2['default'].createElement(_filterer.Filterer, { + colSpan: columns.length, + onFilter: onFilter, + placeholder: filterPlaceholder, + value: currentFilter }) : null, - this.props.topPagination ? _react2['default'].createElement( + topPagination ? _react2['default'].createElement( 'tr', { className: 'reactable-btnPagination' }, _react2['default'].createElement( 'td', - { colSpan: this.props.columns.length }, + { colSpan: columns.length }, _react2['default'].createElement( 'div', { className: 'reactable-topDesign' }, _react2['default'].createElement( 'div', { className: 'reactable-leftElem' }, - this.props.topPaginationElem.left + topPaginationElem.left ), _react2['default'].createElement( 'div', { className: 'reactable-mainElem' }, _react2['default'].createElement(_filterer.FiltererInput, { - onFilter: this.props.onFilter, - placeholder: this.props.filterPlaceholder, - value: this.props.currentFilter + filterCleanBtn: filterCleanBtn, + onClean: onClean, + onFilter: onFilter, + placeholder: filterPlaceholder, + value: currentFilter }), _react2['default'].createElement(_btnPaginator.BtnPaginator, { - locale: this.props.locale, - itemsPerPage: this.props.itemsPerPage, - itemsNumber: this.props.itemsNumber, - numPages: this.props.numPages, - currentPage: this.props.currentPage, - onPageChange: this.props.onPageChange, + locale: locale, + itemsPerPage: itemsPerPage, + itemsNumber: itemsNumber, + numPages: numPages, + currentPage: currentPage, + onPageChange: onPageChange, key: 'paginator' }) ), _react2['default'].createElement( 'div', { className: 'reactable-rightElem' }, - this.props.topPaginationElem.right + topPaginationElem.right ) ) ) diff --git a/src/reactable/filterer.jsx b/src/reactable/filterer.jsx index b8e7c293..a8ccaf1f 100644 --- a/src/reactable/filterer.jsx +++ b/src/reactable/filterer.jsx @@ -2,14 +2,21 @@ import React from 'react'; export class FiltererInput extends React.Component { render() { - const {onFilter, placeholder,value} = this.props + const {onFilter, onClean, filterCleanBtn, placeholder, value} = this.props return ( - onFilter(ev.target.value)} - /> +
+ onFilter(ev.target.value)} + /> + {filterCleanBtn && +
onClean()} className="reactable-btn-clean"> + × +
+ } +
); } }; @@ -24,6 +31,8 @@ export class Filterer extends React.Component { { this.setState({ filter: filter }); }} + filterCleanBtn={filterCleanBtn} + onClean={filter => { + this.setState({ filter: '' }); + }} onPageChange={page => { this.setState({ currentPage: page }); this.scrollToTop(); diff --git a/src/reactable/thead.jsx b/src/reactable/thead.jsx index 12ad992d..be6cf1c4 100644 --- a/src/reactable/thead.jsx +++ b/src/reactable/thead.jsx @@ -34,20 +34,22 @@ export class Thead extends React.Component { } render() { + const {sort, sortableColumns, filtering, columns, onFilter, onClean, filterPlaceholder, currentFilter, topPagination, filterCleanBtn, locale, itemsPerPage, itemsNumber, numPages, currentPage, onPageChange, topPaginationElem} = this.props; + // Declare the list of Ths var Ths = []; - for (var index = 0; index < this.props.columns.length; index++) { - var column = this.props.columns[index]; + for (var index = 0; index < columns.length; index++) { + var column = columns[index]; var thClass = `reactable-th-${column.key.replace(/\s+/g, '-').toLowerCase()}`; var sortClass = ''; - if (this.props.sortableColumns[column.key]) { + if (sortableColumns[column.key]) { sortClass += 'reactable-header-sortable '; } - if (this.props.sort.column === column.key) { + if (sort.column === column.key) { sortClass += 'reactable-header-sort'; - if (this.props.sort.direction === 1) { + if (sort.direction === 1) { sortClass += '-asc'; } else { @@ -82,39 +84,41 @@ export class Thead extends React.Component { var props = filterPropsFrom(this.props); return ( - {this.props.filtering === true ? + {filtering === true ? : null } - {this.props.topPagination ? + {topPagination ? - +
- {this.props.topPaginationElem.left} + {topPaginationElem.left}
- {this.props.topPaginationElem.right} + {topPaginationElem.right}
From 9b1ac0960e2ce0864c706c958c7766be214330f8 Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Thu, 18 Feb 2016 16:03:58 +0100 Subject: [PATCH 21/35] visible items for Inbox checkboxes fix --- build/reactable.js | 15 ++++++++------- lib/reactable/table.js | 15 ++++++++------- src/reactable/table.jsx | 11 ++++++----- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/build/reactable.js b/build/reactable.js index 6d371ac7..aa86f818 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -1563,17 +1563,18 @@ window.ReactDOM["default"] = window.ReactDOM; }, { key: 'visibleItems', value: function visibleItems() { - return this.currentChildren.map(function (item) { - var _item$props = item.props; - var i = _item$props.i; - var id = _item$props.id; + return this.currentChildren.map(function (row) { + var _row$props = row.props; + var i = _row$props.i; + var id = _row$props.id; var iOrId = i != null ? i : id; - var idOrKey = iOrId != null ? iOrId : item.key; + var idOrKey = iOrId != null ? iOrId : row.key; var data = { id: idOrKey }; - Object.keys(item.props.data).forEach(function (key) { - data[key] = item.props.data[key].value; + Object.keys(row.props.data).forEach(function (key) { + var col = row.props.data[key]; + data[key] = col.props.value != null ? col.props.value : col.value; }); return data; diff --git a/lib/reactable/table.js b/lib/reactable/table.js index d41630b9..363b94ae 100644 --- a/lib/reactable/table.js +++ b/lib/reactable/table.js @@ -344,17 +344,18 @@ var Table = (function (_React$Component) { }, { key: 'visibleItems', value: function visibleItems() { - return this.currentChildren.map(function (item) { - var _item$props = item.props; - var i = _item$props.i; - var id = _item$props.id; + return this.currentChildren.map(function (row) { + var _row$props = row.props; + var i = _row$props.i; + var id = _row$props.id; var iOrId = i != null ? i : id; - var idOrKey = iOrId != null ? iOrId : item.key; + var idOrKey = iOrId != null ? iOrId : row.key; var data = { id: idOrKey }; - Object.keys(item.props.data).forEach(function (key) { - data[key] = item.props.data[key].value; + Object.keys(row.props.data).forEach(function (key) { + var col = row.props.data[key]; + data[key] = col.props.value != null ? col.props.value : col.value; }); return data; diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index 52dac624..7717defe 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -305,14 +305,15 @@ export class Table extends React.Component { } visibleItems() { - return this.currentChildren.map(item => { - const {i, id} = item.props; + return this.currentChildren.map(row => { + const {i, id} = row.props; const iOrId = i != null ? i : id; - const idOrKey = iOrId != null ? iOrId : item.key; + const idOrKey = iOrId != null ? iOrId : row.key; const data = {id: idOrKey}; - Object.keys(item.props.data).forEach(key => { - data[key] = item.props.data[key].value; + Object.keys(row.props.data).forEach(key => { + const col = row.props.data[key]; + data[key] = col.props.value != null ? col.props.value : col.value; }); return data; From 7b464395a4c47bf5eec3c13ad0cf2c7ca4bae2d2 Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Tue, 23 Feb 2016 13:28:56 +0100 Subject: [PATCH 22/35] added onChange for the btnPaginator page change --- build/reactable.js | 3 +++ lib/reactable/table.js | 3 +++ src/reactable/table.jsx | 2 ++ 3 files changed, 8 insertions(+) diff --git a/build/reactable.js b/build/reactable.js index aa86f818..cf1af140 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -1732,6 +1732,9 @@ window.ReactDOM["default"] = window.ReactDOM; _this.setState({ filter: '' }); }, onPageChange: function (page) { + var onPageChange = _this.props.onPageChange; + + onPageChange && onPageChange(page); _this.setState({ currentPage: page }); _this.scrollToTop(); }, diff --git a/lib/reactable/table.js b/lib/reactable/table.js index 363b94ae..f85af46e 100644 --- a/lib/reactable/table.js +++ b/lib/reactable/table.js @@ -513,6 +513,9 @@ var Table = (function (_React$Component) { _this.setState({ filter: '' }); }, onPageChange: function (page) { + var onPageChange = _this.props.onPageChange; + + onPageChange && onPageChange(page); _this.setState({ currentPage: page }); _this.scrollToTop(); }, diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index 7717defe..8472303a 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -474,6 +474,8 @@ export class Table extends React.Component { this.setState({ filter: '' }); }} onPageChange={page => { + const {onPageChange} = this.props; + onPageChange && onPageChange(page); this.setState({ currentPage: page }); this.scrollToTop(); }} From 624684dceaba8b01dc077eeb4d4cd59f0cc393ea Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Wed, 16 Mar 2016 14:55:58 +0100 Subject: [PATCH 23/35] WIL-1502 Kantoor > Delete filter/search box under Medewerker and Service Manager --- src/reactable/thead.jsx | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/reactable/thead.jsx b/src/reactable/thead.jsx index c3b5cada..a8785c48 100644 --- a/src/reactable/thead.jsx +++ b/src/reactable/thead.jsx @@ -121,14 +121,16 @@ export class Thead extends React.Component {
{topPaginationElem.left}
-
- +
+ {filtering && + + } Date: Thu, 31 Mar 2016 14:46:41 +0200 Subject: [PATCH 24/35] a fix for the filter. If 'filtering == false' => all filter disabled; If 'topPagination == true' => default filter disabled. --- src/reactable/table.jsx | 9 ++++----- src/reactable/thead.jsx | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index 530e1c24..4b4149af 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -405,11 +405,10 @@ export class Table extends React.Component { // Determine if we render the filter box let filtering = false; if ( - this.props.filterable && - !this.props.topPagination && - Array.isArray(this.props.filterable) && - this.props.filterable.length > 0 && - !this.props.hideFilterInput + Array.isArray(this.props.filterable) && + this.props.filterable.length > 0 && + !this.props.hideFilterInput + ) { filtering = true; } diff --git a/src/reactable/thead.jsx b/src/reactable/thead.jsx index a8785c48..e50d2d72 100644 --- a/src/reactable/thead.jsx +++ b/src/reactable/thead.jsx @@ -106,13 +106,13 @@ export class Thead extends React.Component { var props = filterPropsFrom(this.props); return ( - {filtering === true ? + {!topPagination && filtering && : null + /> } {topPagination ? From 49b7505e58293f528839197be8b3d9ad3d9354c1 Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Fri, 1 Apr 2016 13:25:33 +0200 Subject: [PATCH 25/35] set the label depending on props --- src/reactable/thead.jsx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/reactable/thead.jsx b/src/reactable/thead.jsx index e50d2d72..7703c7b1 100644 --- a/src/reactable/thead.jsx +++ b/src/reactable/thead.jsx @@ -15,20 +15,21 @@ export class Thead extends React.Component { if (typeof th.props !== 'undefined') { column.props = filterPropsFrom(th.props); - // use the content as the label & key - if (typeof th.props.children !== 'undefined') { - column.label = th.props.children; - column.key = column.label; + //set the label depending on the props + if (typeof th.props.label !== 'undefined'){ + column.label = th.props.label + } else if (typeof th.props.children !== 'undefined'){ + column.label = th.props.children + } else if (typeof th.props.column === 'string') { + column.label = th.props.column; } // the key in the column attribute supersedes the one defined previously if (typeof th.props.column === 'string') { column.key = th.props.column; - - // in case we don't have a label yet - if (typeof column.label === 'undefined') { - column.label = column.key; - } + } else { + // use the content as the key + column.key = th.props.children; } } From f8f2dd3b0e6953262b59e77e433fcd871b937487 Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Fri, 1 Apr 2016 14:11:50 +0200 Subject: [PATCH 26/35] build --- build/reactable.js | 36 +- build/tests/reactable_test.js | 2620 +-------------------------------- lib/reactable/filterer.js | 1 + lib/reactable/table.js | 5 +- lib/reactable/td.js | 4 + lib/reactable/thead.js | 25 +- 6 files changed, 65 insertions(+), 2626 deletions(-) diff --git a/build/reactable.js b/build/reactable.js index 98ad78b4..22a30829 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -284,6 +284,7 @@ window.ReactDOM["default"] = window.ReactDOM; if (typeof this.props.colSpan === 'undefined') { throw new TypeError('Must pass a colSpan argument to Filterer'); } + return _react["default"].createElement( "tr", { className: "reactable-filterer" }, @@ -461,6 +462,10 @@ window.ReactDOM["default"] = window.ReactDOM; onClick: this.handleClick.bind(this) }; + if (typeof this.props.style !== 'undefined') { + tdProps.style = this.props.style; + } + // Attach any properties on the column to this Td object to allow things like custom event handlers if (typeof this.props.column === 'object') { for (var key in this.props.column) { @@ -749,16 +754,15 @@ window.ReactDOM["default"] = window.ReactDOM; // Manually transfer props var props = (0, _libFilter_props_from.filterPropsFrom)(this.props); - return _react['default'].createElement( 'thead', props, - filtering === true ? _react['default'].createElement(_filterer.Filterer, { + !topPagination && filtering && _react['default'].createElement(_filterer.Filterer, { colSpan: columns.length, onFilter: onFilter, placeholder: filterPlaceholder, value: currentFilter - }) : null, + }), topPagination ? _react['default'].createElement( 'tr', { className: 'reactable-btnPagination' }, @@ -775,8 +779,8 @@ window.ReactDOM["default"] = window.ReactDOM; ), _react['default'].createElement( 'div', - { className: 'reactable-mainElem' }, - _react['default'].createElement(_filterer.FiltererInput, { + { className: filtering ? 'reactable-mainElem' : 'reactable-mainElem no-filter' }, + filtering && _react['default'].createElement(_filterer.FiltererInput, { filterCleanBtn: filterCleanBtn, onClean: onClean, onFilter: onFilter, @@ -818,20 +822,21 @@ window.ReactDOM["default"] = window.ReactDOM; if (typeof th.props !== 'undefined') { column.props = (0, _libFilter_props_from.filterPropsFrom)(th.props); - // use the content as the label & key - if (typeof th.props.children !== 'undefined') { + //set the label depending on the props + if (typeof th.props.label !== 'undefined') { + column.label = th.props.label; + } else if (typeof th.props.children !== 'undefined') { column.label = th.props.children; - column.key = column.label; + } else if (typeof th.props.column === 'string') { + column.label = th.props.column; } // the key in the column attribute supersedes the one defined previously if (typeof th.props.column === 'string') { column.key = th.props.column; - - // in case we don't have a label yet - if (typeof column.label === 'undefined') { - column.label = column.key; - } + } else { + // use the content as the key + column.key = th.props.children; } } @@ -1685,7 +1690,7 @@ window.ReactDOM["default"] = window.ReactDOM; // Determine if we render the filter box var filtering = false; - if (this.props.filterable && !this.props.topPagination && Array.isArray(this.props.filterable) && this.props.filterable.length > 0 && !this.props.hideFilterInput) { + if (Array.isArray(this.props.filterable) && this.props.filterable.length > 0 && !this.props.hideFilterInput) { filtering = true; } @@ -1750,9 +1755,6 @@ window.ReactDOM["default"] = window.ReactDOM; filtering: filtering, onFilter: function (filter) { _this.setState({ filter: filter }); - if (_this.props.onFilter) { - _this.props.onFilter(filter); - } }, filterCleanBtn: filterCleanBtn, onClean: function (filter) { diff --git a/build/tests/reactable_test.js b/build/tests/reactable_test.js index dbdc4d43..a327bdaa 100644 --- a/build/tests/reactable_test.js +++ b/build/tests/reactable_test.js @@ -1,2593 +1,27 @@ -(function (global, factory) { - if (typeof define === 'function' && define.amd) { - define(['exports'], factory); - } else if (typeof exports !== 'undefined') { - factory(exports); - } else { - var mod = { - exports: {} - }; - factory(mod.exports); - global.reactable_test = mod.exports; - } -})(this, function (exports) { - 'use strict'; - - var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; - - var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - - var _get = function get(_x2, _x3, _x4) { var _again = true; _function: while (_again) { var object = _x2, property = _x3, receiver = _x4; _again = false; if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x2 = parent; _x3 = property; _x4 = receiver; _again = true; desc = parent = undefined; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; - - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - - function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - var ReactTestUtils = React.addons.TestUtils; - var expect = chai.expect; - - var ReactableTestUtils = { - resetTestEnvironment: function resetTestEnvironment() { - ReactDOM.unmountComponentAtNode($('div#test-node')[0]); - $('div#test-node').remove(); - }, - - // Expect the row specified to have the specified class - expectRowClass: function expectRowClass(rowIndex, className) { - var row = $($('#table tbody.reactable-data tr')[rowIndex]); - expect(row).to.have['class'](className); - }, - - // Expect the columns of a the data row specified to have the values in the array as their text values - expectRowText: function expectRowText(rowIndex, textArray) { - var row = $($('#table tbody.reactable-data tr')[rowIndex]).find('td'); - - expect(row.length).to.equal(textArray.length); - - for (var i = 0; i < row.length; i++) { - expect($(row[i])).to.have.text(textArray[i]); - } - }, - - testNode: function testNode() { - var testNode = $('
').attr('id', 'test-node'); - $('body').append(testNode); - testNode.empty(); - return testNode[0]; - } - }; - - describe('Reactable', function () { - describe('directly passing a data array', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ Name: 'Griffin Smith', Age: '18' }, { Age: '23', Name: 'Lee Salminen' }, { Age: '28', Position: 'Developer' }, { Name: 'Leonor Hyatt', Position: null }] }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the table', function () { - expect($('table#table.table')).to.exist; - }); - - it('renders the column headers in the table', function () { - var headers = []; - $('thead th').each(function () { - headers.push($(this).text()); - }); - - expect(headers).to.eql(['Name', 'Age', 'Position']); - }); - - it('renders the first row with the correct data', function () { - ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']); - }); - - it('renders the second row with the correct data', function () { - ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']); - }); - - it('renders the third row with the correct data', function () { - ReactableTestUtils.expectRowText(2, ['', '28', 'Developer']); - }); - - it('handles null values', function () { - ReactableTestUtils.expectRowText(3, ['Leonor Hyatt', '', '']); - }); - }); - - describe('adding s to the ', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table' }, - React.createElement(Reactable.Tr, { data: { Name: 'Griffin Smith', Age: '18' } }), - React.createElement(Reactable.Tr, { data: { Age: '23', Name: 'Lee Salminen' } }), - React.createElement(Reactable.Tr, { data: { Age: '28', Position: 'Developer' } }) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the table', function () { - expect($('table#table.table')).to.exist; - }); - - it('renders the column headers in the table', function () { - var headers = []; - $('thead th').each(function () { - headers.push($(this).text()); - }); - - expect(headers).to.eql(['Name', 'Age', 'Position']); - }); - - it('renders the first row with the correct data', function () { - ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']); - }); - - it('renders the second row with the correct data', function () { - ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']); - }); - - it('renders the third row with the correct data', function () { - ReactableTestUtils.expectRowText(2, ['', '28', 'Developer']); - }); - }); - - describe('adding s', function () { - context('with only one s', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table' }, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name' }, - React.createElement( - 'b', - null, - 'Griffin Smith' - ) - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - React.createElement( - 'em', - null, - '18' - ) - ) - ), - null, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Position' }, - React.createElement( - 'b', - null, - 'Developer' - ) - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - React.createElement( - 'em', - null, - '28' - ) - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the table', function () { - expect($('table#table.table')).to.exist; - }); - - it('renders the column headers in the table', function () { - var headers = []; - $('thead th').each(function () { - headers.push($(this).text()); - }); - - expect(headers).to.eql(['Name', 'Age', 'Position']); - }); - - it('renders the first row with the correct data', function () { - ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']); - }); - - it('renders the second row with the correct data', function () { - ReactableTestUtils.expectRowText(1, ['', '28', 'Developer']); - }); - }); - }); - - describe('Adding a ', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table', sortable: ['Name'], filterable: ['Name', 'Age'] }, - React.createElement(Reactable.Tr, { className: 'rowClass1', data: { Name: 'Griffin Smith', Age: '18' } }), - React.createElement(Reactable.Tr, { className: 'rowClass2', data: { Age: '23', Name: 'Lee Salminen' } }), - React.createElement(Reactable.Tr, { className: 'rowClass3', data: { Age: '28', Position: 'Developer' } }), - React.createElement( - Reactable.Tfoot, - { id: 'tfoot' }, - React.createElement( - 'tr', - null, - React.createElement( - 'td', - { id: 'tfoot-stuff' }, - 'Test' - ) - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the table', function () { - expect($('#table')).to.exist; - }); - - it('renders the regular data rows', function () { - ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']); - ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']); - ReactableTestUtils.expectRowText(2, ['', '28', 'Developer']); - }); - - it('renders the tfoot', function () { - expect($('#tfoot')).to.exist; - }); - - it('renders the children of the tfoot', function () { - expect($('#tfoot-stuff')).to.exist; - }); - - context('when sorting', function () { - before(function () { - ReactTestUtils.Simulate.click($('th')[0]); - }); - - it('leaves the tfoot alone', function () { - expect($('table :last-child')).to.match('tfoot'); - }); - }); - - context('when filtering', function () { - before(function () { - var $filter = $('.reactable-filter-input'); - - $filter.val('griffin'); - ReactTestUtils.Simulate.keyUp($filter[0]); - }); - - it('leaves the tfoot alone', function () { - expect($('table :last-child')).to.match('tfoot'); - }); - }); - }); - - describe('passing through HTML props', function () { - describe('adding s with className to the
s to the
', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table' }, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name' }, - 'Griffin Smith' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name' }, - 'Lee Salminen' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name' }, - 'Ian Zhang' - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the table', function () { - expect($('table#table.table')).to.exist; - }); - - it('renders the column headers in the table', function () { - var headers = []; - $('thead th').each(function () { - headers.push($(this).text()); - }); - - expect(headers).to.eql(['Name']); - }); - - it('renders the first row with the correct data', function () { - ReactableTestUtils.expectRowText(0, ['Griffin Smith']); - }); - - it('renders the second row with the correct data', function () { - ReactableTestUtils.expectRowText(1, ['Lee Salminen']); - }); - - it('renders the third row with the correct data', function () { - ReactableTestUtils.expectRowText(2, ['Ian Zhang']); - }); - }); - - context('with multiple s', function () { - context('with plain text', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table' }, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name' }, - 'Griffin Smith' - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - '18' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name' }, - 'Lee Salminen' - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - '23' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Position' }, - 'Developer' - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - '28' - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the table', function () { - expect($('table#table.table')).to.exist; - }); - - it('renders the column headers in the table', function () { - var headers = []; - $('thead th').each(function () { - headers.push($(this).text()); - }); - - expect(headers).to.eql(['Name', 'Age', 'Position']); - }); - - it('renders the first row with the correct data', function () { - ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']); - }); - - it('renders the second row with the correct data', function () { - ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']); - }); - - it('renders the third row with the correct data', function () { - ReactableTestUtils.expectRowText(2, ['', '28', 'Developer']); - }); - }); - }); - - context('with React.DOM nodes inside', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table' }, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name' }, - React.createElement( - 'b', - null, - 'Griffin Smith' - ) - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - React.createElement( - 'em', - null, - '18' - ) - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name' }, - React.createElement( - 'b', - null, - 'Lee Salminen' - ) - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - React.createElement( - 'em', - null, - '23' - ) - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Position' }, - React.createElement( - 'b', - null, - 'Developer' - ) - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - React.createElement( - 'em', - null, - '28' - ) - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the table', function () { - expect($('table#table.table')).to.exist; - }); - - it('renders the column headers in the table', function () { - var headers = []; - $('thead th').each(function () { - headers.push($(this).text()); - }); - - expect(headers).to.eql(['Name', 'Age', 'Position']); - }); - - it('renders the first row with the correct data', function () { - ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']); - }); - - it('renders the second row with the correct data', function () { - ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']); - }); - - it('renders the third row with the correct data', function () { - ReactableTestUtils.expectRowText(2, ['', '28', 'Developer']); - }); - }); - - context('with null s', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table' }, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name' }, - React.createElement( - 'b', - null, - 'Griffin Smith' - ) - ), - null - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name' }, - React.createElement( - 'b', - null, - 'Lee Salminen' - ) - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - React.createElement( - 'em', - null, - '23' - ) - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Position' }, - React.createElement( - 'b', - null, - 'Developer' - ) - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - React.createElement( - 'em', - null, - '28' - ) - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the table', function () { - expect($('table#table.table')).to.exist; - }); - - it('renders the column headers in the table', function () { - var headers = []; - $('thead th').each(function () { - headers.push($(this).text()); - }); - - expect(headers).to.eql(['Name', 'Age', 'Position']); - }); - - it('renders the first row with the correct data', function () { - ReactableTestUtils.expectRowText(0, ['Griffin Smith', '', '']); - }); - - it('renders the second row with the correct data', function () { - ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']); - }); - - it('renders the third row with the correct data', function () { - ReactableTestUtils.expectRowText(2, ['', '28', 'Developer']); - }); - }); - - context('with null
', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table' }, - React.createElement(Reactable.Tr, { className: 'rowClass1', data: { Name: 'Griffin Smith', Age: '18' } }), - React.createElement(Reactable.Tr, { className: 'rowClass2', data: { Age: '23', Name: 'Lee Salminen' } }), - React.createElement(Reactable.Tr, { className: 'rowClass3', data: { Age: '28', Position: 'Developer' } }) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the table', function () { - expect($('table#table.table')).to.exist; - }); - - it('renders the column headers in the table', function () { - var headers = []; - $('thead th').each(function () { - headers.push($(this).text()); - }); - - expect(headers).to.eql(['Name', 'Age', 'Position']); - }); - - it('renders the first row with the correct class name', function () { - ReactableTestUtils.expectRowClass(0, 'rowClass1'); - }); - - it('renders the second row with the correct class name', function () { - ReactableTestUtils.expectRowClass(1, 'rowClass2'); - }); - - it('renders the third row with the correct class name', function () { - ReactableTestUtils.expectRowClass(2, 'rowClass3'); - }); - }); - - describe('adding
s with classNames to the ', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table' }, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name', className: 'name-1' }, - 'Griffin Smith' - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - '18' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name', className: 'name-2' }, - 'Lee Salminen' - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - '23' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Position', className: 'position' }, - 'Developer' - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - '28' - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the first column with the correct class name', function () { - expect($('td.name-1')).to.have.text('Griffin Smith'); - }); - - it('renders the second column with the correct class name', function () { - expect($('td.name-2')).to.have.text('Lee Salminen'); - }); - - it('renders the third column with the correct class name', function () { - expect($('td.position')).to.have.text('Developer'); - }); - }); - }); - - describe('specifying an array of columns', function () { - describe('as strings', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ Name: 'Griffin Smith', Age: '18', HideThis: 'one' }, { Age: '23', Name: 'Lee Salminen', HideThis: 'two' }, { Age: '28', Position: 'Developer' }], columns: ['Name', 'Age'] }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('omits columns not in the list', function () { - var columns = $('tr.reactable-column-header th'); - expect(columns.length).to.equal(2); - expect($(columns[0])).to.have.text('Name'); - expect($(columns[1])).to.have.text('Age'); - }); - - it('adds class name for each column base on its label', function () { - var columns = $('tr.reactable-column-header th'); - expect($(columns[0])).to.have['class']('reactable-th-name'); - expect($(columns[1])).to.have['class']('reactable-th-age'); - }); - }); - - describe('as objects', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ name: 'Griffin Smith', age: '18', HideThis: 'one' }, { age: '23', name: 'Lee Salminen', HideThis: 'two' }, { age: '28', Position: 'Developer' }], columns: [{ key: 'name', label: 'Name' }, { key: 'age', label: 'Age' }] }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('omits columns not in the list', function () { - var columns = $('tr.reactable-column-header th'); - expect(columns.length).to.equal(2); - }); - - it('allows changing the labels of the columns', function () { - var columns = $('tr.reactable-column-header th'); - expect($(columns[0])).to.have.text('Name'); - expect($(columns[1])).to.have.text('Age'); - }); - - it('adds class name for each column base on its key', function () { - var columns = $('tr.reactable-column-header th'); - expect($(columns[0])).to.have['class']('reactable-th-name'); - expect($(columns[1])).to.have['class']('reactable-th-age'); - }); - }); - }); - - describe('specifying columns using a ', function () { - describe('and an element for the column title', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { id: 'table', data: [{ Name: Reactable.unsafe('Griffin Smith'), Age: '18' }, { Age: '28', Position: Reactable.unsafe('Developer') }, { Age: '23', Name: Reactable.unsafe('Lee Salminen') }] }, - React.createElement( - Reactable.Thead, - null, - React.createElement( - Reactable.Th, - { column: 'Name', id: 'my-name' }, - React.createElement( - 'strong', - null, - 'name' - ) - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders only the columns in the Thead', function () { - expect($('#table tbody tr:first td')).to.exist; - expect($('#table thead tr:first th')).to.exist; - }); - - it('renders the contents of the Th', function () { - expect($('#table>thead>tr>th>strong')).to.exist; - }); - - it('passes through the properties of the Th', function () { - expect($('#table>thead>tr>th')).to.have.id('my-name'); - }); - }); - - describe('and a string for the column title', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { id: 'table', data: [{ Name: Reactable.unsafe('Griffin Smith'), Age: '18' }, { Age: '28', Position: Reactable.unsafe('Developer') }, { Age: '23', Name: Reactable.unsafe('Lee Salminen') }] }, - React.createElement( - Reactable.Thead, - null, - React.createElement( - Reactable.Th, - { column: 'Name', id: 'my-name' }, - 'name' - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders only the columns in the Thead', function () { - expect($('#table tbody tr:first td')).to.exist; - expect($('#table thead tr:first th')).to.exist; - }); - - it('renders the contents of the Th', function () { - expect($('#table>thead>tr>th')).to.exist; - }); - - it('passes through the properties of the Th', function () { - expect($('#table>thead>tr>th')).to.have.id('my-name'); - }); - }); - }); - - describe('unsafe() strings', function () { - context('in the
directly', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ Name: Reactable.unsafe('Griffin Smith'), Age: '18' }, { Age: '28', Position: Reactable.unsafe('Developer') }, { Age: '23', Name: Reactable.unsafe('Lee Salminen') }], sortable: ['Name'] }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the HTML in the table cells', function () { - var griffins_name = $('span#griffins-name'); - expect(griffins_name.length).to.equal(1); - expect(griffins_name).to.have.text('Griffin Smith'); - - var lees_name = $('span#lees-name'); - expect(lees_name.length).to.equal(1); - expect(lees_name).to.have.text('Lee Salminen'); - - var who_knows_job = $('span#who-knows-job'); - expect(who_knows_job.length).to.equal(1); - expect(who_knows_job).to.have.text('Developer'); - }); - - it('still allows sorting', function () { - var nameHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.click(nameHeader); - - ReactableTestUtils.expectRowText(0, ['28', 'Developer', '']); - ReactableTestUtils.expectRowText(1, ['18', '', 'Griffin Smith']); - ReactableTestUtils.expectRowText(2, ['23', '', 'Lee Salminen']); - }); - }); - - context('in column labels', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ Name: 'Griffin Smith', Age: '18' }, { Age: '23', Name: 'Lee Salminen' }, { Age: '28', Position: 'Developer' }], columns: [{ key: 'Name', label: Reactable.unsafe('Name') }, { key: 'Age', label: Reactable.unsafe('Age') }, { key: 'Position', label: Reactable.unsafe('Position') }] }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the HTML in the column headers', function () { - var headers = []; - $('thead th').each(function () { - headers.push($(this).html()); - }); - - expect(headers).to.eql(['Name', 'Age', 'Position']); - }); - }); - - context('in the s', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table' }, - React.createElement(Reactable.Tr, { data: { Name: Reactable.unsafe('Griffin Smith'), Age: '18' } }), - React.createElement(Reactable.Tr, { data: { Age: '23', Name: Reactable.unsafe('Lee Salminen') } }), - React.createElement(Reactable.Tr, { data: { Age: '28', Position: Reactable.unsafe('Developer') } }) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the HTML in the table cells', function () { - var griffins_name = $('span#griffins-name'); - expect(griffins_name.length).to.equal(1); - expect(griffins_name).to.have.text('Griffin Smith'); - - var lees_name = $('span#lees-name'); - expect(lees_name.length).to.equal(1); - expect(lees_name).to.have.text('Lee Salminen'); - - var who_knows_job = $('span#who-knows-job'); - expect(who_knows_job.length).to.equal(1); - expect(who_knows_job).to.have.text('Developer'); - }); - }); - - context('in the s', function () { - before(function () { - this.component = ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', columns: ['State', 'Description', 'Tag'], noDataText: 'No matching records found.' }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('shows the "no data" message', function () { - var $text = $('.reactable-no-data').text(); - expect($text).to.eq('No matching records found.'); - }); - }); - - context('when filtered without any matches', function () { - before(function () { - this.component = ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table', - filterable: ['State', 'Tag'], - filterPlaceholder: 'Filter Results', - filterBy: 'xxxxx', - noDataText: 'No matching records found.', - columns: ['State', 'Description', 'Tag'] }, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'State' }, - 'New York' - ), - React.createElement( - Reactable.Td, - { column: 'Description' }, - 'this is some text' - ), - React.createElement( - Reactable.Td, - { column: 'Tag' }, - 'new' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'State' }, - 'New Mexico' - ), - React.createElement( - Reactable.Td, - { column: 'Description' }, - 'lorem ipsum' - ), - React.createElement( - Reactable.Td, - { column: 'Tag' }, - 'old' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'State' }, - 'Colorado' - ), - React.createElement( - Reactable.Td, - { column: 'Description' }, - 'new description that shouldnt match filter' - ), - React.createElement( - Reactable.Td, - { column: 'Tag' }, - 'old' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'State' }, - 'Alaska' - ), - React.createElement( - Reactable.Td, - { column: 'Description' }, - 'bacon' - ), - React.createElement( - Reactable.Td, - { column: 'Tag' }, - 'renewed' - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('shows the "no data" message', function () { - var text = $('.reactable-no-data').text(); - expect(text).to.eq('No matching records found.'); - }); - }); - - context('when initialized with an empty array for `data` prop', function () { - before(function () { - this.component = ReactDOM.render(React.createElement(Reactable.Table, { data: [], className: 'table', id: 'table', columns: ['State', 'Description', 'Tag'], noDataText: 'No matching records found.' }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('shows the "no data" message', function () { - var $text = $('.reactable-no-data').text(); - expect($text).to.eq('No matching records found.'); - }); - }); - }); - - describe('visibleItems()', function () { - var _Reactable = Reactable; - var Table = _Reactable.Table; - var Thead = _Reactable.Thead; - var Tr = _Reactable.Tr; - var Th = _Reactable.Th; - var Td = _Reactable.Td; - - var data = [{ name: "Lee SomeoneElse", age: 18 }, { name: "Lee Salminen", age: 23 }, { name: "No Age", age: null }]; - - var Tester = (function (_React$Component) { - _inherits(Tester, _React$Component); - - function Tester() { - _classCallCheck(this, Tester); - - _get(Object.getPrototypeOf(Tester.prototype), 'constructor', this).apply(this, arguments); - } - - _createClass(Tester, [{ - key: 'componentDidMount', - value: function componentDidMount() { - this.props.run && this.props.run(this); - } - }, { - key: 'render', - value: function render() { - return React.createElement( - Table, - _extends({ ref: 'table', className: 'table', id: 'table', - filterable: ['Name', 'Age'] }, this.props), - React.createElement( - Thead, - null, - React.createElement( - Th, - { column: 'Name' }, - 'The Name' - ), - React.createElement( - Th, - { column: 'Age' }, - 'The Age' - ) - ), - data.map(function (item, i) { - return React.createElement( - Tr, - { key: i, i: i < 2 ? i : null }, - React.createElement(Td, { column: 'Name', data: item.name }), - React.createElement(Td, { column: 'Age', data: item.age }) - ); - }), - React.createElement( - Tr, - { i: true }, - React.createElement(Td, { column: 'Name', data: "hi" }), - React.createElement(Td, { column: 'Age', data: 5 }) - ), - React.createElement( - Tr, - { id: "id" }, - React.createElement(Td, { column: 'Name', data: "hi" }), - React.createElement(Td, { column: 'Age', data: 7 }) - ) - ); - } - }]); - - return Tester; - })(React.Component); - - var doTest = function doTest(runMe) { - var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; - return ReactDOM.render(React.createElement(Tester, _extends({ run: runMe }, options)), ReactableTestUtils.testNode()); - }; - - after(ReactableTestUtils.resetTestEnvironment); - - it('works', function () { - doTest(function (me) { - var items = me.refs.table.visibleItems(); - expect(items.length).to.eql(5); - expect(items[0].Age).to.eql(18); - }); - }); - it('works when filtered', function () { - doTest(function (me) { - var items = me.refs.table.visibleItems(); - expect(items.length).to.eql(2); - expect(items[1].Age).to.eql(23); - }, { filterBy: 'lee' }); - }); - it('works when paged', function () { - doTest(function (me) { - var items = me.refs.table.visibleItems(); - expect(items.length).to.eql(1); - expect(items[0].Age).to.eql(18); - }, { itemsPerPage: 1 }); - }); - it('has keys', function () { - doTest(function (me) { - var items = me.refs.table.visibleItems(); - expect(items[1].id).to.eql(1); - // id is not defined and key is a string - expect(items[2].id).to.eql("2"); - // Falsy ids still count - expect(items[0].id).to.eql(0); - expect(items[3].id).to.eql(true); - expect(items[4].id).to.eql("id"); - }); - }); - }); - }); -}); +(function(global,factory){if(typeof define === 'function' && define.amd){define(['exports'],factory);}else if(typeof exports !== 'undefined'){factory(exports);}else {var mod={exports:{}};factory(mod.exports);global.reactable_test = mod.exports;}})(this,function(exports){'use strict';var _extends=Object.assign || function(target){for(var i=1;i < arguments.length;i++) {var source=arguments[i];for(var key in source) {if(Object.prototype.hasOwnProperty.call(source,key)){target[key] = source[key];}}}return target;};var _createClass=(function(){function defineProperties(target,props){for(var i=0;i < props.length;i++) {var descriptor=props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if('value' in descriptor)descriptor.writable = true;Object.defineProperty(target,descriptor.key,descriptor);}}return function(Constructor,protoProps,staticProps){if(protoProps)defineProperties(Constructor.prototype,protoProps);if(staticProps)defineProperties(Constructor,staticProps);return Constructor;};})();var _get=function get(_x2,_x3,_x4){var _again=true;_function: while(_again) {var object=_x2,property=_x3,receiver=_x4;_again = false;if(object === null)object = Function.prototype;var desc=Object.getOwnPropertyDescriptor(object,property);if(desc === undefined){var parent=Object.getPrototypeOf(object);if(parent === null){return undefined;}else {_x2 = parent;_x3 = property;_x4 = receiver;_again = true;desc = parent = undefined;continue _function;}}else if('value' in desc){return desc.value;}else {var getter=desc.get;if(getter === undefined){return undefined;}return getter.call(receiver);}}};function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError('Cannot call a class as a function');}}function _inherits(subClass,superClass){if(typeof superClass !== 'function' && superClass !== null){throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass);}subClass.prototype = Object.create(superClass && superClass.prototype,{constructor:{value:subClass,enumerable:false,writable:true,configurable:true}});if(superClass)Object.setPrototypeOf?Object.setPrototypeOf(subClass,superClass):subClass.__proto__ = superClass;}var ReactTestUtils=React.addons.TestUtils;var expect=chai.expect;var ReactableTestUtils={resetTestEnvironment:function resetTestEnvironment(){ReactDOM.unmountComponentAtNode($('div#test-node')[0]);$('div#test-node').remove();}, // Expect the row specified to have the specified class +expectRowClass:function expectRowClass(rowIndex,className){var row=$($('#table tbody.reactable-data tr')[rowIndex]);expect(row).to.have['class'](className);}, // Expect the columns of a the data row specified to have the values in the array as their text values +expectRowText:function expectRowText(rowIndex,textArray){var row=$($('#table tbody.reactable-data tr')[rowIndex]).find('td');expect(row.length).to.equal(textArray.length);for(var i=0;i < row.length;i++) {expect($(row[i])).to.have.text(textArray[i]);}},testNode:function testNode(){var testNode=$('
').attr('id','test-node');$('body').append(testNode);testNode.empty();return testNode[0];}};describe('Reactable',function(){describe('directly passing a data array',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{Name:'Griffin Smith',Age:'18'},{Age:'23',Name:'Lee Salminen'},{Age:'28',Position:'Developer'},{Name:'Leonor Hyatt',Position:null}]}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the table',function(){expect($('table#table.table')).to.exist;});it('renders the column headers in the table',function(){var headers=[];$('thead th').each(function(){headers.push($(this).text());});expect(headers).to.eql(['Name','Age','Position']);});it('renders the first row with the correct data',function(){ReactableTestUtils.expectRowText(0,['Griffin Smith','18','']);});it('renders the second row with the correct data',function(){ReactableTestUtils.expectRowText(1,['Lee Salminen','23','']);});it('renders the third row with the correct data',function(){ReactableTestUtils.expectRowText(2,['','28','Developer']);});it('handles null values',function(){ReactableTestUtils.expectRowText(3,['Leonor Hyatt','','']);});});describe('adding
s to the
s', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table' }, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name' }, - Reactable.unsafe('Griffin Smith') - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - '18' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name' }, - Reactable.unsafe('Lee Salminen') - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - '23' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Position' }, - Reactable.unsafe('Developer') - ), - React.createElement( - Reactable.Td, - { column: 'Age' }, - '28' - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the HTML in the table cells', function () { - var griffins_name = $('span#griffins-name'); - expect(griffins_name.length).to.equal(1); - expect(griffins_name).to.have.text('Griffin Smith'); - - var lees_name = $('span#lees-name'); - expect(lees_name.length).to.equal(1); - expect(lees_name).to.have.text('Lee Salminen'); - - var who_knows_job = $('span#who-knows-job'); - expect(who_knows_job.length).to.equal(1); - expect(who_knows_job).to.have.text('Developer'); - }); - }); - }); - - describe('pagination', function () { - describe('specifying pageButtonLimit', function () { - - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Test Person' }, { 'Name': 'Ian Zhang', 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18', 'Position': 'Software Developer' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Test Person' }, { 'Name': 'Ian Zhang', 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18', 'Position': 'Software Developer' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Test Person' }, { 'Name': 'Ian Zhang', 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18', 'Position': 'Software Developer' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }], itemsPerPage: 2, pageButtonLimit: 8 }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('shows no more page buttons than the pageButtonLimit', function () { - var pageButtons = $('#table tbody.reactable-pagination a.reactable-page-button'); - expect(pageButtons.length).to.equal(8); - }); - }); - describe('specifying itemsPerPage', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Test Person' }, { 'Name': 'Ian Zhang', 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18', 'Position': 'Software Developer' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }], itemsPerPage: 4 }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('provides buttons for each page', function () { - var pageButtons = $('#table tbody.reactable-pagination a.reactable-page-button'); - expect(pageButtons.length).to.equal(3); - expect($(pageButtons[0])).to.have.text('1'); - expect($(pageButtons[1])).to.have.text('2'); - expect($(pageButtons[2])).to.have.text('3'); - }); - - it('displays only the first n rows', function () { - expect($('#table tbody.reactable-data tr').length).to.equal(4); - }); - - it('specifies a class on the currently active page', function () { - var activePage = $('#table tbody.reactable-pagination a.reactable-page-button.reactable-current-page'); - expect(activePage.length).to.equal(1); - expect(activePage).to.have.text('1'); - }); - - it('does not show previous button', function () { - var previousButton = $('#table tbody.reactable-pagination a.reactable-previous-page'); - expect(previousButton.length).to.equal(0); - }); - - it('shows next button', function () { - var nextButton = $('#table tbody.reactable-pagination a.reactable-next-page'); - expect(nextButton.length).to.equal(1); - }); - - describe('clicking page buttons', function () { - beforeEach(function () { - var page2 = $('#table tbody.reactable-pagination a.reactable-page-button')[1]; - ReactTestUtils.Simulate.click(page2); - }); - - it('loads the next n rows', function () { - var rows = $('#table tbody.reactable-data tr'); - expect($($(rows[0]).find('td')[0])).to.have.text('Test Person'); - expect($($(rows[1]).find('td')[0])).to.have.text('Ian Zhang'); - expect($($(rows[2]).find('td')[0])).to.have.text('Griffin Smith'); - expect($($(rows[3]).find('td')[0])).to.have.text('Lee Salminen'); - }); - - it('puts an active class on the new active page', function () { - var activePage = $('#table tbody.reactable-pagination a.reactable-page-button.reactable-current-page'); - expect(activePage.length).to.equal(1); - expect(activePage).to.have.text('2'); - }); - - it('can go back to the original page', function () { - var page1 = $('#table tbody.reactable-pagination a.reactable-page-button')[0]; - ReactTestUtils.Simulate.click(page1); - - var rows = $('#table tbody.reactable-data tr'); - expect($($(rows[0]).find('td')[0])).to.have.text('Griffin Smith'); - expect($($(rows[1]).find('td')[0])).to.have.text('Lee Salminen'); - expect($($(rows[2]).find('td')[0])).to.have.text(''); - expect($($(rows[3]).find('td')[0])).to.have.text('Griffin Smith'); - }); - - it('shows previous button', function () { - var previousButton = $('#table tbody.reactable-pagination a.reactable-previous-page'); - expect(previousButton.length).to.equal(1); - }); - }); - }); - - describe('specifying more itemsPerPage than items', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Test Person' }, { 'Name': 'Ian Zhang', 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18', 'Position': 'Software Developer' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }], itemsPerPage: 20 }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders all rows', function () { - expect($('#table tbody.reactable-data tr').length).to.equal(9); - }); - - it('provides buttons for 1 page', function () { - var pageButtons = $('#table tbody.reactable-pagination a.reactable-page-button'); - expect(pageButtons.length).to.equal(1); - expect($(pageButtons[0])).to.have.text('1'); - }); - - it('does not show previous and next buttons', function () { - var previousButton = $('#table tbody.reactable-pagination a.reactable-previous-page'); - var nextButton = $('#table tbody.reactable-pagination a.reactable-next-page'); - expect(previousButton.length + nextButton.length).to.equal(0); - }); - }); - - describe('not specifying itemsPerPage', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Test Person' }, { 'Name': 'Ian Zhang', 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18', 'Position': 'Software Developer' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }] }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders all rows', function () { - expect($('#table tbody.reactable-data tr').length).to.equal(9); - }); - }); - - describe('specifying 0 itemsPerPage', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Test Person' }, { 'Name': 'Ian Zhang', 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18', 'Position': 'Software Developer' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }], itemsPerPage: 0 }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders all rows', function () { - expect($('#table tbody.reactable-data tr').length).to.equal(9); - }); - }); - - describe('onPageChange hook', function () { - var currentPage = undefined; - var callback = function callback(page) { - currentPage = page; - }; - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18' }, { 'Age': '23', 'Name': 'Test Person' }, { 'Name': 'Ian Zhang', 'Age': '28', 'Position': 'Developer' }, { 'Name': 'Griffin Smith', 'Age': '18', 'Position': 'Software Developer' }, { 'Age': '23', 'Name': 'Lee Salminen' }, { 'Age': '28', 'Position': 'Developer' }], itemsPerPage: 4, onPageChange: callback }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('emits the number of the currently selected page (zero based) when onPageChange event is triggered', function () { - var page1 = $('#table tbody.reactable-pagination a.reactable-page-button')[0]; - var page2 = $('#table tbody.reactable-pagination a.reactable-page-button')[1]; - var page3 = $('#table tbody.reactable-pagination a.reactable-page-button')[2]; - ReactTestUtils.Simulate.click(page2); - expect(currentPage).to.equal(1); - ReactTestUtils.Simulate.click(page1); - expect(currentPage).to.equal(0); - ReactTestUtils.Simulate.click(page3); - expect(currentPage).to.equal(2); - }); - }); - }); - - describe('sorting', function () { - describe('no default sort', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ Name: 'Lee Salminen', Age: '23', Position: 'Programmer' }, { Name: 'Griffin Smith', Age: '18', Position: 'Engineer' }, { Name: 'Ian Zhang', Age: '28', Position: 'Developer' }], - sortable: [{ - column: 'Name', - sortFunction: function sortFunction(a, b) { - // Sort by last name - var nameA = a.split(' '); - var nameB = b.split(' '); - - return nameA[1].localeCompare(nameB[1]); - } - }, 'Age', 'Position'] }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders all rows with no sort', function () { - ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']); - }); - - it('adds reactable-header-sortable to all headers', function () { - var header = $('#table thead tr.reactable-column-header th')[0]; - expect($(header)).to.have['class']('reactable-header-sortable'); - - header = $('#table thead tr.reactable-column-header th')[1]; - expect($(header)).to.have['class']('reactable-header-sortable'); - - header = $('#table thead tr.reactable-column-header th')[2]; - expect($(header)).to.have['class']('reactable-header-sortable'); - }); - - it('sorts by text in ascending order', function () { - var positionHeader = $('#table thead tr.reactable-column-header th')[2]; - ReactTestUtils.Simulate.click(positionHeader); - - ReactableTestUtils.expectRowText(0, ['Ian Zhang', '28', 'Developer']); - ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(2, ['Lee Salminen', '23', 'Programmer']); - - // Make sure the headers have the right classes - expect($(positionHeader)).to.have['class']('reactable-header-sort-asc'); - }); - - it('sorts by text in descending order', function () { - var positionHeader = $('#table thead tr.reactable-column-header th')[2]; - ReactTestUtils.Simulate.click(positionHeader); - - ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']); - - // Make sure the headers have the right classes - expect($(positionHeader)).to.have['class']('reactable-header-sort-desc'); - }); - - it('sorts by last name in ascending order', function () { - var nameHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.click(nameHeader); - - ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']); - - // Make sure the headers have the right classes - expect($(nameHeader)).to.have['class']('reactable-header-sort-asc'); - }); - - it('sorts by last name in descending order', function () { - var nameHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.click(nameHeader); - - ReactableTestUtils.expectRowText(0, ['Ian Zhang', '28', 'Developer']); - ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(2, ['Lee Salminen', '23', 'Programmer']); - - // Make sure the headers have the right classes - expect($(nameHeader)).to.have['class']('reactable-header-sort-desc'); - }); - - it('sorts by last name in ascending order by enter keydown', function () { - var nameHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.keyDown(nameHeader, { keyCode: 13 }); - - ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']); - - // Make sure the headers have the right classes - expect($(nameHeader)).to.have['class']('reactable-header-sort-asc'); - }); - - it('does not sort on non-enter keydown', function () { - var nameHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.keyDown(nameHeader, { keyCode: 10 }); - - ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']); - - // Make sure the headers have the right classes - expect($(nameHeader)).to.have['class']('reactable-header-sort-asc'); - }); - }); - - describe('passing `true` to sortable', function () { - var component; - before(function () { - this.render = function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ Name: 'Lee Salminen', Age: '23', Position: 'Programmer' }, { Name: 'Griffin Smith', Age: '18', Position: 'Engineer' }, { Name: 'Ian Zhang', Age: '28', Position: 'Developer' }], - sortable: true }), ReactableTestUtils.testNode()); - }; - - this.render(); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('sorts by the first column in ascending order', function () { - var nameHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.click(nameHeader); - - ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(1, ['Ian Zhang', '28', 'Developer']); - ReactableTestUtils.expectRowText(2, ['Lee Salminen', '23', 'Programmer']); - - // Make sure the headers have the right classes - expect($(nameHeader)).to.have['class']('reactable-header-sort-asc'); - }); - - it('sorts by the first column in descending order', function () { - var nameHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.click(nameHeader); - - ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(1, ['Ian Zhang', '28', 'Developer']); - ReactableTestUtils.expectRowText(2, ['Griffin Smith', '18', 'Engineer']); - - // Make sure the headers have the right classes - expect($(nameHeader)).to.have['class']('reactable-header-sort-desc'); - }); - - it('sorts by the second column in ascending order', function () { - var nameHeader = $('#table thead tr.reactable-column-header th')[1]; - ReactTestUtils.Simulate.click(nameHeader); - - ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']); - - // Make sure the headers have the right classes - expect($(nameHeader)).to.have['class']('reactable-header-sort-asc'); - }); - - it('sorts by the second column in descending order', function () { - var nameHeader = $('#table thead tr.reactable-column-header th')[1]; - ReactTestUtils.Simulate.click(nameHeader); - - ReactableTestUtils.expectRowText(0, ['Ian Zhang', '28', 'Developer']); - ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(2, ['Griffin Smith', '18', 'Engineer']); - - // Make sure the headers have the right classes - expect($(nameHeader)).to.have['class']('reactable-header-sort-desc'); - }); - - it('sorts by the third column in ascending order', function () { - var positionHeader = $('#table thead tr.reactable-column-header th')[2]; - ReactTestUtils.Simulate.click(positionHeader); - - ReactableTestUtils.expectRowText(0, ['Ian Zhang', '28', 'Developer']); - ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(2, ['Lee Salminen', '23', 'Programmer']); - - // Make sure the headers have the right classes - expect($(positionHeader)).to.have['class']('reactable-header-sort-asc'); - }); - - it('sorts by the third column in descending order', function () { - var positionHeader = $('#table thead tr.reactable-column-header th')[2]; - ReactTestUtils.Simulate.click(positionHeader); - - ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']); - - // Make sure the headers have the right classes - expect($(positionHeader)).to.have['class']('reactable-header-sort-desc'); - }); - - it('Keeps the same sort after rerendering', function () { - expect(this.render).to.not['throw'](Error); - - ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']); - }); - }); - - describe('default sort', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ Name: 'Lee Salminen', Age: '23', Position: 'Programmer' }, { Name: 'Griffin Smith', Age: '18', Position: 'Engineer' }, { Name: 'Ian Zhang', Age: '28', Position: 'Developer' }], - sortable: [{ - column: 'Name', - sortFunction: function sortFunction(a, b) { - // Sort by last name - var nameA = a.split(' '); - var nameB = b.split(' '); - - return nameA[1].localeCompare(nameB[1]); - } - }, 'Age', 'Position'], - defaultSort: { column: 'Age', direction: 'desc' } }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders all rows sorted by default column age descending', function () { - ReactableTestUtils.expectRowText(0, ['Ian Zhang', '28', 'Developer']); - ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(2, ['Griffin Smith', '18', 'Engineer']); - }); - }); - - describe('sort descending by default flag', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ Name: 'Lee Salminen', Age: '23', Position: 'Programmer' }, { Name: 'Griffin Smith', Age: '18', Position: 'Engineer' }, { Name: 'Ian Zhang', Age: '28', Position: 'Developer' }], - sortable: [{ - column: 'Name', - sortFunction: function sortFunction(a, b) { - // Sort by last name - var nameA = a.split(' '); - var nameB = b.split(' '); - - return nameA[1].localeCompare(nameB[1]); - } - }, 'Age', 'Position'], - defaultSort: { column: 'Age' }, - defaultSortDescending: true }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders all rows sorted by default column age descending', function () { - ReactableTestUtils.expectRowText(0, ['Ian Zhang', '28', 'Developer']); - ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(2, ['Griffin Smith', '18', 'Engineer']); - }); - - it('sorts by the age column in ascending order', function () { - var positionHeader = $('#table thead tr.reactable-column-header th')[1]; - ReactTestUtils.Simulate.click(positionHeader); - - ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']); - - // Make sure the headers have the right classes - expect($(positionHeader)).to.have['class']('reactable-header-sort-asc'); - }); - }); - - describe('default sort no direction specified', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ Name: 'Lee Salminen', Age: '23', Position: 'Programmer' }, { Name: 'Griffin Smith', Age: '18', Position: 'Engineer' }, { Name: 'Ian Zhang', Age: '28', Position: 'Developer' }], - sortable: [{ - column: 'Name', - sortFunction: function sortFunction(a, b) { - // Sort by last name - var nameA = a.split(' '); - var nameB = b.split(' '); - - return nameA[1].localeCompare(nameB[1]); - } - }, 'Age', 'Position'], - defaultSort: 'Age' }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders all rows sorted by default column age ascending', function () { - ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']); - }); - }); - - describe('unsortable column', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ Name: 'Lee Salminen', Age: '23', Position: 'Programmer' }, { Name: 'Griffin Smith', Age: '18', Position: 'Engineer' }, { Name: 'Ian Zhang', Age: '28', Position: 'Developer' }], - sortable: ['Age', 'Position'] }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('leaves columns unsorted', function () { - var nameHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.click(nameHeader); - - ReactableTestUtils.expectRowText(0, ['Lee Salminen', '23', 'Programmer']); - ReactableTestUtils.expectRowText(1, ['Griffin Smith', '18', 'Engineer']); - ReactableTestUtils.expectRowText(2, ['Ian Zhang', '28', 'Developer']); - }); - }); - - [Reactable.Sort.Numeric, Reactable.Sort.NumericInteger].forEach(function (method) { - describe('numeric sort', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ Count: '23' }, { Count: '18' }, { Count: '28' }, { Count: '1.23' }, { Count: 'a' }, { Count: 'z' }, { Count: '123' }], - columns: [{ key: 'Count', sortable: method }] }), ReactableTestUtils.testNode()); - }); - - after(function () { - ReactableTestUtils.resetTestEnvironment(); - }); - - it('sorts columns numerically', function () { - var sortHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.click(sortHeader); - - ReactableTestUtils.expectRowText(0, ['1.23']); - ReactableTestUtils.expectRowText(1, ['18']); - ReactableTestUtils.expectRowText(2, ['23']); - ReactableTestUtils.expectRowText(3, ['28']); - ReactableTestUtils.expectRowText(4, ['123']); - ReactableTestUtils.expectRowText(5, ['a']); - ReactableTestUtils.expectRowText(6, ['z']); - }); - }); - }); - - describe('numeric sort with Tr and Td specified', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { - className: 'table', - id: 'table', - columns: [{ key: 'Count', sortable: Reactable.Sort.Numeric }] }, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Count' }, - '23' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Count' }, - '18' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Count' }, - '28' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Count' }, - '1.23' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Count' }, - 'a' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Count' }, - 'z' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Count' }, - '123' - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(function () { - ReactableTestUtils.resetTestEnvironment(); - }); - - it('sorts columns numerically', function () { - var sortHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.click(sortHeader); - - ReactableTestUtils.expectRowText(0, ['1.23']); - ReactableTestUtils.expectRowText(1, ['18']); - ReactableTestUtils.expectRowText(2, ['23']); - ReactableTestUtils.expectRowText(3, ['28']); - ReactableTestUtils.expectRowText(4, ['123']); - ReactableTestUtils.expectRowText(5, ['a']); - ReactableTestUtils.expectRowText(6, ['z']); - }); - }); - - describe('numeric sort with Tr and Td specified and custom value', function () { - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { - className: 'table', - id: 'table', - columns: [{ key: 'Count', sortable: Reactable.Sort.Numeric }] }, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Count', value: 23 }, - 'twenty-three' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Count', value: 18 }, - 'eighteen' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Count', value: 28 }, - 'twenty-eight' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Count', value: 1.23 }, - 'one point two three' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Count', value: 'a' }, - 'a' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Count', value: 'z' }, - 'z' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Count', value: 123 }, - 'one hundred twenty-three' - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(function () { - ReactableTestUtils.resetTestEnvironment(); - }); - - it('sorts columns numerically', function () { - var sortHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.click(sortHeader); - - ReactableTestUtils.expectRowText(0, ['one point two three']); - ReactableTestUtils.expectRowText(1, ['eighteen']); - ReactableTestUtils.expectRowText(2, ['twenty-three']); - ReactableTestUtils.expectRowText(3, ['twenty-eight']); - ReactableTestUtils.expectRowText(4, ['one hundred twenty-three']); - ReactableTestUtils.expectRowText(5, ['a']); - ReactableTestUtils.expectRowText(6, ['z']); - }); - }); - - describe('currency sort', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ Price: '1.25' }, { Price: '$1.01' }, { Price: '1' }, { Price: '$10,000' }, { Price: '$10,500' }, { Price: '$10' }, { Price: 'a' }, { Price: 'z' }, { Price: '$2' }, { Price: '$.5' }, { Price: '$0.60' }, { Price: '.1' }], - columns: [{ key: 'Price', sortable: Reactable.Sort.Currency }] }), ReactableTestUtils.testNode()); - }); - - after(function () { - ReactableTestUtils.resetTestEnvironment(); - }); - - it('sorts columns numerically. parsing out currency symbols', function () { - var sortHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.click(sortHeader); - - ReactableTestUtils.expectRowText(0, ['.1']); - ReactableTestUtils.expectRowText(1, ['$.5']); - ReactableTestUtils.expectRowText(2, ['$0.60']); - ReactableTestUtils.expectRowText(3, ['1']); - ReactableTestUtils.expectRowText(4, ['$1.01']); - ReactableTestUtils.expectRowText(5, ['1.25']); - ReactableTestUtils.expectRowText(6, ['$2']); - ReactableTestUtils.expectRowText(7, ['$10']); - ReactableTestUtils.expectRowText(8, ['$10,000']); - ReactableTestUtils.expectRowText(9, ['$10,500']); - ReactableTestUtils.expectRowText(10, ['a']); - ReactableTestUtils.expectRowText(11, ['z']); - }); - }); - - describe('date sort', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ 'Date': '1/1/2014 11:00 AM' }, { 'Date': '1/1/2013 11:00 AM' }, { 'Date': '1/1/2014 4:30 PM' }, { 'Date': '4/3/2013' }, { 'Date': 'a' }, { 'Date': 'z' }], - columns: [{ key: 'Date', sortable: Reactable.Sort.Date }] }), ReactableTestUtils.testNode()); - }); - - after(function () { - ReactableTestUtils.resetTestEnvironment(); - }); - - it('sorts columns by date', function () { - var sortHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.click(sortHeader); - - ReactableTestUtils.expectRowText(0, ['1/1/2013 11:00 AM']); - ReactableTestUtils.expectRowText(1, ['4/3/2013']); - ReactableTestUtils.expectRowText(2, ['1/1/2014 11:00 AM']); - ReactableTestUtils.expectRowText(3, ['1/1/2014 4:30 PM']); - ReactableTestUtils.expectRowText(4, ['a']); - ReactableTestUtils.expectRowText(5, ['z']); - }); - }); - - describe('case insensitive sorting', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ 'Name': 'Lee Salminen' }, { 'Name': 'Griffin Smith' }, { 'Name': 'Ian Zhang' }, { 'Name': 'lee Salminen' }, { 'Name': 'griffin smith' }, { 'Name': 'Ian zhang' }], - columns: [{ key: 'Name', sortable: Reactable.Sort.CaseInsensitive }] }), ReactableTestUtils.testNode()); - }); - - after(function () { - ReactableTestUtils.resetTestEnvironment(); - }); - - it('sorts columns by value - case insensitive', function () { - var sortHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.click(sortHeader); - - ReactableTestUtils.expectRowText(0, ['Griffin Smith']); - ReactableTestUtils.expectRowText(1, ['griffin smith']); - ReactableTestUtils.expectRowText(2, ['Ian Zhang']); - ReactableTestUtils.expectRowText(3, ['Ian zhang']); - ReactableTestUtils.expectRowText(4, ['Lee Salminen']); - ReactableTestUtils.expectRowText(5, ['lee Salminen']); - }); - }); - - describe('custom sort with React Components', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ 'Rank': React.createElement( - 'span', - { className: '3' }, - 'Third' - ) }, { 'Rank': React.createElement( - 'span', - { className: '1' }, - 'First' - ) }, { 'Rank': React.createElement( - 'span', - { className: '2' }, - 'Second' - ) }], - columns: [{ - key: 'Rank', sortable: function sortable(a, b) { - // sort based on classname - return a.props.className.localeCompare(b.props.className); - } - }] }), ReactableTestUtils.testNode()); - }); - - after(function () { - ReactableTestUtils.resetTestEnvironment(); - }); - - it('sorts columns by value', function () { - var sortHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.click(sortHeader); - - ReactableTestUtils.expectRowText(0, ['First']); - ReactableTestUtils.expectRowText(1, ['Second']); - ReactableTestUtils.expectRowText(2, ['Third']); - }); - }); - - describe('sorts and calls onSort callback via props', function () { - var sortColumn = null; - - var callback = function callback(sortObject) { - sortColumn = sortObject.column; - }; - - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ 'Rank': React.createElement( - 'span', - { className: '3' }, - 'Third' - ) }, { 'Rank': React.createElement( - 'span', - { className: '1' }, - 'First' - ) }, { 'Rank': React.createElement( - 'span', - { className: '2' }, - 'Second' - ) }], - columns: [{ - key: 'Rank', sortable: function sortable(a, b) { - // sort based on classname - return a.props.className.localeCompare(b.props.className); - } - }], - onSort: callback }), ReactableTestUtils.testNode()); - }); - - after(function () { - ReactableTestUtils.resetTestEnvironment(); - }); - - it('returns currentSort object to callback for utilization', function () { - var sortHeader = $('#table thead tr.reactable-column-header th')[0]; - ReactTestUtils.Simulate.click(sortHeader); - - expect(sortColumn).to.equal('Rank'); - }); - }); - }); - - describe('filtering', function () { - describe('filtering with javascript objects for data', function () { - var data = [{ name: "Lee SomeoneElse", age: 18 }, { name: "Lee Salminen", age: 23 }, { name: "No Age", age: null }]; - var filterBy; - var onFilter = function onFilter(filter) { - filterBy = filter; - }; - before(function () { - ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table', - filterable: ['Name', 'Age'], - onFilter: onFilter }, - React.createElement( - Reactable.Tr, - null, - React.createElement(Reactable.Td, { column: 'Name', data: data[0].name }), - React.createElement(Reactable.Td, { column: 'Age', data: data[0].age }) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement(Reactable.Td, { column: 'Name', data: data[1].name }), - React.createElement(Reactable.Td, { column: 'Age', data: data[1].age }) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement(Reactable.Td, { column: 'Name', data: data[2].name }), - React.createElement(Reactable.Td, { column: 'Age', data: data[2].age }) - ) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('filters case insensitive on specified columns', function () { - var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input'); - - $filter.val('lee'); - React.addons.TestUtils.Simulate.keyUp($filter[0]); - - ReactableTestUtils.expectRowText(0, ['Lee SomeoneElse', '18']); - ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23']); - }); - it('calls onFilter event handler', function () { - var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input'); - var textToSearch = 'lee'; - - $filter.val(textToSearch); - React.addons.TestUtils.Simulate.keyUp($filter[0]); - - expect(filterBy).to.equal(textToSearch); - }); - }); - - describe('basic case-insensitive filtering', function () { - before(function () { - this.component = ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table', - filterable: ['State', 'Tag'], - filterPlaceholder: 'Filter Results', - columns: ['State', 'Description', 'Tag'] }, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'State' }, - 'New York' - ), - React.createElement( - Reactable.Td, - { column: 'Description' }, - 'this is some text' - ), - React.createElement( - Reactable.Td, - { column: 'Tag' }, - 'new' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'State' }, - 'New Mexico' - ), - React.createElement( - Reactable.Td, - { column: 'Description' }, - 'lorem ipsum' - ), - React.createElement( - Reactable.Td, - { column: 'Tag' }, - 'old' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'State' }, - 'Colorado' - ), - React.createElement( - Reactable.Td, - { column: 'Description' }, - 'new description that shouldnt match filter' - ), - React.createElement( - Reactable.Td, - { column: 'Tag' }, - 'old' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'State' }, - 'Alaska' - ), - React.createElement( - Reactable.Td, - { column: 'Description' }, - 'bacon' - ), - React.createElement( - Reactable.Td, - { column: 'Tag' }, - 'renewed' - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - context('from the filterer field', function () { - it('filters case insensitive on specified columns', function () { - var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input'); - - $filter.val('new'); - React.addons.TestUtils.Simulate.keyUp($filter[0]); - - ReactableTestUtils.expectRowText(0, ['New York', 'this is some text', 'new']); - ReactableTestUtils.expectRowText(1, ['New Mexico', 'lorem ipsum', 'old']); - ReactableTestUtils.expectRowText(2, ['Alaska', 'bacon', 'renewed']); - }); - - it('filter placeholder is set', function () { - var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input'); - expect($filter.attr("placeholder")).to.equal('Filter Results'); - }); - }); - - context('from the function', function () { - before(function () { - this.component.filterBy('york'); - }); - - it('applies the filtering', function () { - ReactableTestUtils.expectRowText(0, ['New York', 'this is some text', 'new']); - }); - - it('updates the value of the filterer', function () { - var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input'); - expect($filter).to.have.value('york'); - }); - }); - - context('from filterBy prop', function () { - before(function () { - ReactableTestUtils.resetTestEnvironment(); - - var ParentComponent = React.createClass({ - displayName: 'ParentComponent', - - getInitialState: function getInitialState() { - return { customFilterText: 'new' }; - }, - - handleChange: function handleChange(event) { - this.setState({ customFilterText: event.target.value }); - }, - - render: function render() { - return React.createElement( - 'div', - null, - React.createElement('input', { type: 'text', ref: 'customFilterInput', id: 'customFilterInput', value: this.state.customFilterText, onChange: this.handleChange }), - React.createElement( - Reactable.Table, - { className: 'table', id: 'table', - filterable: ['State', 'Tag'], - filterPlaceholder: 'Filter Results', - filterBy: this.state.customFilterText, - columns: ['State', 'Description', 'Tag'] }, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'State' }, - 'New York' - ), - React.createElement( - Reactable.Td, - { column: 'Description' }, - 'this is some text' - ), - React.createElement( - Reactable.Td, - { column: 'Tag' }, - 'new' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'State' }, - 'New Mexico' - ), - React.createElement( - Reactable.Td, - { column: 'Description' }, - 'lorem ipsum' - ), - React.createElement( - Reactable.Td, - { column: 'Tag' }, - 'old' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'State' }, - 'Colorado' - ), - React.createElement( - Reactable.Td, - { column: 'Description' }, - 'new description that shouldnt match filter' - ), - React.createElement( - Reactable.Td, - { column: 'Tag' }, - 'old' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'State' }, - 'Alaska' - ), - React.createElement( - Reactable.Td, - { column: 'Description' }, - 'bacon' - ), - React.createElement( - Reactable.Td, - { column: 'Tag' }, - 'renewed' - ) - ) - ) - ); - } - }); - - this.component = ReactDOM.render(React.createElement(ParentComponent), ReactableTestUtils.testNode()); - }); - - it('filters case insensitive on specified columns', function () { - ReactableTestUtils.expectRowText(0, ['New York', 'this is some text', 'new']); - ReactableTestUtils.expectRowText(1, ['New Mexico', 'lorem ipsum', 'old']); - ReactableTestUtils.expectRowText(2, ['Alaska', 'bacon', 'renewed']); - var $builtInFilter = $('#table thead tr.reactable-filterer input.reactable-filter-input'); - expect($builtInFilter).to.have.value('new'); - - // Simulate changing input on parent component and re-rendering Reactable.Table with new props. - var node = this.component.refs.customFilterInput; - node.value = 'alaska'; - ReactTestUtils.Simulate.change(customFilterInput); - - ReactableTestUtils.expectRowText(0, ['Alaska', 'bacon', 'renewed']); - expect($builtInFilter).to.have.value('alaska'); - }); - }); - }); - - context('filtering with prop and hiding filter input', function () { - before(function () { - this.component = ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table', - filterable: ['State', 'Tag'], - filterPlaceholder: 'Filter Results', - filterBy: 'new', - hideFilterInput: true, - columns: ['State', 'Description', 'Tag'] }, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'State' }, - 'New York' - ), - React.createElement( - Reactable.Td, - { column: 'Description' }, - 'this is some text' - ), - React.createElement( - Reactable.Td, - { column: 'Tag' }, - 'new' - ) - ), - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'State' }, - 'New Mexico' - ), - React.createElement( - Reactable.Td, - { column: 'Description' }, - 'lorem ipsum' - ), - React.createElement( - Reactable.Td, - { column: 'Tag' }, - 'old' - ) - ) - ), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('does not render the filter input box', function () { - expect($('#table thead tr.reactable-filterer input.reactable-filter-input').length).to.equal(0); - }); - }); - - context('filtering and pagination together', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ 'State': 'New York', 'Description': 'this is some text', 'Tag': 'new' }, { 'State': 'New Mexico', 'Description': 'lorem ipsum', 'Tag': 'old' }, { 'State': 'Colorado', 'Description': 'new description that shouldn\'t match filter', - 'Tag': 'old' }, { 'State': 'Alaska', 'Description': 'bacon', 'Tag': 'renewed' }], - filterable: ['State', 'Tag'], - columns: ['State', 'Description', 'Tag'], - itemsPerPage: 2 }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - afterEach(function () { - var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input'); - $filter.val(''); - React.addons.TestUtils.Simulate.keyUp($filter[0]); - }); - - it('updates the pagination links', function () { - var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input'); - - $filter.val('colorado'); - React.addons.TestUtils.Simulate.keyUp($filter[0]); - - var pageButtons = $('#table tbody.reactable-pagination a.reactable-page-button'); - expect(pageButtons.length).to.equal(1); - expect($(pageButtons[0])).to.have.text('1'); - }); - - it('updates the current page if necessary', function () { - var $filter = $('#table thead tr.reactable-filterer input.reactable-filter-input'); - var $pageButtons = $('#table tbody.reactable-pagination a.reactable-page-button'); - - // Go to the last page - React.addons.TestUtils.Simulate.click($pageButtons[1]); - - // Then filter so that that page doesn't exist anymore - $filter.val('colorado'); - React.addons.TestUtils.Simulate.keyUp($filter[0]); - - ReactableTestUtils.expectRowText(0, ['Colorado', "new description that shouldn't match filter", 'old']); - var activePage = $('#table tbody.reactable-pagination ' + 'a.reactable-page-button.reactable-current-page'); - expect(activePage.length).to.equal(1); - expect(activePage).to.have.text('1'); - }); - }); - }); - - describe('directly passing a data array with non-string data', function () { - before(function () { - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table', data: [{ Name: 'Griffin Smith', Age: 18 }, { Age: 23, Name: { toString: function toString() { - return 'Lee Salminen'; - } } }, { Age: 28.45, Position: 'Developer' }] }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('renders the table', function () { - expect($('table#table.table')).to.exist; - }); - - it('renders the column headers in the table', function () { - var headers = []; - $('thead th').each(function () { - headers.push($(this).text()); - }); - - expect(headers).to.eql(['Name', 'Age', 'Position']); - }); - - it('renders the first row with the correct data', function () { - ReactableTestUtils.expectRowText(0, ['Griffin Smith', '18', '']); - }); - - it('renders the second row with the correct data', function () { - ReactableTestUtils.expectRowText(1, ['Lee Salminen', '23', '']); - }); - - it('renders the third row with the correct data', function () { - ReactableTestUtils.expectRowText(2, ['', '28.45', 'Developer']); - }); - }); - - describe('multiple tables on a page', function () { - before(function () { - this.parentTestNode = ReactableTestUtils.testNode(); - this.testNode1 = $('
').attr('id', 'test-node-1'); - this.testNode2 = $('
').attr('id', 'test-node-2'); - - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table1', data: [{ Name: 'Griffin Smith', Age: '18' }, { Age: '23', Name: 'Lee Salminen' }, { Age: '28', Position: 'Developer' }] }), this.testNode1[0]); - - ReactDOM.render(React.createElement(Reactable.Table, { className: 'table', id: 'table2', data: [{ Moniker: 'Griffin Smith', Elderliness: '18' }, { Elderliness: '23', Moniker: 'Lee Salminen' }, { Elderliness: '28', Title: 'Developer' }] }), this.testNode2[0]); - }); - - after(function () { - $(this.parentTestNode).empty().remove(); - }); - - it('renders the column headers in the first table', function () { - var headers = []; - this.testNode1.find('thead th').each(function () { - headers.push($(this).text()); - }); - - expect(headers).to.eql(['Name', 'Age', 'Position']); - }); - - it('renders the column headers in the second table', function () { - var headers = []; - this.testNode2.find('thead th').each(function () { - headers.push($(this).text()); - }); - - expect(headers).to.eql(['Moniker', 'Elderliness', 'Title']); - }); - }); - - describe('handleClick callbacks', function () { - before(function () { - this.clicked = false; - - ReactDOM.render(React.createElement( - Reactable.Table, - { className: 'table', id: 'table' }, - React.createElement( - Reactable.Tr, - null, - React.createElement( - Reactable.Td, - { column: 'Name', handleClick: (function () { - this.clicked = true; - }).bind(this) }, - React.createElement( - 'b', - null, - 'Griffin Smith' - ) - ) - ) - ), ReactableTestUtils.testNode()); - - ReactTestUtils.Simulate.click($('td')[0]); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('calls the callbacks on click', function () { - expect(this.clicked).to.eq(true); - }); - }); - - describe('table with no data', function () { - context('when noDataText prop is null', function () { - before(function () { - this.component = ReactDOM.render(React.createElement(Reactable.Table, { data: [], columns: ['State', 'Description', 'Tag'] }), ReactableTestUtils.testNode()); - }); - - after(ReactableTestUtils.resetTestEnvironment); - - it('does not render the reactable-no-data element', function () { - expect($('.reactable-no-data').length).to.eq(0); - }); - }); - - context('when initialized without
',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table'},React.createElement(Reactable.Tr,{data:{Name:'Griffin Smith',Age:'18'}}),React.createElement(Reactable.Tr,{data:{Age:'23',Name:'Lee Salminen'}}),React.createElement(Reactable.Tr,{data:{Age:'28',Position:'Developer'}})),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the table',function(){expect($('table#table.table')).to.exist;});it('renders the column headers in the table',function(){var headers=[];$('thead th').each(function(){headers.push($(this).text());});expect(headers).to.eql(['Name','Age','Position']);});it('renders the first row with the correct data',function(){ReactableTestUtils.expectRowText(0,['Griffin Smith','18','']);});it('renders the second row with the correct data',function(){ReactableTestUtils.expectRowText(1,['Lee Salminen','23','']);});it('renders the third row with the correct data',function(){ReactableTestUtils.expectRowText(2,['','28','Developer']);});});describe('adding s',function(){context('with only one s',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table'},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name'},React.createElement('b',null,'Griffin Smith')),React.createElement(Reactable.Td,{column:'Age'},React.createElement('em',null,'18'))),null,React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Position'},React.createElement('b',null,'Developer')),React.createElement(Reactable.Td,{column:'Age'},React.createElement('em',null,'28')))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the table',function(){expect($('table#table.table')).to.exist;});it('renders the column headers in the table',function(){var headers=[];$('thead th').each(function(){headers.push($(this).text());});expect(headers).to.eql(['Name','Age','Position']);});it('renders the first row with the correct data',function(){ReactableTestUtils.expectRowText(0,['Griffin Smith','18','']);});it('renders the second row with the correct data',function(){ReactableTestUtils.expectRowText(1,['','28','Developer']);});});});describe('Adding a ',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',sortable:['Name'],filterable:['Name','Age']},React.createElement(Reactable.Tr,{className:'rowClass1',data:{Name:'Griffin Smith',Age:'18'}}),React.createElement(Reactable.Tr,{className:'rowClass2',data:{Age:'23',Name:'Lee Salminen'}}),React.createElement(Reactable.Tr,{className:'rowClass3',data:{Age:'28',Position:'Developer'}}),React.createElement(Reactable.Tfoot,{id:'tfoot'},React.createElement('tr',null,React.createElement('td',{id:'tfoot-stuff'},'Test')))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the table',function(){expect($('#table')).to.exist;});it('renders the regular data rows',function(){ReactableTestUtils.expectRowText(0,['Griffin Smith','18','']);ReactableTestUtils.expectRowText(1,['Lee Salminen','23','']);ReactableTestUtils.expectRowText(2,['','28','Developer']);});it('renders the tfoot',function(){expect($('#tfoot')).to.exist;});it('renders the children of the tfoot',function(){expect($('#tfoot-stuff')).to.exist;});context('when sorting',function(){before(function(){ReactTestUtils.Simulate.click($('th')[0]);});it('leaves the tfoot alone',function(){expect($('table :last-child')).to.match('tfoot');});});context('when filtering',function(){before(function(){var $filter=$('.reactable-filter-input');$filter.val('griffin');ReactTestUtils.Simulate.keyUp($filter[0]);});it('leaves the tfoot alone',function(){expect($('table :last-child')).to.match('tfoot');});});});describe('passing through HTML props',function(){describe('adding s with className to the
s to the
',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table'},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name'},'Griffin Smith')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name'},'Lee Salminen')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name'},'Ian Zhang'))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the table',function(){expect($('table#table.table')).to.exist;});it('renders the column headers in the table',function(){var headers=[];$('thead th').each(function(){headers.push($(this).text());});expect(headers).to.eql(['Name']);});it('renders the first row with the correct data',function(){ReactableTestUtils.expectRowText(0,['Griffin Smith']);});it('renders the second row with the correct data',function(){ReactableTestUtils.expectRowText(1,['Lee Salminen']);});it('renders the third row with the correct data',function(){ReactableTestUtils.expectRowText(2,['Ian Zhang']);});});context('with multiple s',function(){context('with plain text',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table'},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name'},'Griffin Smith'),React.createElement(Reactable.Td,{column:'Age'},'18')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name'},'Lee Salminen'),React.createElement(Reactable.Td,{column:'Age'},'23')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Position'},'Developer'),React.createElement(Reactable.Td,{column:'Age'},'28'))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the table',function(){expect($('table#table.table')).to.exist;});it('renders the column headers in the table',function(){var headers=[];$('thead th').each(function(){headers.push($(this).text());});expect(headers).to.eql(['Name','Age','Position']);});it('renders the first row with the correct data',function(){ReactableTestUtils.expectRowText(0,['Griffin Smith','18','']);});it('renders the second row with the correct data',function(){ReactableTestUtils.expectRowText(1,['Lee Salminen','23','']);});it('renders the third row with the correct data',function(){ReactableTestUtils.expectRowText(2,['','28','Developer']);});});});context('with React.DOM nodes inside',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table'},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name'},React.createElement('b',null,'Griffin Smith')),React.createElement(Reactable.Td,{column:'Age'},React.createElement('em',null,'18'))),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name'},React.createElement('b',null,'Lee Salminen')),React.createElement(Reactable.Td,{column:'Age'},React.createElement('em',null,'23'))),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Position'},React.createElement('b',null,'Developer')),React.createElement(Reactable.Td,{column:'Age'},React.createElement('em',null,'28')))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the table',function(){expect($('table#table.table')).to.exist;});it('renders the column headers in the table',function(){var headers=[];$('thead th').each(function(){headers.push($(this).text());});expect(headers).to.eql(['Name','Age','Position']);});it('renders the first row with the correct data',function(){ReactableTestUtils.expectRowText(0,['Griffin Smith','18','']);});it('renders the second row with the correct data',function(){ReactableTestUtils.expectRowText(1,['Lee Salminen','23','']);});it('renders the third row with the correct data',function(){ReactableTestUtils.expectRowText(2,['','28','Developer']);});});context('with null s',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table'},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name'},React.createElement('b',null,'Griffin Smith')),null),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name'},React.createElement('b',null,'Lee Salminen')),React.createElement(Reactable.Td,{column:'Age'},React.createElement('em',null,'23'))),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Position'},React.createElement('b',null,'Developer')),React.createElement(Reactable.Td,{column:'Age'},React.createElement('em',null,'28')))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the table',function(){expect($('table#table.table')).to.exist;});it('renders the column headers in the table',function(){var headers=[];$('thead th').each(function(){headers.push($(this).text());});expect(headers).to.eql(['Name','Age','Position']);});it('renders the first row with the correct data',function(){ReactableTestUtils.expectRowText(0,['Griffin Smith','','']);});it('renders the second row with the correct data',function(){ReactableTestUtils.expectRowText(1,['Lee Salminen','23','']);});it('renders the third row with the correct data',function(){ReactableTestUtils.expectRowText(2,['','28','Developer']);});});context('with null
',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table'},React.createElement(Reactable.Tr,{className:'rowClass1',data:{Name:'Griffin Smith',Age:'18'}}),React.createElement(Reactable.Tr,{className:'rowClass2',data:{Age:'23',Name:'Lee Salminen'}}),React.createElement(Reactable.Tr,{className:'rowClass3',data:{Age:'28',Position:'Developer'}})),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the table',function(){expect($('table#table.table')).to.exist;});it('renders the column headers in the table',function(){var headers=[];$('thead th').each(function(){headers.push($(this).text());});expect(headers).to.eql(['Name','Age','Position']);});it('renders the first row with the correct class name',function(){ReactableTestUtils.expectRowClass(0,'rowClass1');});it('renders the second row with the correct class name',function(){ReactableTestUtils.expectRowClass(1,'rowClass2');});it('renders the third row with the correct class name',function(){ReactableTestUtils.expectRowClass(2,'rowClass3');});});describe('adding
s with classNames to the ',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table'},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name',className:'name-1'},'Griffin Smith'),React.createElement(Reactable.Td,{column:'Age'},'18')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name',className:'name-2'},'Lee Salminen'),React.createElement(Reactable.Td,{column:'Age'},'23')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Position',className:'position'},'Developer'),React.createElement(Reactable.Td,{column:'Age'},'28'))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the first column with the correct class name',function(){expect($('td.name-1')).to.have.text('Griffin Smith');});it('renders the second column with the correct class name',function(){expect($('td.name-2')).to.have.text('Lee Salminen');});it('renders the third column with the correct class name',function(){expect($('td.position')).to.have.text('Developer');});});});describe('adding
with style to the ',function(){before(function(){var tdStyle={width:"100px"};ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table'},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name',className:'name-1',style:tdStyle},'Griffin Smith'),React.createElement(Reactable.Td,{column:'Age'},'18'))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the first column with the width',function(){expect($('td.name-1')).to.have.attr('style').match(/width/);});});describe('specifying an array of columns',function(){describe('as strings',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{Name:'Griffin Smith',Age:'18',HideThis:'one'},{Age:'23',Name:'Lee Salminen',HideThis:'two'},{Age:'28',Position:'Developer'}],columns:['Name','Age']}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('omits columns not in the list',function(){var columns=$('tr.reactable-column-header th');expect(columns.length).to.equal(2);expect($(columns[0])).to.have.text('Name');expect($(columns[1])).to.have.text('Age');});it('adds class name for each column base on its label',function(){var columns=$('tr.reactable-column-header th');expect($(columns[0])).to.have['class']('reactable-th-name');expect($(columns[1])).to.have['class']('reactable-th-age');});});describe('as objects',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{name:'Griffin Smith',age:'18',HideThis:'one'},{age:'23',name:'Lee Salminen',HideThis:'two'},{age:'28',Position:'Developer'}],columns:[{key:'name',label:'Name'},{key:'age',label:'Age'}]}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('omits columns not in the list',function(){var columns=$('tr.reactable-column-header th');expect(columns.length).to.equal(2);});it('allows changing the labels of the columns',function(){var columns=$('tr.reactable-column-header th');expect($(columns[0])).to.have.text('Name');expect($(columns[1])).to.have.text('Age');});it('adds class name for each column base on its key',function(){var columns=$('tr.reactable-column-header th');expect($(columns[0])).to.have['class']('reactable-th-name');expect($(columns[1])).to.have['class']('reactable-th-age');});});});describe('specifying columns using a ',function(){describe('and an element for the column title',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{id:'table',data:[{Name:Reactable.unsafe('Griffin Smith'),Age:'18'},{Age:'28',Position:Reactable.unsafe('Developer')},{Age:'23',Name:Reactable.unsafe('Lee Salminen')}]},React.createElement(Reactable.Thead,null,React.createElement(Reactable.Th,{column:'Name',id:'my-name'},React.createElement('strong',null,'name')))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders only the columns in the Thead',function(){expect($('#table tbody tr:first td')).to.exist;expect($('#table thead tr:first th')).to.exist;});it('renders the contents of the Th',function(){expect($('#table>thead>tr>th>strong')).to.exist;});it('passes through the properties of the Th',function(){expect($('#table>thead>tr>th')).to.have.id('my-name');});});describe('and a string for the column title',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{id:'table',data:[{Name:Reactable.unsafe('Griffin Smith'),Age:'18'},{Age:'28',Position:Reactable.unsafe('Developer')},{Age:'23',Name:Reactable.unsafe('Lee Salminen')}]},React.createElement(Reactable.Thead,null,React.createElement(Reactable.Th,{column:'Name',id:'my-name'},'name'))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders only the columns in the Thead',function(){expect($('#table tbody tr:first td')).to.exist;expect($('#table thead tr:first th')).to.exist;});it('renders the contents of the Th',function(){expect($('#table>thead>tr>th')).to.exist;});it('passes through the properties of the Th',function(){expect($('#table>thead>tr>th')).to.have.id('my-name');});});});describe('unsafe() strings',function(){context('in the
directly',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{Name:Reactable.unsafe('Griffin Smith'),Age:'18'},{Age:'28',Position:Reactable.unsafe('Developer')},{Age:'23',Name:Reactable.unsafe('Lee Salminen')}],sortable:['Name']}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the HTML in the table cells',function(){var griffins_name=$('span#griffins-name');expect(griffins_name.length).to.equal(1);expect(griffins_name).to.have.text('Griffin Smith');var lees_name=$('span#lees-name');expect(lees_name.length).to.equal(1);expect(lees_name).to.have.text('Lee Salminen');var who_knows_job=$('span#who-knows-job');expect(who_knows_job.length).to.equal(1);expect(who_knows_job).to.have.text('Developer');});it('still allows sorting',function(){var nameHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.click(nameHeader);ReactableTestUtils.expectRowText(0,['28','Developer','']);ReactableTestUtils.expectRowText(1,['18','','Griffin Smith']);ReactableTestUtils.expectRowText(2,['23','','Lee Salminen']);});});context('in column labels',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{Name:'Griffin Smith',Age:'18'},{Age:'23',Name:'Lee Salminen'},{Age:'28',Position:'Developer'}],columns:[{key:'Name',label:Reactable.unsafe('Name')},{key:'Age',label:Reactable.unsafe('Age')},{key:'Position',label:Reactable.unsafe('Position')}]}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the HTML in the column headers',function(){var headers=[];$('thead th').each(function(){headers.push($(this).html());});expect(headers).to.eql(['Name','Age','Position']);});});context('in the s',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table'},React.createElement(Reactable.Tr,{data:{Name:Reactable.unsafe('Griffin Smith'),Age:'18'}}),React.createElement(Reactable.Tr,{data:{Age:'23',Name:Reactable.unsafe('Lee Salminen')}}),React.createElement(Reactable.Tr,{data:{Age:'28',Position:Reactable.unsafe('Developer')}})),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the HTML in the table cells',function(){var griffins_name=$('span#griffins-name');expect(griffins_name.length).to.equal(1);expect(griffins_name).to.have.text('Griffin Smith');var lees_name=$('span#lees-name');expect(lees_name.length).to.equal(1);expect(lees_name).to.have.text('Lee Salminen');var who_knows_job=$('span#who-knows-job');expect(who_knows_job.length).to.equal(1);expect(who_knows_job).to.have.text('Developer');});});context('in the s',function(){before(function(){this.component = ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',columns:['State','Description','Tag'],noDataText:'No matching records found.'}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('shows the "no data" message',function(){var $text=$('.reactable-no-data').text();expect($text).to.eq('No matching records found.');});});context('when filtered without any matches',function(){before(function(){this.component = ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',filterable:['State','Tag'],filterPlaceholder:'Filter Results',filterBy:'xxxxx',noDataText:'No matching records found.',columns:['State','Description','Tag']},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'State'},'New York'),React.createElement(Reactable.Td,{column:'Description'},'this is some text'),React.createElement(Reactable.Td,{column:'Tag'},'new')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'State'},'New Mexico'),React.createElement(Reactable.Td,{column:'Description'},'lorem ipsum'),React.createElement(Reactable.Td,{column:'Tag'},'old')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'State'},'Colorado'),React.createElement(Reactable.Td,{column:'Description'},'new description that shouldnt match filter'),React.createElement(Reactable.Td,{column:'Tag'},'old')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'State'},'Alaska'),React.createElement(Reactable.Td,{column:'Description'},'bacon'),React.createElement(Reactable.Td,{column:'Tag'},'renewed'))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('shows the "no data" message',function(){var text=$('.reactable-no-data').text();expect(text).to.eq('No matching records found.');});});context('when initialized with an empty array for `data` prop',function(){before(function(){this.component = ReactDOM.render(React.createElement(Reactable.Table,{data:[],className:'table',id:'table',columns:['State','Description','Tag'],noDataText:'No matching records found.'}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('shows the "no data" message',function(){var $text=$('.reactable-no-data').text();expect($text).to.eq('No matching records found.');});});});describe('visibleItems()',function(){var _Reactable=Reactable;var Table=_Reactable.Table;var Thead=_Reactable.Thead;var Tr=_Reactable.Tr;var Th=_Reactable.Th;var Td=_Reactable.Td;var data=[{name:"Lee SomeoneElse",age:18},{name:"Lee Salminen",age:23},{name:"No Age",age:null}];var Tester=(function(_React$Component){_inherits(Tester,_React$Component);function Tester(){_classCallCheck(this,Tester);_get(Object.getPrototypeOf(Tester.prototype),'constructor',this).apply(this,arguments);}_createClass(Tester,[{key:'componentDidMount',value:function componentDidMount(){this.props.run && this.props.run(this);}},{key:'render',value:function render(){return React.createElement(Table,_extends({ref:'table',className:'table',id:'table',filterable:['Name','Age']},this.props),React.createElement(Thead,null,React.createElement(Th,{column:'Name'},'The Name'),React.createElement(Th,{column:'Age'},'The Age')),data.map(function(item,i){return React.createElement(Tr,{key:i,i:i < 2?i:null},React.createElement(Td,{column:'Name',data:item.name}),React.createElement(Td,{column:'Age',data:item.age}));}),React.createElement(Tr,{i:true},React.createElement(Td,{column:'Name',data:"hi"}),React.createElement(Td,{column:'Age',data:5})),React.createElement(Tr,{id:"id"},React.createElement(Td,{column:'Name',data:"hi"}),React.createElement(Td,{column:'Age',data:7})));}}]);return Tester;})(React.Component);var doTest=function doTest(runMe){var options=arguments.length <= 1 || arguments[1] === undefined?{}:arguments[1];return ReactDOM.render(React.createElement(Tester,_extends({run:runMe},options)),ReactableTestUtils.testNode());};after(ReactableTestUtils.resetTestEnvironment);it('works',function(){doTest(function(me){var items=me.refs.table.visibleItems();expect(items.length).to.eql(5);expect(items[0].Age).to.eql(18);});});it('works when filtered',function(){doTest(function(me){var items=me.refs.table.visibleItems();expect(items.length).to.eql(2);expect(items[1].Age).to.eql(23);},{filterBy:'lee'});});it('works when paged',function(){doTest(function(me){var items=me.refs.table.visibleItems();expect(items.length).to.eql(1);expect(items[0].Age).to.eql(18);},{itemsPerPage:1});});it('has keys',function(){doTest(function(me){var items=me.refs.table.visibleItems();expect(items[1].id).to.eql(1); // id is not defined and key is a string +expect(items[2].id).to.eql("2"); // Falsy ids still count +expect(items[0].id).to.eql(0);expect(items[3].id).to.eql(true);expect(items[4].id).to.eql("id");});});});});}); diff --git a/lib/reactable/filterer.js b/lib/reactable/filterer.js index 30aa6dd3..8a053dd8 100644 --- a/lib/reactable/filterer.js +++ b/lib/reactable/filterer.js @@ -80,6 +80,7 @@ var Filterer = (function (_React$Component2) { if (typeof this.props.colSpan === 'undefined') { throw new TypeError('Must pass a colSpan argument to Filterer'); } + return _react2["default"].createElement( "tr", { className: "reactable-filterer" }, diff --git a/lib/reactable/table.js b/lib/reactable/table.js index ee1645a5..47041b05 100644 --- a/lib/reactable/table.js +++ b/lib/reactable/table.js @@ -443,7 +443,7 @@ var Table = (function (_React$Component) { // Determine if we render the filter box var filtering = false; - if (this.props.filterable && !this.props.topPagination && Array.isArray(this.props.filterable) && this.props.filterable.length > 0 && !this.props.hideFilterInput) { + if (Array.isArray(this.props.filterable) && this.props.filterable.length > 0 && !this.props.hideFilterInput) { filtering = true; } @@ -508,9 +508,6 @@ var Table = (function (_React$Component) { filtering: filtering, onFilter: function (filter) { _this.setState({ filter: filter }); - if (_this.props.onFilter) { - _this.props.onFilter(filter); - } }, filterCleanBtn: filterCleanBtn, onClean: function (filter) { diff --git a/lib/reactable/td.js b/lib/reactable/td.js index 7b49fac7..71fae9de 100644 --- a/lib/reactable/td.js +++ b/lib/reactable/td.js @@ -48,6 +48,10 @@ var Td = (function (_React$Component) { onClick: this.handleClick.bind(this) }; + if (typeof this.props.style !== 'undefined') { + tdProps.style = this.props.style; + } + // Attach any properties on the column to this Td object to allow things like custom event handlers if (typeof this.props.column === 'object') { for (var key in this.props.column) { diff --git a/lib/reactable/thead.js b/lib/reactable/thead.js index 7fa9ceac..9d800d5e 100644 --- a/lib/reactable/thead.js +++ b/lib/reactable/thead.js @@ -117,12 +117,12 @@ var Thead = (function (_React$Component) { return _react2['default'].createElement( 'thead', props, - filtering === true ? _react2['default'].createElement(_filterer.Filterer, { + !topPagination && filtering && _react2['default'].createElement(_filterer.Filterer, { colSpan: columns.length, onFilter: onFilter, placeholder: filterPlaceholder, value: currentFilter - }) : null, + }), topPagination ? _react2['default'].createElement( 'tr', { className: 'reactable-btnPagination' }, @@ -139,8 +139,8 @@ var Thead = (function (_React$Component) { ), _react2['default'].createElement( 'div', - { className: 'reactable-mainElem' }, - _react2['default'].createElement(_filterer.FiltererInput, { + { className: filtering ? 'reactable-mainElem' : 'reactable-mainElem no-filter' }, + filtering && _react2['default'].createElement(_filterer.FiltererInput, { filterCleanBtn: filterCleanBtn, onClean: onClean, onFilter: onFilter, @@ -182,20 +182,21 @@ var Thead = (function (_React$Component) { if (typeof th.props !== 'undefined') { column.props = (0, _libFilter_props_from.filterPropsFrom)(th.props); - // use the content as the label & key - if (typeof th.props.children !== 'undefined') { + //set the label depending on the props + if (typeof th.props.label !== 'undefined') { + column.label = th.props.label; + } else if (typeof th.props.children !== 'undefined') { column.label = th.props.children; - column.key = column.label; + } else if (typeof th.props.column === 'string') { + column.label = th.props.column; } // the key in the column attribute supersedes the one defined previously if (typeof th.props.column === 'string') { column.key = th.props.column; - - // in case we don't have a label yet - if (typeof column.label === 'undefined') { - column.label = column.key; - } + } else { + // use the content as the key + column.key = th.props.children; } } From fea7aba45c9406721794a5fbb239fcac07c6421f Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Tue, 5 Apr 2016 18:29:40 +0200 Subject: [PATCH 27/35] Add onVisibleChange() prop this way you always can know what is visible --- src/reactable/table.jsx | 47 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index 4b4149af..21fb2085 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -213,6 +213,40 @@ export class Table extends React.Component { this.filterBy(nextProps.filterBy != null ? nextProps.filterBy : this.state.filter); } + componentDidUpdate() { + this.diffChildren() + } + + componentDidMount() { + this.diffChildren() + } + + diffChildren() { + const {onVisibleChange} = this.props + const {lastChildren, lastIds, currentChildren} = this + if (!onVisibleChange || !currentChildren) {return} + + if (lastChildren === currentChildren) {return} + const currentIds = this.childrenToData(currentChildren, true) + + let same + if (lastIds && lastIds.length === currentIds.length) { + same = true + for (let i = 0; i < currentIds.length; i++) { + if (lastIds[i] !== currentIds[i]) { + same = false + break + } + } + } + + this.lastIds = currentIds + this.lastChildren = currentChildren + if (!same) { + onVisibleChange(currentIds) + } + } + applyFilter(filter, children) { // Helper function to apply filter text to a list of table rows filter = filter.toLowerCase(); @@ -303,13 +337,17 @@ export class Table extends React.Component { } } - visibleItems() { - return this.currentChildren.map(row => { + childrenToData(children, onlyIds) { + return children.map(row => { const {i, id} = row.props; const iOrId = i != null ? i : id; const idOrKey = iOrId != null ? iOrId : row.key; - const data = {id: idOrKey}; + if (onlyIds) { + return idOrKey + } + + const data = {id: idOrKey}; Object.keys(row.props.data).forEach(key => { const col = row.props.data[key]; data[key] = col.props.value != null ? col.props.value : col.value; @@ -318,6 +356,9 @@ export class Table extends React.Component { return data; }) } + visibleItems(onlyIds) { + return this.childrenToData(onlyIds) + } scrollToTop() { if (this.tableEl) { From a8d0c00721578bf3105c2f1e620dd5b410bc5a82 Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Tue, 5 Apr 2016 18:29:47 +0200 Subject: [PATCH 28/35] build --- build/reactable.js | 61 +++++++++++++++++++++++++++++++++++++++--- lib/reactable/table.js | 61 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 114 insertions(+), 8 deletions(-) diff --git a/build/reactable.js b/build/reactable.js index 22a30829..08e8fdf4 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -1502,6 +1502,50 @@ window.ReactDOM["default"] = window.ReactDOM; this.sortByCurrentSort(); this.filterBy(nextProps.filterBy != null ? nextProps.filterBy : this.state.filter); } + }, { + key: 'componentDidUpdate', + value: function componentDidUpdate() { + this.diffChildren(); + } + }, { + key: 'componentDidMount', + value: function componentDidMount() { + this.diffChildren(); + } + }, { + key: 'diffChildren', + value: function diffChildren() { + var onVisibleChange = this.props.onVisibleChange; + var lastChildren = this.lastChildren; + var lastIds = this.lastIds; + var currentChildren = this.currentChildren; + + if (!onVisibleChange || !currentChildren) { + return; + } + + if (lastChildren === currentChildren) { + return; + } + var currentIds = this.childrenToData(currentChildren, true); + + var same = undefined; + if (lastIds && lastIds.length === currentIds.length) { + same = true; + for (var i = 0; i < currentIds.length; i++) { + if (lastIds[i] !== currentIds[i]) { + same = false; + break; + } + } + } + + this.lastIds = currentIds; + this.lastChildren = currentChildren; + if (!same) { + onVisibleChange(currentIds); + } + } }, { key: 'applyFilter', value: function applyFilter(filter, children) { @@ -1590,17 +1634,21 @@ window.ReactDOM["default"] = window.ReactDOM; } } }, { - key: 'visibleItems', - value: function visibleItems() { - return this.currentChildren.map(function (row) { + key: 'childrenToData', + value: function childrenToData(children, onlyIds) { + return children.map(function (row) { var _row$props = row.props; var i = _row$props.i; var id = _row$props.id; var iOrId = i != null ? i : id; var idOrKey = iOrId != null ? iOrId : row.key; - var data = { id: idOrKey }; + if (onlyIds) { + return idOrKey; + } + + var data = { id: idOrKey }; Object.keys(row.props.data).forEach(function (key) { var col = row.props.data[key]; data[key] = col.props.value != null ? col.props.value : col.value; @@ -1609,6 +1657,11 @@ window.ReactDOM["default"] = window.ReactDOM; return data; }); } + }, { + key: 'visibleItems', + value: function visibleItems(onlyIds) { + return this.childrenToData(onlyIds); + } }, { key: 'scrollToTop', value: function scrollToTop() { diff --git a/lib/reactable/table.js b/lib/reactable/table.js index 47041b05..126826c7 100644 --- a/lib/reactable/table.js +++ b/lib/reactable/table.js @@ -255,6 +255,50 @@ var Table = (function (_React$Component) { this.sortByCurrentSort(); this.filterBy(nextProps.filterBy != null ? nextProps.filterBy : this.state.filter); } + }, { + key: 'componentDidUpdate', + value: function componentDidUpdate() { + this.diffChildren(); + } + }, { + key: 'componentDidMount', + value: function componentDidMount() { + this.diffChildren(); + } + }, { + key: 'diffChildren', + value: function diffChildren() { + var onVisibleChange = this.props.onVisibleChange; + var lastChildren = this.lastChildren; + var lastIds = this.lastIds; + var currentChildren = this.currentChildren; + + if (!onVisibleChange || !currentChildren) { + return; + } + + if (lastChildren === currentChildren) { + return; + } + var currentIds = this.childrenToData(currentChildren, true); + + var same = undefined; + if (lastIds && lastIds.length === currentIds.length) { + same = true; + for (var i = 0; i < currentIds.length; i++) { + if (lastIds[i] !== currentIds[i]) { + same = false; + break; + } + } + } + + this.lastIds = currentIds; + this.lastChildren = currentChildren; + if (!same) { + onVisibleChange(currentIds); + } + } }, { key: 'applyFilter', value: function applyFilter(filter, children) { @@ -343,17 +387,21 @@ var Table = (function (_React$Component) { } } }, { - key: 'visibleItems', - value: function visibleItems() { - return this.currentChildren.map(function (row) { + key: 'childrenToData', + value: function childrenToData(children, onlyIds) { + return children.map(function (row) { var _row$props = row.props; var i = _row$props.i; var id = _row$props.id; var iOrId = i != null ? i : id; var idOrKey = iOrId != null ? iOrId : row.key; - var data = { id: idOrKey }; + if (onlyIds) { + return idOrKey; + } + + var data = { id: idOrKey }; Object.keys(row.props.data).forEach(function (key) { var col = row.props.data[key]; data[key] = col.props.value != null ? col.props.value : col.value; @@ -362,6 +410,11 @@ var Table = (function (_React$Component) { return data; }); } + }, { + key: 'visibleItems', + value: function visibleItems(onlyIds) { + return this.childrenToData(onlyIds); + } }, { key: 'scrollToTop', value: function scrollToTop() { From 8917034a3e3df3756feedd43213db3b7f515d122 Mon Sep 17 00:00:00 2001 From: maciejc Date: Wed, 11 May 2016 17:25:14 +0200 Subject: [PATCH 29/35] WIL-1617 inbox > when going to next page something flickers --- src/reactable/table.jsx | 10 ++++++---- src/reactable/thead.jsx | 8 +++++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index 21fb2085..b7b05041 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -361,8 +361,8 @@ export class Table extends React.Component { } scrollToTop() { - if (this.tableEl) { - this.tableEl.scrollIntoView(); + if (this.headEl) { + this.headEl.scrollIntoView(); } } @@ -492,9 +492,11 @@ export class Table extends React.Component { let noDataText = this.props.noDataText ? : null; this.currentChildren = currentChildren; - return
s',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table'},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name'},Reactable.unsafe('Griffin Smith')),React.createElement(Reactable.Td,{column:'Age'},'18')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name'},Reactable.unsafe('Lee Salminen')),React.createElement(Reactable.Td,{column:'Age'},'23')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Position'},Reactable.unsafe('Developer')),React.createElement(Reactable.Td,{column:'Age'},'28'))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the HTML in the table cells',function(){var griffins_name=$('span#griffins-name');expect(griffins_name.length).to.equal(1);expect(griffins_name).to.have.text('Griffin Smith');var lees_name=$('span#lees-name');expect(lees_name.length).to.equal(1);expect(lees_name).to.have.text('Lee Salminen');var who_knows_job=$('span#who-knows-job');expect(who_knows_job.length).to.equal(1);expect(who_knows_job).to.have.text('Developer');});});});describe('pagination',function(){describe('specifying pageButtonLimit',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Test Person'},{'Name':'Ian Zhang','Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18','Position':'Software Developer'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Test Person'},{'Name':'Ian Zhang','Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18','Position':'Software Developer'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Test Person'},{'Name':'Ian Zhang','Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18','Position':'Software Developer'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'}],itemsPerPage:2,pageButtonLimit:8}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('shows no more page buttons than the pageButtonLimit',function(){var pageButtons=$('#table tbody.reactable-pagination a.reactable-page-button');expect(pageButtons.length).to.equal(8);});});describe('specifying itemsPerPage',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Test Person'},{'Name':'Ian Zhang','Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18','Position':'Software Developer'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'}],itemsPerPage:4}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('provides buttons for each page',function(){var pageButtons=$('#table tbody.reactable-pagination a.reactable-page-button');expect(pageButtons.length).to.equal(3);expect($(pageButtons[0])).to.have.text('1');expect($(pageButtons[1])).to.have.text('2');expect($(pageButtons[2])).to.have.text('3');});it('displays only the first n rows',function(){expect($('#table tbody.reactable-data tr').length).to.equal(4);});it('specifies a class on the currently active page',function(){var activePage=$('#table tbody.reactable-pagination a.reactable-page-button.reactable-current-page');expect(activePage.length).to.equal(1);expect(activePage).to.have.text('1');});it('does not show previous button',function(){var previousButton=$('#table tbody.reactable-pagination a.reactable-previous-page');expect(previousButton.length).to.equal(0);});it('shows next button',function(){var nextButton=$('#table tbody.reactable-pagination a.reactable-next-page');expect(nextButton.length).to.equal(1);});describe('clicking page buttons',function(){beforeEach(function(){var page2=$('#table tbody.reactable-pagination a.reactable-page-button')[1];ReactTestUtils.Simulate.click(page2);});it('loads the next n rows',function(){var rows=$('#table tbody.reactable-data tr');expect($($(rows[0]).find('td')[0])).to.have.text('Test Person');expect($($(rows[1]).find('td')[0])).to.have.text('Ian Zhang');expect($($(rows[2]).find('td')[0])).to.have.text('Griffin Smith');expect($($(rows[3]).find('td')[0])).to.have.text('Lee Salminen');});it('puts an active class on the new active page',function(){var activePage=$('#table tbody.reactable-pagination a.reactable-page-button.reactable-current-page');expect(activePage.length).to.equal(1);expect(activePage).to.have.text('2');});it('can go back to the original page',function(){var page1=$('#table tbody.reactable-pagination a.reactable-page-button')[0];ReactTestUtils.Simulate.click(page1);var rows=$('#table tbody.reactable-data tr');expect($($(rows[0]).find('td')[0])).to.have.text('Griffin Smith');expect($($(rows[1]).find('td')[0])).to.have.text('Lee Salminen');expect($($(rows[2]).find('td')[0])).to.have.text('');expect($($(rows[3]).find('td')[0])).to.have.text('Griffin Smith');});it('shows previous button',function(){var previousButton=$('#table tbody.reactable-pagination a.reactable-previous-page');expect(previousButton.length).to.equal(1);});});});describe('specifying more itemsPerPage than items',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Test Person'},{'Name':'Ian Zhang','Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18','Position':'Software Developer'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'}],itemsPerPage:20}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders all rows',function(){expect($('#table tbody.reactable-data tr').length).to.equal(9);});it('provides buttons for 1 page',function(){var pageButtons=$('#table tbody.reactable-pagination a.reactable-page-button');expect(pageButtons.length).to.equal(1);expect($(pageButtons[0])).to.have.text('1');});it('does not show previous and next buttons',function(){var previousButton=$('#table tbody.reactable-pagination a.reactable-previous-page');var nextButton=$('#table tbody.reactable-pagination a.reactable-next-page');expect(previousButton.length + nextButton.length).to.equal(0);});});describe('not specifying itemsPerPage',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Test Person'},{'Name':'Ian Zhang','Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18','Position':'Software Developer'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'}]}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders all rows',function(){expect($('#table tbody.reactable-data tr').length).to.equal(9);});});describe('specifying 0 itemsPerPage',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Test Person'},{'Name':'Ian Zhang','Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18','Position':'Software Developer'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'}],itemsPerPage:0}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders all rows',function(){expect($('#table tbody.reactable-data tr').length).to.equal(9);});});describe('onPageChange hook',function(){var currentPage=undefined;var callback=function callback(page){currentPage = page;};before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18'},{'Age':'23','Name':'Test Person'},{'Name':'Ian Zhang','Age':'28','Position':'Developer'},{'Name':'Griffin Smith','Age':'18','Position':'Software Developer'},{'Age':'23','Name':'Lee Salminen'},{'Age':'28','Position':'Developer'}],itemsPerPage:4,onPageChange:callback}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('emits the number of the currently selected page (zero based) when onPageChange event is triggered',function(){var page1=$('#table tbody.reactable-pagination a.reactable-page-button')[0];var page2=$('#table tbody.reactable-pagination a.reactable-page-button')[1];var page3=$('#table tbody.reactable-pagination a.reactable-page-button')[2];ReactTestUtils.Simulate.click(page2);expect(currentPage).to.equal(1);ReactTestUtils.Simulate.click(page1);expect(currentPage).to.equal(0);ReactTestUtils.Simulate.click(page3);expect(currentPage).to.equal(2);});});});describe('sorting',function(){describe('no default sort',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{Name:'Lee Salminen',Age:'23',Position:'Programmer'},{Name:'Griffin Smith',Age:'18',Position:'Engineer'},{Name:'Ian Zhang',Age:'28',Position:'Developer'}],sortable:[{column:'Name',sortFunction:function sortFunction(a,b){ // Sort by last name +var nameA=a.split(' ');var nameB=b.split(' ');return nameA[1].localeCompare(nameB[1]);}},'Age','Position']}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders all rows with no sort',function(){ReactableTestUtils.expectRowText(0,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(1,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(2,['Ian Zhang','28','Developer']);});it('adds reactable-header-sortable to all headers',function(){var header=$('#table thead tr.reactable-column-header th')[0];expect($(header)).to.have['class']('reactable-header-sortable');header = $('#table thead tr.reactable-column-header th')[1];expect($(header)).to.have['class']('reactable-header-sortable');header = $('#table thead tr.reactable-column-header th')[2];expect($(header)).to.have['class']('reactable-header-sortable');});it('sorts by text in ascending order',function(){var positionHeader=$('#table thead tr.reactable-column-header th')[2];ReactTestUtils.Simulate.click(positionHeader);ReactableTestUtils.expectRowText(0,['Ian Zhang','28','Developer']);ReactableTestUtils.expectRowText(1,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(2,['Lee Salminen','23','Programmer']); // Make sure the headers have the right classes +expect($(positionHeader)).to.have['class']('reactable-header-sort-asc');});it('sorts by text in descending order',function(){var positionHeader=$('#table thead tr.reactable-column-header th')[2];ReactTestUtils.Simulate.click(positionHeader);ReactableTestUtils.expectRowText(0,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(1,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(2,['Ian Zhang','28','Developer']); // Make sure the headers have the right classes +expect($(positionHeader)).to.have['class']('reactable-header-sort-desc');});it('sorts by last name in ascending order',function(){var nameHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.click(nameHeader);ReactableTestUtils.expectRowText(0,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(1,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(2,['Ian Zhang','28','Developer']); // Make sure the headers have the right classes +expect($(nameHeader)).to.have['class']('reactable-header-sort-asc');});it('sorts by last name in descending order',function(){var nameHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.click(nameHeader);ReactableTestUtils.expectRowText(0,['Ian Zhang','28','Developer']);ReactableTestUtils.expectRowText(1,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(2,['Lee Salminen','23','Programmer']); // Make sure the headers have the right classes +expect($(nameHeader)).to.have['class']('reactable-header-sort-desc');});it('sorts by last name in ascending order by enter keydown',function(){var nameHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.keyDown(nameHeader,{keyCode:13});ReactableTestUtils.expectRowText(0,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(1,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(2,['Ian Zhang','28','Developer']); // Make sure the headers have the right classes +expect($(nameHeader)).to.have['class']('reactable-header-sort-asc');});it('does not sort on non-enter keydown',function(){var nameHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.keyDown(nameHeader,{keyCode:10});ReactableTestUtils.expectRowText(0,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(1,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(2,['Ian Zhang','28','Developer']); // Make sure the headers have the right classes +expect($(nameHeader)).to.have['class']('reactable-header-sort-asc');});});describe('passing `true` to sortable',function(){var component;before(function(){this.render = function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{Name:'Lee Salminen',Age:'23',Position:'Programmer'},{Name:'Griffin Smith',Age:'18',Position:'Engineer'},{Name:'Ian Zhang',Age:'28',Position:'Developer'}],sortable:true}),ReactableTestUtils.testNode());};this.render();});after(ReactableTestUtils.resetTestEnvironment);it('sorts by the first column in ascending order',function(){var nameHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.click(nameHeader);ReactableTestUtils.expectRowText(0,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(1,['Ian Zhang','28','Developer']);ReactableTestUtils.expectRowText(2,['Lee Salminen','23','Programmer']); // Make sure the headers have the right classes +expect($(nameHeader)).to.have['class']('reactable-header-sort-asc');});it('sorts by the first column in descending order',function(){var nameHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.click(nameHeader);ReactableTestUtils.expectRowText(0,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(1,['Ian Zhang','28','Developer']);ReactableTestUtils.expectRowText(2,['Griffin Smith','18','Engineer']); // Make sure the headers have the right classes +expect($(nameHeader)).to.have['class']('reactable-header-sort-desc');});it('sorts by the second column in ascending order',function(){var nameHeader=$('#table thead tr.reactable-column-header th')[1];ReactTestUtils.Simulate.click(nameHeader);ReactableTestUtils.expectRowText(0,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(1,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(2,['Ian Zhang','28','Developer']); // Make sure the headers have the right classes +expect($(nameHeader)).to.have['class']('reactable-header-sort-asc');});it('sorts by the second column in descending order',function(){var nameHeader=$('#table thead tr.reactable-column-header th')[1];ReactTestUtils.Simulate.click(nameHeader);ReactableTestUtils.expectRowText(0,['Ian Zhang','28','Developer']);ReactableTestUtils.expectRowText(1,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(2,['Griffin Smith','18','Engineer']); // Make sure the headers have the right classes +expect($(nameHeader)).to.have['class']('reactable-header-sort-desc');});it('sorts by the third column in ascending order',function(){var positionHeader=$('#table thead tr.reactable-column-header th')[2];ReactTestUtils.Simulate.click(positionHeader);ReactableTestUtils.expectRowText(0,['Ian Zhang','28','Developer']);ReactableTestUtils.expectRowText(1,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(2,['Lee Salminen','23','Programmer']); // Make sure the headers have the right classes +expect($(positionHeader)).to.have['class']('reactable-header-sort-asc');});it('sorts by the third column in descending order',function(){var positionHeader=$('#table thead tr.reactable-column-header th')[2];ReactTestUtils.Simulate.click(positionHeader);ReactableTestUtils.expectRowText(0,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(1,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(2,['Ian Zhang','28','Developer']); // Make sure the headers have the right classes +expect($(positionHeader)).to.have['class']('reactable-header-sort-desc');});it('Keeps the same sort after rerendering',function(){expect(this.render).to.not['throw'](Error);ReactableTestUtils.expectRowText(0,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(1,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(2,['Ian Zhang','28','Developer']);});});describe('default sort',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{Name:'Lee Salminen',Age:'23',Position:'Programmer'},{Name:'Griffin Smith',Age:'18',Position:'Engineer'},{Name:'Ian Zhang',Age:'28',Position:'Developer'}],sortable:[{column:'Name',sortFunction:function sortFunction(a,b){ // Sort by last name +var nameA=a.split(' ');var nameB=b.split(' ');return nameA[1].localeCompare(nameB[1]);}},'Age','Position'],defaultSort:{column:'Age',direction:'desc'}}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders all rows sorted by default column age descending',function(){ReactableTestUtils.expectRowText(0,['Ian Zhang','28','Developer']);ReactableTestUtils.expectRowText(1,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(2,['Griffin Smith','18','Engineer']);});});describe('sort descending by default flag',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{Name:'Lee Salminen',Age:'23',Position:'Programmer'},{Name:'Griffin Smith',Age:'18',Position:'Engineer'},{Name:'Ian Zhang',Age:'28',Position:'Developer'}],sortable:[{column:'Name',sortFunction:function sortFunction(a,b){ // Sort by last name +var nameA=a.split(' ');var nameB=b.split(' ');return nameA[1].localeCompare(nameB[1]);}},'Age','Position'],defaultSort:{column:'Age'},defaultSortDescending:true}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders all rows sorted by default column age descending',function(){ReactableTestUtils.expectRowText(0,['Ian Zhang','28','Developer']);ReactableTestUtils.expectRowText(1,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(2,['Griffin Smith','18','Engineer']);});it('sorts by the age column in ascending order',function(){var positionHeader=$('#table thead tr.reactable-column-header th')[1];ReactTestUtils.Simulate.click(positionHeader);ReactableTestUtils.expectRowText(0,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(1,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(2,['Ian Zhang','28','Developer']); // Make sure the headers have the right classes +expect($(positionHeader)).to.have['class']('reactable-header-sort-asc');});});describe('default sort no direction specified',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{Name:'Lee Salminen',Age:'23',Position:'Programmer'},{Name:'Griffin Smith',Age:'18',Position:'Engineer'},{Name:'Ian Zhang',Age:'28',Position:'Developer'}],sortable:[{column:'Name',sortFunction:function sortFunction(a,b){ // Sort by last name +var nameA=a.split(' ');var nameB=b.split(' ');return nameA[1].localeCompare(nameB[1]);}},'Age','Position'],defaultSort:'Age'}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders all rows sorted by default column age ascending',function(){ReactableTestUtils.expectRowText(0,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(1,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(2,['Ian Zhang','28','Developer']);});});describe('unsortable column',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{Name:'Lee Salminen',Age:'23',Position:'Programmer'},{Name:'Griffin Smith',Age:'18',Position:'Engineer'},{Name:'Ian Zhang',Age:'28',Position:'Developer'}],sortable:['Age','Position']}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('leaves columns unsorted',function(){var nameHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.click(nameHeader);ReactableTestUtils.expectRowText(0,['Lee Salminen','23','Programmer']);ReactableTestUtils.expectRowText(1,['Griffin Smith','18','Engineer']);ReactableTestUtils.expectRowText(2,['Ian Zhang','28','Developer']);});});[Reactable.Sort.Numeric,Reactable.Sort.NumericInteger].forEach(function(method){describe('numeric sort',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{Count:'23'},{Count:'18'},{Count:'28'},{Count:'1.23'},{Count:'a'},{Count:'z'},{Count:'123'}],columns:[{key:'Count',sortable:method}]}),ReactableTestUtils.testNode());});after(function(){ReactableTestUtils.resetTestEnvironment();});it('sorts columns numerically',function(){var sortHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.click(sortHeader);ReactableTestUtils.expectRowText(0,['1.23']);ReactableTestUtils.expectRowText(1,['18']);ReactableTestUtils.expectRowText(2,['23']);ReactableTestUtils.expectRowText(3,['28']);ReactableTestUtils.expectRowText(4,['123']);ReactableTestUtils.expectRowText(5,['a']);ReactableTestUtils.expectRowText(6,['z']);});});});describe('numeric sort with Tr and Td specified',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',columns:[{key:'Count',sortable:Reactable.Sort.Numeric}]},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Count'},'23')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Count'},'18')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Count'},'28')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Count'},'1.23')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Count'},'a')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Count'},'z')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Count'},'123'))),ReactableTestUtils.testNode());});after(function(){ReactableTestUtils.resetTestEnvironment();});it('sorts columns numerically',function(){var sortHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.click(sortHeader);ReactableTestUtils.expectRowText(0,['1.23']);ReactableTestUtils.expectRowText(1,['18']);ReactableTestUtils.expectRowText(2,['23']);ReactableTestUtils.expectRowText(3,['28']);ReactableTestUtils.expectRowText(4,['123']);ReactableTestUtils.expectRowText(5,['a']);ReactableTestUtils.expectRowText(6,['z']);});});describe('numeric sort with Tr and Td specified and custom value',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',columns:[{key:'Count',sortable:Reactable.Sort.Numeric}]},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Count',value:23},'twenty-three')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Count',value:18},'eighteen')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Count',value:28},'twenty-eight')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Count',value:1.23},'one point two three')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Count',value:'a'},'a')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Count',value:'z'},'z')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Count',value:123},'one hundred twenty-three'))),ReactableTestUtils.testNode());});after(function(){ReactableTestUtils.resetTestEnvironment();});it('sorts columns numerically',function(){var sortHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.click(sortHeader);ReactableTestUtils.expectRowText(0,['one point two three']);ReactableTestUtils.expectRowText(1,['eighteen']);ReactableTestUtils.expectRowText(2,['twenty-three']);ReactableTestUtils.expectRowText(3,['twenty-eight']);ReactableTestUtils.expectRowText(4,['one hundred twenty-three']);ReactableTestUtils.expectRowText(5,['a']);ReactableTestUtils.expectRowText(6,['z']);});});describe('currency sort',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{Price:'1.25'},{Price:'$1.01'},{Price:'1'},{Price:'$10,000'},{Price:'$10,500'},{Price:'$10'},{Price:'a'},{Price:'z'},{Price:'$2'},{Price:'$.5'},{Price:'$0.60'},{Price:'.1'}],columns:[{key:'Price',sortable:Reactable.Sort.Currency}]}),ReactableTestUtils.testNode());});after(function(){ReactableTestUtils.resetTestEnvironment();});it('sorts columns numerically. parsing out currency symbols',function(){var sortHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.click(sortHeader);ReactableTestUtils.expectRowText(0,['.1']);ReactableTestUtils.expectRowText(1,['$.5']);ReactableTestUtils.expectRowText(2,['$0.60']);ReactableTestUtils.expectRowText(3,['1']);ReactableTestUtils.expectRowText(4,['$1.01']);ReactableTestUtils.expectRowText(5,['1.25']);ReactableTestUtils.expectRowText(6,['$2']);ReactableTestUtils.expectRowText(7,['$10']);ReactableTestUtils.expectRowText(8,['$10,000']);ReactableTestUtils.expectRowText(9,['$10,500']);ReactableTestUtils.expectRowText(10,['a']);ReactableTestUtils.expectRowText(11,['z']);});});describe('date sort',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{'Date':'1/1/2014 11:00 AM'},{'Date':'1/1/2013 11:00 AM'},{'Date':'1/1/2014 4:30 PM'},{'Date':'4/3/2013'},{'Date':'a'},{'Date':'z'}],columns:[{key:'Date',sortable:Reactable.Sort.Date}]}),ReactableTestUtils.testNode());});after(function(){ReactableTestUtils.resetTestEnvironment();});it('sorts columns by date',function(){var sortHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.click(sortHeader);ReactableTestUtils.expectRowText(0,['1/1/2013 11:00 AM']);ReactableTestUtils.expectRowText(1,['4/3/2013']);ReactableTestUtils.expectRowText(2,['1/1/2014 11:00 AM']);ReactableTestUtils.expectRowText(3,['1/1/2014 4:30 PM']);ReactableTestUtils.expectRowText(4,['a']);ReactableTestUtils.expectRowText(5,['z']);});});describe('case insensitive sorting',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{'Name':'Lee Salminen'},{'Name':'Griffin Smith'},{'Name':'Ian Zhang'},{'Name':'lee Salminen'},{'Name':'griffin smith'},{'Name':'Ian zhang'}],columns:[{key:'Name',sortable:Reactable.Sort.CaseInsensitive}]}),ReactableTestUtils.testNode());});after(function(){ReactableTestUtils.resetTestEnvironment();});it('sorts columns by value - case insensitive',function(){var sortHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.click(sortHeader);ReactableTestUtils.expectRowText(0,['Griffin Smith']);ReactableTestUtils.expectRowText(1,['griffin smith']);ReactableTestUtils.expectRowText(2,['Ian Zhang']);ReactableTestUtils.expectRowText(3,['Ian zhang']);ReactableTestUtils.expectRowText(4,['Lee Salminen']);ReactableTestUtils.expectRowText(5,['lee Salminen']);});});describe('custom sort with React Components',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{'Rank':React.createElement('span',{className:'3'},'Third')},{'Rank':React.createElement('span',{className:'1'},'First')},{'Rank':React.createElement('span',{className:'2'},'Second')}],columns:[{key:'Rank',sortable:function sortable(a,b){ // sort based on classname +return a.props.className.localeCompare(b.props.className);}}]}),ReactableTestUtils.testNode());});after(function(){ReactableTestUtils.resetTestEnvironment();});it('sorts columns by value',function(){var sortHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.click(sortHeader);ReactableTestUtils.expectRowText(0,['First']);ReactableTestUtils.expectRowText(1,['Second']);ReactableTestUtils.expectRowText(2,['Third']);});});describe('sorts and calls onSort callback via props',function(){var sortColumn=null;var callback=function callback(sortObject){sortColumn = sortObject.column;};before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{'Rank':React.createElement('span',{className:'3'},'Third')},{'Rank':React.createElement('span',{className:'1'},'First')},{'Rank':React.createElement('span',{className:'2'},'Second')}],columns:[{key:'Rank',sortable:function sortable(a,b){ // sort based on classname +return a.props.className.localeCompare(b.props.className);}}],onSort:callback}),ReactableTestUtils.testNode());});after(function(){ReactableTestUtils.resetTestEnvironment();});it('returns currentSort object to callback for utilization',function(){var sortHeader=$('#table thead tr.reactable-column-header th')[0];ReactTestUtils.Simulate.click(sortHeader);expect(sortColumn).to.equal('Rank');});});});describe('filtering',function(){describe('filtering with javascript objects for data',function(){var data=[{name:"Lee SomeoneElse",age:18},{name:"Lee Salminen",age:23},{name:"No Age",age:null}];var filterBy;var onFilter=function onFilter(filter){filterBy = filter;};before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',filterable:['Name','Age'],onFilter:onFilter},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name',data:data[0].name}),React.createElement(Reactable.Td,{column:'Age',data:data[0].age})),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name',data:data[1].name}),React.createElement(Reactable.Td,{column:'Age',data:data[1].age})),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name',data:data[2].name}),React.createElement(Reactable.Td,{column:'Age',data:data[2].age}))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('filters case insensitive on specified columns',function(){var $filter=$('#table thead tr.reactable-filterer input.reactable-filter-input');$filter.val('lee');React.addons.TestUtils.Simulate.keyUp($filter[0]);ReactableTestUtils.expectRowText(0,['Lee SomeoneElse','18']);ReactableTestUtils.expectRowText(1,['Lee Salminen','23']);});it('calls onFilter event handler',function(){var $filter=$('#table thead tr.reactable-filterer input.reactable-filter-input');var textToSearch='lee';$filter.val(textToSearch);React.addons.TestUtils.Simulate.keyUp($filter[0]);expect(filterBy).to.equal(textToSearch);});});describe('basic case-insensitive filtering',function(){before(function(){this.component = ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',filterable:['State','Tag'],filterPlaceholder:'Filter Results',columns:['State','Description','Tag']},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'State'},'New York'),React.createElement(Reactable.Td,{column:'Description'},'this is some text'),React.createElement(Reactable.Td,{column:'Tag'},'new')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'State'},'New Mexico'),React.createElement(Reactable.Td,{column:'Description'},'lorem ipsum'),React.createElement(Reactable.Td,{column:'Tag'},'old')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'State'},'Colorado'),React.createElement(Reactable.Td,{column:'Description'},'new description that shouldnt match filter'),React.createElement(Reactable.Td,{column:'Tag'},'old')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'State'},'Alaska'),React.createElement(Reactable.Td,{column:'Description'},'bacon'),React.createElement(Reactable.Td,{column:'Tag'},'renewed'))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);context('from the filterer field',function(){it('filters case insensitive on specified columns',function(){var $filter=$('#table thead tr.reactable-filterer input.reactable-filter-input');$filter.val('new');React.addons.TestUtils.Simulate.keyUp($filter[0]);ReactableTestUtils.expectRowText(0,['New York','this is some text','new']);ReactableTestUtils.expectRowText(1,['New Mexico','lorem ipsum','old']);ReactableTestUtils.expectRowText(2,['Alaska','bacon','renewed']);});it('filter placeholder is set',function(){var $filter=$('#table thead tr.reactable-filterer input.reactable-filter-input');expect($filter.attr("placeholder")).to.equal('Filter Results');});});context('from the function',function(){before(function(){this.component.filterBy('york');});it('applies the filtering',function(){ReactableTestUtils.expectRowText(0,['New York','this is some text','new']);});it('updates the value of the filterer',function(){var $filter=$('#table thead tr.reactable-filterer input.reactable-filter-input');expect($filter).to.have.value('york');});});context('from filterBy prop',function(){before(function(){ReactableTestUtils.resetTestEnvironment();var ParentComponent=React.createClass({displayName:'ParentComponent',getInitialState:function getInitialState(){return {customFilterText:'new'};},handleChange:function handleChange(event){this.setState({customFilterText:event.target.value});},render:function render(){return React.createElement('div',null,React.createElement('input',{type:'text',ref:'customFilterInput',id:'customFilterInput',value:this.state.customFilterText,onChange:this.handleChange}),React.createElement(Reactable.Table,{className:'table',id:'table',filterable:['State','Tag'],filterPlaceholder:'Filter Results',filterBy:this.state.customFilterText,columns:['State','Description','Tag']},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'State'},'New York'),React.createElement(Reactable.Td,{column:'Description'},'this is some text'),React.createElement(Reactable.Td,{column:'Tag'},'new')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'State'},'New Mexico'),React.createElement(Reactable.Td,{column:'Description'},'lorem ipsum'),React.createElement(Reactable.Td,{column:'Tag'},'old')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'State'},'Colorado'),React.createElement(Reactable.Td,{column:'Description'},'new description that shouldnt match filter'),React.createElement(Reactable.Td,{column:'Tag'},'old')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'State'},'Alaska'),React.createElement(Reactable.Td,{column:'Description'},'bacon'),React.createElement(Reactable.Td,{column:'Tag'},'renewed'))));}});this.component = ReactDOM.render(React.createElement(ParentComponent),ReactableTestUtils.testNode());});it('filters case insensitive on specified columns',function(){ReactableTestUtils.expectRowText(0,['New York','this is some text','new']);ReactableTestUtils.expectRowText(1,['New Mexico','lorem ipsum','old']);ReactableTestUtils.expectRowText(2,['Alaska','bacon','renewed']);var $builtInFilter=$('#table thead tr.reactable-filterer input.reactable-filter-input');expect($builtInFilter).to.have.value('new'); // Simulate changing input on parent component and re-rendering Reactable.Table with new props. +var node=this.component.refs.customFilterInput;node.value = 'alaska';ReactTestUtils.Simulate.change(customFilterInput);ReactableTestUtils.expectRowText(0,['Alaska','bacon','renewed']);expect($builtInFilter).to.have.value('alaska');});});});context('filtering with prop and hiding filter input',function(){before(function(){this.component = ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',filterable:['State','Tag'],filterPlaceholder:'Filter Results',filterBy:'new',hideFilterInput:true,columns:['State','Description','Tag']},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'State'},'New York'),React.createElement(Reactable.Td,{column:'Description'},'this is some text'),React.createElement(Reactable.Td,{column:'Tag'},'new')),React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'State'},'New Mexico'),React.createElement(Reactable.Td,{column:'Description'},'lorem ipsum'),React.createElement(Reactable.Td,{column:'Tag'},'old'))),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('does not render the filter input box',function(){expect($('#table thead tr.reactable-filterer input.reactable-filter-input').length).to.equal(0);});});context('filtering and pagination together',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{'State':'New York','Description':'this is some text','Tag':'new'},{'State':'New Mexico','Description':'lorem ipsum','Tag':'old'},{'State':'Colorado','Description':'new description that shouldn\'t match filter','Tag':'old'},{'State':'Alaska','Description':'bacon','Tag':'renewed'}],filterable:['State','Tag'],columns:['State','Description','Tag'],itemsPerPage:2}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);afterEach(function(){var $filter=$('#table thead tr.reactable-filterer input.reactable-filter-input');$filter.val('');React.addons.TestUtils.Simulate.keyUp($filter[0]);});it('updates the pagination links',function(){var $filter=$('#table thead tr.reactable-filterer input.reactable-filter-input');$filter.val('colorado');React.addons.TestUtils.Simulate.keyUp($filter[0]);var pageButtons=$('#table tbody.reactable-pagination a.reactable-page-button');expect(pageButtons.length).to.equal(1);expect($(pageButtons[0])).to.have.text('1');});it('updates the current page if necessary',function(){var $filter=$('#table thead tr.reactable-filterer input.reactable-filter-input');var $pageButtons=$('#table tbody.reactable-pagination a.reactable-page-button'); // Go to the last page +React.addons.TestUtils.Simulate.click($pageButtons[1]); // Then filter so that that page doesn't exist anymore +$filter.val('colorado');React.addons.TestUtils.Simulate.keyUp($filter[0]);ReactableTestUtils.expectRowText(0,['Colorado',"new description that shouldn't match filter",'old']);var activePage=$('#table tbody.reactable-pagination ' + 'a.reactable-page-button.reactable-current-page');expect(activePage.length).to.equal(1);expect(activePage).to.have.text('1');});});});describe('directly passing a data array with non-string data',function(){before(function(){ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table',data:[{Name:'Griffin Smith',Age:18},{Age:23,Name:{toString:function toString(){return 'Lee Salminen';}}},{Age:28.45,Position:'Developer'}]}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('renders the table',function(){expect($('table#table.table')).to.exist;});it('renders the column headers in the table',function(){var headers=[];$('thead th').each(function(){headers.push($(this).text());});expect(headers).to.eql(['Name','Age','Position']);});it('renders the first row with the correct data',function(){ReactableTestUtils.expectRowText(0,['Griffin Smith','18','']);});it('renders the second row with the correct data',function(){ReactableTestUtils.expectRowText(1,['Lee Salminen','23','']);});it('renders the third row with the correct data',function(){ReactableTestUtils.expectRowText(2,['','28.45','Developer']);});});describe('multiple tables on a page',function(){before(function(){this.parentTestNode = ReactableTestUtils.testNode();this.testNode1 = $('
').attr('id','test-node-1');this.testNode2 = $('
').attr('id','test-node-2');ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table1',data:[{Name:'Griffin Smith',Age:'18'},{Age:'23',Name:'Lee Salminen'},{Age:'28',Position:'Developer'}]}),this.testNode1[0]);ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table2',data:[{Moniker:'Griffin Smith',Elderliness:'18'},{Elderliness:'23',Moniker:'Lee Salminen'},{Elderliness:'28',Title:'Developer'}]}),this.testNode2[0]);});after(function(){$(this.parentTestNode).empty().remove();});it('renders the column headers in the first table',function(){var headers=[];this.testNode1.find('thead th').each(function(){headers.push($(this).text());});expect(headers).to.eql(['Name','Age','Position']);});it('renders the column headers in the second table',function(){var headers=[];this.testNode2.find('thead th').each(function(){headers.push($(this).text());});expect(headers).to.eql(['Moniker','Elderliness','Title']);});});describe('handleClick callbacks',function(){before(function(){this.clicked = false;ReactDOM.render(React.createElement(Reactable.Table,{className:'table',id:'table'},React.createElement(Reactable.Tr,null,React.createElement(Reactable.Td,{column:'Name',handleClick:(function(){this.clicked = true;}).bind(this)},React.createElement('b',null,'Griffin Smith')))),ReactableTestUtils.testNode());ReactTestUtils.Simulate.click($('td')[0]);});after(ReactableTestUtils.resetTestEnvironment);it('calls the callbacks on click',function(){expect(this.clicked).to.eq(true);});});describe('table with no data',function(){context('when noDataText prop is null',function(){before(function(){this.component = ReactDOM.render(React.createElement(Reactable.Table,{data:[],columns:['State','Description','Tag']}),ReactableTestUtils.testNode());});after(ReactableTestUtils.resetTestEnvironment);it('does not render the reactable-no-data element',function(){expect($('.reactable-no-data').length).to.eq(0);});});context('when initialized without
{this.props.noDataText}
this.tableEl = t}> + return
{columns && columns.length > 0 ? - this.headEl = t} + columns={columns} topPagination={topPagination} itemsNumber={filteredChildren.length} itemsPerPage={itemsPerPage} diff --git a/src/reactable/thead.jsx b/src/reactable/thead.jsx index 7703c7b1..6a04b344 100644 --- a/src/reactable/thead.jsx +++ b/src/reactable/thead.jsx @@ -54,6 +54,12 @@ export class Thead extends React.Component { this.props.onSort(column.key); } } + + scrollIntoView() { + if (this.domEl && this.domEl.offsetParent === null) { + this.domEl.scrollIntoView(); + } + } render() { const {sort, sortableColumns, filtering, columns, onFilter, onClean, filterPlaceholder, currentFilter, topPagination, filterCleanBtn, locale, itemsPerPage, itemsNumber, numPages, currentPage, onPageChange, topPaginationElem} = this.props; @@ -106,7 +112,7 @@ export class Thead extends React.Component { // Manually transfer props var props = filterPropsFrom(this.props); return ( - + this.domEl = el)}}> {!topPagination && filtering && Date: Fri, 13 May 2016 15:04:49 +0200 Subject: [PATCH 30/35] build --- build/reactable.js | 27 ++++++++++++++++++++------- lib/reactable/table.js | 14 ++++++++------ lib/reactable/thead.js | 13 ++++++++++++- 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/build/reactable.js b/build/reactable.js index 08e8fdf4..a779097f 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -689,9 +689,18 @@ window.ReactDOM["default"] = window.ReactDOM; this.props.onSort(column.key); } } + }, { + key: 'scrollIntoView', + value: function scrollIntoView() { + if (this.domEl && this.domEl.offsetParent === null) { + this.domEl.scrollIntoView(); + } + } }, { key: 'render', value: function render() { + var _this = this; + var _props = this.props; var sort = _props.sort; var sortableColumns = _props.sortableColumns; @@ -756,7 +765,9 @@ window.ReactDOM["default"] = window.ReactDOM; var props = (0, _libFilter_props_from.filterPropsFrom)(this.props); return _react['default'].createElement( 'thead', - props, + _extends({}, props, { ref: function ref(el) { + return _this.domEl = el; + } }), !topPagination && filtering && _react['default'].createElement(_filterer.Filterer, { colSpan: columns.length, onFilter: onFilter, @@ -1665,8 +1676,8 @@ window.ReactDOM["default"] = window.ReactDOM; }, { key: 'scrollToTop', value: function scrollToTop() { - if (this.tableEl) { - this.tableEl.scrollIntoView(); + if (this.headEl) { + this.headEl.scrollIntoView(); } } }, { @@ -1792,10 +1803,12 @@ window.ReactDOM["default"] = window.ReactDOM; this.currentChildren = currentChildren; return _react['default'].createElement( 'table', - { ref: function (t) { - return _this.tableEl = t; - } }, - columns && columns.length > 0 ? _react['default'].createElement(_thead.Thead, { columns: columns, + null, + columns && columns.length > 0 ? _react['default'].createElement(_thead.Thead, { + ref: function (t) { + return _this.headEl = t; + }, + columns: columns, topPagination: topPagination, itemsNumber: filteredChildren.length, itemsPerPage: itemsPerPage, diff --git a/lib/reactable/table.js b/lib/reactable/table.js index 126826c7..60f07bc2 100644 --- a/lib/reactable/table.js +++ b/lib/reactable/table.js @@ -418,8 +418,8 @@ var Table = (function (_React$Component) { }, { key: 'scrollToTop', value: function scrollToTop() { - if (this.tableEl) { - this.tableEl.scrollIntoView(); + if (this.headEl) { + this.headEl.scrollIntoView(); } } }, { @@ -545,10 +545,12 @@ var Table = (function (_React$Component) { this.currentChildren = currentChildren; return _react2['default'].createElement( 'table', - { ref: function (t) { - return _this.tableEl = t; - } }, - columns && columns.length > 0 ? _react2['default'].createElement(_thead.Thead, { columns: columns, + null, + columns && columns.length > 0 ? _react2['default'].createElement(_thead.Thead, { + ref: function (t) { + return _this.headEl = t; + }, + columns: columns, topPagination: topPagination, itemsNumber: filteredChildren.length, itemsPerPage: itemsPerPage, diff --git a/lib/reactable/thead.js b/lib/reactable/thead.js index 9d800d5e..f657826b 100644 --- a/lib/reactable/thead.js +++ b/lib/reactable/thead.js @@ -49,9 +49,18 @@ var Thead = (function (_React$Component) { this.props.onSort(column.key); } } + }, { + key: 'scrollIntoView', + value: function scrollIntoView() { + if (this.domEl && this.domEl.offsetParent === null) { + this.domEl.scrollIntoView(); + } + } }, { key: 'render', value: function render() { + var _this = this; + var _props = this.props; var sort = _props.sort; var sortableColumns = _props.sortableColumns; @@ -116,7 +125,9 @@ var Thead = (function (_React$Component) { var props = (0, _libFilter_props_from.filterPropsFrom)(this.props); return _react2['default'].createElement( 'thead', - props, + _extends({}, props, { ref: function ref(el) { + return _this.domEl = el; + } }), !topPagination && filtering && _react2['default'].createElement(_filterer.Filterer, { colSpan: columns.length, onFilter: onFilter, From 10320953d34ab1029f3c0699a37b9208571a148e Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Fri, 19 Aug 2016 16:13:01 +0200 Subject: [PATCH 31/35] missing span fix --- src/reactable/btnPaginator.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reactable/btnPaginator.jsx b/src/reactable/btnPaginator.jsx index dbe1bfeb..d06afce7 100644 --- a/src/reactable/btnPaginator.jsx +++ b/src/reactable/btnPaginator.jsx @@ -58,7 +58,7 @@ export class BtnPaginator extends React.Component { renderCounter() { const {itemsNumber, locale} = this.props return
- {this.calcRange()} {tr.of[locale]} {itemsNumber} + {this.calcRange()} {tr.of[locale]} {itemsNumber}
} From 9f9adc54b376d4e3e6cc7edae56af9e6cdcab139 Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Fri, 19 Aug 2016 16:35:29 +0200 Subject: [PATCH 32/35] added props to filter_props --- src/reactable/lib/filter_props_from.jsx | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/reactable/lib/filter_props_from.jsx b/src/reactable/lib/filter_props_from.jsx index 88e9197a..8de81cb8 100644 --- a/src/reactable/lib/filter_props_from.jsx +++ b/src/reactable/lib/filter_props_from.jsx @@ -8,7 +8,23 @@ const internalProps = { itemsPerPage: true, childNode: true, data: true, - children: true + children: true, + topPagination: true, + itemsNumber: true, + numPages: true, + currentPage: true, + topPaginationElem: true, + filtering: true, + onFilter: true, + filterCleanBtn: true, + onClean: true, + onPageChange: true, + filterPlaceholder: true, + currentFilter: true, + sort: true, + sortableColumns: true, + onSort: true, + locale: true, }; export function filterPropsFrom(baseProps) { @@ -22,4 +38,3 @@ export function filterPropsFrom(baseProps) { return props; } - From 56ef307e69c7901974448ee9f7610e200087ab9e Mon Sep 17 00:00:00 2001 From: Adrian Kolakowski Date: Fri, 19 Aug 2016 16:43:40 +0200 Subject: [PATCH 33/35] locale bug fix --- src/reactable/table.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/reactable/table.jsx b/src/reactable/table.jsx index b7b05041..89a74903 100644 --- a/src/reactable/table.jsx +++ b/src/reactable/table.jsx @@ -494,7 +494,7 @@ export class Table extends React.Component { this.currentChildren = currentChildren; return
{columns && columns.length > 0 ? - this.headEl = t} columns={columns} topPagination={topPagination} @@ -526,7 +526,7 @@ export class Table extends React.Component { sortableColumns={this._sortable} onSort={this.onSort.bind(this)} key="thead" - locale={props.locale} + locale={this.props.locale} /> : null } @@ -536,7 +536,7 @@ export class Table extends React.Component { Date: Fri, 19 Aug 2016 16:56:32 +0200 Subject: [PATCH 34/35] unknown prop bug fix --- src/reactable/td.jsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/reactable/td.jsx b/src/reactable/td.jsx index c695c821..eeb31891 100644 --- a/src/reactable/td.jsx +++ b/src/reactable/td.jsx @@ -22,10 +22,8 @@ export class Td extends React.Component { // Attach any properties on the column to this Td object to allow things like custom event handlers if (typeof(this.props.column) === 'object') { - for (var key in this.props.column) { - if (key !== 'key' && key !== 'name') { - tdProps[key] = this.props.column[key]; - } + for (var key in this.props.column.props) { + tdProps[key] = this.props.column[key]; } } From 82a6fdb566bd42816adaaefcff839f91f35be15e Mon Sep 17 00:00:00 2001 From: Wout Mertens Date: Fri, 19 Aug 2016 19:03:54 +0200 Subject: [PATCH 35/35] build --- build/reactable.js | 42 ++++++++++++++++++-------- lib/reactable/btnPaginator.js | 14 ++++++--- lib/reactable/lib/filter_props_from.js | 18 ++++++++++- lib/reactable/table.js | 4 +-- lib/reactable/td.js | 6 ++-- 5 files changed, 60 insertions(+), 24 deletions(-) diff --git a/build/reactable.js b/build/reactable.js index a779097f..86f06c3b 100644 --- a/build/reactable.js +++ b/build/reactable.js @@ -26,7 +26,23 @@ window.ReactDOM["default"] = window.ReactDOM; itemsPerPage: true, childNode: true, data: true, - children: true + children: true, + topPagination: true, + itemsNumber: true, + numPages: true, + currentPage: true, + topPaginationElem: true, + filtering: true, + onFilter: true, + filterCleanBtn: true, + onClean: true, + onPageChange: true, + filterPlaceholder: true, + currentFilter: true, + sort: true, + sortableColumns: true, + onSort: true, + locale: true }; function filterPropsFrom(baseProps) { @@ -468,10 +484,8 @@ window.ReactDOM["default"] = window.ReactDOM; // Attach any properties on the column to this Td object to allow things like custom event handlers if (typeof this.props.column === 'object') { - for (var key in this.props.column) { - if (key !== 'key' && key !== 'name') { - tdProps[key] = this.props.column[key]; - } + for (var key in this.props.column.props) { + tdProps[key] = this.props.column[key]; } } @@ -1018,11 +1032,15 @@ window.ReactDOM["default"] = window.ReactDOM; return _react["default"].createElement( "div", { className: "counter" }, - this.calcRange(), - " ", - tr.of[locale], - " ", - itemsNumber + _react["default"].createElement( + "span", + null, + this.calcRange(), + " ", + tr.of[locale], + " ", + itemsNumber + ) ); } }, { @@ -1839,7 +1857,7 @@ window.ReactDOM["default"] = window.ReactDOM; sortableColumns: this._sortable, onSort: this.onSort.bind(this), key: 'thead', - locale: props.locale + locale: this.props.locale }) : null, _react['default'].createElement( 'tbody', @@ -1849,7 +1867,7 @@ window.ReactDOM["default"] = window.ReactDOM; pagination ? _react['default'].createElement(_paginator.Paginator, { bottomPagination: bottomPagination, itemsNumber: filteredChildren.length, itemsPerPage: itemsPerPage, - locale: props.locale, + locale: this.props.locale, colSpan: columns.length, pageButtonLimit: pageButtonLimit, numPages: numPages, diff --git a/lib/reactable/btnPaginator.js b/lib/reactable/btnPaginator.js index b1d11977..0e6b2c95 100644 --- a/lib/reactable/btnPaginator.js +++ b/lib/reactable/btnPaginator.js @@ -99,11 +99,15 @@ var BtnPaginator = (function (_React$Component) { return _react2["default"].createElement( "div", { className: "counter" }, - this.calcRange(), - " ", - tr.of[locale], - " ", - itemsNumber + _react2["default"].createElement( + "span", + null, + this.calcRange(), + " ", + tr.of[locale], + " ", + itemsNumber + ) ); } }, { diff --git a/lib/reactable/lib/filter_props_from.js b/lib/reactable/lib/filter_props_from.js index 730e5084..c6952c98 100644 --- a/lib/reactable/lib/filter_props_from.js +++ b/lib/reactable/lib/filter_props_from.js @@ -14,7 +14,23 @@ var internalProps = { itemsPerPage: true, childNode: true, data: true, - children: true + children: true, + topPagination: true, + itemsNumber: true, + numPages: true, + currentPage: true, + topPaginationElem: true, + filtering: true, + onFilter: true, + filterCleanBtn: true, + onClean: true, + onPageChange: true, + filterPlaceholder: true, + currentFilter: true, + sort: true, + sortableColumns: true, + onSort: true, + locale: true }; function filterPropsFrom(baseProps) { diff --git a/lib/reactable/table.js b/lib/reactable/table.js index 60f07bc2..c54f1cf7 100644 --- a/lib/reactable/table.js +++ b/lib/reactable/table.js @@ -581,7 +581,7 @@ var Table = (function (_React$Component) { sortableColumns: this._sortable, onSort: this.onSort.bind(this), key: 'thead', - locale: props.locale + locale: this.props.locale }) : null, _react2['default'].createElement( 'tbody', @@ -591,7 +591,7 @@ var Table = (function (_React$Component) { pagination ? _react2['default'].createElement(_paginator.Paginator, { bottomPagination: bottomPagination, itemsNumber: filteredChildren.length, itemsPerPage: itemsPerPage, - locale: props.locale, + locale: this.props.locale, colSpan: columns.length, pageButtonLimit: pageButtonLimit, numPages: numPages, diff --git a/lib/reactable/td.js b/lib/reactable/td.js index 71fae9de..00a07e5e 100644 --- a/lib/reactable/td.js +++ b/lib/reactable/td.js @@ -54,10 +54,8 @@ var Td = (function (_React$Component) { // Attach any properties on the column to this Td object to allow things like custom event handlers if (typeof this.props.column === 'object') { - for (var key in this.props.column) { - if (key !== 'key' && key !== 'name') { - tdProps[key] = this.props.column[key]; - } + for (var key in this.props.column.props) { + tdProps[key] = this.props.column[key]; } }