Created
November 30, 2015 10:29
-
-
Save dawncold/8f8c32aaf263000e35d0 to your computer and use it in GitHub Desktop.
React todo mvc
This file contains 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
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="UTF-8"/> | |
<title>Hello React!</title> | |
<style> | |
li.todo-item.completed span { | |
text-decoration: line-through; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="example"></div> | |
<script src="{{ static_url('mobile/js/r/bundle.js') }}"></script> | |
</body> | |
</html> |
This file contains 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 React = require('react'); | |
var ReactDOM = require('react-dom'); | |
var classNames = require('classnames'); | |
var director = require('director'); | |
var TodoInput = React.createClass({ | |
getInitialState: function () { | |
"use strict"; | |
return {input: ''}; | |
}, | |
changeHandler: function (e) { | |
"use strict"; | |
this.setState({input: e.target.value.trim()}); | |
}, | |
addHandler: function (e) { | |
"use strict"; | |
e.preventDefault(); | |
var todo = {id: (new Date()).getTime(), text: this.state.input, completed: false}; | |
this.props.onTodoAdded(todo); | |
this.setState({input: ''}); | |
}, | |
render: function () { | |
"use strict"; | |
return ( | |
<form className="add-todo-form" onSubmit={this.addHandler}> | |
<input type="text" onChange={this.changeHandler} value={this.state.input} placeholder="add something..."/> | |
</form> | |
); | |
} | |
}); | |
var TodoItem = React.createClass({ | |
getInitialState: function () { | |
"use strict"; | |
return {editing: false, text: this.props.todo.text} | |
}, | |
handleStateChange: function (e) { | |
"use strict"; | |
this.props.onItemStateChanged(e.target.checked); | |
}, | |
handleItemEdit: function () { | |
"use strict"; | |
if (!this.props.todo.completed) { | |
this.setState({editing: true}); | |
} | |
}, | |
handleTextChange: function (e) { | |
"use strict"; | |
if (this.state.editing) { | |
this.setState({text: e.target.value}); | |
} | |
}, | |
handleItemEditSubmit: function (e) { | |
"use strict"; | |
e.preventDefault(); | |
var todo = this.props.todo; | |
todo.text = this.state.text; | |
this.props.onItemEditSubmit(todo); | |
this.setState({editing: false}); | |
}, | |
render: function () { | |
"use strict"; | |
var todoItemClassNames = classNames('todo-item', { | |
completed: this.props.todo.completed | |
}); | |
var todoContent; | |
if (this.state.editing) { | |
todoContent = ( | |
<form className="edit-todo" onSubmit={this.handleItemEditSubmit}> | |
<input type="text" value={this.state.text} onChange={this.handleTextChange}/> | |
</form> | |
); | |
} else { | |
todoContent = ( | |
<li className={todoItemClassNames}> | |
<input type="checkbox" onChange={this.handleStateChange} checked={this.props.todo.completed}/> | |
<span onDoubleClick={this.handleItemEdit}>{this.props.todo.text}</span> | |
<a href="#" onClick={this.props.onDeleted}>[ X ]</a> | |
</li> | |
); | |
} | |
return todoContent; | |
} | |
}); | |
var TodoList = React.createClass({ | |
render: function () { | |
var todos = this.props.data.map(function (todo) { | |
"use strict"; | |
return ( | |
<TodoItem | |
key={todo.id} | |
todo={todo} | |
onItemEditSubmit={this.props.onItemEditSubmit} | |
onItemStateChanged={this.props.onItemStateChanged.bind(null, todo)} | |
onDeleted={this.props.onDeleted.bind(null, todo)} | |
/> | |
); | |
}, this); | |
return ( | |
<ul> | |
{todos} | |
</ul> | |
); | |
} | |
}); | |
var TodoFooter = React.createClass({ | |
render: function () { | |
return ( | |
<div> | |
Total: {this.props.data.length} | |
<a href="#/">All</a> | |
<a href="#/active">Active</a> | |
<a href="#/completed">Completed</a> | |
</div> | |
); | |
} | |
}); | |
var app = app || {}; | |
app.ALL = 'all'; | |
app.ACTIVE = 'active'; | |
app.COMPLETED = 'completed'; | |
var TodoApp = React.createClass({ | |
getInitialState: function () { | |
"use strict"; | |
return {todo: [], show: app.ALL}; | |
}, | |
componentDidMount: function () { | |
"use strict"; | |
var setState = this.setState; | |
var routers = director.Router({ | |
'/': setState.bind(this, {show: app.ALL}), | |
'/active': setState.bind(this, {show: app.ACTIVE}), | |
'/completed': setState.bind(this, {show: app.COMPLETED}) | |
}); | |
routers.init('/'); | |
}, | |
handleNewTodo: function (todo) { | |
"use strict"; | |
var todos = this.state.todo; | |
this.setState({todo: todos.concat(todo)}); | |
}, | |
handleItemStateChanged: function (changedItem, state) { | |
"use strict"; | |
this.setState({ | |
todo: this.state.todo.map(function(todo) { | |
if (todo.id === changedItem.id) { | |
todo.completed = state; | |
} | |
return todo; | |
}) | |
}); | |
}, | |
handleDelete: function (todoToDelete) { | |
"use strict"; | |
this.setState({ | |
todo: this.state.todo.filter(function (todo) { | |
return todo.id !== todoToDelete.id; | |
}) | |
}); | |
}, | |
handleItemEditSubmit: function (editedTodo) { | |
"use strict"; | |
this.setState({ | |
todo: this.state.todo.map(function (todo) { | |
if (todo.id === editedTodo.id) { | |
todo.text = editedTodo.text | |
} | |
return todo; | |
}) | |
}); | |
}, | |
render: function(){ | |
"use strict"; | |
var show = this.state.show; | |
var todos = this.state.todo.filter(function (todo) { | |
if (show === app.ALL) { | |
return true; | |
} else if (show === app.ACTIVE) { | |
return !todo.completed; | |
} else if (show === app.COMPLETED) { | |
return todo.completed; | |
} | |
}); | |
return ( | |
<div> | |
<TodoInput onTodoAdded={this.handleNewTodo}/> | |
<TodoList | |
data={todos} | |
onItemStateChanged={this.handleItemStateChanged} | |
onDeleted={this.handleDelete} | |
onItemEditSubmit={this.handleItemEditSubmit} | |
/> | |
<TodoFooter data={todos} /> | |
</div> | |
); | |
} | |
}); | |
ReactDOM.render( | |
<TodoApp />, | |
document.getElementById('example') | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment