thinking.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. let ProductCategoryRow = React.createClass({
  2. render: function () {
  3. return (<tr><th colSpan="2">{this.props.category}</th></tr>);
  4. }
  5. });
  6. let ProductRow = React.createClass({
  7. render: function () {
  8. let name = this.props.product.stocked
  9. ? this.props.product.name
  10. : <span style={{ color: "red" }}>{this.props.product.name}</span>;
  11. return (
  12. <tr>
  13. <td>{name}</td>
  14. <td>{this.props.product.price}</td>
  15. </tr>
  16. );
  17. }
  18. });
  19. let ProductTable = React.createClass({
  20. render: function () {
  21. let rows = [];
  22. let lastCategory = null;
  23. this.props.products.forEach(function (product) {
  24. // Apply name and stock filters.
  25. if (product.name.indexOf(this.props.filterText) === -1 || (!product.stocked && this.props.inStockOnly)) {
  26. return;
  27. }
  28. if (product.category !== lastCategory) {
  29. rows.push(<ProductCategoryRow category={product.category} key={product.category} />);
  30. }
  31. rows.push(<ProductRow product={product} key={product.name} />);
  32. lastCategory = product.category;
  33. }.bind(this));
  34. return (
  35. <table>
  36. <thead>
  37. <tr>
  38. <th>Name</th>
  39. <th>Price</th>
  40. </tr>
  41. </thead>
  42. <tbody>
  43. {rows}
  44. </tbody>
  45. </table>
  46. );
  47. }
  48. });
  49. let SearchBar = React.createClass({
  50. handleChange: function () {
  51. this.props.onUserInput(
  52. this.refs.filterTextInput.value,
  53. this.refs.inStockOnlyInput.checked
  54. );
  55. },
  56. render: function () {
  57. return (
  58. <form>
  59. <input
  60. type="text"
  61. placeholder="Search..."
  62. ref="filterTextInput"
  63. value={this.props.filterText}
  64. onChange={this.handleChange}
  65. />
  66. <p>
  67. <input
  68. type="checkbox"
  69. ref="inStockOnlyInput"
  70. checked={this.props.inStockOnly}
  71. onChange={this.handleChange}
  72. />
  73. {" "}
  74. Only show products in stock
  75. </p>
  76. </form>
  77. );
  78. }
  79. });
  80. let FilterableProductTable = React.createClass({
  81. getInitialState: function () {
  82. let state = {
  83. filterText: "",
  84. inStockOnly: false
  85. };
  86. return state;
  87. },
  88. handleUserInput: function (filterText, inStockOnly) {
  89. this.setState({ filterText: filterText, inStockOnly: inStockOnly });
  90. },
  91. render: function () {
  92. return (
  93. <div>
  94. <SearchBar
  95. filterText={this.state.filterText}
  96. inStockOnly={this.state.inStockOnly}
  97. onUserInput={this.handleUserInput}
  98. />
  99. <ProductTable
  100. products={this.props.products}
  101. filterText={this.state.filterText}
  102. inStockOnly={this.state.inStockOnly}
  103. />
  104. </div>
  105. );
  106. }
  107. });
  108. let PRODUCTS = [
  109. { category: "Sporting Goods", price: "$49.99", stocked: true, name: "Football" },
  110. { category: "Sporting Goods", price: "$9.99", stocked: true, name: "Baseball" },
  111. { category: "Sporting Goods", price: "$29.99", stocked: false, name: "Basketball" },
  112. { category: "Electronics", price: "$99.99", stocked: true, name: "iPod Touch" },
  113. { category: "Electronics", price: "$399.99", stocked: false, name: "iPhone 5" },
  114. { category: "Electronics", price: "$199.99", stocked: true, name: "Nexus 7" }
  115. ];
  116. ReactDOM.render(
  117. <FilterableProductTable products={PRODUCTS} />,
  118. document.getElementById("content")
  119. );