summaryrefslogtreecommitdiffstats
path: root/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js')
-rw-r--r--third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/app.jsx207
-rw-r--r--third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/footer.jsx58
-rw-r--r--third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/todoItem.jsx93
-rw-r--r--third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/utils.jsx49
4 files changed, 407 insertions, 0 deletions
diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/app.jsx b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/app.jsx
new file mode 100644
index 0000000000..1e1e2a3e12
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/app.jsx
@@ -0,0 +1,207 @@
+/**
+ * @jsx React.DOM
+ */
+/*jshint quotmark:false */
+/*jshint white:false */
+/*jshint trailing:false */
+/*jshint newcap:false */
+/*global Utils, ALL_TODOS, ACTIVE_TODOS, COMPLETED_TODOS,
+ TodoItem, TodoFooter, React, Router*/
+
+(function (window, React) {
+ 'use strict';
+
+ window.ALL_TODOS = 'all';
+ window.ACTIVE_TODOS = 'active';
+ window.COMPLETED_TODOS = 'completed';
+
+ var ENTER_KEY = 13;
+
+ var TodoApp = React.createClass({
+ getInitialState: function () {
+ var todos = Utils.store('react-todos');
+ return {
+ todos: todos,
+ nowShowing: ALL_TODOS,
+ editing: null
+ };
+ },
+
+ componentDidMount: function () {
+ var router = Router({
+ '/': this.setState.bind(this, {nowShowing: ALL_TODOS}),
+ '/active': this.setState.bind(this, {nowShowing: ACTIVE_TODOS}),
+ '/completed': this.setState.bind(this, {nowShowing: COMPLETED_TODOS})
+ });
+ router.init();
+ this.refs.newField.getDOMNode().focus();
+ },
+
+ handleNewTodoKeyDown: function (event) {
+ if (event.which !== ENTER_KEY) {
+ return;
+ }
+
+ var val = this.refs.newField.getDOMNode().value.trim();
+ var todos;
+ var newTodo;
+
+ if (val) {
+ todos = this.state.todos;
+ newTodo = {
+ id: Utils.uuid(),
+ title: val,
+ completed: false
+ };
+ this.setState({todos: todos.concat([newTodo])});
+ this.refs.newField.getDOMNode().value = '';
+ }
+
+ return false;
+ },
+
+ toggleAll: function (event) {
+ var checked = event.target.checked;
+
+ this.state.todos.forEach(function (todo) {
+ todo.completed = checked;
+ });
+
+ this.setState({todos: this.state.todos});
+ },
+
+ toggle: function (todo) {
+ todo.completed = !todo.completed;
+ this.setState({todos: this.state.todos});
+ },
+
+ destroy: function (todo) {
+ var newTodos = this.state.todos.filter(function (candidate) {
+ return candidate.id !== todo.id;
+ });
+
+ this.setState({todos: newTodos});
+ },
+
+ edit: function (todo, callback) {
+ // refer to todoItem.js `handleEdit` for the reasoning behind the
+ // callback
+ this.setState({editing: todo.id}, function () {
+ callback();
+ });
+ },
+
+ save: function (todo, text) {
+ todo.title = text;
+ this.setState({todos: this.state.todos, editing: null});
+ },
+
+ cancel: function () {
+ this.setState({editing: null});
+ },
+
+ clearCompleted: function () {
+ var newTodos = this.state.todos.filter(function (todo) {
+ return !todo.completed;
+ });
+
+ this.setState({todos: newTodos});
+ },
+
+ componentDidUpdate: function () {
+ Utils.store('react-todos', this.state.todos);
+ },
+
+ render: function () {
+ var footer = null;
+ var main = null;
+ var todoItems = {};
+ var activeTodoCount;
+ var completedCount;
+
+ var shownTodos = this.state.todos.filter(function (todo) {
+ switch (this.state.nowShowing) {
+ case ACTIVE_TODOS:
+ return !todo.completed;
+ case COMPLETED_TODOS:
+ return todo.completed;
+ default:
+ return true;
+ }
+ }.bind(this));
+
+ shownTodos.forEach(function (todo) {
+ todoItems[todo.id] = (
+ <TodoItem
+ 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={this.cancel}
+ />
+ );
+ }.bind(this));
+
+ activeTodoCount = this.state.todos.filter(function (todo) {
+ return !todo.completed;
+ }).length;
+
+ completedCount = this.state.todos.length - activeTodoCount;
+
+ if (activeTodoCount || completedCount) {
+ footer =
+ <TodoFooter
+ count={activeTodoCount}
+ completedCount={completedCount}
+ nowShowing={this.state.nowShowing}
+ onClearCompleted={this.clearCompleted}
+ />;
+ }
+
+ if (this.state.todos.length) {
+ main = (
+ <section id="main">
+ <input
+ id="toggle-all"
+ type="checkbox"
+ onChange={this.toggleAll}
+ checked={activeTodoCount === 0}
+ />
+ <ul id="todo-list">
+ {todoItems}
+ </ul>
+ </section>
+ );
+ }
+
+ return (
+ <div>
+ <header id="header">
+ <h1>todos</h1>
+ <input
+ ref="newField"
+ id="new-todo"
+ placeholder="What needs to be done?"
+ onKeyDown={this.handleNewTodoKeyDown}
+ />
+ </header>
+ {main}
+ {footer}
+ </div>
+ );
+ }
+ });
+
+ React.renderComponent(<TodoApp />, document.getElementById('todoapp'));
+ React.renderComponent(
+ <div>
+ <p>Double-click to edit a todo</p>
+ <p>Created by{' '}
+ <a href="http://github.com/petehunt/">petehunt</a>
+ </p>
+ <p>Part of{' '}<a href="http://todomvc.com">TodoMVC</a></p>
+ </div>,
+ document.getElementById('info'));
+})(window, React);
diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/footer.jsx b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/footer.jsx
new file mode 100644
index 0000000000..5a896553da
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/footer.jsx
@@ -0,0 +1,58 @@
+/**
+ * @jsx React.DOM
+ */
+/*jshint quotmark:false */
+/*jshint white:false */
+/*jshint trailing:false */
+/*jshint newcap:false */
+/*global React, ALL_TODOS, ACTIVE_TODOS, Utils, COMPLETED_TODOS */
+(function (window) {
+ 'use strict';
+
+ window.TodoFooter = React.createClass({
+ render: function () {
+ var activeTodoWord = Utils.pluralize(this.props.count, 'item');
+ var clearButton = null;
+
+ if (this.props.completedCount > 0) {
+ clearButton = (
+ <button
+ id="clear-completed"
+ onClick={this.props.onClearCompleted}>
+ {''}Clear completed ({this.props.completedCount}){''}
+ </button>
+ );
+ }
+
+ var show = {
+ ALL_TODOS: '',
+ ACTIVE_TODOS: '',
+ COMPLETED_TODOS: ''
+ };
+ show[this.props.nowShowing] = 'selected';
+
+ return (
+ <footer id="footer">
+ <span id="todo-count">
+ <strong>{this.props.count}</strong>
+ {' '}{activeTodoWord}{' '}left{''}
+ </span>
+ <ul id="filters">
+ <li>
+ <a href="#/" class={show[ALL_TODOS]}>All</a>
+ </li>
+ {' '}
+ <li>
+ <a href="#/active" class={show[ACTIVE_TODOS]}>Active</a>
+ </li>
+ {' '}
+ <li>
+ <a href="#/completed" class={show[COMPLETED_TODOS]}>Completed</a>
+ </li>
+ </ul>
+ {clearButton}
+ </footer>
+ );
+ }
+ });
+})(window);
diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/todoItem.jsx b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/todoItem.jsx
new file mode 100644
index 0000000000..87f6c1c6b3
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/todoItem.jsx
@@ -0,0 +1,93 @@
+/**
+ * @jsx React.DOM
+ */
+/*jshint quotmark: false */
+/*jshint white: false */
+/*jshint trailing: false */
+/*jshint newcap: false */
+/*global React, Utils */
+(function (window) {
+ 'use strict';
+
+ var ESCAPE_KEY = 27;
+ var ENTER_KEY = 13;
+
+ window.TodoItem = React.createClass({
+ handleSubmit: function () {
+ var val = this.state.editText.trim();
+ if (val) {
+ this.props.onSave(val);
+ this.setState({editText: val});
+ } else {
+ this.props.onDestroy();
+ }
+ return false;
+ },
+ handleEdit: function () {
+ // react optimizes renders by batching them. This means you can't call
+ // parent's `onEdit` (which in this case triggeres a re-render), and
+ // immediately manipulate the DOM as if the rendering's over. Put it as a
+ // callback. Refer to app.js' `edit` method
+ this.props.onEdit(function () {
+ var node = this.refs.editField.getDOMNode();
+ node.focus();
+ node.setSelectionRange(node.value.length, node.value.length);
+ }.bind(this));
+ },
+
+ handleKeyDown: function (event) {
+ if (event.keyCode === ESCAPE_KEY) {
+ this.setState({editText: this.props.todo.title});
+ this.props.onCancel();
+ } else if (event.keyCode === ENTER_KEY) {
+ this.handleSubmit();
+ } else {
+ this.setState({editText: event.target.value});
+ }
+ },
+
+ handleChange: function (event) {
+ this.setState({editText: event.target.value});
+ },
+
+ getInitialState: function () {
+ return {editText: this.props.todo.title};
+ },
+
+ componentWillReceiveProps: function (nextProps) {
+ if (nextProps.todo.title !== this.props.todo.title) {
+ this.setState(this.getInitialState());
+ }
+ },
+
+ render: function () {
+ return (
+ <li class={Utils.stringifyObjKeys({
+ completed: this.props.todo.completed,
+ editing: this.props.editing
+ })}>
+ <div class="view">
+ <input
+ class="toggle"
+ type="checkbox"
+ checked={this.props.todo.completed ? 'checked' : null}
+ onChange={this.props.onToggle}
+ />
+ <label onDoubleClick={this.handleEdit}>
+ {this.props.todo.title}
+ </label>
+ <button class='destroy' onClick={this.props.onDestroy} />
+ </div>
+ <input
+ ref="editField"
+ class="edit"
+ value={this.state.editText}
+ onBlur={this.handleSubmit}
+ onChange={this.handleChange}
+ onKeyDown={this.handleKeyDown}
+ />
+ </li>
+ );
+ }
+ });
+})(window);
diff --git a/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/utils.jsx b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/utils.jsx
new file mode 100644
index 0000000000..3ce698563a
--- /dev/null
+++ b/third_party/webkit/PerformanceTests/Speedometer/resources/todomvc/labs/architecture-examples/react/js/utils.jsx
@@ -0,0 +1,49 @@
+(function (window) {
+ 'use strict';
+
+ window.Utils = {
+ uuid: function () {
+ /*jshint bitwise:false */
+ var i, random;
+ var uuid = '';
+
+ for (i = 0; i < 32; i++) {
+ random = Math.random() * 16 | 0;
+ if (i === 8 || i === 12 || i === 16 || i === 20) {
+ uuid += '-';
+ }
+ uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random))
+ .toString(16);
+ }
+
+ return uuid;
+ },
+
+ pluralize: function (count, word) {
+ return count === 1 ? word : word + 's';
+ },
+
+ store: function (namespace, data) {
+ if (data) {
+ return localStorage.setItem(namespace, JSON.stringify(data));
+ }
+
+ var store = localStorage.getItem(namespace);
+ return (store && JSON.parse(store)) || [];
+ },
+
+ stringifyObjKeys: function (obj) {
+ var s = '';
+ var key;
+
+ for (key in obj) {
+ if (obj.hasOwnProperty(key) && obj[key]) {
+ s += key + ' ';
+ }
+ }
+
+ return s.trim();
+ }
+ };
+
+})(window);