Spicke

как то так

Nov 30th, 2017
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2.  
  3. <html xmlns="http://www.w3.org/1999/xhtml">
  4.   <head>
  5.     <title>Таблица</title>
  6.     <meta charset="UTF-8">
  7.     <link rel="stylesheet" type="text/css" href="style.css">
  8.   </head>
  9.   <body>
  10.     <div id="app">
  11.     </div>
  12.     <script src="react/build/react.js"></script>
  13.     <script src="react/build/react-dom.js"></script>
  14.     <script>
  15.       var Excel = React.createClass({
  16.         displayName: 'Excel',
  17.        
  18.         propTypes: {
  19.           headers: React.PropTypes.arrayOf(
  20.             React.PropTypes.string
  21.           ),
  22.           initialData: React.PropTypes.arrayOf(
  23.             React.PropTypes.arrayOf(
  24.               React.PropTypes.string
  25.             )
  26.           ),
  27.         },
  28.  
  29.         getInitialState: function() {
  30.           return {
  31.             data: this.props.initialData,
  32.             sortby: null,
  33.             descending: false,
  34.             edit: null, // [row index, cell index],
  35.             search: false,
  36.           };
  37.         },
  38.        
  39.         _sort: function(e) {
  40.           var column = e.target.cellIndex;
  41.           var data = this.state.data.slice();
  42.           var descending = this.state.sortby === column && !this.state.descending;
  43.           data.sort(function(a, b) {
  44.             return descending
  45.               ? (a[column] < b[column] ? 1 : -1)
  46.               : (a[column] > b[column] ? 1 : -1);
  47.           });
  48.           this.setState({
  49.             data: data,
  50.             sortby: column,
  51.             descending: descending,
  52.           });
  53.         },
  54.        
  55.         _showEditor: function(e) {
  56.           this.setState({edit: {
  57.             row: parseInt(e.target.dataset.row, 10),
  58.             cell: e.target.cellIndex,
  59.           }});
  60.         },
  61.        
  62.         _save: function(e) {
  63.           e.preventDefault();
  64.           var input = e.target.firstChild;
  65.           var data = this.state.data.slice();
  66.           data[this.state.edit.row][this.state.edit.cell] = input.value;
  67.           this.setState({
  68.             edit: null,
  69.             data: data,
  70.           });
  71.         },
  72.        
  73.         _preSearchData: null,
  74.        
  75.         _toggleSearch: function() {
  76.           if (this.state.search) {
  77.             this.setState({
  78.               data: this._preSearchData,
  79.               search: false,
  80.             });
  81.             this._preSearchData = null;
  82.           } else {
  83.             this._preSearchData = this.state.data;
  84.             this.setState({
  85.               search: true,
  86.             });
  87.           }
  88.         },
  89.        
  90.         _search: function(e) {
  91.           var needle = e.target.value.toLowerCase();
  92.           if (!needle) {
  93.             this.setState({data: this._preSearchData});
  94.             return;
  95.           }
  96.           var idx = e.target.dataset.idx;
  97.           var searchdata = this._preSearchData.filter(function(row) {
  98.             return row[idx].toString().toLowerCase().indexOf(needle) > -1;
  99.           });
  100.           this.setState({data: searchdata});
  101.         },
  102.        
  103.         _download: function(format, ev) {
  104.           var contents = format === 'json'
  105.             ? JSON.stringify(this.state.data)
  106.             : this.state.data.reduce(function(result, row) {
  107.                 return result
  108.                   + row.reduce(function(rowresult, cell, idx) {
  109.                       return rowresult
  110.                         + '"'
  111.                         + cell.replace(/"/g, '""')
  112.                         + '"'
  113.                         + (idx < row.length - 1 ? ',' : '');
  114.                     }, '')
  115.                   + "\n";
  116.               }, '');
  117.  
  118.           var URL = window.URL || window.webkitURL;
  119.           var blob = new Blob([contents], {type: 'text/' + format});
  120.           ev.target.href = URL.createObjectURL(blob);
  121.           ev.target.download = 'data.' + format;
  122.         },
  123.        
  124.         render: function() {
  125.           return (
  126.             React.DOM.div(null,
  127.               this._renderToolbar(),
  128.               this._renderTable()
  129.             )
  130.           );
  131.         },
  132.        
  133.         _renderToolbar: function() {
  134.           return  React.DOM.div({className: 'toolbar'},
  135.             React.DOM.button({
  136.               onClick: this._toggleSearch,
  137.             }, 'Поиск'),
  138.             React.DOM.a({
  139.               onClick: this._download.bind(this, 'json'),
  140.               href: 'data.json',
  141.             }, 'Экспорт таблицы в JSON'),
  142.             React.DOM.a({
  143.               onClick: this._download.bind(this, 'csv'),
  144.               href: 'data.csv',
  145.             }, 'Экспорт таблицы в CSV')
  146.           );
  147.         },
  148.        
  149.         _renderSearch: function() {
  150.           if (!this.state.search) {
  151.             return null;
  152.           }
  153.           return (
  154.             React.DOM.tr({onChange: this._search},
  155.               this.props.headers.map(function(_ignore, idx) {
  156.                 return React.DOM.td({key: idx},
  157.                   React.DOM.input({
  158.                     type: 'text',
  159.                     'data-idx': idx,
  160.                   })
  161.                 );
  162.               })
  163.             )
  164.           );
  165.         },
  166.        
  167.        
  168.         _renderTable: function() {
  169.           return (
  170.             React.DOM.table(null,
  171.               React.DOM.thead({onClick: this._sort},
  172.                 React.DOM.tr(null,
  173.                   this.props.headers.map(function(title, idx) {
  174.                     if (this.state.sortby === idx) {
  175.                       title += this.state.descending ? ' \u2191' : ' \u2193';
  176.                     }
  177.                     return React.DOM.th({key: idx}, title);
  178.                   }, this)
  179.                 )
  180.               ),
  181.               React.DOM.tbody({onDoubleClick: this._showEditor},
  182.                 this._renderSearch(),
  183.                 this.state.data.map(function(row, rowidx) {
  184.                   return (
  185.                     React.DOM.tr({key: rowidx},
  186.                       row.map(function(cell, idx) {
  187.                         var content = cell;
  188.                         var edit = this.state.edit;
  189.                         if (edit && edit.row === rowidx && edit.cell === idx) {
  190.                           content = React.DOM.form({onSubmit: this._save},
  191.                             React.DOM.input({
  192.                               type: 'text',
  193.                               defaultValue: cell,
  194.                             })
  195.                           );
  196.                         }
  197.  
  198.                         return React.DOM.td({
  199.                           key: idx,
  200.                           'data-row': rowidx,
  201.                         }, content);
  202.                       }, this)
  203.                     )
  204.                   );
  205.                 }, this)
  206.               )
  207.             )
  208.           );
  209.         }
  210.       });
  211.      
  212.  
  213.       var headers = [
  214.         "Название", "Автор", "Язык", "Дата публикации", "Продажи"
  215.       ];
  216.      
  217.       var data = [
  218.          ["Властелин колец", "Р. Р. Толкин", "Английский", "1954-1955", "150 миллионов"],
  219.          ["Принц Ле Пети (Маленький принц)", "Антуан де Сент-Экзюпери", "Французский", "1943", "140 миллионов"],
  220.          ["Гарри Поттер и философский камень", "Дж. К. Роулинг", "Английский", "1997", "107 миллионов"],
  221.          ["И тогда их не было", "Агата Кристи", "Английский", "1939", "100 миллионов"],
  222.          ["Мечта о Красной палате", "Цао Сюэцин", "Китайский", "1754-1791", "100 миллионов"],
  223.          ["Хоббит", "Р. Р. Толкиен", "Английский", "1937", "100 миллионов"],
  224.          ["Она: история приключений", "Х. Райдер Хаггард", "Английский", "1887", "100 миллионов"],
  225.        ];
  226.      
  227.       var Ex = ReactDOM.render(
  228.         React.createElement(Excel, {
  229.           headers: headers,
  230.           initialData: data,
  231.         }),
  232.         document.getElementById("app")
  233.       );
  234.     </script>
  235.   </body>
  236. </html>
Advertisement
Add Comment
Please, Sign In to add comment