forked from tastejs/todomvc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
99011a6
commit 9c7b1a2
Showing
33 changed files
with
42,840 additions
and
1 deletion.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<!doctype html> | ||
<html lang="en" data-framework="typescript"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>React • TodoMVC</title> | ||
<link rel="stylesheet" href="node_modules/todomvc-common/base.css"> | ||
<link rel="stylesheet" href="node_modules/todomvc-app-css/index.css"> | ||
</head> | ||
<body> | ||
<section class="todoapp"></section> | ||
<footer class="info"> | ||
<p>Double-click to edit a todo</p> | ||
<p>Created by <a href="http://github.com/remojansen/">Remo H. Jansen</a></p> | ||
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p> | ||
</footer> | ||
<script type="text/javascript" src="node_modules/todomvc-common/base.js"></script> | ||
<script type="text/javascript" src="node_modules/react/dist/react-with-addons.js"></script> | ||
<script type="text/javascript" src="node_modules/classnames/index.js"></script> | ||
<script type="text/javascript" src="node_modules/director/build/director.js"></script> | ||
|
||
<script type="text/javascript" src="js/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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/*jshint quotmark:false */ | ||
/*jshint white:false */ | ||
/*jshint trailing:false */ | ||
/*jshint newcap:false */ | ||
/*global React, Router*/ | ||
var __extends = (this && this.__extends) || function (d, b) { | ||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
/// <reference path="../typings/tsd.d.ts" /> | ||
/// <reference path="./interfaces.d.ts"/> | ||
var TodoModel_1 = require("./TodoModel"); | ||
var footer_1 = require("./footer"); | ||
var todoItem_1 = require("./todoItem"); | ||
var constants_1 = require("./constants"); | ||
var TodoApp = (function (_super) { | ||
__extends(TodoApp, _super); | ||
function TodoApp(props) { | ||
_super.call(this, props); | ||
this.state = { | ||
nowShowing: constants_1.ALL_TODOS, | ||
editing: null | ||
}; | ||
} | ||
TodoApp.prototype.componentDidMount = function () { | ||
var setState = this.setState; | ||
var router = Router({ | ||
'/': setState.bind(this, { nowShowing: constants_1.ALL_TODOS }), | ||
'/active': setState.bind(this, { nowShowing: constants_1.ACTIVE_TODOS }), | ||
'/completed': setState.bind(this, { nowShowing: constants_1.COMPLETED_TODOS }) | ||
}); | ||
router.init('/'); | ||
}; | ||
TodoApp.prototype.handleNewTodoKeyDown = function (event) { | ||
if (event.keyCode !== constants_1.ENTER_KEY) { | ||
return; | ||
} | ||
event.preventDefault(); | ||
var val = React.findDOMNode(this.refs["newField"]).value.trim(); | ||
if (val) { | ||
this.props.model.addTodo(val); | ||
React.findDOMNode(this.refs["newField"]).value = ''; | ||
} | ||
}; | ||
TodoApp.prototype.toggleAll = function (event) { | ||
var target = event.target; | ||
var checked = target.checked; | ||
this.props.model.toggleAll(checked); | ||
}; | ||
TodoApp.prototype.toggle = function (todoToToggle) { | ||
this.props.model.toggle(todoToToggle); | ||
}; | ||
TodoApp.prototype.destroy = function (todo) { | ||
this.props.model.destroy(todo); | ||
}; | ||
TodoApp.prototype.edit = function (todo) { | ||
this.setState({ editing: todo.id }); | ||
}; | ||
TodoApp.prototype.save = function (todoToSave, text) { | ||
this.props.model.save(todoToSave, text); | ||
this.setState({ editing: null }); | ||
}; | ||
TodoApp.prototype.cancel = function () { | ||
this.setState({ editing: null }); | ||
}; | ||
TodoApp.prototype.clearCompleted = function () { | ||
this.props.model.clearCompleted(); | ||
}; | ||
TodoApp.prototype.render = function () { | ||
var _this = this; | ||
var footer; | ||
var main; | ||
var todos = this.props.model.todos; | ||
var shownTodos = todos.filter(function (todo) { | ||
switch (_this.state.nowShowing) { | ||
case constants_1.ACTIVE_TODOS: | ||
return !todo.completed; | ||
case constants_1.COMPLETED_TODOS: | ||
return todo.completed; | ||
default: | ||
return true; | ||
} | ||
}); | ||
var todoItems = shownTodos.map(function (todo) { | ||
return (React.createElement(todoItem_1.TodoItem, {"key": todo.id, "todo": todo, "onToggle": _this.toggle.bind(_this, todo), "onDestroy": _this.destroy.bind(_this, todo), "onEdit": _this.edit.bind(_this, todo), "editing": _this.state.editing === todo.id, "onSave": _this.save.bind(_this, todo), "onCancel": function (e) { return _this.cancel(); }})); | ||
}); | ||
var activeTodoCount = todos.reduce(function (accum, todo) { | ||
return todo.completed ? accum : accum + 1; | ||
}, 0); | ||
var completedCount = todos.length - activeTodoCount; | ||
if (activeTodoCount || completedCount) { | ||
footer = | ||
React.createElement(footer_1.TodoFooter, {"count": activeTodoCount, "completedCount": completedCount, "nowShowing": this.state.nowShowing, "onClearCompleted": function (e) { return _this.clearCompleted(); }}); | ||
} | ||
if (todos.length) { | ||
main = (React.createElement("section", {"className": "main"}, React.createElement("input", {"className": "toggle-all", "type": "checkbox", "onChange": function (e) { return _this.toggleAll(e); }, "checked": activeTodoCount === 0}), React.createElement("ul", {"className": "todo-list"}, todoItems))); | ||
} | ||
return (React.createElement("div", null, React.createElement("header", {"className": "header"}, React.createElement("h1", null, "todos"), React.createElement("input", {"ref": "newField", "className": "new-todo", "placeholder": "What needs to be done?", "onKeyDown": function (e) { return _this.handleNewTodoKeyDown(e); }, "autoFocus": true})), main, footer)); | ||
}; | ||
return TodoApp; | ||
})(React.Component); | ||
var model = new TodoModel_1.TodoModel('react-todos'); | ||
function render() { | ||
React.render(React.createElement(TodoApp, {"model": model}), document.getElementsByClassName('todoapp')[0]); | ||
} | ||
model.subscribe(render); | ||
render(); |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
/*jshint quotmark:false */ | ||
/*jshint white:false */ | ||
/*jshint trailing:false */ | ||
/*jshint newcap:false */ | ||
/*global React, Router*/ | ||
|
||
/// <reference path="../typings/tsd.d.ts" /> | ||
/// <reference path="./interfaces.d.ts"/> | ||
|
||
declare var Router; | ||
|
||
import { TodoModel } from "./TodoModel"; | ||
import { TodoFooter } from "./footer"; | ||
import { TodoItem } from "./todoItem"; | ||
import { ALL_TODOS, ACTIVE_TODOS, COMPLETED_TODOS, ENTER_KEY } from "./constants"; | ||
|
||
class TodoApp extends React.Component<IAppProps, IAppState> { | ||
|
||
public state : IAppState; | ||
|
||
constructor(props : IAppProps) { | ||
super(props); | ||
this.state = { | ||
nowShowing: ALL_TODOS, | ||
editing: null | ||
}; | ||
} | ||
|
||
public componentDidMount() { | ||
var setState = this.setState; | ||
var router = Router({ | ||
'/': setState.bind(this, {nowShowing: ALL_TODOS}), | ||
'/active': setState.bind(this, {nowShowing: ACTIVE_TODOS}), | ||
'/completed': setState.bind(this, {nowShowing: COMPLETED_TODOS}) | ||
}); | ||
router.init('/'); | ||
} | ||
|
||
public handleNewTodoKeyDown(event : __React.KeyboardEvent) { | ||
if (event.keyCode !== ENTER_KEY) { | ||
return; | ||
} | ||
|
||
event.preventDefault(); | ||
|
||
var val = React.findDOMNode<HTMLInputElement>(this.refs["newField"]).value.trim(); | ||
|
||
if (val) { | ||
this.props.model.addTodo(val); | ||
React.findDOMNode<HTMLInputElement>(this.refs["newField"]).value = ''; | ||
} | ||
} | ||
|
||
public toggleAll(event : __React.FormEvent) { | ||
var target : any = event.target; | ||
var checked = target.checked; | ||
this.props.model.toggleAll(checked); | ||
} | ||
|
||
public toggle(todoToToggle : ITodo) { | ||
this.props.model.toggle(todoToToggle); | ||
} | ||
|
||
public destroy(todo : ITodo) { | ||
this.props.model.destroy(todo); | ||
} | ||
|
||
public edit(todo : ITodo) { | ||
this.setState({editing: todo.id}); | ||
} | ||
|
||
public save(todoToSave : ITodo, text : String) { | ||
this.props.model.save(todoToSave, text); | ||
this.setState({editing: null}); | ||
} | ||
|
||
public cancel() { | ||
this.setState({editing: null}); | ||
} | ||
|
||
public clearCompleted() { | ||
this.props.model.clearCompleted(); | ||
} | ||
|
||
public render() { | ||
var footer; | ||
var main; | ||
const todos = this.props.model.todos; | ||
|
||
var shownTodos = todos.filter((todo) => { | ||
switch (this.state.nowShowing) { | ||
case ACTIVE_TODOS: | ||
return !todo.completed; | ||
case COMPLETED_TODOS: | ||
return todo.completed; | ||
default: | ||
return true; | ||
} | ||
}); | ||
|
||
var todoItems = shownTodos.map((todo) => { | ||
return ( | ||
<TodoItem | ||
key={todo.id} | ||
todo={todo} | ||
onToggle={this.toggle.bind(this, todo)} | ||
onDestroy={this.destroy.bind(this, todo)} | ||
onEdit={this.edit.bind(this, todo)} | ||
editing={this.state.editing === todo.id} | ||
onSave={this.save.bind(this, todo)} | ||
onCancel={ e => this.cancel() } | ||
/> | ||
); | ||
}); | ||
|
||
// Note: It's usually better to use immutable data structures since they're | ||
// easier to reason about and React works very well with them. That's why | ||
// we use map(), filter() and reduce() everywhere instead of mutating the | ||
// array or todo items themselves. | ||
var activeTodoCount = todos.reduce(function (accum, todo) { | ||
return todo.completed ? accum : accum + 1; | ||
}, 0); | ||
|
||
var completedCount = todos.length - activeTodoCount; | ||
|
||
if (activeTodoCount || completedCount) { | ||
footer = | ||
<TodoFooter | ||
count={activeTodoCount} | ||
completedCount={completedCount} | ||
nowShowing={this.state.nowShowing} | ||
onClearCompleted={ e=> this.clearCompleted() } | ||
/>; | ||
} | ||
|
||
if (todos.length) { | ||
main = ( | ||
<section className="main"> | ||
<input | ||
className="toggle-all" | ||
type="checkbox" | ||
onChange={ e => this.toggleAll(e) } | ||
checked={activeTodoCount === 0} | ||
/> | ||
<ul className="todo-list"> | ||
{todoItems} | ||
</ul> | ||
</section> | ||
); | ||
} | ||
|
||
return ( | ||
<div> | ||
<header className="header"> | ||
<h1>todos</h1> | ||
<input | ||
ref="newField" | ||
className="new-todo" | ||
placeholder="What needs to be done?" | ||
onKeyDown={ e => this.handleNewTodoKeyDown(e) } | ||
autoFocus={true} | ||
/> | ||
</header> | ||
{main} | ||
{footer} | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
var model = new TodoModel('react-todos'); | ||
|
||
function render() { | ||
React.render( | ||
<TodoApp model={model}/>, | ||
document.getElementsByClassName('todoapp')[0] | ||
); | ||
} | ||
|
||
model.subscribe(render); | ||
render(); |
Oops, something went wrong.