Skip to content

Commit c5c7722

Browse files
baseline for episode 17
1 parent b052d63 commit c5c7722

File tree

8 files changed

+437
-0
lines changed

8 files changed

+437
-0
lines changed

ep17-edit-todo/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#### Setting up the application
2+
3+
```
4+
npm install
5+
npm start
6+
```
7+
8+
Visit http://localhost:8080 in browser.
9+
10+
#### Notes
11+
12+
* `npm install random-key --save`
13+
* [Source code](...)

ep17-edit-todo/app/components/App.jsx

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import React from 'react';
2+
import DisplayList from './DisplayList';
3+
4+
var rand = require('random-key');
5+
6+
export default class App extends React.Component {
7+
8+
constructor () {
9+
super();
10+
this.state = { title: '', todos: [
11+
{ title: 'eggs', done: false, id: 1 },
12+
{ title: 'banana', done: false, id: 2 },
13+
{ title: 'bread', done: false, id: 3 }
14+
] };
15+
}
16+
17+
handleDone (idToBeMarkedAsDone) {
18+
var _todos = this.state.todos;
19+
var todo = _todos.filter((todo) => {
20+
return todo.id === idToBeMarkedAsDone;
21+
})[0];
22+
23+
todo.done = !todo.done;
24+
25+
this.setState({ todos: _todos });
26+
}
27+
28+
handleDelete (idToBeDeleted) {
29+
var newTodos = this.state.todos.filter( (todo) => {
30+
return todo.id != idToBeDeleted
31+
} )
32+
33+
this.setState({ todos: newTodos});
34+
}
35+
36+
handleSubmit (event) {
37+
event.preventDefault();
38+
39+
var title = this.state.title;
40+
var newTodos = this.state.todos.concat({ title: title,
41+
id: rand.generate(),
42+
done: false });
43+
44+
this.setState({ title: '', todos: newTodos });
45+
}
46+
47+
handleChange (event) {
48+
var title = event.target.value;
49+
this.setState({ title: title });
50+
}
51+
52+
handleClearCompleted (event) {
53+
var newTodos = this.state.todos.filter((todo) => { return !todo.done});
54+
this.setState({ todos: newTodos });
55+
}
56+
57+
render () {
58+
return <div>
59+
<h1> TODO </h1>
60+
<form onSubmit={this.handleSubmit.bind(this)}>
61+
<input type="text"
62+
onChange={this.handleChange.bind(this)}
63+
value={this.state.title} />
64+
</form>
65+
66+
<DisplayList
67+
handleDone={this.handleDone.bind(this)}
68+
handleDelete={this.handleDelete.bind(this)}
69+
todos={this.state.todos} />
70+
71+
<footer>
72+
All: ({ this.state.todos.length }) |
73+
Completed: ({ this.state.todos.filter((todo) => { return todo.done }).length }) |
74+
Pending: ({ this.state.todos.filter((todo) => { return !todo.done }).length }) |
75+
<a href='#' onClick={this.handleClearCompleted.bind(this)}>Clear Completed</a>
76+
</footer>
77+
</div>;
78+
}
79+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from 'react';
2+
3+
export default class DisplayItem extends React.Component {
4+
5+
render () {
6+
var todo = this.props.todo;
7+
8+
return <li className={ todo.done ? 'done' : '' }>
9+
<input
10+
checked={todo.done}
11+
onChange={this.props.handleDone.bind(null, todo.id)}
12+
type="checkbox"
13+
style={{ fontSize: 'x-large' }} />
14+
15+
<label>
16+
{ todo.title }
17+
</label>
18+
19+
<a href='#'
20+
className="destroy"
21+
onClick={ this.props.handleDelete.bind(null, todo.id) }>
22+
[x]
23+
</a>
24+
</li>;
25+
}
26+
27+
}
28+
29+
DisplayItem.propTypes = {
30+
todo: React.PropTypes.object.isRequired,
31+
handleDone: React.PropTypes.func.isRequired,
32+
handleDelete: React.PropTypes.func.isRequired
33+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React from 'react';
2+
import DisplayItem from './DisplayItem';
3+
4+
export default class DisplayList extends React.Component {
5+
6+
render () {
7+
return <ul id="todo-list">
8+
{ this.props.todos.map((todo, i) => {
9+
return <section id="main" key={todo.title}>
10+
<DisplayItem
11+
todo={todo}
12+
handleDone={this.props.handleDone}
13+
handleDelete={this.props.handleDelete} />
14+
</section>
15+
}) }
16+
</ul>
17+
}
18+
19+
}
20+
21+
DisplayList.propTypes = {
22+
todos: React.PropTypes.array.isRequired,
23+
handleDone: React.PropTypes.func.isRequired,
24+
handleDelete: React.PropTypes.func.isRequired
25+
}

ep17-edit-todo/app/main.jsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import './stylesheets/main.css';
2+
3+
import React from 'react';
4+
import App from './components/App';
5+
6+
main();
7+
8+
function main() {
9+
var div = document.createElement('div');
10+
div.setAttribute("id", "todoapp");
11+
document.body.appendChild(div);
12+
13+
React.render(<App />, div);
14+
}
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
html,
2+
body {
3+
margin: 0;
4+
padding: 0;
5+
}
6+
7+
body {
8+
font: 14px "Helvetica Neue", Helvetica, Arial, sans-serif;
9+
line-height: 1.4em;
10+
background: #eeeeee;
11+
color: #333333;
12+
width: 520px;
13+
margin: 0 auto;
14+
-webkit-font-smoothing: antialiased;
15+
}
16+
17+
#todoapp {
18+
background: #fff;
19+
padding: 20px;
20+
margin-bottom: 40px;
21+
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
22+
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
23+
-ms-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
24+
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
25+
box-shadow: rgba(0, 0, 0, 0.2) 0 2px 6px 0;
26+
-webkit-border-radius: 0 0 5px 5px;
27+
-moz-border-radius: 0 0 5px 5px;
28+
-ms-border-radius: 0 0 5px 5px;
29+
-o-border-radius: 0 0 5px 5px;
30+
border-radius: 0 0 5px 5px;
31+
}
32+
33+
#todoapp h1 {
34+
font-size: 36px;
35+
font-weight: bold;
36+
text-align: center;
37+
padding: 0 0 10px 0;
38+
}
39+
40+
#todoapp input[type="text"] {
41+
width: 466px;
42+
font-size: 24px;
43+
font-family: inherit;
44+
line-height: 1.4em;
45+
border: 0;
46+
outline: none;
47+
padding: 6px;
48+
border: 1px solid #999999;
49+
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
50+
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
51+
-ms-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
52+
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
53+
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px 0 inset;
54+
}
55+
56+
#todoapp input::-webkit-input-placeholder {
57+
font-style: italic;
58+
}
59+
60+
#todo-list {
61+
margin: 10px 0;
62+
padding: 0;
63+
list-style: none;
64+
}
65+
66+
#todo-list li {
67+
padding: 18px 20px 18px 0;
68+
position: relative;
69+
font-size: 24px;
70+
border-bottom: 1px solid #cccccc;
71+
}
72+
73+
#todo-list li:last-child {
74+
border-bottom: none;
75+
}
76+
77+
#todo-list li.done label {
78+
color: #777777;
79+
text-decoration: line-through;
80+
}
81+
82+
#todo-list .destroy {
83+
position: absolute;
84+
right: 5px;
85+
top: 20px;
86+
display: none;
87+
cursor: pointer;
88+
width: 20px;
89+
height: 20px;
90+
}
91+
92+
#todo-list li:hover .destroy {
93+
display: block;
94+
}
95+
96+
#todo-list .destroy:hover {
97+
background-position: 0 -20px;
98+
}
99+
100+
#todo-list li.editing {
101+
border-bottom: none;
102+
margin-top: -1px;
103+
padding: 0;
104+
}
105+
106+
#todo-list li.editing:last-child {
107+
margin-bottom: -1px;
108+
}
109+
110+
#todo-list li .view label {
111+
word-break: break-word;
112+
}
113+
114+
#todoapp footer {
115+
margin: 0 -20px -20px -20px;
116+
overflow: hidden;
117+
color: #555555;
118+
background: #f4fce8;
119+
border-top: 1px solid #ededed;
120+
padding: 0 20px;
121+
line-height: 37px;
122+
-webkit-border-radius: 0 0 5px 5px;
123+
-moz-border-radius: 0 0 5px 5px;
124+
-ms-border-radius: 0 0 5px 5px;
125+
-o-border-radius: 0 0 5px 5px;
126+
border-radius: 0 0 5px 5px;
127+
}
128+
129+
#clear-completed {
130+
float: right;
131+
line-height: 20px;
132+
text-decoration: none;
133+
background: rgba(0, 0, 0, 0.1);
134+
color: #555555;
135+
font-size: 11px;
136+
margin-top: 8px;
137+
margin-bottom: 8px;
138+
padding: 0 10px 1px;
139+
cursor: pointer;
140+
-webkit-border-radius: 12px;
141+
-moz-border-radius: 12px;
142+
-ms-border-radius: 12px;
143+
-o-border-radius: 12px;
144+
border-radius: 12px;
145+
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
146+
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
147+
-ms-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
148+
-o-box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
149+
box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 0 0;
150+
}
151+
152+
#clear-completed:hover {
153+
background: rgba(0, 0, 0, 0.15);
154+
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
155+
-moz-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
156+
-ms-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
157+
-o-box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
158+
box-shadow: rgba(0, 0, 0, 0.3) 0 -1px 0 0;
159+
}
160+
161+
#clear-completed:active {
162+
position: relative;
163+
top: 1px;
164+
}
165+
166+
#todo-count span {
167+
font-weight: bold;
168+
}
169+
170+
#instructions {
171+
margin: 10px auto;
172+
color: #777777;
173+
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
174+
text-align: center;
175+
}
176+
177+
#instructions a {
178+
color: #336699;
179+
}
180+
181+
#credits {
182+
margin: 30px auto;
183+
color: #999;
184+
text-shadow: rgba(255, 255, 255, 0.8) 0 1px 0;
185+
text-align: center;
186+
}
187+
188+
#credits a {
189+
color: #888;
190+
}

ep17-edit-todo/package.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "learning-reactjs-in-steps",
3+
"version": "0.0.1",
4+
"description": "Learn ReactJS in steps",
5+
"main": "index.js",
6+
"scripts": {
7+
"test": "echo \"Error: no test specified\" && exit 1",
8+
"build": "TAGET=build webpack",
9+
"start": "TARGET=dev webpack-dev-server --devtool eval --progress --colors --hot"
10+
},
11+
"author": "Neeraj Singh",
12+
"license": "ISC",
13+
"devDependencies": {
14+
"babel-core": "^5.6.15",
15+
"babel-loader": "^5.3.1",
16+
"css-loader": "^0.15.1",
17+
"html-webpack-plugin": "^1.5.2",
18+
"node-libs-browser": "^0.5.2",
19+
"react-hot-loader": "^1.2.7",
20+
"style-loader": "^0.12.3",
21+
"webpack": "^1.10.1",
22+
"webpack-dev-server": "^1.10.1",
23+
"webpack-merge": "^0.1.2"
24+
},
25+
"dependencies": {
26+
"random-key": "^0.3.2",
27+
"react": "^0.13.3"
28+
}
29+
}

0 commit comments

Comments
 (0)