Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Todomvc create react app es6 #4

Open
wants to merge 5 commits into
base: todomvc-create-react-app-es6
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/react/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ yarn-debug.log*
yarn-error.log*
todolist.txt
package-lock.json
/.vscode
28 changes: 20 additions & 8 deletions examples/react/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class App extends Component {
super(props);
this.state = { nowShowing: ALL_TODOS, editing: null, newTodo: '' };
}

componentDidMount() {
const setState = this.setState;
const router = Router({
Expand All @@ -21,9 +22,11 @@ class App extends Component {
});
router.init('/');
}

handleChange(event) {
this.setState({ newTodo: event.target.value });
}

handleNewTodoKeyDown(event) {
if (event.keyCode !== ENTER_KEY) {
return;
Expand All @@ -38,29 +41,37 @@ class App extends Component {
this.setState({ newTodo: '' });
}
}

toggleAll(event) {
const checked = event.target.checked;
this.props.model.toggleAll(checked);
}

toggle(todoToToggle) {
this.props.model.toggle(todoToToggle);
}

destroy(todo) {
this.props.model.destroy(todo);
}

edit(todo) {
this.setState({ editing: todo.id });
}

save(todoToSave, text) {
this.props.model.save(todoToSave, text);
this.setState({ editing: null });
}

cancel() {
this.setState({ editing: null });
}

clearCompleted() {
this.props.model.clearCompleted();
}

render() {
let footer;
let main;
Expand All @@ -77,7 +88,6 @@ class App extends Component {
}
}, this);


const todoItems = shownTodos.map((todo) => {
return (
<TodoItem
Expand All @@ -87,7 +97,7 @@ class App extends Component {
onDestroy={() => this.destroy(todo)}
onEdit={() => this.edit(todo)}
editing={this.state.editing === todo.id}
onSave={this.save.bind(this, todo)}
onSave={(text) => this.save(todo, text)}
onCancel={() => this.cancel()}
/>
);
Expand All @@ -99,7 +109,8 @@ class App extends Component {

const completedCount = todos.length - activeTodoCount;

if (activeTodoCount || completedCount) {
const shouldShowFooter = activeTodoCount > 0 || completedCount > 0;
if (shouldShowFooter) {
footer = (
<TodoFooter
count={activeTodoCount}
Expand All @@ -110,13 +121,14 @@ class App extends Component {
);
}

if (todos.length) {
const shouldShowToggleAllCheckbox = todos.length > 0;
if (shouldShowToggleAllCheckbox) {
main = (
<section className="main">
<input
className='toggle-all'
className="toggle-all"
type="checkbox"
onChange={this.toggleAll.bind(this)}
onChange={(event) => this.toggleAll(event)}
checked={activeTodoCount === 0}
/>
<ul className="todo-list">{todoItems}</ul>
Expand All @@ -132,8 +144,8 @@ class App extends Component {
className="new-todo"
placeholder="What needs to be done?"
value={this.state.newTodo}
onKeyDown={this.handleNewTodoKeyDown.bind(this)}
onChange={this.handleChange.bind(this)}
onKeyDown={(event) => this.handleNewTodoKeyDown(event)}
onChange={(event) => this.handleChange(event)}
autoFocus={true}
/>
</header>
Expand Down
26 changes: 11 additions & 15 deletions examples/react/src/Footer.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import React, { Component } from 'react';
import Utils, { ALL_TODOS, ACTIVE_TODOS, COMPLETED_TODOS } from "./utils";
import classNames from "classnames";
import Utils, { ALL_TODOS, ACTIVE_TODOS, COMPLETED_TODOS } from './utils';
import classNames from 'classnames';

class TodoFooter extends Component {
render () {
const activeTodoWord = Utils.pluralize(this.props.count, "item");
render() {
const activeTodoWord = Utils.pluralize(this.props.count, 'item');
let clearButton = null;

if (this.props.completedCount > 0) {
clearButton = (
<button
className="clear-completed"
onClick={this.props.onClearCompleted}
>
onClick={this.props.onClearCompleted}>
Clear completed
</button>
);
Expand All @@ -28,26 +27,23 @@ class TodoFooter extends Component {
<li>
<a
href="#/"
className={classNames({ selected: nowShowing === ALL_TODOS })}
>
className={classNames({ selected: nowShowing === ALL_TODOS })}>
All
</a>
</li>{" "}
</li>{' '}
<li>
<a
href="#/active"
className={classNames({ selected: nowShowing === ACTIVE_TODOS })}
>
className={classNames({ selected: nowShowing === ACTIVE_TODOS })}>
Active
</a>
</li>{" "}
</li>{' '}
<li>
<a
href="#/completed"
className={classNames({
selected: nowShowing === COMPLETED_TODOS
})}
>
})}>
Completed
</a>
</li>
Expand All @@ -56,6 +52,6 @@ class TodoFooter extends Component {
</footer>
);
}
};
}

export default TodoFooter;
10 changes: 5 additions & 5 deletions examples/react/src/TodoItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ class TodoItem extends Component {
constructor(props) {
super(props);
this.state = { editText: this.props.todo.title };
this.handleKeyDown = this.handleKeyDown.bind(this);
}
handleSubmit(event) {

handleSubmit() {
const val = this.state.editText.trim();
if (val) {
this.props.onSave(val);
Expand All @@ -31,7 +31,7 @@ class TodoItem extends Component {
this.setState({ editText: this.props.todo.title });
this.props.onCancel(event);
} else if (event.which === ENTER_KEY) {
this.handleSubmit(event);
this.handleSubmit();
}
}

Expand Down Expand Up @@ -82,12 +82,12 @@ class TodoItem extends Component {
className="toggle"
type="checkbox"
checked={this.props.todo.completed}
onChange={(event)=> this.props.onToggle(event)}
onChange={() => this.props.onToggle()}
/>
<label onDoubleClick={() => this.handleEdit()}>
{this.props.todo.title}
</label>
<button className="destroy" onClick={this.props.onDestroy} />
<button className="destroy" onClick={() => this.props.onDestroy()} />
</div>
<input
ref="editField"
Expand Down
10 changes: 5 additions & 5 deletions examples/react/src/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import TodoModel from './todoModel'
import TodoModel from './todoModel';
import 'todomvc-app-css/index.css';

const model = new TodoModel('react-todos');

function render() {
ReactDOM.render(
<App model={model}/>,
document.getElementsByClassName('todoapp')[0]
);
ReactDOM.render(
<App model={model} />,
document.getElementsByClassName('todoapp')[0]
);
}

model.subscribe(render);
Expand Down
17 changes: 15 additions & 2 deletions examples/react/src/todoModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,44 +11,55 @@ class TodoModel {
this.todos = Utils.store(key);
this.onChanges = [];
}

subscribe(onChange) {
this.onChanges.push(onChange);
}

inform() {
Utils.store(this.key, this.todos);
this.onChanges.forEach((cb) => cb())
this.onChanges.forEach((cb) => cb());
}

addTodo(title) {
this.todos = this.todos.concat({
id: Utils.uuid(),
title: title,
completed: false
});

this.inform();
}

toggleAll(checked) {
// 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() and filter() everywhere instead of mutating the array or
// todo items themselves.
this.todos = this.todos.map((todo) =>
Utils.extend({}, todo, { completed: checked })
)
);

this.inform();
}

toggle(todoToToggle) {
this.todos = this.todos.map(
(todo) =>
todo !== todoToToggle
? todo
: Utils.extend({}, todo, { completed: !todo.completed })
);

this.inform();
}

destroy(todo) {
this.todos = this.todos.filter((candidate) => candidate !== todo);

this.inform();
}

save(todoToSave, text) {
this.todos = this.todos.map(
(todo) =>
Expand All @@ -57,8 +68,10 @@ class TodoModel {

this.inform();
}

clearCompleted() {
this.todos = this.todos.filter((todo) => !todo.completed);

this.inform();
}
}
Expand Down
33 changes: 17 additions & 16 deletions examples/react/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,41 @@ export const COMPLETED_TODOS = 'completed';
export default {
uuid() {
/*jshint bitwise:false */
var i, random;
var uuid = '';
let i, random;
let uuid = '';

for (i = 0; i < 32; i++) {
random = Math.random() * 16 | 0;
random = (Math.random() * 16) | 0;
if (i === 8 || i === 12 || i === 16 || i === 20) {
uuid += '-';
}
// eslint-disable-next-line
uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random))
.toString(16);
uuid += (i === 12 ? 4 : i === 16 ? (random & 3) | 8 : random).toString(
16
);
}

return uuid;
},

pluralize (count, word) {
pluralize(count, word) {
return count === 1 ? word : word + 's';
},

store (namespace, data) {
if (data) {
store(namespace, data = undefined) {
if (data === undefined) {
const store = localStorage.getItem(namespace);
return store === null ? [] : JSON.parse(store);
} else {
return localStorage.setItem(namespace, JSON.stringify(data));
}

var store = localStorage.getItem(namespace);
return (store && JSON.parse(store)) || [];
},

extend () {
var newObj = {};
for (var i = 0; i < arguments.length; i++) {
var obj = arguments[i];
for (var key in obj) {
extend() {
let newObj = {};
for (let i = 0; i < arguments.length; i++) {
const obj = arguments[i];
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
Expand Down