mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Merge pull request #307 from chenglou/todomvc-director
sync with tastejs todomvc
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
# TodoMVC-director
|
||||
|
||||
This is the exact copy of the React-powered [TodoMVC](http://todomvc.com/labs/architecture-examples/react/). To test it, use [bower](http://bower.io) to fetch the dependencies:
|
||||
|
||||
`bower install`
|
||||
|
||||
Then fire up a server here:
|
||||
|
||||
`python -m SimpleHTTPServer`
|
||||
|
||||
And go visit `localhost:8000`.
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "todomvc-react",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"todomvc-common": "~0.1.7",
|
||||
"react": "~0.4.0",
|
||||
"director": "~1.2.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<!doctype html>
|
||||
<html lang="en" data-framework="react">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>React • TodoMVC</title>
|
||||
<link rel="stylesheet" href="bower_components/todomvc-common/base.css">
|
||||
</head>
|
||||
<body>
|
||||
<section id="todoapp"></section>
|
||||
<footer id="info"></footer>
|
||||
<div id="benchmark"></div>
|
||||
|
||||
<script src="bower_components/todomvc-common/base.js"></script>
|
||||
<script src="bower_components/react/react.js"></script>
|
||||
<script src="bower_components/react/JSXTransformer.js"></script>
|
||||
<script src="bower_components/director/build/director.min.js"></script>
|
||||
|
||||
<script type="text/jsx" src="js/utils.jsx"></script>
|
||||
<script type="text/jsx" src="js/todoItem.jsx"></script>
|
||||
<script type="text/jsx" src="js/footer.jsx"></script>
|
||||
<script type="text/jsx" src="js/app.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -1,425 +0,0 @@
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background: none;
|
||||
font-size: 100%;
|
||||
vertical-align: baseline;
|
||||
font-family: inherit;
|
||||
color: inherit;
|
||||
-webkit-appearance: none;
|
||||
/*-moz-appearance: none;*/
|
||||
-ms-appearance: none;
|
||||
-o-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
body {
|
||||
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
line-height: 1.4em;
|
||||
background: #eaeaea url('bg.png');
|
||||
color: #4d4d4d;
|
||||
width: 550px;
|
||||
margin: 0 auto;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-font-smoothing: antialiased;
|
||||
-ms-font-smoothing: antialiased;
|
||||
-o-font-smoothing: antialiased;
|
||||
font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.todoapp {
|
||||
background: #fff;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
margin: 130px 0 40px 0;
|
||||
border: 1px solid #ccc;
|
||||
position: relative;
|
||||
border-top-left-radius: 2px;
|
||||
border-top-right-radius: 2px;
|
||||
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
|
||||
0 25px 50px 0 rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.todoapp:before {
|
||||
content: '';
|
||||
border-left: 1px solid #f5d6d6;
|
||||
border-right: 1px solid #f5d6d6;
|
||||
width: 2px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 40px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.todoapp input::-webkit-input-placeholder {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.todoapp input:-moz-placeholder {
|
||||
font-style: italic;
|
||||
color: #a9a9a9;
|
||||
}
|
||||
|
||||
.todoapp h1 {
|
||||
position: absolute;
|
||||
top: -120px;
|
||||
width: 100%;
|
||||
font-size: 70px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
color: #b3b3b3;
|
||||
color: rgba(255, 255, 255, 0.3);
|
||||
text-shadow: -1px -1px rgba(0, 0, 0, 0.2);
|
||||
-webkit-text-rendering: optimizeLegibility;
|
||||
-moz-text-rendering: optimizeLegibility;
|
||||
-ms-text-rendering: optimizeLegibility;
|
||||
-o-text-rendering: optimizeLegibility;
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
.header {
|
||||
padding-top: 15px;
|
||||
border-radius: inherit;
|
||||
}
|
||||
|
||||
.header:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
height: 15px;
|
||||
z-index: 2;
|
||||
border-bottom: 1px solid #6c615c;
|
||||
background: #8d7d77;
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8)));
|
||||
background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
|
||||
background: -moz-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
|
||||
background: -o-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
|
||||
background: -ms-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
|
||||
background: linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101, 84, 76, 0.8));
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,StartColorStr='#9d8b83', EndColorStr='#847670');
|
||||
border-top-left-radius: 1px;
|
||||
border-top-right-radius: 1px;
|
||||
}
|
||||
|
||||
.new-todo,
|
||||
.edit {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
font-size: 24px;
|
||||
font-family: inherit;
|
||||
line-height: 1.4em;
|
||||
border: 0;
|
||||
outline: none;
|
||||
color: inherit;
|
||||
padding: 6px;
|
||||
border: 1px solid #999;
|
||||
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
-ms-box-sizing: border-box;
|
||||
-o-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-font-smoothing: antialiased;
|
||||
-ms-font-smoothing: antialiased;
|
||||
-o-font-smoothing: antialiased;
|
||||
font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.new-todo {
|
||||
padding: 16px 16px 16px 60px;
|
||||
border: none;
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
z-index: 2;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.main {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
border-top: 1px dotted #adadad;
|
||||
}
|
||||
|
||||
.toggle-all-label {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.toggle-all {
|
||||
position: absolute;
|
||||
top: -42px;
|
||||
left: -4px;
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
border: none; /* Mobile Safari */
|
||||
}
|
||||
|
||||
.toggle-all:before {
|
||||
content: '»';
|
||||
font-size: 28px;
|
||||
color: #d9d9d9;
|
||||
padding: 0 25px 7px;
|
||||
}
|
||||
|
||||
.toggle-all:checked:before {
|
||||
color: #737373;
|
||||
}
|
||||
|
||||
.todo-list {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.todo-list li {
|
||||
position: relative;
|
||||
font-size: 24px;
|
||||
border-bottom: 1px dotted #ccc;
|
||||
}
|
||||
|
||||
.todo-list li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.todo-list li.editing {
|
||||
border-bottom: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.todo-list li.editing .edit {
|
||||
display: block;
|
||||
width: 506px;
|
||||
padding: 13px 17px 12px 17px;
|
||||
margin: 0 0 0 43px;
|
||||
}
|
||||
|
||||
.todo-list li.editing .view {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.todo-list li .toggle {
|
||||
text-align: center;
|
||||
width: 40px;
|
||||
/* auto, since non-WebKit browsers doesn't support input styling */
|
||||
height: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto 0;
|
||||
border: none; /* Mobile Safari */
|
||||
-webkit-appearance: none;
|
||||
/*-moz-appearance: none;*/
|
||||
-ms-appearance: none;
|
||||
-o-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
.todo-list li .toggle:after {
|
||||
content: '✔';
|
||||
line-height: 43px; /* 40 + a couple of pixels visual adjustment */
|
||||
font-size: 20px;
|
||||
color: #d9d9d9;
|
||||
text-shadow: 0 -1px 0 #bfbfbf;
|
||||
}
|
||||
|
||||
.todo-list li .toggle:checked:after {
|
||||
color: #85ada7;
|
||||
text-shadow: 0 1px 0 #669991;
|
||||
bottom: 1px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.todo-list li label {
|
||||
word-break: break-word;
|
||||
padding: 15px;
|
||||
margin-left: 45px;
|
||||
display: block;
|
||||
line-height: 1.2;
|
||||
-webkit-transition: color 0.4s;
|
||||
-moz-transition: color 0.4s;
|
||||
-ms-transition: color 0.4s;
|
||||
-o-transition: color 0.4s;
|
||||
transition: color 0.4s;
|
||||
}
|
||||
|
||||
.todo-list li.completed label {
|
||||
color: #a9a9a9;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.todo-list li .destroy {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 10px;
|
||||
bottom: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: auto 0;
|
||||
font-size: 22px;
|
||||
color: #a88a8a;
|
||||
-webkit-transition: all 0.2s;
|
||||
-moz-transition: all 0.2s;
|
||||
-ms-transition: all 0.2s;
|
||||
-o-transition: all 0.2s;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.todo-list li .destroy:hover {
|
||||
text-shadow: 0 0 1px #000,
|
||||
0 0 10px rgba(199, 107, 107, 0.8);
|
||||
-webkit-transform: scale(1.3);
|
||||
-moz-transform: scale(1.3);
|
||||
-ms-transform: scale(1.3);
|
||||
-o-transform: scale(1.3);
|
||||
transform: scale(1.3);
|
||||
}
|
||||
|
||||
.todo-list li .destroy:after {
|
||||
content: '✖';
|
||||
}
|
||||
|
||||
.todo-list li:hover .destroy {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.todo-list li .edit {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.todo-list li.editing:last-child {
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
color: #777;
|
||||
padding: 0 15px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: -31px;
|
||||
left: 0;
|
||||
height: 20px;
|
||||
z-index: 1;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.footer:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 31px;
|
||||
left: 0;
|
||||
height: 50px;
|
||||
z-index: -1;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.3),
|
||||
0 6px 0 -3px rgba(255, 255, 255, 0.8),
|
||||
0 7px 1px -3px rgba(0, 0, 0, 0.3),
|
||||
0 43px 0 -6px rgba(255, 255, 255, 0.8),
|
||||
0 44px 2px -6px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.todo-count {
|
||||
float: left;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.filters {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.filters li {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.filters li a {
|
||||
color: #83756f;
|
||||
margin: 2px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.filters li a.selected {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.clear-completed {
|
||||
float: right;
|
||||
position: relative;
|
||||
line-height: 20px;
|
||||
text-decoration: none;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
font-size: 11px;
|
||||
padding: 0 10px;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.clear-completed:hover {
|
||||
background: rgba(0, 0, 0, 0.15);
|
||||
box-shadow: 0 -1px 0 0 rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.info {
|
||||
margin: 65px auto 0;
|
||||
color: #a6a6a6;
|
||||
font-size: 12px;
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.7);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.info a {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/*
|
||||
Hack to remove background from Mobile Safari.
|
||||
Can't use it globally since it destroys checkboxes in Firefox and Opera
|
||||
*/
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
.toggle-all,
|
||||
.todo-list li .toggle {
|
||||
background: none;
|
||||
}
|
||||
|
||||
.todo-list li .toggle {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.toggle-all {
|
||||
top: -56px;
|
||||
left: -15px;
|
||||
width: 65px;
|
||||
height: 41px;
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
}
|
||||
|
||||
.hidden{
|
||||
display:none;
|
||||
}
|
||||
|
||||
#benchmark {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.submitButton {
|
||||
display: none;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.1 KiB |
@@ -1,19 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<title>React • TodoMVC</title>
|
||||
<link rel="stylesheet" href="css/base.css">
|
||||
<!--[if IE]>
|
||||
<script src="js/ie.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="todoapp"></div>
|
||||
<div id="benchmark"></div>
|
||||
<script src="../../build/react.js"></script>
|
||||
<script src="../../build/JSXTransformer.js"></script>
|
||||
<script type="text/jsx" src="js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,255 +0,0 @@
|
||||
/**
|
||||
* @jsx React.DOM
|
||||
*/
|
||||
|
||||
var Utils = {
|
||||
// https://gist.github.com/1308368
|
||||
uuid: function(a,b){for(b=a='';a++<36;b+=a*51&52?(a^15?8^Math.random()*(a^20?16:4):4).toString(16):'-');return b},
|
||||
pluralize: function( count, word ) {
|
||||
return count === 1 ? word : word + 's';
|
||||
},
|
||||
store: function( namespace, data ) {
|
||||
if ( arguments.length > 1 ) {
|
||||
return localStorage.setItem( namespace, JSON.stringify( data ) );
|
||||
} else {
|
||||
var store = localStorage.getItem( namespace );
|
||||
return ( store && JSON.parse( store ) ) || [];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function cx(obj) {
|
||||
var s = '';
|
||||
for (var key in obj) {
|
||||
if (!obj.hasOwnProperty(key)) {
|
||||
continue;
|
||||
}
|
||||
if (obj[key]) {
|
||||
s += key + ' ';
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
var TodoItem = React.createClass({
|
||||
handleSubmit: function() {
|
||||
var val = this.state.editText;
|
||||
if (val) {
|
||||
this.props.onSave(val);
|
||||
this.setState({editField: ''});
|
||||
}
|
||||
return false;
|
||||
},
|
||||
handleEdit: function() {
|
||||
this.props.onEdit();
|
||||
this.refs.editField.getDOMNode().focus();
|
||||
},
|
||||
handleKey: function(event) {
|
||||
if (event.nativeEvent.keyCode === 27) {
|
||||
this.handleSubmit();
|
||||
}
|
||||
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={cx({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>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<input
|
||||
ref="editField"
|
||||
class="edit"
|
||||
value={this.state.editText}
|
||||
onBlur={this.handleSubmit}
|
||||
onKeyUp={this.handleKey}
|
||||
/>
|
||||
<input type="submit" class="submitButton" />
|
||||
</form>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var TodoFooter = React.createClass({
|
||||
render: function() {
|
||||
var activeTodoWord = Utils.pluralize(this.props.count, 'todo');
|
||||
var clearButton = null;
|
||||
|
||||
if (this.props.completedCount > 0) {
|
||||
clearButton = (
|
||||
<button class="clear-completed" onClick={this.props.onClearCompleted}>Clear completed ({this.props.completedCount})</button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<footer class="footer">
|
||||
<span class="todo-count"><strong>{this.props.count}</strong>{' '}{activeTodoWord}{' '}left</span>
|
||||
{clearButton}
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
var TodoApp = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
todos: Utils.store('react-todos'),
|
||||
editing: {}
|
||||
};
|
||||
},
|
||||
|
||||
handleSubmit: function() {
|
||||
var val = this.refs.newField.getDOMNode().value.trim();
|
||||
if (val) {
|
||||
var todos = this.state.todos;
|
||||
var 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.nativeEvent.target.checked;
|
||||
this.state.todos.map(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) {
|
||||
this.state.todos.map(function(todo) {
|
||||
this.state.editing[todo.id] = false;
|
||||
}.bind(this));
|
||||
this.state.editing[todo.id] = true;
|
||||
this.setState({editing: this.state.editing});
|
||||
},
|
||||
|
||||
save: function(todo, text) {
|
||||
todo.title = text;
|
||||
this.state.editing[todo.id] = false;
|
||||
this.setState({todos: this.state.todos, editing: this.state.editing});
|
||||
},
|
||||
|
||||
clearCompleted: function() {
|
||||
var newTodos = this.state.todos.filter(function(todo) {
|
||||
return !todo.completed;
|
||||
});
|
||||
this.setState({todos: newTodos});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
Utils.store('react-todos', this.state.todos);
|
||||
var footer = null;
|
||||
var main = null;
|
||||
var todoItems = this.state.todos.map(function(todo) {
|
||||
return (
|
||||
<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)}
|
||||
/>
|
||||
);
|
||||
}.bind(this));
|
||||
|
||||
var activeTodoCount = this.state.todos.filter(function(todo) {
|
||||
return !todo.completed;
|
||||
}).length;
|
||||
var completedCount = todoItems.length - activeTodoCount;
|
||||
if (activeTodoCount || completedCount) {
|
||||
footer =
|
||||
<TodoFooter
|
||||
count={activeTodoCount}
|
||||
completedCount={completedCount}
|
||||
onClearCompleted={this.clearCompleted.bind(this)}
|
||||
/>;
|
||||
}
|
||||
|
||||
if (todoItems.length) {
|
||||
main = (
|
||||
<section class="main">
|
||||
<input class="toggle-all" type="checkbox" onChange={this.toggleAll.bind(this)} />
|
||||
<label class="toggle-all-label">Mark all as complete</label>
|
||||
<ul class="todo-list">
|
||||
{todoItems}
|
||||
</ul>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<section class="todoapp">
|
||||
<header class="header">
|
||||
<h1>todos</h1>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<input
|
||||
ref="newField"
|
||||
class="new-todo"
|
||||
placeholder="What needs to be done?"
|
||||
autofocus="autofocus"
|
||||
/>
|
||||
<input type="submit" class="submitButton" />
|
||||
</form>
|
||||
</header>
|
||||
{main}
|
||||
{footer}
|
||||
</section>
|
||||
<footer class="info">
|
||||
<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>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
React.renderComponent(<TodoApp />, document.getElementById('todoapp'));
|
||||
|
||||
// Some benchmarking that requires either a custom build of React or more
|
||||
// modules exposed from React.*
|
||||
// var initTime = ReactMount.totalInstantiationTime + ReactMount.totalInjectionTime;
|
||||
// var benchmark = document.getElementById('benchmark');
|
||||
// setInterval(function() {
|
||||
// benchmark.innerHTML = (
|
||||
// 'Init render time = ' + initTime + 'ms' +
|
||||
// '<br />' +
|
||||
// 'Post-init render time = ' + (ReactMount.totalInstantiationTime + ReactMount.totalInjectionTime - initTime) + 'ms'
|
||||
// );
|
||||
// }, 1000);
|
||||
@@ -1,34 +0,0 @@
|
||||
/*! HTML5 Shiv pre3.6 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||
Uncompressed source: https://github.com/aFarkas/html5shiv */
|
||||
(function(l,f){function m(){var a=e.elements;return"string"==typeof a?a.split(" "):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();
|
||||
a.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+m().join().replace(/\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c("'+a+'")'})+");return n}")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement("p");d=d.getElementsByTagName("head")[0]||d.documentElement;c.innerHTML="x<style>article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}</style>";
|
||||
c=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o="_html5shiv",h=0,n={},g;(function(){try{var a=f.createElement("a");a.innerHTML="<xyz></xyz>";j="hidden"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement("a");var c=f.createDocumentFragment();b="undefined"==typeof c.cloneNode||
|
||||
"undefined"==typeof c.createDocumentFragment||"undefined"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:"default",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment();
|
||||
for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);
|
||||
|
||||
/* ES5-shim
|
||||
https://github.com/kriskowal/es5-shim
|
||||
Copyright 2009-2012 by contributors, MIT License */
|
||||
(function(definition){if(typeof define=="function")define(definition);else if(typeof YUI=="function")YUI.add("es5",definition);else definition()})(function(){if(!Function.prototype.bind)Function.prototype.bind=function bind(that){var target=this;if(typeof target!="function")throw new TypeError("Function.prototype.bind called on incompatible "+target);var args=slice.call(arguments,1);var bound=function(){if(this instanceof bound){var result=target.apply(this,args.concat(slice.call(arguments)));if(Object(result)===
|
||||
result)return result;return this}else return target.apply(that,args.concat(slice.call(arguments)))};if(target.prototype)bound.prototype=Object.create(target.prototype);return bound};var call=Function.prototype.call;var prototypeOfArray=Array.prototype;var prototypeOfObject=Object.prototype;var slice=prototypeOfArray.slice;var _toString=call.bind(prototypeOfObject.toString);var owns=call.bind(prototypeOfObject.hasOwnProperty);var defineGetter;var defineSetter;var lookupGetter;var lookupSetter;var supportsAccessors;
|
||||
if(supportsAccessors=owns(prototypeOfObject,"__defineGetter__")){defineGetter=call.bind(prototypeOfObject.__defineGetter__);defineSetter=call.bind(prototypeOfObject.__defineSetter__);lookupGetter=call.bind(prototypeOfObject.__lookupGetter__);lookupSetter=call.bind(prototypeOfObject.__lookupSetter__)}if([1,2].splice(0).length!=2){var array_splice=Array.prototype.splice;Array.prototype.splice=function(start,deleteCount){if(!arguments.length)return[];else return array_splice.apply(this,[start===void 0?
|
||||
0:start,deleteCount===void 0?this.length-start:deleteCount].concat(slice.call(arguments,2)))}}if(!Array.isArray)Array.isArray=function isArray(obj){return _toString(obj)=="[object Array]"};var boxedString=Object("a"),splitString=boxedString[0]!="a"||!(0 in boxedString);if(!Array.prototype.forEach)Array.prototype.forEach=function forEach(fun){var object=toObject(this),self=splitString&&_toString(this)=="[object String]"?this.split(""):object,thisp=arguments[1],i=-1,length=self.length>>>0;if(_toString(fun)!=
|
||||
"[object Function]")throw new TypeError;while(++i<length)if(i in self)fun.call(thisp,self[i],i,object)};if(!Array.prototype.map)Array.prototype.map=function map(fun){var object=toObject(this),self=splitString&&_toString(this)=="[object String]"?this.split(""):object,length=self.length>>>0,result=Array(length),thisp=arguments[1];if(_toString(fun)!="[object Function]")throw new TypeError(fun+" is not a function");for(var i=0;i<length;i++)if(i in self)result[i]=fun.call(thisp,self[i],i,object);return result};
|
||||
if(!Array.prototype.filter)Array.prototype.filter=function filter(fun){var object=toObject(this),self=splitString&&_toString(this)=="[object String]"?this.split(""):object,length=self.length>>>0,result=[],value,thisp=arguments[1];if(_toString(fun)!="[object Function]")throw new TypeError(fun+" is not a function");for(var i=0;i<length;i++)if(i in self){value=self[i];if(fun.call(thisp,value,i,object))result.push(value)}return result};if(!Array.prototype.every)Array.prototype.every=function every(fun){var object=
|
||||
toObject(this),self=splitString&&_toString(this)=="[object String]"?this.split(""):object,length=self.length>>>0,thisp=arguments[1];if(_toString(fun)!="[object Function]")throw new TypeError(fun+" is not a function");for(var i=0;i<length;i++)if(i in self&&!fun.call(thisp,self[i],i,object))return false;return true};if(!Array.prototype.some)Array.prototype.some=function some(fun){var object=toObject(this),self=splitString&&_toString(this)=="[object String]"?this.split(""):object,length=self.length>>>
|
||||
0,thisp=arguments[1];if(_toString(fun)!="[object Function]")throw new TypeError(fun+" is not a function");for(var i=0;i<length;i++)if(i in self&&fun.call(thisp,self[i],i,object))return true;return false};if(!Array.prototype.reduce)Array.prototype.reduce=function reduce(fun){var object=toObject(this),self=splitString&&_toString(this)=="[object String]"?this.split(""):object,length=self.length>>>0;if(_toString(fun)!="[object Function]")throw new TypeError(fun+" is not a function");if(!length&&arguments.length==
|
||||
1)throw new TypeError("reduce of empty array with no initial value");var i=0;var result;if(arguments.length>=2)result=arguments[1];else{do{if(i in self){result=self[i++];break}if(++i>=length)throw new TypeError("reduce of empty array with no initial value");}while(true)}for(;i<length;i++)if(i in self)result=fun.call(void 0,result,self[i],i,object);return result};if(!Array.prototype.reduceRight)Array.prototype.reduceRight=function reduceRight(fun){var object=toObject(this),self=splitString&&_toString(this)==
|
||||
"[object String]"?this.split(""):object,length=self.length>>>0;if(_toString(fun)!="[object Function]")throw new TypeError(fun+" is not a function");if(!length&&arguments.length==1)throw new TypeError("reduceRight of empty array with no initial value");var result,i=length-1;if(arguments.length>=2)result=arguments[1];else{do{if(i in self){result=self[i--];break}if(--i<0)throw new TypeError("reduceRight of empty array with no initial value");}while(true)}do if(i in this)result=fun.call(void 0,result,
|
||||
self[i],i,object);while(i--);return result};if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function indexOf(sought){var self=splitString&&_toString(this)=="[object String]"?this.split(""):toObject(this),length=self.length>>>0;if(!length)return-1;var i=0;if(arguments.length>1)i=toInteger(arguments[1]);i=i>=0?i:Math.max(0,length+i);for(;i<length;i++)if(i in self&&self[i]===sought)return i;return-1};if(!Array.prototype.lastIndexOf||[0,1].lastIndexOf(0,-3)!=-1)Array.prototype.lastIndexOf=
|
||||
function lastIndexOf(sought){var self=splitString&&_toString(this)=="[object String]"?this.split(""):toObject(this),length=self.length>>>0;if(!length)return-1;var i=length-1;if(arguments.length>1)i=Math.min(i,toInteger(arguments[1]));i=i>=0?i:length-Math.abs(i);for(;i>=0;i--)if(i in self&&sought===self[i])return i;return-1};if(!Object.keys){var hasDontEnumBug=true,dontEnums=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],dontEnumsLength=
|
||||
dontEnums.length;for(var key in{"toString":null})hasDontEnumBug=false;Object.keys=function keys(object){if(typeof object!="object"&&typeof object!="function"||object===null)throw new TypeError("Object.keys called on a non-object");var keys=[];for(var name in object)if(owns(object,name))keys.push(name);if(hasDontEnumBug)for(var i=0,ii=dontEnumsLength;i<ii;i++){var dontEnum=dontEnums[i];if(owns(object,dontEnum))keys.push(dontEnum)}return keys}}var negativeDate=-621987552E5,negativeYearString="-000001";
|
||||
if(!Date.prototype.toISOString||(new Date(negativeDate)).toISOString().indexOf(negativeYearString)===-1)Date.prototype.toISOString=function toISOString(){var result,length,value,year,month;if(!isFinite(this))throw new RangeError("Date.prototype.toISOString called on non-finite value.");year=this.getUTCFullYear();month=this.getUTCMonth();year+=Math.floor(month/12);month=(month%12+12)%12;result=[month+1,this.getUTCDate(),this.getUTCHours(),this.getUTCMinutes(),this.getUTCSeconds()];year=(year<0?"-":
|
||||
year>9999?"+":"")+("00000"+Math.abs(year)).slice(0<=year&&year<=9999?-4:-6);length=result.length;while(length--){value=result[length];if(value<10)result[length]="0"+value}return year+"-"+result.slice(0,2).join("-")+"T"+result.slice(2).join(":")+"."+("000"+this.getUTCMilliseconds()).slice(-3)+"Z"};var dateToJSONIsSupported=false;try{dateToJSONIsSupported=Date.prototype.toJSON&&(new Date(NaN)).toJSON()===null&&(new Date(negativeDate)).toJSON().indexOf(negativeYearString)!==-1&&Date.prototype.toJSON.call({toISOString:function(){return true}})}catch(e){}if(!dateToJSONIsSupported)Date.prototype.toJSON=
|
||||
function toJSON(key){var o=Object(this),tv=toPrimitive(o),toISO;if(typeof tv==="number"&&!isFinite(tv))return null;toISO=o.toISOString;if(typeof toISO!="function")throw new TypeError("toISOString property is not callable");return toISO.call(o)};if(!Date.parse||"Date.parse is buggy")Date=function(NativeDate){function Date(Y,M,D,h,m,s,ms){var length=arguments.length;if(this instanceof NativeDate){var date=length==1&&String(Y)===Y?new NativeDate(Date.parse(Y)):length>=7?new NativeDate(Y,M,D,h,m,s,ms):
|
||||
length>=6?new NativeDate(Y,M,D,h,m,s):length>=5?new NativeDate(Y,M,D,h,m):length>=4?new NativeDate(Y,M,D,h):length>=3?new NativeDate(Y,M,D):length>=2?new NativeDate(Y,M):length>=1?new NativeDate(Y):new NativeDate;date.constructor=Date;return date}return NativeDate.apply(this,arguments)}var isoDateExpression=new RegExp("^"+"(\\d{4}|[+-]\\d{6})"+"(?:-(\\d{2})"+"(?:-(\\d{2})"+"(?:"+"T(\\d{2})"+":(\\d{2})"+"(?:"+":(\\d{2})"+"(?:\\.(\\d{3}))?"+")?"+"("+"Z|"+"(?:"+"([-+])"+"(\\d{2})"+":(\\d{2})"+")"+")?)?)?)?"+
|
||||
"$");var months=[0,31,59,90,120,151,181,212,243,273,304,334,365];function dayFromMonth(year,month){var t=month>1?1:0;return months[month]+Math.floor((year-1969+t)/4)-Math.floor((year-1901+t)/100)+Math.floor((year-1601+t)/400)+365*(year-1970)}for(var key in NativeDate)Date[key]=NativeDate[key];Date.now=NativeDate.now;Date.UTC=NativeDate.UTC;Date.prototype=NativeDate.prototype;Date.prototype.constructor=Date;Date.parse=function parse(string){var match=isoDateExpression.exec(string);if(match){var year=
|
||||
Number(match[1]),month=Number(match[2]||1)-1,day=Number(match[3]||1)-1,hour=Number(match[4]||0),minute=Number(match[5]||0),second=Number(match[6]||0),millisecond=Number(match[7]||0),offset=!match[4]||match[8]?0:Number(new NativeDate(1970,0)),signOffset=match[9]==="-"?1:-1,hourOffset=Number(match[10]||0),minuteOffset=Number(match[11]||0),result;if(hour<(minute>0||second>0||millisecond>0?24:25)&&minute<60&&second<60&&millisecond<1E3&&month>-1&&month<12&&hourOffset<24&&minuteOffset<60&&day>-1&&day<dayFromMonth(year,
|
||||
month+1)-dayFromMonth(year,month)){result=((dayFromMonth(year,month)+day)*24+hour+hourOffset*signOffset)*60;result=((result+minute+minuteOffset*signOffset)*60+second)*1E3+millisecond+offset;if(-864E13<=result&&result<=864E13)return result}return NaN}return NativeDate.parse.apply(this,arguments)};return Date}(Date);if(!Date.now)Date.now=function now(){return(new Date).getTime()};if("0".split(void 0,0).length){var string_split=String.prototype.split;String.prototype.split=function(separator,limit){if(separator===
|
||||
void 0&&limit===0)return[];return string_split.apply(this,arguments)}}if("".substr&&"0b".substr(-1)!=="b"){var string_substr=String.prototype.substr;String.prototype.substr=function(start,length){return string_substr.call(this,start<0?(start=this.length+start)<0?0:start:start,length)}}var ws="\t\n\x0B\f\r \u00a0\u1680\u180e\u2000\u2001\u2002\u2003"+"\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028"+"\u2029\ufeff";if(!String.prototype.trim||ws.trim()){ws="["+ws+"]";var trimBeginRegexp=
|
||||
new RegExp("^"+ws+ws+"*"),trimEndRegexp=new RegExp(ws+ws+"*$");String.prototype.trim=function trim(){if(this===undefined||this===null)throw new TypeError("can't convert "+this+" to object");return String(this).replace(trimBeginRegexp,"").replace(trimEndRegexp,"")}}function toInteger(n){n=+n;if(n!==n)n=0;else if(n!==0&&n!==1/0&&n!==-(1/0))n=(n>0||-1)*Math.floor(Math.abs(n));return n}function isPrimitive(input){var type=typeof input;return input===null||type==="undefined"||type==="boolean"||type===
|
||||
"number"||type==="string"}function toPrimitive(input){var val,valueOf,toString;if(isPrimitive(input))return input;valueOf=input.valueOf;if(typeof valueOf==="function"){val=valueOf.call(input);if(isPrimitive(val))return val}toString=input.toString;if(typeof toString==="function"){val=toString.call(input);if(isPrimitive(val))return val}throw new TypeError;}var toObject=function(o){if(o==null)throw new TypeError("can't convert "+o+" to object");return Object(o)}});
|
||||
Reference in New Issue
Block a user