Created
January 12, 2017 21:36
-
-
Save adamabernathy/6ac71d56df86b9896de93e248147d29b to your computer and use it in GitHub Desktop.
additive search problem
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| var Excel = React.createClass({ | |
| displayName: 'Excel', | |
| __preSearchData: null, | |
| _log: [], | |
| propTypes: { | |
| headers: React.PropTypes.arrayOf( | |
| React.PropTypes.string | |
| ), | |
| initialData: React.PropTypes.arrayOf( | |
| React.PropTypes.arrayOf(React.PropTypes.string) | |
| ) | |
| }, | |
| getInitialState: function () { | |
| return { | |
| data: this.props.initialData, | |
| sortBy: null, | |
| descending: false, | |
| edit: null, // {row: index, cell: index} | |
| search: false | |
| }; | |
| }, | |
| componentDidMount: function () { | |
| document.onkeydown = function (e) { | |
| if (e.altKey && e.shiftKey && e.keyCode === 82) { | |
| // ALT + SHIFT + R(eplay) | |
| console.log("Boom"); | |
| this._replay(); | |
| } | |
| else if (e.ctrlKey && e.keyCode === 90) { | |
| console.log("Undoing...") | |
| this._revertState(); | |
| } | |
| }.bind(this); | |
| }, | |
| _logSetState: function (newState) { | |
| // want to remember the old state via a clone | |
| this._log.push(JSON.parse(JSON.stringify(this._log.length === 0 ? this.state : newState))); | |
| this.setState(newState); | |
| }, | |
| _replay: function () { | |
| if (this._log.length === 0) { | |
| console.warn("No state to replay"); | |
| return; | |
| } | |
| var idx = -1; | |
| var interval = setInterval(function () { | |
| idx++; | |
| if (idx === this._log.length - 1) { | |
| // last element in array | |
| clearInterval(interval); | |
| } | |
| this.setState(this._log[idx]); | |
| }.bind(this), 1000); | |
| }, | |
| _revertState: function () { | |
| if (this._log.length === 0) { | |
| console.warn("No state to replay"); | |
| return; | |
| } | |
| console.log(this._log); | |
| console.log(this._log.length - 2); | |
| this.setState(this._log[this._log.length - 1]); | |
| }, | |
| _sort: function (e) { | |
| var col = e.target.cellIndex; | |
| var data = this.state.data.slice(); | |
| var descending = this.state.sortBy === col && !this.state.descending; | |
| data.sort(function (a, b) { | |
| return descending | |
| ? (a[col] < b[col] ? 1 : -1) | |
| : (a[col] > b[col] ? 1 : -1) | |
| }); | |
| this.setState({ | |
| data: data, | |
| sortBy: col, | |
| descending: descending | |
| }); | |
| }, | |
| _showEditor: function (e) { | |
| this.setState({ | |
| edit: { | |
| row: parseInt(e.target.dataset.row, 10), | |
| cell: e.target.cellIndex | |
| } | |
| }) | |
| }, | |
| _save: function (e) { | |
| e.preventDefault(); // block default behavior | |
| var input = e.target.firstChild; | |
| var data = this.state.data.slice(); | |
| data[this.state.edit.row][this.state.edit.cell] = input.value | |
| console.log({ | |
| row: this.state.edit.row, | |
| cell: this.state.edit.cell, | |
| value: input.value | |
| }); | |
| this._logSetState({ | |
| edit: null, | |
| data: data | |
| }); | |
| }, | |
| _toggleSearch: function () { | |
| if (this.state.search) { | |
| this.setState({ | |
| data: this.__preSearchData, | |
| // search: false | |
| }); | |
| this.__preSearchData = null; | |
| } | |
| else { | |
| this.__preSearchData = this.state.data; | |
| this.setState({ search: true }); | |
| } | |
| }, | |
| _search: function (e) { | |
| var needle = e.target.value.toLowerCase(); | |
| console.log(needle) | |
| if (!needle) { | |
| // No search string | |
| this.setState({ data: this.__preSearchData }); | |
| return; | |
| } | |
| var idx = e.target.dataset.idx; // what column to search | |
| var searchData = this.__preSearchData.filter(function (row) { | |
| return row[1].toString().toLowerCase().indexOf("tol") > -1 && | |
| row[idx].toString().toLowerCase().indexOf(needle) > -1 | |
| }); // bool | |
| this.setState({ data: searchData }); | |
| }, | |
| _renderToolbar: function () { | |
| return React.DOM.button({ | |
| onClick: this._toggleSearch, | |
| className: "toolbar" | |
| }, "Search"); | |
| }, | |
| _renderSearch: function () { | |
| // Bail out | |
| if (!this.state.search) { return null } | |
| return (React.DOM.tr( | |
| { onChange: this._search }, | |
| this.props.headers.map(function (_ignore, idx) { | |
| return React.DOM.td( | |
| { key: idx }, | |
| React.DOM.input({ type: "text", "data-idx": idx })) | |
| }) | |
| )) | |
| }, | |
| _renderTable: function () { | |
| return ( | |
| React.DOM.table(null, | |
| // Generate the header | |
| React.DOM.thead({ onClick: this._sort }, | |
| React.DOM.tr(null, | |
| this.props.headers.map(function (title, idx) { | |
| if (this.state.sortBy === idx) { | |
| title += this.state.descending ? " \u2191" : " \u2193"; | |
| } | |
| return React.DOM.th({ key: idx }, title); | |
| }, this) | |
| ) | |
| ), | |
| // Generate the table body | |
| React.DOM.tbody({ onDoubleClick: this._showEditor }, | |
| this._renderSearch(), | |
| this.state.data.map(function (row, rowIdx) { | |
| return ( | |
| React.DOM.tr({ key: rowIdx }, | |
| row.map(function (cell, idx) { | |
| var content = cell; | |
| var _edit = this.state.edit; | |
| // Change the node type and allow for editing | |
| if (_edit && _edit.row === rowIdx && _edit.cell === idx) { | |
| content = React.DOM.form({ onSubmit: this._save }, | |
| React.DOM.input({ | |
| type: "text", | |
| defaultValue: content | |
| }) | |
| ) | |
| } | |
| return React.DOM.td({ | |
| key: idx, | |
| "data-row": rowIdx | |
| }, content); | |
| }, this) // row.map | |
| ) | |
| ); | |
| }, this) // state.data.map | |
| ) | |
| ) | |
| ); | |
| }, | |
| render: function () { | |
| return ( | |
| React.DOM.div( | |
| null, | |
| this._renderToolbar(), | |
| this._renderTable() | |
| ) | |
| ) | |
| } | |
| }); | |
| var headers = [ | |
| "Book", "Author", "Language", "Published", "Sales" | |
| ]; | |
| var data = [ | |
| ["The Lord of the Rings", "J. R. R. Tolkien", "English", "1954–1955", "150 million"], | |
| ["Le Petit Prince (The Little Prince)", "Antoine de Saint-Exupéry", "French", "1943", "140 million"], | |
| ["Harry Potter and the Philosopher's Stone", "J. K. Rowling", "English", "1997", "107 million"], | |
| ["And Then There Were None", "Agatha Christie", "English", "1939", "100 million"], | |
| ["Dream of the Red Chamber", "Cao Xueqin", "Chinese", "1754–1791", "100 million"], | |
| ["The Hobbit", "J. R. R. Tolkien", "English", "1937", "100 million"], | |
| ["She: A History of Adventure", "H. Rider Haggard", "English", "1887", "100 million"], | |
| ]; | |
| ReactDOM.render( | |
| React.createElement(Excel, { | |
| headers: headers, | |
| initialData: data, | |
| }), | |
| document.getElementById("app") | |
| ); |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I can get the filter to "filter" by hijacking LN 46, but I can't figure out how to get the values of all the other boxes. I could directly access them by a
document.querySelectAll()but would that violate the state methodologies?