-
Notifications
You must be signed in to change notification settings - Fork 9
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
Dane Harnett
committed
Oct 8, 2020
1 parent
9c20467
commit 655e676
Showing
20 changed files
with
25,432 additions
and
0 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
<!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/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,119 @@ | ||
"use strict"; | ||
var __extends = (this && this.__extends) || (function () { | ||
var extendStatics = Object.setPrototypeOf || | ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || | ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; | ||
return function (d, b) { | ||
extendStatics(d, b); | ||
function __() { this.constructor = d; } | ||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); | ||
}; | ||
})(); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var React = require("react"); | ||
var ReactDOM = require("react-dom"); | ||
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) { | ||
var _this = _super.call(this, props) || this; | ||
_this.state = { | ||
nowShowing: constants_1.ALL_TODOS, | ||
editing: null | ||
}; | ||
return _this; | ||
} | ||
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 = ReactDOM.findDOMNode(this.refs["newField"]).value.trim(); | ||
if (val) { | ||
this.props.model.addTodo(val); | ||
ReactDOM.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", { id: "toggle-all", className: "toggle-all", type: "checkbox", onChange: function (e) { return _this.toggleAll(e); }, checked: activeTodoCount === 0 }), | ||
React.createElement("label", { htmlFor: "toggle-all" }, "Mark all as complete"), | ||
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() { | ||
ReactDOM.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,187 @@ | ||
/*jshint quotmark:false */ | ||
/*jshint white:false */ | ||
/*jshint trailing:false */ | ||
/*jshint newcap:false */ | ||
/*global React, Router*/ | ||
|
||
/// <reference path="./interfaces.d.ts"/> | ||
|
||
declare var Router; | ||
import * as React from "react"; | ||
import * as ReactDOM from "react-dom"; | ||
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 = (ReactDOM.findDOMNode(this.refs["newField"]) as HTMLInputElement).value.trim(); | ||
|
||
if (val) { | ||
this.props.model.addTodo(val); | ||
(ReactDOM.findDOMNode(this.refs["newField"]) as HTMLInputElement).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 | ||
id="toggle-all" | ||
className="toggle-all" | ||
type="checkbox" | ||
onChange={ e => this.toggleAll(e) } | ||
checked={activeTodoCount === 0} | ||
/> | ||
<label | ||
htmlFor="toggle-all" | ||
> | ||
Mark all as complete | ||
</label> | ||
<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() { | ||
ReactDOM.render( | ||
<TodoApp model={model}/>, | ||
document.getElementsByClassName('todoapp')[0] | ||
); | ||
} | ||
|
||
model.subscribe(render); | ||
render(); |
Oops, something went wrong.