├── .gitignore
├── .jshintrc
├── LICENSE.md
├── NEWS.md
├── README.md
├── gulpfile.js
├── package.json
├── public
├── css
│ └── style.css
└── index.html
├── reactodo.png
├── src
├── Constants.js
├── Page.js
├── app.jsx
├── components
│ ├── Project.jsx
│ ├── Reactodo.jsx
│ ├── Settings.jsx
│ ├── TodoItem.jsx
│ ├── Welcome.jsx
│ └── reusable
│ │ └── EditInput.jsx
└── utils
│ ├── Base64.js
│ ├── classNames.js
│ ├── exportProject.js
│ ├── exportTextFile.js
│ ├── extend.js
│ ├── normaliseContentEditableHTML.js
│ ├── partial.js
│ ├── trim.js
│ └── uuid.js
└── vendor
├── react-0.11.2.js
└── react-0.11.2.min.js
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | dist/
3 | node_modules/
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "browser": true,
3 | "node": true,
4 | "jquery": true,
5 |
6 | "curly": true,
7 | "devel": true,
8 | "globals": {
9 | "React": true,
10 | "validator": true
11 | },
12 | "noempty": true,
13 | "newcap": false,
14 | "undef": true,
15 | "unused": "vars",
16 |
17 | "asi": true,
18 | "boss": true,
19 | "eqnull": true,
20 | "expr": true,
21 | "funcscope": true,
22 | "globalstrict": true,
23 | "laxbreak": true,
24 | "laxcomma": true,
25 | "sub": true
26 | }
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 | -----------
3 |
4 | Copyright (c) 2014, Jonathan Buchanan
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | this software and associated documentation files (the "Software"), to deal in
8 | the Software without restriction, including without limitation the rights to
9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | the Software, and to permit persons to whom the Software is furnished to do so,
11 | subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/NEWS.md:
--------------------------------------------------------------------------------
1 | 0.2.3 – 2014-11-27
2 | ------------------------
3 |
4 | * Upgraded to React 0.12.1.
5 |
6 | 0.2.2 – 2014-03-23
7 | ------------------------
8 |
9 | * Upgraded to React 0.10.0.
10 |
11 | 0.2.1 – 2014-02-21
12 | ------------------------
13 |
14 | * Upgraded to React 0.9.0.
15 |
16 | 0.2.0 – 2014-02-07
17 | ------------------------
18 |
19 | * **Backwards-incompatible change** – linebreaks are now stored as ` `
20 | rather than `\n` – long lines will now wrap.
21 |
22 | * Fixed: clicking to edit one project name then another no longer copies the
23 | former's name to the latter.
24 |
25 | * All HTML tags except the ` `s used for linebreaks are now stripped after
26 | editing a TODO. In browsers which insert a `
` or `
` when you press
27 | Enter in a `contentEditable`, these are normalised to `
` before saving.
28 |
29 | * Sessions can now be switched on the fly without reloading the page.
30 |
31 | * Added a quick session switching dropdown to the header, which activates when
32 | there are multiple sessions available.
33 |
34 | * Added exporting of projects as a `.todo.txt` file.
35 |
36 | * Added session management to the settings screen - add, rename and delete.
37 |
38 | * Session switcher `
` on the Welcome page now uses a `
` to
39 | suggest completions for existing session names from `localStorage`.
40 |
41 | * The active session name is now displayed in ``.
42 |
43 | 0.1.0 – 2014-01-28
44 | ------------------------
45 |
46 | * Initial release.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # reactodo
2 |
3 | Multiple localStorage TODO lists, built with [React](http://facebook.github.io/react)
4 |
5 | * http://insin.github.io/reactodo/
6 |
7 | Designed and styled after quick, disposable TODO tracking of the type commonly
8 | done in a programmer's text editor, but with a few interactive niceties to
9 | manage items instead of cut + paste.
10 |
11 | 
12 |
13 | ## Build
14 |
15 | Install dependencies:
16 |
17 | ```
18 | npm install
19 | ```
20 |
21 | Develop:
22 |
23 | ```
24 | npm run dev
25 | ```
26 |
27 | Production build:
28 |
29 | ```
30 | npm run dist
31 | ```
32 |
33 | ## MIT Licensed
34 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var path = require('path')
2 |
3 | var browserify = require('browserify')
4 | var del = require('del')
5 | var glob = require('glob')
6 | var gulp = require('gulp')
7 | var source = require('vinyl-source-stream')
8 |
9 | var concat = require('gulp-concat')
10 | var flatten = require('gulp-flatten')
11 | var jshint = require('gulp-jshint')
12 | var plumber = require('gulp-plumber')
13 | var react = require('gulp-react')
14 | var rename = require('gulp-rename')
15 | var streamify = require('gulp-streamify')
16 | var template = require('gulp-template')
17 | var uglify = require('gulp-uglify')
18 | var gutil = require('gulp-util')
19 |
20 | process.env.NODE_ENV = gutil.env.production ? 'production' : 'development'
21 |
22 | var version = require('./package.json').version
23 | var jsSrc = ['./src/**/*.js', './src/**/*.jsx']
24 | var jsExt = (gutil.env.production ? 'min.js' : 'js')
25 |
26 | gulp.task('clean', function(cb) {
27 | del(['./build/**/*', './dist/**/*'], cb)
28 | })
29 |
30 | gulp.task('transpile-js', function() {
31 | return gulp.src(jsSrc)
32 | .pipe(plumber())
33 | .pipe(react({
34 | harmony: true
35 | }))
36 | .pipe(flatten())
37 | .pipe(gulp.dest('./build/modules'))
38 | })
39 |
40 | gulp.task('lint', ['transpile-js'], function() {
41 | return gulp.src('./build/modules/*.js')
42 | .pipe(jshint('./.jshintrc'))
43 | .pipe(jshint.reporter('jshint-stylish'))
44 | })
45 |
46 | gulp.task('bundle-js', ['lint'], function() {
47 | var b = browserify('./build/modules/app.js', {
48 | debug: !gutil.env.production
49 | , detectGlobals: false
50 | })
51 | b.external('react')
52 |
53 | // Expose each module as a bare require, because
54 | glob.sync('./build/modules/*.js').forEach(function(module) {
55 | var expose = module.split('/').pop().split('.').shift()
56 | if (expose != 'app') {
57 | b.require(module, {expose: expose})
58 | }
59 | })
60 |
61 | var stream = b.bundle()
62 | .pipe(source('app.js'))
63 | .pipe(gulp.dest('./build'))
64 |
65 | if (gutil.env.production) {
66 | stream = stream
67 | .pipe(rename('app.min.js'))
68 | .pipe(streamify(uglify()))
69 | .pipe(gulp.dest('./build'))
70 | }
71 |
72 | return stream
73 | })
74 |
75 | gulp.task('bundle-deps', function() {
76 | var b = browserify({detectGlobals: false})
77 | b.require('react')
78 | b.transform('envify')
79 |
80 | var stream = b.bundle()
81 | .pipe(source('deps.js'))
82 | .pipe(gulp.dest('./build'))
83 |
84 | if (gutil.env.production) {
85 | stream = stream.pipe(rename('deps.min.js'))
86 | .pipe(streamify(uglify()))
87 | .pipe(gulp.dest('./build'))
88 | }
89 |
90 | return stream
91 | })
92 |
93 | gulp.task('dist-js', ['bundle-js'], function() {
94 | return gulp.src('./build/app.' + jsExt)
95 | .pipe(gulp.dest('./dist/js'))
96 | })
97 |
98 | gulp.task('dist-deps', ['bundle-deps'], function() {
99 | return gulp.src('./build/deps.' + jsExt)
100 | .pipe(gulp.dest('./dist/js'))
101 | })
102 |
103 | gulp.task('dist-css', function() {
104 | return gulp.src('./public/css/*.css')
105 | .pipe(gulp.dest('./dist/css'))
106 | })
107 |
108 | gulp.task('dist-html', function() {
109 | return gulp.src('./public/index.html')
110 | .pipe(template({
111 | version: version
112 | , jsExt: jsExt
113 | }))
114 | .pipe(gulp.dest('./dist'))
115 | })
116 |
117 | gulp.task('dist', ['dist-js', 'dist-deps', 'dist-css', 'dist-html'])
118 |
119 | gulp.task('watch', function() {
120 | gulp.watch(jsSrc, ['dist-js'])
121 | gulp.watch('./public/css/*.css', ['dist-css'])
122 | gulp.watch('./public/index.html', ['dist-html'])
123 | })
124 |
125 | gulp.task('default', ['dist', 'watch'])
126 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "reactodo",
3 | "version": "0.2.4",
4 | "description": "Multiple localStorage TODO lists, built with React",
5 | "scripts": {
6 | "dev": "gulp clean && gulp",
7 | "dist": "gulp clean && gulp dist --production"
8 | },
9 | "dependencies": {
10 | "react": "~0.12.2"
11 | },
12 | "devDependencies": {
13 | "browserify": "^8.1.3",
14 | "del": "^1.1.1",
15 | "envify": "^3.2.0",
16 | "glob": "^4.3.5",
17 | "gulp": "^3.8.10",
18 | "gulp-concat": "^2.4.3",
19 | "gulp-flatten": "0.0.4",
20 | "gulp-jshint": "^1.9.2",
21 | "gulp-plumber": "^0.6.6",
22 | "gulp-react": "^2.0.0",
23 | "gulp-rename": "^1.2.0",
24 | "gulp-streamify": "0.0.5",
25 | "gulp-template": "^2.1.0",
26 | "gulp-uglify": "^1.1.0",
27 | "gulp-util": "^3.0.3",
28 | "jshint-stylish": "^1.0.0",
29 | "vinyl-source-stream": "^1.0.0"
30 | },
31 | "author": "Jonathan Buchanan ",
32 | "repository": {
33 | "type": "git",
34 | "url": "http://github.com/insin/reactodo.git"
35 | },
36 | "license": "MIT"
37 | }
38 |
--------------------------------------------------------------------------------
/public/css/style.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 1em 2em;
3 | margin: 0;
4 | background-color: #272822;
5 | color: #f8f8f2;
6 | font-family: consolas, monospace;
7 | font-size: 16px;
8 | }
9 |
10 | a {
11 | color: #f8f8f2;
12 | }
13 |
14 | h1 {
15 | margin: 0 0 16px 0;
16 | }
17 |
18 | h1 small {
19 | color: #5b5c56;
20 | font-size: 24px;
21 | }
22 |
23 | h2 {
24 | margin: 8px 0;
25 | font-size: 1em;
26 | }
27 |
28 | h2:first-child {
29 | margin-top: 0;
30 | }
31 |
32 | h2:last-child {
33 | margin-bottom: 0;
34 | }
35 |
36 | td, th {
37 | padding: 5px 10px;
38 | text-align: left;
39 | }
40 |
41 | input[type=text] {
42 | background-color: #272822;
43 | color: #f8f8f2;
44 | border: none;
45 | border-bottom: 1px solid #5b5c56;
46 | font-family: consolas, monospace;
47 | font-size: 16px;
48 | }
49 |
50 | .footer {
51 | font-size: small;
52 | text-align: center;
53 | color: #5b5c56;
54 | }
55 |
56 | .footer a {
57 | color: #5b5c56;
58 | }
59 |
60 | .button {
61 | background-color: #49483e;
62 | color: #f8f8f2;
63 | border-radius: 9px;
64 | cursor: pointer;
65 | padding: 2px 8px;
66 | font-weight: normal;
67 | }
68 |
69 | .button:hover {
70 | background-color: #5b5c56;
71 | }
72 |
73 | .menu-container {
74 | position: relative;
75 | }
76 |
77 | .menu {
78 | position: absolute;
79 | top: 100%;
80 | left: 0;
81 | z-index: 1000;
82 | float: left;
83 | min-width: 160px;
84 | border: 1px solid #5b5c56;
85 | background-color: #272822;
86 | }
87 |
88 | .menu-item {
89 | color: #fff;
90 | white-space: nowrap;
91 | cursor: pointer;
92 | padding: 5px 20px;
93 | }
94 |
95 | .menu-item:hover {
96 | background-color: #49483e;
97 | }
98 |
99 | .tab-bar {
100 | display: table;
101 | width: 100%;
102 | }
103 |
104 | .tabs {
105 | margin: 0;
106 | padding: 0;
107 | }
108 |
109 | .project-tabs {
110 | display: table-cell;
111 | vertical-align: bottom;
112 | }
113 |
114 | .app-tabs {
115 | display: table-cell;
116 | width: 1px;
117 | vertical-align: bottom;
118 | }
119 |
120 | .tabs li {
121 | margin: 0;
122 | padding: 8px 16px;
123 | list-style: none;
124 | display: inline-block;
125 | cursor: pointer;
126 | border-top-right-radius: 12px;
127 | border-top-left-radius: 12px;
128 | }
129 |
130 | .tabs li:hover {
131 | background-color: #49483e;
132 | }
133 |
134 | .tabs li.active {
135 | background-color: #5b5c56;
136 | cursor: default;
137 | }
138 |
139 | .panel {
140 | border: 1px solid #5b5c56;
141 | border-bottom-right-radius: 12px;
142 | border-bottom-left-radius: 12px;
143 | padding: 12px;
144 | }
145 |
146 | .panel p {
147 | margin-left: 12px;
148 | margin-right: 12px;
149 | }
150 |
151 | td.project-order, td.project-show, td.session-current {
152 | text-align: center;
153 | }
154 |
155 | .todo-item {
156 | display: table;
157 | width: 100%;
158 | padding: 6px 0;
159 | margin: 8px 0;
160 | }
161 |
162 | .todo-item:last-child {
163 | margin-bottom: 0;
164 | }
165 |
166 | .todo-item:hover {
167 | background-color: #49483e;
168 | }
169 |
170 | .dragging {
171 | opacity: 0.5;
172 | }
173 |
174 | .dropzone.dragover {
175 | outline: 1px dashed #5b5c56;
176 | }
177 |
178 | .doing-dropzone.empty {
179 | margin: 8px 0;
180 | padding: 6px 0;
181 | color: #5b5c56;
182 | text-align: center;
183 | }
184 |
185 | .todo-item .todo-item-toolbar {
186 | display: table-cell;
187 | height: 100%;
188 | width: 1px;
189 | padding: 0 12px 0 6px;
190 | white-space: pre;
191 | }
192 |
193 | .todo-item .todo-item-text {
194 | display: table-cell;
195 | height: 100%;
196 | }
197 |
198 | /* Hack for IE contentEditable difference - make p behave like br */
199 | .todo-item .todo-item-text p {
200 | margin: 0;
201 | }
202 |
203 | .todo-item .todo-item-handle {
204 | display: table-cell;
205 | text-align: center;
206 | height: 100%;
207 | width: 1px;
208 | padding: 0 6px 0 12px;
209 | }
210 |
211 | .todo-item .todo-item-handle {
212 | visibility: hidden;
213 | }
214 |
215 | .todo-item:hover .todo-item-handle {
216 | visibility: visible;
217 | }
218 |
219 | .handle {
220 | cursor: move
221 | }
222 |
223 | .control {
224 | cursor: pointer;
225 | }
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | reactodo
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/reactodo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/insin/reactodo/a44cee068eb2866697f866aff48467fef3ceffe2/reactodo.png
--------------------------------------------------------------------------------
/src/Constants.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | LOCALSTORAGE_PREFIX: 'reactodo:'
5 | , ENTER_KEY: 13
6 | , ESCAPE_KEY: 27
7 | , NBSP: '\u00A0'
8 | , UP_ARROW: '\u2191'
9 | , DOWN_ARROW: '\u2193'
10 | , CHECK: 'X'
11 | , SETTINGS: '\u2605'
12 | , DRAG_HANDLE: '\u2630'
13 | , STOP: '\u25A0'
14 | , TRIANGLE_DOWN: '\u25BC'
15 | , TRIANGLE_UP: '\u25B2'
16 | }
--------------------------------------------------------------------------------
/src/Page.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Page = {
4 | WELCOME: 1
5 | , SETTINGS: 2
6 | , TODO_LISTS: 3
7 | }
8 |
9 | module.exports = Page
--------------------------------------------------------------------------------
/src/app.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var React = require('react')
4 |
5 | var Reactodo = require('Reactodo')
6 |
7 | var trim = require('trim')
8 |
9 | var sessionMatch = /^\?(.+)/.exec(trim(decodeURIComponent(window.location.search)))
10 | var session = (sessionMatch != null ? sessionMatch[1] : '')
11 |
12 | React.render(, document.getElementById('reactodo'))
--------------------------------------------------------------------------------
/src/components/Project.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var React = require('react')
4 |
5 | var Constants = require('Constants')
6 | var TodoItem = require('TodoItem')
7 |
8 | var $c = require('classNames')
9 |
10 | var Project = React.createClass({
11 | getInitialState() {
12 | return {
13 | dragoverTodoId: null
14 | , dragoverDoing: false
15 | }
16 | },
17 |
18 | addTodo() {
19 | this.props.onAddTodo(this.props.project)
20 | },
21 |
22 | deleteDoneTodos() {
23 | if (confirm('Are you sure you want to delete all completed TODOs in ' + this.props.project.name + '?')) {
24 | this.props.onDeleteDoneTodos(this.props.project)
25 | }
26 | },
27 |
28 | /** Indicates that the [DOING] dropzone is a drop target. */
29 | handleDragEnterDoing(e) {
30 | e.preventDefault()
31 | },
32 |
33 | /** Sets the drop effect for the [DOING] dropzone. */
34 | handleDragOverDoing(e) {
35 | e.preventDefault()
36 | e.dataTransfer.dropEffect = 'move'
37 | if (!this.state.dragoverDoing) {
38 | this.setState({
39 | dragoverTodoId: null
40 | , dragoverDoing: true
41 | })
42 | }
43 | },
44 |
45 | /** Removes the drop effect for the [DOING] dropzone. */
46 | handeDragLeaveDoing(e) {
47 | if (this.state.dragoverDoing) {
48 | this.setState({dragoverDoing: false})
49 | }
50 | },
51 |
52 | /** Handles a TODO being dropped on the [DOING] dropzone. */
53 | handleDropDoing(e) {
54 | e.preventDefault()
55 | var index = Number(e.dataTransfer.getData('text'))
56 | if (this.state.dragoverDoing) {
57 | this.setState({
58 | dragoverTodoId: null
59 | , dragoverDoing: false
60 | })
61 | }
62 | this.props.onDoTodo(this.props.project, this.props.project.todos[index])
63 | },
64 |
65 | onToggleTodo(todo) {
66 | this.props.onToggleTodo(this.props.project, todo)
67 | },
68 |
69 | onDoTodo(todo) {
70 | this.props.onDoTodo(this.props.project, todo)
71 | },
72 |
73 | stopDoingTodo() {
74 | this.props.onStopDoingTodo(this.props.project)
75 | },
76 |
77 | onEditTodo(todo, newText) {
78 | this.props.onEditTodo(this.props.project, todo, newText)
79 | },
80 |
81 | onDeleteTodo(todo) {
82 | this.props.onDeleteTodo(this.props.project, todo)
83 | },
84 |
85 | onDragOverTodo(todo) {
86 | if (this.state.dragoverTodoId != todo.id) {
87 | this.setState({dragoverTodoId: todo.id})
88 | }
89 | },
90 |
91 | onDragLeaveTodo() {
92 | this.setState({dragoverTodoId: null})
93 | },
94 |
95 | onDragEndTodo() {
96 | this.setState({
97 | dragoverTodoId: null
98 | , dragoverDoing: false
99 | })
100 | },
101 |
102 | onMoveTodo(fromIndex, toIndex) {
103 | this.props.onMoveTodo(this.props.project, fromIndex, toIndex)
104 | },
105 |
106 | render() {
107 | var doing, todos = [], dones = []
108 | this.props.project.todos.forEach((todo, index) => {
109 | var currentlyDoing = (this.props.project.doing === todo.id)
110 | var todoItem =
126 | if (currentlyDoing) {
127 | doing = todoItem
128 | }
129 | else {
130 | ;(todo.done ? dones : todos).push(todoItem)
131 | }
132 | })
133 |
134 | var doneHeading
135 | if (dones.length > 0) {
136 | doneHeading = [DONE] -
137 | }
138 |
139 | var stopDoing
140 | if (doing) {
141 | stopDoing = {Constants.STOP}
142 | }
143 |
144 | return
145 |
[DOING] {stopDoing}
146 |
153 | {doing || "Drop a TODO here when it's in progress"}
154 |
155 |
[TODO] +
156 | {todos}
157 | {doneHeading}
158 | {dones}
159 |
160 | }
161 | })
162 |
163 | module.exports = Project
--------------------------------------------------------------------------------
/src/components/Reactodo.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var React = require('react')
4 |
5 | var Page = require('Page')
6 | var Project = require('Project')
7 | var Settings = require('Settings')
8 | var Welcome = require('Welcome')
9 |
10 | var $c = require('classNames')
11 | var extend = require('extend')
12 | var partial = require('partial')
13 | var uuid = require('uuid')
14 |
15 | var {LOCALSTORAGE_PREFIX, SETTINGS, TRIANGLE_DOWN, TRIANGLE_UP} = require('Constants')
16 |
17 | var Reactodo = React.createClass({
18 | getInitialState() {
19 | return this.getStateForSession(this.props.session)
20 | },
21 |
22 | /**
23 | * Gets state for the named session, loading from localStorage if available.
24 | */
25 | getStateForSession(session) {
26 | var storedJSON = localStorage[LOCALSTORAGE_PREFIX + session]
27 | var storedState = storedJSON ? JSON.parse(storedJSON) : {}
28 | var state = extend({
29 | activeProjectId: null
30 | , editTodoId: null
31 | , projects: []
32 | , showingSessionMenu: false
33 | }, storedState)
34 | state.page =
35 | (state.projects.length && state.activeProjectId !== null
36 | ? Page.TODO_LISTS
37 | : Page.WELCOME)
38 | return state
39 | },
40 |
41 | componentDidMount() {
42 | this.updateWindowTitle()
43 | },
44 |
45 | /**
46 | * Reloads state if the session name has changed.
47 | */
48 | componentWillReceiveProps(nextProps) {
49 | if (this.props.session !== nextProps.session) {
50 | var sessionState = this.getStateForSession(nextProps.session)
51 | if (nextProps.keepPage) {
52 | // If the new session doesn't have any TODO lists, don't send it to the
53 | // TODO lists page, or the user will get an empty screen. If the new
54 | // session does have TODO lists and we're on the Welcome page, don't
55 | // stay on the Welcome page.
56 | if (!(sessionState.page === Page.WELCOME && this.state.page === Page.TODO_LISTS) &&
57 | !(sessionState.page === Page.TODO_LISTS && this.state.page === Page.WELCOME)) {
58 | sessionState.page = this.state.page
59 | }
60 | }
61 | this.setState(sessionState)
62 | }
63 | },
64 |
65 | /**
66 | * Stores session state when there's been a state change. Ensures the window
67 | * title is updated if the session changed as part of the update.
68 | */
69 | componentDidUpdate(prevProps, prevState) {
70 | if (prevProps.session !== this.props.session) {
71 | this.updateWindowTitle()
72 | }
73 | localStorage[LOCALSTORAGE_PREFIX + this.props.session] = JSON.stringify({
74 | activeProjectId: this.state.activeProjectId
75 | , projects: this.state.projects
76 | })
77 | },
78 |
79 | updateWindowTitle() {
80 | if (this.props.session) {
81 | document.title = this.props.session + ' - reactodo'
82 | }
83 | else {
84 | document.title = 'reactodo'
85 | }
86 | },
87 |
88 | /**
89 | * Switches to another named session on the fly. If a keepPage option is
90 | * passed and is truthy, the current page state will be retained.
91 | */
92 | switchSession(session, options) {
93 | options = extend({keepPage: false}, options)
94 | if (typeof history !== 'undefined' && history.replaceState) {
95 | history.replaceState(session, session + ' - reactodo', '?' + encodeURIComponent(session))
96 | }
97 | this.setProps({session: session, keepPage: options.keepPage})
98 | },
99 |
100 | /**
101 | * Determines session names present in localStorage.
102 | */
103 | getSessions() {
104 | return Object.keys(localStorage)
105 | .filter(function(p) { return p.indexOf(LOCALSTORAGE_PREFIX) === 0 })
106 | .map(function(p) { return p.substring(LOCALSTORAGE_PREFIX.length) })
107 | },
108 |
109 | /** Adds a new session without switching to it. */
110 | addSession(sessionName) {
111 | localStorage[LOCALSTORAGE_PREFIX + sessionName] = JSON.stringify({
112 | activeProjectId: null
113 | , projects: []
114 | })
115 | this.forceUpdate()
116 | },
117 |
118 | /**
119 | * Copies session state from one name to another and deletes the original. If
120 | * the original was the active session, switches to it.
121 | */
122 | editSessionName(session, newName) {
123 | localStorage[LOCALSTORAGE_PREFIX + newName] =
124 | localStorage[LOCALSTORAGE_PREFIX + session]
125 | this.deleteSession(session)
126 | if (this.props.session === session) {
127 | this.switchSession(newName, {keepPage: true})
128 | }
129 | },
130 |
131 | deleteSession(sessionName) {
132 | delete localStorage[LOCALSTORAGE_PREFIX + sessionName]
133 | this.forceUpdate()
134 | },
135 |
136 | setPage(page) {
137 | this.setState({page: page})
138 | },
139 |
140 | /**
141 | * Sets the given project id as active and switches to displaying its TODOs if
142 | * currently on another screen.
143 | */
144 | setActiveProject(projectId) {
145 | this.setState({
146 | activeProjectId: projectId
147 | , page: Page.TODO_LISTS
148 | })
149 | },
150 |
151 | addProject(projectName) {
152 | var id = uuid()
153 | this.state.projects.push({id: id, name: projectName, doing: null, todos: []})
154 | this.setState({projects: this.state.projects})
155 | },
156 |
157 | editProjectName(project, projectName) {
158 | project.name = projectName
159 | this.setState({projects: this.state.projects})
160 | },
161 |
162 | moveProjectUp(project, index) {
163 | this.state.projects.splice(index - 1, 0, this.state.projects.splice(index, 1)[0])
164 | this.setState({projects: this.state.projects})
165 | },
166 |
167 | moveProjectDown(project, index) {
168 | this.state.projects.splice(index + 1, 0, this.state.projects.splice(index, 1)[0])
169 | this.setState({projects: this.state.projects})
170 | },
171 |
172 | toggleProjectVisible(project) {
173 | project.hidden = !project.hidden
174 | this.setState({projects: this.state.projects})
175 | },
176 |
177 | /**
178 | * Deletes a project and sets the next adjacent project as active if there are
179 | * any.
180 | */
181 | deleteProject(project, index) {
182 | this.state.projects.splice(index, 1)
183 | var activeProjectId = this.state.activeProjectId
184 | if (this.state.projects.length === 0) {
185 | activeProjectId = null
186 | }
187 | else if (activeProjectId === project.id) {
188 | if (index <= this.state.projects.length - 1) {
189 | activeProjectId = this.state.projects[index].id
190 | }
191 | else {
192 | activeProjectId = this.state.projects[index - 1].id
193 | }
194 | }
195 | this.setState({
196 | activeProjectId: activeProjectId
197 | , projects: this.state.projects
198 | })
199 | },
200 |
201 | addTodo(project) {
202 | var id = uuid()
203 | project.todos.unshift({id: id , done: false, text: ''})
204 | this.setState({
205 | editTodoId: id
206 | , projects: this.state.projects
207 | })
208 | },
209 |
210 | editTodo(project, todo, newText) {
211 | todo.text = newText
212 | this.setState({
213 | editTodoId: null
214 | , projects: this.state.projects
215 | })
216 | },
217 |
218 | moveTodo(project, fromIndex, toIndex) {
219 | var fromTodo = project.todos[fromIndex]
220 | , toTodo = project.todos[toIndex]
221 | if (fromTodo.done !== toTodo.done) {
222 | fromTodo.done = toTodo.done
223 | }
224 | project.todos.splice(toIndex, 0, project.todos.splice(fromIndex, 1)[0])
225 | this.setState({projects: this.state.projects})
226 | },
227 |
228 | toggleTodo(project, todo) {
229 | todo.done = !todo.done
230 | if (project.doing === todo.id) {
231 | project.doing = null
232 | }
233 | this.setState({projects: this.state.projects})
234 | },
235 |
236 | doTodo(project, todo) {
237 | project.doing = todo.id
238 | if (todo.done) {
239 | todo.done = false
240 | }
241 | this.setState({projects: this.state.projects})
242 | },
243 |
244 | stopDoingTodo(project) {
245 | project.doing = null
246 | this.setState({projects: this.state.projects})
247 | },
248 |
249 | deleteTodo(project, todo) {
250 | for (var i = 0, l = project.todos.length; i < l; i++) {
251 | if (project.todos[i].id === todo.id) {
252 | project.todos.splice(i, 1)
253 | if (project.doing === todo.id) {
254 | project.doing = null
255 | }
256 | return this.setState({projects: this.state.projects})
257 | }
258 | }
259 | },
260 |
261 | deleteDoneTodos(project) {
262 | project.todos = project.todos.filter(function(todo) { return !todo.done })
263 | this.setState({projects: this.state.projects})
264 | },
265 |
266 | showSessionMenu() {
267 | this.setState({showingSessionMenu: true})
268 | },
269 |
270 | pickSession(session, e) {
271 | e.preventDefault()
272 | e.stopPropagation()
273 | this.hideSessionMenu()
274 | this.switchSession(session, {keepPage: true})
275 | },
276 |
277 | hideSessionMenu() {
278 | this.setState({showingSessionMenu: false})
279 | },
280 |
281 | render() {
282 | var tabs = []
283 | var content
284 |
285 | if (this.state.page === Page.WELCOME) {
286 | content =
292 | }
293 | else if (this.state.page === Page.SETTINGS) {
294 | content =
309 | }
310 |
311 | // Always display project tabs when available
312 | this.state.projects.forEach(project => {
313 | if (project.hidden) { return }
314 | var isActiveProject = (this.state.page === Page.TODO_LISTS &&
315 | this.state.activeProjectId === project.id)
316 | tabs.push(
319 | {project.name}
320 | )
321 | if (isActiveProject) {
322 | content =
334 | }
335 | })
336 |
337 | // Ensure there's something in tabs so its display isn't collapsed (Chrome)
338 | if (!tabs.length) { tabs.push(' ') }
339 |
340 | var sessions = this.getSessions()
341 | var multipleSessions = sessions.length > 1
342 | var activeSession
343 | var sessionMenu
344 | if (!this.state.showingSessionMenu) {
345 | var sessionName = this.props.session
346 | if (multipleSessions) {
347 | sessionName += ' ' + TRIANGLE_DOWN
348 | }
349 | activeSession =
350 | {sessionName}
351 |
352 | }
353 | else {
354 | activeSession =
355 | {this.props.session + ' ' + TRIANGLE_UP}
356 |
357 |
358 | sessions.sort()
359 | sessions.splice(sessions.indexOf(this.props.session), 1)
360 |
361 | var menuItems = sessions.map((session, index) => {
362 | var sessionName = session || '(Default)'
363 | return
364 | {sessionName}
365 |
366 | })
367 |
368 | sessionMenu = {menuItems}
369 | }
370 |
371 | return
372 |
373 | reactodo {' '}
374 | {activeSession}{sessionMenu}
375 |
376 |
386 |
387 | {content}
388 |
389 |
390 | }
391 | })
392 |
393 | module.exports = Reactodo
--------------------------------------------------------------------------------
/src/components/Settings.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var React = require('react')
4 |
5 | var EditInput = require('EditInput')
6 |
7 | var exportProject = require('exportProject')
8 | var exportTextFile = require('exportTextFile')
9 | var partial = require('partial')
10 |
11 | var {CHECK, DOWN_ARROW, NBSP, UP_ARROW} = require('Constants')
12 |
13 | var Settings = React.createClass({
14 | getInitialState() {
15 | return {
16 | addingProject: false
17 | , addingSession: false
18 | , editingProjectName: null
19 | , editingSessionName: null
20 | }
21 | },
22 |
23 | addProject(projectName) {
24 | if (!this.state.addingProject) {
25 | this.setState({addingProject: true})
26 | }
27 | else {
28 | this.setState({addingProject: false})
29 | this.props.onAddProject(projectName)
30 | }
31 | },
32 |
33 | cancelAddProject() {
34 | this.setState({addingProject: false})
35 | },
36 |
37 | editProjectName(project, projectName) {
38 | if (this.state.editingProjectName !== project.id) {
39 | this.setState({editingProjectName: project.id})
40 | }
41 | else {
42 | this.setState({editingProjectName: null})
43 | this.props.onEditProjectName(project, projectName)
44 | }
45 | },
46 |
47 | cancelEditProjectName() {
48 | this.setState({editingProjectName: null})
49 | },
50 |
51 | deleteProject(project, index) {
52 | if (confirm('Are you sure you want to delete "' + project.name + '"?')) {
53 | this.props.onDeleteProject(project, index)
54 | }
55 | },
56 |
57 | sessionNameAlreadyExists(name) {
58 | return (this.props.getSessions().indexOf(name) != -1)
59 | },
60 |
61 | addSession(sessionName) {
62 | if (!this.state.addingSession) {
63 | this.setState({addingSession: true})
64 | }
65 | else {
66 | if (this.sessionNameAlreadyExists(sessionName)) {
67 | return alert('A session named "' + sessionName + '" already exists.')
68 | }
69 | this.setState({addingSession: false})
70 | this.props.onAddSession(sessionName)
71 | }
72 | },
73 |
74 | cancelAddSession() {
75 | this.setState({addingSession: false})
76 | },
77 |
78 | editSessionName(session, newName) {
79 | if (this.state.editingSessionName !== session) {
80 | this.setState({editingSessionName: session})
81 | }
82 | else {
83 | if (this.sessionNameAlreadyExists(newName) && newName !== session) {
84 | return alert('A session named "' + newName + '" already exists.')
85 | }
86 | this.setState({editingSessionName: null})
87 | if (newName !== session) {
88 | this.props.onEditSessionName(session, newName)
89 | }
90 | }
91 | },
92 |
93 | cancelEditSessionName() {
94 | this.setState({editingSessionName: null})
95 | },
96 |
97 | deleteSession(session) {
98 | if (confirm('Are you sure you want to delete "' + session +
99 | '"? All Projects and TODOs will be lost.')) {
100 | this.props.onDeleteSession(session)
101 | }
102 | this.forceUpdate()
103 | },
104 |
105 | toggleProjectVisible(project) {
106 | this.props.onToggleProjectVisible(project)
107 | },
108 |
109 | exportProject(project) {
110 | exportTextFile(exportProject(project), project.name + '.todo.txt')
111 | },
112 |
113 | render() {
114 | var addProject
115 | if (this.state.addingProject) {
116 | addProject =
121 | }
122 | else {
123 | addProject = +
124 | }
125 |
126 | var projects
127 | if (this.props.projects.length) {
128 | projects =
129 |
130 |
131 |
132 | Name
133 | Order
134 | Show?
135 | {NBSP}
136 | {NBSP}
137 |
138 |
139 |
140 | {this.props.projects.map(this.renderProject)}
141 |
142 |
143 |
Click on a project's name to edit it.
144 |
145 | }
146 |
147 | var addSession
148 | if (this.state.addingSession) {
149 | addSession =
154 | }
155 | else {
156 | addSession = +
157 | }
158 |
159 | var sessions =
160 |
161 |
162 |
163 | Name
164 | Current?
165 | {NBSP}
166 | {NBSP}
167 |
168 |
169 |
170 | {this.props.getSessions().map(this.renderSession)}
171 |
172 |
173 |
Click on a session's name to edit it.
174 |
175 |
176 | return
177 |
[PROJECTS] {addProject}
178 | {projects}
179 | [SESSIONS] {addSession}
180 | {sessions}
181 |
182 | },
183 |
184 | renderProject(project, i, projects) {
185 | var first = (i === 0)
186 | var last = (i == projects.length - 1)
187 | var up = (first ? {NBSP} :
188 |
189 | {UP_ARROW}
190 |
191 | )
192 | var down = (last ? {NBSP} :
193 |
194 | {DOWN_ARROW}
195 |
196 | )
197 | var projectName
198 | if (this.state.editingProjectName === project.id) {
199 | projectName =
205 | }
206 | else {
207 | projectName =
208 | {project.name}
209 |
210 | }
211 |
212 | return
213 | {projectName}
214 | {up}{NBSP}{down}
215 |
216 |
217 | [{project.hidden ? NBSP : CHECK}]
218 |
219 |
220 |
221 | Export
222 |
223 |
224 | Delete
225 |
226 |
227 | },
228 |
229 | renderSession(session) {
230 | var displayName = (session === '' ? '(Default)' : session)
231 | var isActiveSession = (session === this.props.session)
232 | var sessionName
233 | if (this.state.editingSessionName === session) {
234 | sessionName =
240 | }
241 | else {
242 | sessionName =
243 | {displayName}
244 |
245 | }
246 | var switchSession = NBSP
247 | var deleteSession = NBSP
248 | if (!isActiveSession) {
249 | switchSession =
250 | Switch
251 |
252 | deleteSession =
253 | Delete
254 |
255 | }
256 |
257 | return
258 | {sessionName}
259 | {isActiveSession ? '[' + CHECK + ']' : NBSP}
260 | {switchSession}
261 | {deleteSession}
262 |
263 | }
264 | })
265 |
266 | module.exports = Settings
--------------------------------------------------------------------------------
/src/components/TodoItem.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var React = require('react')
4 |
5 | var $c = require('classNames')
6 | var normaliseContentEditableHTML = require('normaliseContentEditableHTML')
7 | var partial = require('partial')
8 |
9 | var {CHECK, DRAG_HANDLE, NBSP} = require('Constants')
10 |
11 | var TodoItem = React.createClass({
12 | getInitialState() {
13 | return {
14 | dragging: false
15 | , editing: this.props.initialEdit || false
16 | }
17 | },
18 |
19 | componentDidMount() {
20 | if (this.props.initialEdit) {
21 | this.refs.text.getDOMNode().focus()
22 | }
23 | },
24 |
25 | componentDidUpdate (prevProps, prevState) {
26 | if (this.state.editing && !prevState.editing) {
27 | this.refs.text.getDOMNode().focus()
28 | }
29 | },
30 |
31 | handleTextClick() {
32 | if (!this.state.editing) {
33 | this.setState({editing: true})
34 | }
35 | },
36 |
37 | handleTextBlur() {
38 | if (this.state.editing) {
39 | var text = normaliseContentEditableHTML(this.refs.text.getDOMNode().innerHTML)
40 | // Re-apply normalised HTML to the TODO's text
41 | if (text) {
42 | this.refs.text.getDOMNode().innerHTML = text
43 | }
44 | this.setState({editing: false})
45 | if (!text) {
46 | this.props.onDelete(this.props.todo)
47 | }
48 | else {
49 | this.props.onEdit(this.props.todo, text)
50 | }
51 | }
52 | },
53 |
54 | handleDragStart(e) {
55 | e.dataTransfer.setData('text', '' + this.props.index)
56 | this.setState({dragging: true})
57 | },
58 |
59 | handleDragEnd(e) {
60 | this.setState({dragging: false})
61 | this.props.onDragEnd()
62 | },
63 |
64 | /** Indicates that this TODO is a drop target. */
65 | handleDragEnter(e) {
66 | e.preventDefault()
67 | },
68 |
69 | /** Sets the drop effect for this TODO. */
70 | handleDragOver(e) {
71 | if (this.state.dragging) {
72 | return
73 | }
74 | e.preventDefault()
75 | e.dataTransfer.dropEffect = 'move'
76 | this.props.onDragOver(this.props.todo)
77 | },
78 |
79 | /** Handles another TODO being dropped on this one. */
80 | handleDrop(e) {
81 | e.preventDefault()
82 | var fromIndex = Number(e.dataTransfer.getData('text'))
83 | this.props.onMoveTodo(fromIndex, this.props.index)
84 | },
85 |
86 | /**
87 | * IE9 doesn't support draggable="true" on s. This hack manually starts
88 | * the drag & drop process onMouseDown. The setTimeout not only bothers me but
89 | * doesn't always seem to work - without it, the classes which set style for
90 | * the item being dragged and dropzones being dragged over aren't applied.
91 | */
92 | handleIE9DragHack(e) {
93 | e.preventDefault()
94 | if (window.event.button === 1) {
95 | var target = e.nativeEvent.target
96 | setTimeout(function() { target.dragDrop() }, 50)
97 | }
98 | },
99 |
100 | render() {
101 | var todoItemClassName = $c('todo-item', {
102 | 'is-todo': !this.props.todo.done
103 | , 'is-done': this.props.todo.done
104 | , 'is-doing': this.props.doing
105 | , 'dropzone': !this.props.doing
106 | , 'dragging': this.state.dragging
107 | , 'dragover': this.props.dragover
108 | })
109 |
110 | var dragHandle
111 | if (!this.props.doing) {
112 | dragHandle =
113 | {DRAG_HANDLE}
120 |
121 | }
122 |
123 | // onDrop is handled by the [DOING] dropZone if that's where this TODO is
124 | // being displayed.
125 | return
132 |
133 | [{this.props.todo.done ? CHECK : NBSP}]
134 |
135 |
143 | {dragHandle}
144 |
145 | }
146 | })
147 |
148 | module.exports = TodoItem
--------------------------------------------------------------------------------
/src/components/Welcome.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var React = require('react')
4 |
5 | var trim = require('trim')
6 |
7 | var {DRAG_HANDLE, ENTER_KEY, SETTINGS, STOP} = require('Constants')
8 |
9 | var Welcome = React.createClass({
10 | switchSession() {
11 | var sessionName = trim(this.refs.sessionName.getDOMNode().value)
12 | if (sessionName) {
13 | this.props.onSwitchSession(sessionName)
14 | }
15 | },
16 |
17 | onSessionNameKeyDown(e) {
18 | if (e.which === ENTER_KEY) {
19 | this.switchSession()
20 | }
21 | },
22 |
23 | render() {
24 | var currentSession
25 | if (!this.props.session) {
26 | currentSession =
27 |
You are currently using the default session.
28 |
29 | If you'd like to switch to a named session which describes your TODOs
30 | (e.g. "work projects" or "personal projects"), enter the name you'd
31 | like to use below:
32 |
33 |
34 | }
35 | else {
36 | currentSession =
37 |
38 | You are currently using a named session - "{this.props.session}" -
39 | bookmark the current address to easily return to this session again
40 | later.
41 |
42 |
43 | If you'd like to switch to another named session enter a name below:
44 |
45 |
46 | }
47 |
48 | var sessions = this.props.getSessions().filter(function(session) {
49 | return session !== ''
50 | })
51 | sessions.sort()
52 | var datalistOptions = sessions.map(function(session) {
53 | return
54 | })
55 |
56 | return
57 |
[WELCOME]
58 |
Reactodo is a TODO app with 3 fixed categories - DOING, TODO and DONE - and multiple TODO lists, or projects.
59 |
It's designed and styled after quick, disposable TODO tracking of the type commonly done in a programmer's text editor, but with a few interactive niceties to manage TODOs instead of cut + paste.
60 |
TODO lists you create are stored locally, so will only be available on this machine and browser.
61 |
[GETTING STARTED]
62 |
To set up some projects, click the {SETTINGS} icon, here or over in the corner.
63 |
[SESSIONS]
64 |
Reactodo allows you to have multiple, independent sessions with their own TODO lists.
65 | {currentSession}
66 |
67 | {datalistOptions}
68 | {' '}
69 | Switch
70 |
71 |
[TIPS]
72 |
73 | To add a TODO , click the + control beside the project's [TODO] heading.
74 | To edit a TODO , click on its text.
75 | To reorder TODOs , drag their {DRAG_HANDLE} handles and drop in the desired location.
76 | When doing a TODO , drag and drop it into the project's [DOING] section.
77 | To complete a TODO , click on its [ ] checkbox.
78 | To stop doing a TODO , click the {STOP} control beside the project's [DOING] heading.
79 | To delete a single TODO , delete all of its text.
80 | To permanently delete completed TODOs , click the - control beside the project's [DONE] heading.
81 |
82 |
83 | }
84 | })
85 |
86 | module.exports = Welcome
--------------------------------------------------------------------------------
/src/components/reusable/EditInput.jsx:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var React = require('react')
4 |
5 | var {ENTER_KEY, ESCAPE_KEY} = require('Constants')
6 |
7 | var trim = require('trim')
8 |
9 | /**
10 | * A text with submit and cancel buttons, which can also be submitted or
11 | * cancelled using the keyboard.
12 | */
13 | var EditInput = React.createClass({
14 | propTypes: {
15 | onCancel: React.PropTypes.func.isRequired
16 | , onSubmit: React.PropTypes.func.isRequired
17 | },
18 |
19 | getDefaultProps() {
20 | return {
21 | autoFocus: true
22 | , button: 'Submit'
23 | , defaultValue: ''
24 | , size: 15
25 | , required: true
26 | , trim: true
27 | }
28 | },
29 |
30 | componentDidMount() {
31 | if (this.props.autoFocus) {
32 | this.refs.input.getDOMNode().focus()
33 | }
34 | },
35 |
36 | submit() {
37 | var value = this.refs.input.getDOMNode().value
38 | if (this.props.trim) {
39 | value = trim(value)
40 | }
41 | if (this.props.required && !value) {
42 | return
43 | }
44 | this.props.onSubmit(value)
45 | },
46 |
47 | cancel() {
48 | this.props.onCancel()
49 | },
50 |
51 | handleKeyDown(e) {
52 | if (e.which === ENTER_KEY) {
53 | this.submit()
54 | }
55 | else if (e.which === ESCAPE_KEY) {
56 | this.cancel()
57 | }
58 | },
59 |
60 | render() {
61 | return
62 | {' '}
69 | {this.props.button} {' '}
70 | Cancel
71 |
72 | }
73 | })
74 |
75 | module.exports = EditInput
--------------------------------------------------------------------------------
/src/utils/Base64.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Base64 encode / decode
4 | * http://www.webtoolkit.info/
5 | *
6 | */
7 |
8 | 'use strict';
9 |
10 | var Base64 = {
11 |
12 | // private property
13 | _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
14 |
15 | // public method for encoding
16 | encode : function (input) {
17 | var output = "";
18 | var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
19 | var i = 0;
20 |
21 | input = Base64._utf8_encode(input);
22 |
23 | while (i < input.length) {
24 |
25 | chr1 = input.charCodeAt(i++);
26 | chr2 = input.charCodeAt(i++);
27 | chr3 = input.charCodeAt(i++);
28 |
29 | enc1 = chr1 >> 2;
30 | enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
31 | enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
32 | enc4 = chr3 & 63;
33 |
34 | if (isNaN(chr2)) {
35 | enc3 = enc4 = 64;
36 | } else if (isNaN(chr3)) {
37 | enc4 = 64;
38 | }
39 |
40 | output = output +
41 | this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
42 | this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
43 |
44 | }
45 |
46 | return output;
47 | },
48 |
49 | // public method for decoding
50 | decode : function (input) {
51 | var output = "";
52 | var chr1, chr2, chr3;
53 | var enc1, enc2, enc3, enc4;
54 | var i = 0;
55 |
56 | input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
57 |
58 | while (i < input.length) {
59 |
60 | enc1 = this._keyStr.indexOf(input.charAt(i++));
61 | enc2 = this._keyStr.indexOf(input.charAt(i++));
62 | enc3 = this._keyStr.indexOf(input.charAt(i++));
63 | enc4 = this._keyStr.indexOf(input.charAt(i++));
64 |
65 | chr1 = (enc1 << 2) | (enc2 >> 4);
66 | chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
67 | chr3 = ((enc3 & 3) << 6) | enc4;
68 |
69 | output = output + String.fromCharCode(chr1);
70 |
71 | if (enc3 != 64) {
72 | output = output + String.fromCharCode(chr2);
73 | }
74 | if (enc4 != 64) {
75 | output = output + String.fromCharCode(chr3);
76 | }
77 |
78 | }
79 |
80 | output = Base64._utf8_decode(output);
81 |
82 | return output;
83 |
84 | },
85 |
86 | // private method for UTF-8 encoding
87 | _utf8_encode : function (string) {
88 | string = string.replace(/\r\n/g,"\n");
89 | var utftext = "";
90 |
91 | for (var n = 0; n < string.length; n++) {
92 |
93 | var c = string.charCodeAt(n);
94 |
95 | if (c < 128) {
96 | utftext += String.fromCharCode(c);
97 | }
98 | else if((c > 127) && (c < 2048)) {
99 | utftext += String.fromCharCode((c >> 6) | 192);
100 | utftext += String.fromCharCode((c & 63) | 128);
101 | }
102 | else {
103 | utftext += String.fromCharCode((c >> 12) | 224);
104 | utftext += String.fromCharCode(((c >> 6) & 63) | 128);
105 | utftext += String.fromCharCode((c & 63) | 128);
106 | }
107 |
108 | }
109 |
110 | return utftext;
111 | },
112 |
113 | // private method for UTF-8 decoding
114 | _utf8_decode : function (utftext) {
115 | var string = "";
116 | var i = 0;
117 | var c, c1, c2, c3;
118 | c = c1 = c2 = 0;
119 |
120 | while ( i < utftext.length ) {
121 |
122 | c = utftext.charCodeAt(i);
123 |
124 | if (c < 128) {
125 | string += String.fromCharCode(c);
126 | i++;
127 | }
128 | else if((c > 191) && (c < 224)) {
129 | c2 = utftext.charCodeAt(i+1);
130 | string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
131 | i += 2;
132 | }
133 | else {
134 | c2 = utftext.charCodeAt(i+1);
135 | c3 = utftext.charCodeAt(i+2);
136 | string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
137 | i += 3;
138 | }
139 |
140 | }
141 |
142 | return string;
143 | }
144 | }
145 |
146 | module.exports = Base64
--------------------------------------------------------------------------------
/src/utils/classNames.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | /**
4 | * Creates a className string including some class names conditionally.
5 | * @param {string=} staticClassName class name(s) which should always be
6 | * included.
7 | * @param {Object.} conditionalClassNames an object mapping class
8 | * names to a value which indicates if the class name should be included -
9 | * class names will be included if their corresponding value is truthy.
10 | * @return {string}
11 | */
12 | function classNames(staticClassName, conditionalClassNames) {
13 | var names = []
14 | if (typeof conditionalClassNames == 'undefined') {
15 | conditionalClassNames = staticClassName
16 | }
17 | else {
18 | names.push(staticClassName)
19 | }
20 | for (var className in conditionalClassNames) {
21 | if (!!conditionalClassNames[className]) {
22 | names.push(className)
23 | }
24 | }
25 | return names.join(' ')
26 | }
27 |
28 | module.exports = classNames
--------------------------------------------------------------------------------
/src/utils/exportProject.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Constants = require('Constants')
4 |
5 | function exportProject(project) {
6 | var doing = ['[DOING]'], todos = ['[TODO]'], dones = ['[DONE]']
7 | project.todos.forEach(function(todo) {
8 | var exportedTODO = exportTODO(todo)
9 | if (project.doing === todo.id) {
10 | doing.push(exportedTODO)
11 | }
12 | else if (todo.done) {
13 | dones.push(exportedTODO)
14 | }
15 | else {
16 | todos.push(exportedTODO)
17 | }
18 | })
19 | return doing.concat(todos).concat(dones).join('\n\n')
20 | }
21 |
22 | var breaks = / /g
23 | var spaces = / /g
24 | var newlines = /\n/g
25 | var lt = /</g
26 | var gt = />/g
27 | var amp = /&/g
28 |
29 | function exportTODO(todo) {
30 | var checkbox = '[' + (todo.done ? Constants.CHECK : ' ') + '] '
31 | var text = todo.text.replace(breaks, '\n')
32 | .replace(spaces, ' ')
33 | .replace(newlines, '\n ')
34 | .replace(lt, '<')
35 | .replace(gt, '>')
36 | .replace(amp, '&')
37 | return checkbox + text
38 | }
39 |
40 | module.exports = exportProject
--------------------------------------------------------------------------------
/src/utils/exportTextFile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var Base64 = require('Base64')
4 |
5 | function exportTextFile(text, filename) {
6 | var a = document.createElement('a')
7 | if ('download' in a) {
8 | a.href = 'data:text/plain;base64,' + Base64.encode(text)
9 | a.download = filename
10 | var event = document.createEvent('MouseEvents')
11 | event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0,
12 | false, false, false, false, 0, null)
13 | a.dispatchEvent(event)
14 | }
15 | else {
16 | if (typeof window.isIE9 !== 'undefined') {
17 | // TODO IE9 only supports data URIs for - do something else for it
18 | return alert('Not supported in this browser yet :-/')
19 | }
20 | window.location.href =
21 | 'data:application/octet-stream;base64,' + Base64.encode(text)
22 | }
23 | }
24 |
25 | module.exports = exportTextFile
--------------------------------------------------------------------------------
/src/utils/extend.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var hasOwn = Object.prototype.hasOwnProperty
4 |
5 | function extend(dest) {
6 | for (var i = 1, l = arguments.length; i < l; i++) {
7 | var src = arguments[i]
8 | if (!src || typeof src != 'object') { continue }
9 | for (var prop in src) {
10 | if (!hasOwn.call(src, prop)) { continue }
11 | dest[prop] = src[prop]
12 | }
13 | }
14 | return dest
15 | }
16 |
17 | module.exports = extend
--------------------------------------------------------------------------------
/src/utils/normaliseContentEditableHTML.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var openBreaks = /]*>|
]*>/g
4 | var breaks = /
]*>|<\/p>|<\/div>/g
5 | var allTags = /<\/?[^>]+>\s*/g
6 | var newlines = /\n/g
7 |
8 | // Leading and trailing whitespace,
s & s
9 | var trimWhitespace = /^(?:\s| |
]*>)*|(?:\s| |
]*>)*$/g
10 |
11 | /**
12 | * Normalises contentEditable innerHTML, stripping all tags except
and
13 | * trimming leading and trailing whitespace. The resulting normalised HTML uses
14 | *
for line breaks.
15 | */
16 | function normaliseContentEditableHTML(html) {
17 | html = html.replace(openBreaks, '')
18 | .replace(breaks, '\n')
19 | .replace(allTags, '')
20 | .replace(newlines, '
')
21 | .replace(trimWhitespace, '')
22 |
23 | return html
24 | }
25 |
26 | module.exports = normaliseContentEditableHTML
--------------------------------------------------------------------------------
/src/utils/partial.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var slice = Array.prototype.slice
4 |
5 | function partial(fn) {
6 | var args = slice.call(arguments, 1)
7 | return function() {
8 | return fn.apply(this, args.concat(slice.call(arguments)))
9 | }
10 | }
11 |
12 | module.exports = partial
--------------------------------------------------------------------------------
/src/utils/trim.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var TRIM_RE = /^\s+|\s+$/g
4 |
5 | function trim(string) {
6 | return string.replace(TRIM_RE, '')
7 | }
8 |
9 | module.exports = trim
--------------------------------------------------------------------------------
/src/utils/uuid.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | function s4() {
4 | return Math.floor((1 + Math.random()) * 0x10000)
5 | .toString(16)
6 | .substring(1)
7 | }
8 |
9 | function uuid() {
10 | return (s4() + s4() + '-' + s4() + '-' + s4() + '-' +
11 | s4() + '-' + s4() + s4() + s4())
12 | }
13 |
14 | module.exports = uuid
--------------------------------------------------------------------------------
/vendor/react-0.11.2.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * React v0.11.2
3 | *
4 | * Copyright 2013-2014 Facebook, Inc.
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.React=e()}}(function(){return function e(t,n,r){function o(a,s){if(!n[a]){if(!t[a]){var u="function"==typeof require&&require;if(!s&&u)return u(a,!0);if(i)return i(a,!0);throw new Error("Cannot find module '"+a+"'")}var c=n[a]={exports:{}};t[a][0].call(c.exports,function(e){var n=t[a][1][e];return o(n?n:e)},c,c.exports,e,t,n,r)}return n[a].exports}for(var i="function"==typeof require&&require,a=0;a
n;n++)e[n].call(t[n]);e.length=0,t.length=0}},reset:function(){this._callbacks=null,this._contexts=null},destructor:function(){this.reset()}}),r.addPoolingTo(n),t.exports=n},{"./PooledClass":26,"./invariant":118,"./mixInto":131}],6:[function(e,t){"use strict";function n(e){return"SELECT"===e.nodeName||"INPUT"===e.nodeName&&"file"===e.type}function r(e){var t=M.getPooled(P.change,_,e);C.accumulateTwoPhaseDispatches(t),R.batchedUpdates(o,t)}function o(e){y.enqueueEvents(e),y.processEventQueue()}function i(e,t){I=e,_=t,I.attachEvent("onchange",r)}function a(){I&&(I.detachEvent("onchange",r),I=null,_=null)}function s(e,t,n){return e===O.topChange?n:void 0}function u(e,t,n){e===O.topFocus?(a(),i(t,n)):e===O.topBlur&&a()}function c(e,t){I=e,_=t,T=e.value,N=Object.getOwnPropertyDescriptor(e.constructor.prototype,"value"),Object.defineProperty(I,"value",A),I.attachEvent("onpropertychange",p)}function l(){I&&(delete I.value,I.detachEvent("onpropertychange",p),I=null,_=null,T=null,N=null)}function p(e){if("value"===e.propertyName){var t=e.srcElement.value;t!==T&&(T=t,r(e))}}function d(e,t,n){return e===O.topInput?n:void 0}function f(e,t,n){e===O.topFocus?(l(),c(t,n)):e===O.topBlur&&l()}function h(e){return e!==O.topSelectionChange&&e!==O.topKeyUp&&e!==O.topKeyDown||!I||I.value===T?void 0:(T=I.value,_)}function v(e){return"INPUT"===e.nodeName&&("checkbox"===e.type||"radio"===e.type)}function m(e,t,n){return e===O.topClick?n:void 0}var g=e("./EventConstants"),y=e("./EventPluginHub"),C=e("./EventPropagators"),E=e("./ExecutionEnvironment"),R=e("./ReactUpdates"),M=e("./SyntheticEvent"),D=e("./isEventSupported"),x=e("./isTextInputElement"),b=e("./keyOf"),O=g.topLevelTypes,P={change:{phasedRegistrationNames:{bubbled:b({onChange:null}),captured:b({onChangeCapture:null})},dependencies:[O.topBlur,O.topChange,O.topClick,O.topFocus,O.topInput,O.topKeyDown,O.topKeyUp,O.topSelectionChange]}},I=null,_=null,T=null,N=null,w=!1;E.canUseDOM&&(w=D("change")&&(!("documentMode"in document)||document.documentMode>8));var S=!1;E.canUseDOM&&(S=D("input")&&(!("documentMode"in document)||document.documentMode>9));var A={get:function(){return N.get.call(this)},set:function(e){T=""+e,N.set.call(this,e)}},k={eventTypes:P,extractEvents:function(e,t,r,o){var i,a;if(n(t)?w?i=s:a=u:x(t)?S?i=d:(i=h,a=f):v(t)&&(i=m),i){var c=i(e,t,r);if(c){var l=M.getPooled(P.change,c,o);return C.accumulateTwoPhaseDispatches(l),l}}a&&a(e,t,r)}};t.exports=k},{"./EventConstants":15,"./EventPluginHub":17,"./EventPropagators":20,"./ExecutionEnvironment":21,"./ReactUpdates":74,"./SyntheticEvent":82,"./isEventSupported":119,"./isTextInputElement":121,"./keyOf":125}],7:[function(e,t){"use strict";var n=0,r={createReactRootIndex:function(){return n++}};t.exports=r},{}],8:[function(e,t){"use strict";function n(e){switch(e){case g.topCompositionStart:return C.compositionStart;case g.topCompositionEnd:return C.compositionEnd;case g.topCompositionUpdate:return C.compositionUpdate}}function r(e,t){return e===g.topKeyDown&&t.keyCode===h}function o(e,t){switch(e){case g.topKeyUp:return-1!==f.indexOf(t.keyCode);case g.topKeyDown:return t.keyCode!==h;case g.topKeyPress:case g.topMouseDown:case g.topBlur:return!0;default:return!1}}function i(e){this.root=e,this.startSelection=c.getSelection(e),this.startValue=this.getText()}var a=e("./EventConstants"),s=e("./EventPropagators"),u=e("./ExecutionEnvironment"),c=e("./ReactInputSelection"),l=e("./SyntheticCompositionEvent"),p=e("./getTextContentAccessor"),d=e("./keyOf"),f=[9,13,27,32],h=229,v=u.canUseDOM&&"CompositionEvent"in window,m=!v||"documentMode"in document&&document.documentMode>8&&document.documentMode<=11,g=a.topLevelTypes,y=null,C={compositionEnd:{phasedRegistrationNames:{bubbled:d({onCompositionEnd:null}),captured:d({onCompositionEndCapture:null})},dependencies:[g.topBlur,g.topCompositionEnd,g.topKeyDown,g.topKeyPress,g.topKeyUp,g.topMouseDown]},compositionStart:{phasedRegistrationNames:{bubbled:d({onCompositionStart:null}),captured:d({onCompositionStartCapture:null})},dependencies:[g.topBlur,g.topCompositionStart,g.topKeyDown,g.topKeyPress,g.topKeyUp,g.topMouseDown]},compositionUpdate:{phasedRegistrationNames:{bubbled:d({onCompositionUpdate:null}),captured:d({onCompositionUpdateCapture:null})},dependencies:[g.topBlur,g.topCompositionUpdate,g.topKeyDown,g.topKeyPress,g.topKeyUp,g.topMouseDown]}};i.prototype.getText=function(){return this.root.value||this.root[p()]},i.prototype.getData=function(){var e=this.getText(),t=this.startSelection.start,n=this.startValue.length-this.startSelection.end;return e.substr(t,e.length-n-t)};var E={eventTypes:C,extractEvents:function(e,t,a,u){var c,p;if(v?c=n(e):y?o(e,u)&&(c=C.compositionEnd):r(e,u)&&(c=C.compositionStart),m&&(y||c!==C.compositionStart?c===C.compositionEnd&&y&&(p=y.getData(),y=null):y=new i(t)),c){var d=l.getPooled(c,a,u);return p&&(d.data=p),s.accumulateTwoPhaseDispatches(d),d}}};t.exports=E},{"./EventConstants":15,"./EventPropagators":20,"./ExecutionEnvironment":21,"./ReactInputSelection":56,"./SyntheticCompositionEvent":80,"./getTextContentAccessor":113,"./keyOf":125}],9:[function(e,t){"use strict";function n(e,t,n){e.insertBefore(t,e.childNodes[n]||null)}var r,o=e("./Danger"),i=e("./ReactMultiChildUpdateTypes"),a=e("./getTextContentAccessor"),s=e("./invariant"),u=a();r="textContent"===u?function(e,t){e.textContent=t}:function(e,t){for(;e.firstChild;)e.removeChild(e.firstChild);if(t){var n=e.ownerDocument||document;e.appendChild(n.createTextNode(t))}};var c={dangerouslyReplaceNodeWithMarkup:o.dangerouslyReplaceNodeWithMarkup,updateTextContent:r,processUpdates:function(e,t){for(var a,u=null,c=null,l=0;a=e[l];l++)if(a.type===i.MOVE_EXISTING||a.type===i.REMOVE_NODE){var p=a.fromIndex,d=a.parentNode.childNodes[p],f=a.parentID;s(d),u=u||{},u[f]=u[f]||[],u[f][p]=d,c=c||[],c.push(d)}var h=o.dangerouslyRenderMarkup(t);if(c)for(var v=0;vt||r.hasOverloadedBooleanValue[e]&&t===!1}var r=e("./DOMProperty"),o=e("./escapeTextForBrowser"),i=e("./memoizeStringOnly"),a=(e("./warning"),i(function(e){return o(e)+'="'})),s={createMarkupForID:function(e){return a(r.ID_ATTRIBUTE_NAME)+o(e)+'"'},createMarkupForProperty:function(e,t){if(r.isStandardName.hasOwnProperty(e)&&r.isStandardName[e]){if(n(e,t))return"";var i=r.getAttributeName[e];return r.hasBooleanValue[e]||r.hasOverloadedBooleanValue[e]&&t===!0?o(i):a(i)+o(t)+'"'}return r.isCustomAttribute(e)?null==t?"":a(e)+o(t)+'"':null},setValueForProperty:function(e,t,o){if(r.isStandardName.hasOwnProperty(t)&&r.isStandardName[t]){var i=r.getMutationMethod[t];if(i)i(e,o);else if(n(t,o))this.deleteValueForProperty(e,t);else if(r.mustUseAttribute[t])e.setAttribute(r.getAttributeName[t],""+o);else{var a=r.getPropertyName[t];r.hasSideEffects[t]&&e[a]===o||(e[a]=o)}}else r.isCustomAttribute(t)&&(null==o?e.removeAttribute(t):e.setAttribute(t,""+o))},deleteValueForProperty:function(e,t){if(r.isStandardName.hasOwnProperty(t)&&r.isStandardName[t]){var n=r.getMutationMethod[t];if(n)n(e,void 0);else if(r.mustUseAttribute[t])e.removeAttribute(r.getAttributeName[t]);else{var o=r.getPropertyName[t],i=r.getDefaultValueForProperty(e.nodeName,o);r.hasSideEffects[t]&&e[o]===i||(e[o]=i)}}else r.isCustomAttribute(t)&&e.removeAttribute(t)}};t.exports=s},{"./DOMProperty":10,"./escapeTextForBrowser":102,"./memoizeStringOnly":127,"./warning":139}],12:[function(e,t){"use strict";function n(e){return e.substring(1,e.indexOf(" "))}var r=e("./ExecutionEnvironment"),o=e("./createNodesFromMarkup"),i=e("./emptyFunction"),a=e("./getMarkupWrap"),s=e("./invariant"),u=/^(<[^ \/>]+)/,c="data-danger-index",l={dangerouslyRenderMarkup:function(e){s(r.canUseDOM);for(var t,l={},p=0;pu;u++){var l=s[u];if(l){var p=l.extractEvents(e,t,r,i);p&&(a=o(a,p))}}return a},enqueueEvents:function(e){e&&(u=o(u,e))},processEventQueue:function(){var e=u;u=null,i(e,c),a(!u)},__purge:function(){s={}},__getListenerBank:function(){return s}};t.exports=p},{"./EventPluginRegistry":18,"./EventPluginUtils":19,"./accumulate":92,"./forEachAccumulated":105,"./invariant":118,"./isEventSupported":119,"./monitorCodeUse":132}],18:[function(e,t){"use strict";function n(){if(a)for(var e in s){var t=s[e],n=a.indexOf(e);if(i(n>-1),!u.plugins[n]){i(t.extractEvents),u.plugins[n]=t;var o=t.eventTypes;for(var c in o)i(r(o[c],t,c))}}}function r(e,t,n){i(!u.eventNameDispatchConfigs.hasOwnProperty(n)),u.eventNameDispatchConfigs[n]=e;var r=e.phasedRegistrationNames;if(r){for(var a in r)if(r.hasOwnProperty(a)){var s=r[a];o(s,t,n)}return!0}return e.registrationName?(o(e.registrationName,t,n),!0):!1}function o(e,t,n){i(!u.registrationNameModules[e]),u.registrationNameModules[e]=t,u.registrationNameDependencies[e]=t.eventTypes[n].dependencies}var i=e("./invariant"),a=null,s={},u={plugins:[],eventNameDispatchConfigs:{},registrationNameModules:{},registrationNameDependencies:{},injectEventPluginOrder:function(e){i(!a),a=Array.prototype.slice.call(e),n()},injectEventPluginsByName:function(e){var t=!1;for(var r in e)if(e.hasOwnProperty(r)){var o=e[r];s.hasOwnProperty(r)&&s[r]===o||(i(!s[r]),s[r]=o,t=!0)}t&&n()},getPluginModuleForEvent:function(e){var t=e.dispatchConfig;if(t.registrationName)return u.registrationNameModules[t.registrationName]||null;for(var n in t.phasedRegistrationNames)if(t.phasedRegistrationNames.hasOwnProperty(n)){var r=u.registrationNameModules[t.phasedRegistrationNames[n]];if(r)return r}return null},_resetEventPlugins:function(){a=null;for(var e in s)s.hasOwnProperty(e)&&delete s[e];u.plugins.length=0;var t=u.eventNameDispatchConfigs;for(var n in t)t.hasOwnProperty(n)&&delete t[n];var r=u.registrationNameModules;for(var o in r)r.hasOwnProperty(o)&&delete r[o]}};t.exports=u},{"./invariant":118}],19:[function(e,t){"use strict";function n(e){return e===v.topMouseUp||e===v.topTouchEnd||e===v.topTouchCancel}function r(e){return e===v.topMouseMove||e===v.topTouchMove}function o(e){return e===v.topMouseDown||e===v.topTouchStart}function i(e,t){var n=e._dispatchListeners,r=e._dispatchIDs;if(Array.isArray(n))for(var o=0;ol;l++){var d=s[l];a.hasOwnProperty(d)&&a[d]||(d===c.topWheel?u("wheel")?v.ReactEventListener.trapBubbledEvent(c.topWheel,"wheel",o):u("mousewheel")?v.ReactEventListener.trapBubbledEvent(c.topWheel,"mousewheel",o):v.ReactEventListener.trapBubbledEvent(c.topWheel,"DOMMouseScroll",o):d===c.topScroll?u("scroll",!0)?v.ReactEventListener.trapCapturedEvent(c.topScroll,"scroll",o):v.ReactEventListener.trapBubbledEvent(c.topScroll,"scroll",v.ReactEventListener.WINDOW_HANDLE):d===c.topFocus||d===c.topBlur?(u("focus",!0)?(v.ReactEventListener.trapCapturedEvent(c.topFocus,"focus",o),v.ReactEventListener.trapCapturedEvent(c.topBlur,"blur",o)):u("focusin")&&(v.ReactEventListener.trapBubbledEvent(c.topFocus,"focusin",o),v.ReactEventListener.trapBubbledEvent(c.topBlur,"focusout",o)),a[c.topBlur]=!0,a[c.topFocus]=!0):f.hasOwnProperty(d)&&v.ReactEventListener.trapBubbledEvent(d,f[d],o),a[d]=!0)}},trapBubbledEvent:function(e,t,n){return v.ReactEventListener.trapBubbledEvent(e,t,n)},trapCapturedEvent:function(e,t,n){return v.ReactEventListener.trapCapturedEvent(e,t,n)},ensureScrollValueMonitoring:function(){if(!p){var e=s.refreshScrollValues;v.ReactEventListener.monitorScrollValue(e),p=!0}},eventNameDispatchConfigs:o.eventNameDispatchConfigs,registrationNameModules:o.registrationNameModules,putListener:o.putListener,getListener:o.getListener,deleteListener:o.deleteListener,deleteAllListeners:o.deleteAllListeners});t.exports=v},{"./EventConstants":15,"./EventPluginHub":17,"./EventPluginRegistry":18,"./ReactEventEmitterMixin":53,"./ViewportMetrics":91,"./isEventSupported":119,"./merge":128}],30:[function(e,t){"use strict";function n(e,t){this.forEachFunction=e,this.forEachContext=t}function r(e,t,n,r){var o=e;o.forEachFunction.call(o.forEachContext,t,r)}function o(e,t,o){if(null==e)return e;var i=n.getPooled(t,o);p(e,r,i),n.release(i)}function i(e,t,n){this.mapResult=e,this.mapFunction=t,this.mapContext=n}function a(e,t,n,r){var o=e,i=o.mapResult,a=!i.hasOwnProperty(n);if(a){var s=o.mapFunction.call(o.mapContext,t,r);i[n]=s}}function s(e,t,n){if(null==e)return e;var r={},o=i.getPooled(r,t,n);return p(e,a,o),i.release(o),r}function u(){return null}function c(e){return p(e,u,null)}var l=e("./PooledClass"),p=e("./traverseAllChildren"),d=(e("./warning"),l.twoArgumentPooler),f=l.threeArgumentPooler;l.addPoolingTo(n,d),l.addPoolingTo(i,f);var h={forEach:o,map:s,count:c};t.exports=h},{"./PooledClass":26,"./traverseAllChildren":138,"./warning":139}],31:[function(e,t){"use strict";var n=e("./ReactDescriptor"),r=e("./ReactOwner"),o=e("./ReactUpdates"),i=e("./invariant"),a=e("./keyMirror"),s=e("./merge"),u=a({MOUNTED:null,UNMOUNTED:null}),c=!1,l=null,p=null,d={injection:{injectEnvironment:function(e){i(!c),p=e.mountImageIntoNode,l=e.unmountIDFromEnvironment,d.BackendIDOperations=e.BackendIDOperations,c=!0}},LifeCycle:u,BackendIDOperations:null,Mixin:{isMounted:function(){return this._lifeCycleState===u.MOUNTED},setProps:function(e,t){var n=this._pendingDescriptor||this._descriptor;this.replaceProps(s(n.props,e),t)},replaceProps:function(e,t){i(this.isMounted()),i(0===this._mountDepth),this._pendingDescriptor=n.cloneAndReplaceProps(this._pendingDescriptor||this._descriptor,e),o.enqueueUpdate(this,t)},_setPropsInternal:function(e,t){var r=this._pendingDescriptor||this._descriptor;this._pendingDescriptor=n.cloneAndReplaceProps(r,s(r.props,e)),o.enqueueUpdate(this,t)},construct:function(e){this.props=e.props,this._owner=e._owner,this._lifeCycleState=u.UNMOUNTED,this._pendingCallbacks=null,this._descriptor=e,this._pendingDescriptor=null},mountComponent:function(e,t,n){i(!this.isMounted());var o=this._descriptor.props;if(null!=o.ref){var a=this._descriptor._owner;r.addComponentAsRefTo(this,o.ref,a)}this._rootNodeID=e,this._lifeCycleState=u.MOUNTED,this._mountDepth=n},unmountComponent:function(){i(this.isMounted());var e=this.props;null!=e.ref&&r.removeComponentAsRefFrom(this,e.ref,this._owner),l(this._rootNodeID),this._rootNodeID=null,this._lifeCycleState=u.UNMOUNTED},receiveComponent:function(e,t){i(this.isMounted()),this._pendingDescriptor=e,this.performUpdateIfNecessary(t)},performUpdateIfNecessary:function(e){if(null!=this._pendingDescriptor){var t=this._descriptor,n=this._pendingDescriptor;this._descriptor=n,this.props=n.props,this._owner=n._owner,this._pendingDescriptor=null,this.updateComponent(e,t)}},updateComponent:function(e,t){var n=this._descriptor;(n._owner!==t._owner||n.props.ref!==t.props.ref)&&(null!=t.props.ref&&r.removeComponentAsRefFrom(this,t.props.ref,t._owner),null!=n.props.ref&&r.addComponentAsRefTo(this,n.props.ref,n._owner))},mountComponentIntoNode:function(e,t,n){var r=o.ReactReconcileTransaction.getPooled();r.perform(this._mountComponentIntoNode,this,e,t,r,n),o.ReactReconcileTransaction.release(r)},_mountComponentIntoNode:function(e,t,n,r){var o=this.mountComponent(e,n,0);p(o,t,r)},isOwnedBy:function(e){return this._owner===e},getSiblingByRef:function(e){var t=this._owner;return t&&t.refs?t.refs[e]:null}}};t.exports=d},{"./ReactDescriptor":49,"./ReactOwner":62,"./ReactUpdates":74,"./invariant":118,"./keyMirror":124,"./merge":128}],32:[function(e,t){"use strict";var n=e("./ReactDOMIDOperations"),r=e("./ReactMarkupChecksum"),o=e("./ReactMount"),i=e("./ReactPerf"),a=e("./ReactReconcileTransaction"),s=e("./getReactRootElementInContainer"),u=e("./invariant"),c=e("./setInnerHTML"),l=1,p=9,d={ReactReconcileTransaction:a,BackendIDOperations:n,unmountIDFromEnvironment:function(e){o.purgeID(e)},mountImageIntoNode:i.measure("ReactComponentBrowserEnvironment","mountImageIntoNode",function(e,t,n){if(u(t&&(t.nodeType===l||t.nodeType===p)),n){if(r.canReuseMarkup(e,s(t)))return;u(t.nodeType!==p)}u(t.nodeType!==p),c(t,e)})};t.exports=d},{"./ReactDOMIDOperations":40,"./ReactMarkupChecksum":58,"./ReactMount":59,"./ReactPerf":63,"./ReactReconcileTransaction":69,"./getReactRootElementInContainer":112,"./invariant":118,"./setInnerHTML":134}],33:[function(e,t){"use strict";function n(e){var t=e._owner||null;return t&&t.constructor&&t.constructor.displayName?" Check the render method of `"+t.constructor.displayName+"`.":""}function r(e,t){for(var n in t)t.hasOwnProperty(n)&&D("function"==typeof t[n])}function o(e,t){var n=N.hasOwnProperty(t)?N[t]:null;A.hasOwnProperty(t)&&D(n===_.OVERRIDE_BASE),e.hasOwnProperty(t)&&D(n===_.DEFINE_MANY||n===_.DEFINE_MANY_MERGED)}function i(e){var t=e._compositeLifeCycleState;D(e.isMounted()||t===S.MOUNTING),D(t!==S.RECEIVING_STATE),D(t!==S.UNMOUNTING)}function a(e,t){D(!h.isValidFactory(t)),D(!h.isValidDescriptor(t));var n=e.prototype;for(var r in t){var i=t[r];if(t.hasOwnProperty(r))if(o(n,r),w.hasOwnProperty(r))w[r](e,i);else{var a=N.hasOwnProperty(r),s=n.hasOwnProperty(r),u=i&&i.__reactDontBind,p="function"==typeof i,d=p&&!a&&!s&&!u;if(d)n.__reactAutoBindMap||(n.__reactAutoBindMap={}),n.__reactAutoBindMap[r]=i,n[r]=i;else if(s){var f=N[r];D(a&&(f===_.DEFINE_MANY_MERGED||f===_.DEFINE_MANY)),f===_.DEFINE_MANY_MERGED?n[r]=c(n[r],i):f===_.DEFINE_MANY&&(n[r]=l(n[r],i))}else n[r]=i}}}function s(e,t){if(t)for(var n in t){var r=t[n];if(t.hasOwnProperty(n)){var o=n in e,i=r;if(o){var a=e[n],s=typeof a,u=typeof r;D("function"===s&&"function"===u),i=l(a,r)}e[n]=i}}}function u(e,t){return D(e&&t&&"object"==typeof e&&"object"==typeof t),P(t,function(t,n){D(void 0===e[n]),e[n]=t}),e}function c(e,t){return function(){var n=e.apply(this,arguments),r=t.apply(this,arguments);return null==n?r:null==r?n:u(n,r)}}function l(e,t){return function(){e.apply(this,arguments),t.apply(this,arguments)}}var p=e("./ReactComponent"),d=e("./ReactContext"),f=e("./ReactCurrentOwner"),h=e("./ReactDescriptor"),v=(e("./ReactDescriptorValidator"),e("./ReactEmptyComponent")),m=e("./ReactErrorUtils"),g=e("./ReactOwner"),y=e("./ReactPerf"),C=e("./ReactPropTransferer"),E=e("./ReactPropTypeLocations"),R=(e("./ReactPropTypeLocationNames"),e("./ReactUpdates")),M=e("./instantiateReactComponent"),D=e("./invariant"),x=e("./keyMirror"),b=e("./merge"),O=e("./mixInto"),P=(e("./monitorCodeUse"),e("./mapObject")),I=e("./shouldUpdateReactComponent"),_=(e("./warning"),x({DEFINE_ONCE:null,DEFINE_MANY:null,OVERRIDE_BASE:null,DEFINE_MANY_MERGED:null})),T=[],N={mixins:_.DEFINE_MANY,statics:_.DEFINE_MANY,propTypes:_.DEFINE_MANY,contextTypes:_.DEFINE_MANY,childContextTypes:_.DEFINE_MANY,getDefaultProps:_.DEFINE_MANY_MERGED,getInitialState:_.DEFINE_MANY_MERGED,getChildContext:_.DEFINE_MANY_MERGED,render:_.DEFINE_ONCE,componentWillMount:_.DEFINE_MANY,componentDidMount:_.DEFINE_MANY,componentWillReceiveProps:_.DEFINE_MANY,shouldComponentUpdate:_.DEFINE_ONCE,componentWillUpdate:_.DEFINE_MANY,componentDidUpdate:_.DEFINE_MANY,componentWillUnmount:_.DEFINE_MANY,updateComponent:_.OVERRIDE_BASE},w={displayName:function(e,t){e.displayName=t},mixins:function(e,t){if(t)for(var n=0;n",this.tagName=e.toUpperCase()}var i=e("./CSSPropertyOperations"),a=e("./DOMProperty"),s=e("./DOMPropertyOperations"),u=e("./ReactBrowserComponentMixin"),c=e("./ReactComponent"),l=e("./ReactBrowserEventEmitter"),p=e("./ReactMount"),d=e("./ReactMultiChild"),f=e("./ReactPerf"),h=e("./escapeTextForBrowser"),v=e("./invariant"),m=e("./keyOf"),g=e("./merge"),y=e("./mixInto"),C=l.deleteListener,E=l.listenTo,R=l.registrationNameModules,M={string:!0,number:!0},D=m({style:null}),x=1;o.Mixin={mountComponent:f.measure("ReactDOMComponent","mountComponent",function(e,t,r){return c.Mixin.mountComponent.call(this,e,t,r),n(this.props),this._createOpenTagMarkupAndPutListeners(t)+this._createContentMarkup(t)+this._tagClose}),_createOpenTagMarkupAndPutListeners:function(e){var t=this.props,n=this._tagOpen;for(var o in t)if(t.hasOwnProperty(o)){var a=t[o];if(null!=a)if(R.hasOwnProperty(o))r(this._rootNodeID,o,a,e);else{o===D&&(a&&(a=t.style=g(t.style)),a=i.createMarkupForStyles(a));var u=s.createMarkupForProperty(o,a);u&&(n+=" "+u)}}if(e.renderToStaticMarkup)return n+">";var c=s.createMarkupForID(this._rootNodeID);return n+" "+c+">"},_createContentMarkup:function(e){var t=this.props.dangerouslySetInnerHTML;if(null!=t){if(null!=t.__html)return t.__html}else{var n=M[typeof this.props.children]?this.props.children:null,r=null!=n?null:this.props.children;if(null!=n)return h(n);if(null!=r){var o=this.mountChildren(r,e);return o.join("")}}return""},receiveComponent:function(e,t){(e!==this._descriptor||null==e._owner)&&c.Mixin.receiveComponent.call(this,e,t)},updateComponent:f.measure("ReactDOMComponent","updateComponent",function(e,t){n(this._descriptor.props),c.Mixin.updateComponent.call(this,e,t),this._updateDOMProperties(t.props,e),this._updateDOMChildren(t.props,e)}),_updateDOMProperties:function(e,t){var n,o,i,s=this.props;for(n in e)if(!s.hasOwnProperty(n)&&e.hasOwnProperty(n))if(n===D){var u=e[n];for(o in u)u.hasOwnProperty(o)&&(i=i||{},i[o]="")}else R.hasOwnProperty(n)?C(this._rootNodeID,n):(a.isStandardName[n]||a.isCustomAttribute(n))&&c.BackendIDOperations.deletePropertyByID(this._rootNodeID,n);for(n in s){var l=s[n],p=e[n];if(s.hasOwnProperty(n)&&l!==p)if(n===D)if(l&&(l=s.style=g(l)),p){for(o in p)!p.hasOwnProperty(o)||l&&l.hasOwnProperty(o)||(i=i||{},i[o]="");for(o in l)l.hasOwnProperty(o)&&p[o]!==l[o]&&(i=i||{},i[o]=l[o])}else i=l;else R.hasOwnProperty(n)?r(this._rootNodeID,n,l,t):(a.isStandardName[n]||a.isCustomAttribute(n))&&c.BackendIDOperations.updatePropertyByID(this._rootNodeID,n,l)}i&&c.BackendIDOperations.updateStylesByID(this._rootNodeID,i)},_updateDOMChildren:function(e,t){var n=this.props,r=M[typeof e.children]?e.children:null,o=M[typeof n.children]?n.children:null,i=e.dangerouslySetInnerHTML&&e.dangerouslySetInnerHTML.__html,a=n.dangerouslySetInnerHTML&&n.dangerouslySetInnerHTML.__html,s=null!=r?null:e.children,u=null!=o?null:n.children,l=null!=r||null!=i,p=null!=o||null!=a;null!=s&&null==u?this.updateChildren(null,t):l&&!p&&this.updateTextContent(""),null!=o?r!==o&&this.updateTextContent(""+o):null!=a?i!==a&&c.BackendIDOperations.updateInnerHTMLByID(this._rootNodeID,a):null!=u&&this.updateChildren(u,t)},unmountComponent:function(){this.unmountChildren(),l.deleteAllListeners(this._rootNodeID),c.Mixin.unmountComponent.call(this)}},y(o,c.Mixin),y(o,o.Mixin),y(o,d.Mixin),y(o,u),t.exports=o},{"./CSSPropertyOperations":4,"./DOMProperty":10,"./DOMPropertyOperations":11,"./ReactBrowserComponentMixin":28,"./ReactBrowserEventEmitter":29,"./ReactComponent":31,"./ReactMount":59,"./ReactMultiChild":60,"./ReactPerf":63,"./escapeTextForBrowser":102,"./invariant":118,"./keyOf":125,"./merge":128,"./mixInto":131}],39:[function(e,t){"use strict";var n=e("./EventConstants"),r=e("./LocalEventTrapMixin"),o=e("./ReactBrowserComponentMixin"),i=e("./ReactCompositeComponent"),a=e("./ReactDOM"),s=a.form,u=i.createClass({displayName:"ReactDOMForm",mixins:[o,r],render:function(){return this.transferPropsTo(s(null,this.props.children))},componentDidMount:function(){this.trapBubbledEvent(n.topLevelTypes.topReset,"reset"),this.trapBubbledEvent(n.topLevelTypes.topSubmit,"submit")}});t.exports=u},{"./EventConstants":15,"./LocalEventTrapMixin":24,"./ReactBrowserComponentMixin":28,"./ReactCompositeComponent":33,"./ReactDOM":36}],40:[function(e,t){"use strict";var n=e("./CSSPropertyOperations"),r=e("./DOMChildrenOperations"),o=e("./DOMPropertyOperations"),i=e("./ReactMount"),a=e("./ReactPerf"),s=e("./invariant"),u=e("./setInnerHTML"),c={dangerouslySetInnerHTML:"`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.",style:"`style` must be set using `updateStylesByID()`."},l={updatePropertyByID:a.measure("ReactDOMIDOperations","updatePropertyByID",function(e,t,n){var r=i.getNode(e);s(!c.hasOwnProperty(t)),null!=n?o.setValueForProperty(r,t,n):o.deleteValueForProperty(r,t)}),deletePropertyByID:a.measure("ReactDOMIDOperations","deletePropertyByID",function(e,t,n){var r=i.getNode(e);s(!c.hasOwnProperty(t)),o.deleteValueForProperty(r,t,n)}),updateStylesByID:a.measure("ReactDOMIDOperations","updateStylesByID",function(e,t){var r=i.getNode(e);n.setValueForStyles(r,t)}),updateInnerHTMLByID:a.measure("ReactDOMIDOperations","updateInnerHTMLByID",function(e,t){var n=i.getNode(e);u(n,t)}),updateTextContentByID:a.measure("ReactDOMIDOperations","updateTextContentByID",function(e,t){var n=i.getNode(e);r.updateTextContent(n,t)}),dangerouslyReplaceNodeWithMarkupByID:a.measure("ReactDOMIDOperations","dangerouslyReplaceNodeWithMarkupByID",function(e,t){var n=i.getNode(e);r.dangerouslyReplaceNodeWithMarkup(n,t)}),dangerouslyProcessChildrenUpdates:a.measure("ReactDOMIDOperations","dangerouslyProcessChildrenUpdates",function(e,t){for(var n=0;nl;l++){var f=s[l];if(f!==i&&f.form===i.form){var h=u.getID(f);c(h);var v=d[h];c(v),v.setState({checked:!1})}}}return t}});t.exports=f},{"./AutoFocusMixin":1,"./DOMPropertyOperations":11,"./LinkedValueUtils":23,"./ReactBrowserComponentMixin":28,"./ReactCompositeComponent":33,"./ReactDOM":36,"./ReactMount":59,"./invariant":118,"./merge":128}],43:[function(e,t){"use strict";var n=e("./ReactBrowserComponentMixin"),r=e("./ReactCompositeComponent"),o=e("./ReactDOM"),i=(e("./warning"),o.option),a=r.createClass({displayName:"ReactDOMOption",mixins:[n],componentWillMount:function(){},render:function(){return i(this.props,this.props.children)}});t.exports=a},{"./ReactBrowserComponentMixin":28,"./ReactCompositeComponent":33,"./ReactDOM":36,"./warning":139}],44:[function(e,t){"use strict";function n(e,t){if(null!=e[t])if(e.multiple){if(!Array.isArray(e[t]))return new Error("The `"+t+"` prop supplied to must be an array if `multiple` is true.")}else if(Array.isArray(e[t]))return new Error("The `"+t+"` prop supplied to must be a scalar value if `multiple` is false.")}function r(e,t){var n,r,o,i=e.props.multiple,a=null!=t?t:e.state.value,s=e.getDOMNode().options;if(i)for(n={},r=0,o=a.length;o>r;++r)n[""+a[r]]=!0;else n=""+a;for(r=0,o=s.length;o>r;r++){var u=i?n.hasOwnProperty(s[r].value):s[r].value===n;u!==s[r].selected&&(s[r].selected=u)}}var o=e("./AutoFocusMixin"),i=e("./LinkedValueUtils"),a=e("./ReactBrowserComponentMixin"),s=e("./ReactCompositeComponent"),u=e("./ReactDOM"),c=e("./merge"),l=u.select,p=s.createClass({displayName:"ReactDOMSelect",mixins:[o,i.Mixin,a],propTypes:{defaultValue:n,value:n},getInitialState:function(){return{value:this.props.defaultValue||(this.props.multiple?[]:"")}},componentWillReceiveProps:function(e){!this.props.multiple&&e.multiple?this.setState({value:[this.state.value]}):this.props.multiple&&!e.multiple&&this.setState({value:this.state.value[0]})},shouldComponentUpdate:function(){return!this._isChanging},render:function(){var e=c(this.props);return e.onChange=this._handleChange,e.value=null,l(e,this.props.children)},componentDidMount:function(){r(this,i.getValue(this))},componentDidUpdate:function(e){var t=i.getValue(this),n=!!e.multiple,o=!!this.props.multiple;(null!=t||n!==o)&&r(this,t)},_handleChange:function(e){var t,n=i.getOnChange(this);n&&(this._isChanging=!0,t=n.call(this,e),this._isChanging=!1);var r;if(this.props.multiple){r=[];for(var o=e.target.options,a=0,s=o.length;s>a;a++)o[a].selected&&r.push(o[a].value)}else r=e.target.value;return this.setState({value:r}),t}});t.exports=p},{"./AutoFocusMixin":1,"./LinkedValueUtils":23,"./ReactBrowserComponentMixin":28,"./ReactCompositeComponent":33,"./ReactDOM":36,"./merge":128}],45:[function(e,t){"use strict";function n(e,t,n,r){return e===n&&t===r}function r(e){var t=document.selection,n=t.createRange(),r=n.text.length,o=n.duplicate();o.moveToElementText(e),o.setEndPoint("EndToStart",n);var i=o.text.length,a=i+r;return{start:i,end:a}}function o(e){var t=window.getSelection();if(0===t.rangeCount)return null;var r=t.anchorNode,o=t.anchorOffset,i=t.focusNode,a=t.focusOffset,s=t.getRangeAt(0),u=n(t.anchorNode,t.anchorOffset,t.focusNode,t.focusOffset),c=u?0:s.toString().length,l=s.cloneRange();l.selectNodeContents(e),l.setEnd(s.startContainer,s.startOffset);var p=n(l.startContainer,l.startOffset,l.endContainer,l.endOffset),d=p?0:l.toString().length,f=d+c,h=document.createRange();h.setStart(r,o),h.setEnd(i,a);var v=h.collapsed;return h.detach(),{start:v?f:d,end:v?d:f}}function i(e,t){var n,r,o=document.selection.createRange().duplicate();"undefined"==typeof t.end?(n=t.start,r=n):t.start>t.end?(n=t.end,r=t.start):(n=t.start,r=t.end),o.moveToElementText(e),o.moveStart("character",n),o.setEndPoint("EndToStart",o),o.moveEnd("character",r-n),o.select()}function a(e,t){var n=window.getSelection(),r=e[c()].length,o=Math.min(t.start,r),i="undefined"==typeof t.end?o:Math.min(t.end,r);if(!n.extend&&o>i){var a=i;i=o,o=a}var s=u(e,o),l=u(e,i);if(s&&l){var p=document.createRange();p.setStart(s.node,s.offset),n.removeAllRanges(),o>i?(n.addRange(p),n.extend(l.node,l.offset)):(p.setEnd(l.node,l.offset),n.addRange(p)),p.detach()}}var s=e("./ExecutionEnvironment"),u=e("./getNodeForCharacterOffset"),c=e("./getTextContentAccessor"),l=s.canUseDOM&&document.selection,p={getOffsets:l?r:o,setOffsets:l?i:a};t.exports=p},{"./ExecutionEnvironment":21,"./getNodeForCharacterOffset":111,"./getTextContentAccessor":113}],46:[function(e,t){"use strict";var n=e("./AutoFocusMixin"),r=e("./DOMPropertyOperations"),o=e("./LinkedValueUtils"),i=e("./ReactBrowserComponentMixin"),a=e("./ReactCompositeComponent"),s=e("./ReactDOM"),u=e("./invariant"),c=e("./merge"),l=(e("./warning"),s.textarea),p=a.createClass({displayName:"ReactDOMTextarea",mixins:[n,o.Mixin,i],getInitialState:function(){var e=this.props.defaultValue,t=this.props.children;null!=t&&(u(null==e),Array.isArray(t)&&(u(t.length<=1),t=t[0]),e=""+t),null==e&&(e="");var n=o.getValue(this);return{initialValue:""+(null!=n?n:e)}},shouldComponentUpdate:function(){return!this._isChanging},render:function(){var e=c(this.props);return u(null==e.dangerouslySetInnerHTML),e.defaultValue=null,e.value=null,e.onChange=this._handleChange,l(e,this.state.initialValue)
20 | },componentDidUpdate:function(){var e=o.getValue(this);if(null!=e){var t=this.getDOMNode();r.setValueForProperty(t,"value",""+e)}},_handleChange:function(e){var t,n=o.getOnChange(this);return n&&(this._isChanging=!0,t=n.call(this,e),this._isChanging=!1),this.setState({value:e.target.value}),t}});t.exports=p},{"./AutoFocusMixin":1,"./DOMPropertyOperations":11,"./LinkedValueUtils":23,"./ReactBrowserComponentMixin":28,"./ReactCompositeComponent":33,"./ReactDOM":36,"./invariant":118,"./merge":128,"./warning":139}],47:[function(e,t){"use strict";function n(){this.reinitializeTransaction()}var r=e("./ReactUpdates"),o=e("./Transaction"),i=e("./emptyFunction"),a=e("./mixInto"),s={initialize:i,close:function(){p.isBatchingUpdates=!1}},u={initialize:i,close:r.flushBatchedUpdates.bind(r)},c=[u,s];a(n,o.Mixin),a(n,{getTransactionWrappers:function(){return c}});var l=new n,p={isBatchingUpdates:!1,batchedUpdates:function(e,t,n){var r=p.isBatchingUpdates;p.isBatchingUpdates=!0,r?e(t,n):l.perform(e,null,t,n)}};t.exports=p},{"./ReactUpdates":74,"./Transaction":90,"./emptyFunction":100,"./mixInto":131}],48:[function(e,t){"use strict";function n(){x.EventEmitter.injectReactEventListener(D),x.EventPluginHub.injectEventPluginOrder(s),x.EventPluginHub.injectInstanceHandle(b),x.EventPluginHub.injectMount(O),x.EventPluginHub.injectEventPluginsByName({SimpleEventPlugin:_,EnterLeaveEventPlugin:u,ChangeEventPlugin:o,CompositionEventPlugin:a,MobileSafariClickEventPlugin:p,SelectEventPlugin:P,BeforeInputEventPlugin:r}),x.DOM.injectComponentClasses({button:m,form:g,img:y,input:C,option:E,select:R,textarea:M,html:N(v.html),head:N(v.head),body:N(v.body)}),x.CompositeComponent.injectMixin(d),x.DOMProperty.injectDOMPropertyConfig(l),x.DOMProperty.injectDOMPropertyConfig(T),x.EmptyComponent.injectEmptyComponent(v.noscript),x.Updates.injectReconcileTransaction(f.ReactReconcileTransaction),x.Updates.injectBatchingStrategy(h),x.RootIndex.injectCreateReactRootIndex(c.canUseDOM?i.createReactRootIndex:I.createReactRootIndex),x.Component.injectEnvironment(f)}var r=e("./BeforeInputEventPlugin"),o=e("./ChangeEventPlugin"),i=e("./ClientReactRootIndex"),a=e("./CompositionEventPlugin"),s=e("./DefaultEventPluginOrder"),u=e("./EnterLeaveEventPlugin"),c=e("./ExecutionEnvironment"),l=e("./HTMLDOMPropertyConfig"),p=e("./MobileSafariClickEventPlugin"),d=e("./ReactBrowserComponentMixin"),f=e("./ReactComponentBrowserEnvironment"),h=e("./ReactDefaultBatchingStrategy"),v=e("./ReactDOM"),m=e("./ReactDOMButton"),g=e("./ReactDOMForm"),y=e("./ReactDOMImg"),C=e("./ReactDOMInput"),E=e("./ReactDOMOption"),R=e("./ReactDOMSelect"),M=e("./ReactDOMTextarea"),D=e("./ReactEventListener"),x=e("./ReactInjection"),b=e("./ReactInstanceHandles"),O=e("./ReactMount"),P=e("./SelectEventPlugin"),I=e("./ServerReactRootIndex"),_=e("./SimpleEventPlugin"),T=e("./SVGDOMPropertyConfig"),N=e("./createFullPageComponent");t.exports={inject:n}},{"./BeforeInputEventPlugin":2,"./ChangeEventPlugin":6,"./ClientReactRootIndex":7,"./CompositionEventPlugin":8,"./DefaultEventPluginOrder":13,"./EnterLeaveEventPlugin":14,"./ExecutionEnvironment":21,"./HTMLDOMPropertyConfig":22,"./MobileSafariClickEventPlugin":25,"./ReactBrowserComponentMixin":28,"./ReactComponentBrowserEnvironment":32,"./ReactDOM":36,"./ReactDOMButton":37,"./ReactDOMForm":39,"./ReactDOMImg":41,"./ReactDOMInput":42,"./ReactDOMOption":43,"./ReactDOMSelect":44,"./ReactDOMTextarea":46,"./ReactDefaultBatchingStrategy":47,"./ReactEventListener":54,"./ReactInjection":55,"./ReactInstanceHandles":57,"./ReactMount":59,"./SVGDOMPropertyConfig":75,"./SelectEventPlugin":76,"./ServerReactRootIndex":77,"./SimpleEventPlugin":78,"./createFullPageComponent":97}],49:[function(e,t){"use strict";function n(e,t){if("function"==typeof t)for(var n in t)if(t.hasOwnProperty(n)){var r=t[n];if("function"==typeof r){var o=r.bind(t);for(var i in r)r.hasOwnProperty(i)&&(o[i]=r[i]);e[n]=o}else e[n]=r}}var r=e("./ReactContext"),o=e("./ReactCurrentOwner"),i=e("./merge"),a=(e("./warning"),function(){});a.createFactory=function(e){var t=Object.create(a.prototype),s=function(e,n){null==e?e={}:"object"==typeof e&&(e=i(e));var a=arguments.length-1;if(1===a)e.children=n;else if(a>1){for(var s=Array(a),u=0;a>u;u++)s[u]=arguments[u+1];e.children=s}var c=Object.create(t);return c._owner=o.current,c._context=r.current,c.props=e,c};return s.prototype=t,s.type=e,t.type=e,n(s,e),t.constructor=s,s},a.cloneAndReplaceProps=function(e,t){var n=Object.create(e.constructor.prototype);return n._owner=e._owner,n._context=e._context,n.props=t,n},a.isValidFactory=function(e){return"function"==typeof e&&e.prototype instanceof a},a.isValidDescriptor=function(e){return e instanceof a},t.exports=a},{"./ReactContext":34,"./ReactCurrentOwner":35,"./merge":128,"./warning":139}],50:[function(e,t){"use strict";function n(){var e=p.current;return e&&e.constructor.displayName||void 0}function r(e,t){e._store.validated||null!=e.props.key||(e._store.validated=!0,i("react_key_warning",'Each child in an array should have a unique "key" prop.',e,t))}function o(e,t,n){m.test(e)&&i("react_numeric_key_warning","Child objects should have non-numeric keys so ordering is preserved.",t,n)}function i(e,t,r,o){var i=n(),a=o.displayName,s=i||a,u=f[e];if(!u.hasOwnProperty(s)){u[s]=!0,t+=i?" Check the render method of "+i+".":" Check the renderComponent call using <"+a+">.";var c=null;r._owner&&r._owner!==p.current&&(c=r._owner.constructor.displayName,t+=" It was passed a child from "+c+"."),t+=" See http://fb.me/react-warning-keys for more information.",d(e,{component:s,componentOwner:c}),console.warn(t)}}function a(){var e=n()||"";h.hasOwnProperty(e)||(h[e]=!0,d("react_object_map_children"))}function s(e,t){if(Array.isArray(e))for(var n=0;no;o++){t=e.ancestors[o];var a=l.getID(t)||"";v._handleTopLevel(e.topLevelType,t,a,e.nativeEvent)}}function i(e){var t=f(window);e(t)}var a=e("./EventListener"),s=e("./ExecutionEnvironment"),u=e("./PooledClass"),c=e("./ReactInstanceHandles"),l=e("./ReactMount"),p=e("./ReactUpdates"),d=e("./getEventTarget"),f=e("./getUnboundedScrollPosition"),h=e("./mixInto");h(r,{destructor:function(){this.topLevelType=null,this.nativeEvent=null,this.ancestors.length=0}}),u.addPoolingTo(r,u.twoArgumentPooler);var v={_enabled:!0,_handleTopLevel:null,WINDOW_HANDLE:s.canUseDOM?window:null,setHandleTopLevel:function(e){v._handleTopLevel=e},setEnabled:function(e){v._enabled=!!e},isEnabled:function(){return v._enabled},trapBubbledEvent:function(e,t,n){var r=n;return r?a.listen(r,t,v.dispatchEvent.bind(null,e)):void 0},trapCapturedEvent:function(e,t,n){var r=n;return r?a.capture(r,t,v.dispatchEvent.bind(null,e)):void 0},monitorScrollValue:function(e){var t=i.bind(null,e);a.listen(window,"scroll",t),a.listen(window,"resize",t)},dispatchEvent:function(e,t){if(v._enabled){var n=r.getPooled(e,t);try{p.batchedUpdates(o,n)}finally{r.release(n)}}}};t.exports=v},{"./EventListener":16,"./ExecutionEnvironment":21,"./PooledClass":26,"./ReactInstanceHandles":57,"./ReactMount":59,"./ReactUpdates":74,"./getEventTarget":109,"./getUnboundedScrollPosition":114,"./mixInto":131}],55:[function(e,t){"use strict";var n=e("./DOMProperty"),r=e("./EventPluginHub"),o=e("./ReactComponent"),i=e("./ReactCompositeComponent"),a=e("./ReactDOM"),s=e("./ReactEmptyComponent"),u=e("./ReactBrowserEventEmitter"),c=e("./ReactPerf"),l=e("./ReactRootIndex"),p=e("./ReactUpdates"),d={Component:o.injection,CompositeComponent:i.injection,DOMProperty:n.injection,EmptyComponent:s.injection,EventPluginHub:r.injection,DOM:a.injection,EventEmitter:u.injection,Perf:c.injection,RootIndex:l.injection,Updates:p.injection};t.exports=d},{"./DOMProperty":10,"./EventPluginHub":17,"./ReactBrowserEventEmitter":29,"./ReactComponent":31,"./ReactCompositeComponent":33,"./ReactDOM":36,"./ReactEmptyComponent":51,"./ReactPerf":63,"./ReactRootIndex":70,"./ReactUpdates":74}],56:[function(e,t){"use strict";function n(e){return o(document.documentElement,e)}var r=e("./ReactDOMSelection"),o=e("./containsNode"),i=e("./focusNode"),a=e("./getActiveElement"),s={hasSelectionCapabilities:function(e){return e&&("INPUT"===e.nodeName&&"text"===e.type||"TEXTAREA"===e.nodeName||"true"===e.contentEditable)},getSelectionInformation:function(){var e=a();return{focusedElem:e,selectionRange:s.hasSelectionCapabilities(e)?s.getSelection(e):null}},restoreSelection:function(e){var t=a(),r=e.focusedElem,o=e.selectionRange;t!==r&&n(r)&&(s.hasSelectionCapabilities(r)&&s.setSelection(r,o),i(r))},getSelection:function(e){var t;if("selectionStart"in e)t={start:e.selectionStart,end:e.selectionEnd};else if(document.selection&&"INPUT"===e.nodeName){var n=document.selection.createRange();n.parentElement()===e&&(t={start:-n.moveStart("character",-e.value.length),end:-n.moveEnd("character",-e.value.length)})}else t=r.getOffsets(e);return t||{start:0,end:0}},setSelection:function(e,t){var n=t.start,o=t.end;if("undefined"==typeof o&&(o=n),"selectionStart"in e)e.selectionStart=n,e.selectionEnd=Math.min(o,e.value.length);else if(document.selection&&"INPUT"===e.nodeName){var i=e.createTextRange();i.collapse(!0),i.moveStart("character",n),i.moveEnd("character",o-n),i.select()}else r.setOffsets(e,t)}};t.exports=s},{"./ReactDOMSelection":45,"./containsNode":94,"./focusNode":104,"./getActiveElement":106}],57:[function(e,t){"use strict";function n(e){return d+e.toString(36)}function r(e,t){return e.charAt(t)===d||t===e.length}function o(e){return""===e||e.charAt(0)===d&&e.charAt(e.length-1)!==d}function i(e,t){return 0===t.indexOf(e)&&r(t,e.length)}function a(e){return e?e.substr(0,e.lastIndexOf(d)):""}function s(e,t){if(p(o(e)&&o(t)),p(i(e,t)),e===t)return e;for(var n=e.length+f,a=n;a=a;a++)if(r(e,a)&&r(t,a))i=a;else if(e.charAt(a)!==t.charAt(a))break;var s=e.substr(0,i);return p(o(s)),s}function c(e,t,n,r,o,u){e=e||"",t=t||"",p(e!==t);var c=i(t,e);p(c||i(e,t));for(var l=0,d=c?a:s,f=e;;f=d(f,t)){var v;if(o&&f===e||u&&f===t||(v=n(f,c,r)),v===!1||f===t)break;p(l++1){var t=e.indexOf(d,1);return t>-1?e.substr(0,t):e}return null},traverseEnterLeave:function(e,t,n,r,o){var i=u(e,t);i!==e&&c(e,i,n,r,!1,!0),i!==t&&c(i,t,n,o,!0,!1)},traverseTwoPhase:function(e,t,n){e&&(c("",e,t,n,!0,!1),c(e,"",t,n,!1,!0))},traverseAncestors:function(e,t,n){c("",e,t,n,!0,!1)},_getFirstCommonAncestorID:u,_getNextDescendantID:s,isAncestorIDOf:i,SEPARATOR:d};t.exports=v},{"./ReactRootIndex":70,"./invariant":118}],58:[function(e,t){"use strict";var n=e("./adler32"),r={CHECKSUM_ATTR_NAME:"data-react-checksum",addChecksumToMarkup:function(e){var t=n(e);return e.replace(">"," "+r.CHECKSUM_ATTR_NAME+'="'+t+'">')},canReuseMarkup:function(e,t){var o=t.getAttribute(r.CHECKSUM_ATTR_NAME);o=o&&parseInt(o,10);var i=n(e);return i===o}};t.exports=r},{"./adler32":93}],59:[function(e,t){"use strict";function n(e){var t=g(e);return t&&T.getID(t)}function r(e){var t=o(e);if(t)if(D.hasOwnProperty(t)){var n=D[t];n!==e&&(C(!s(n,t)),D[t]=e)}else D[t]=e;return t}function o(e){return e&&e.getAttribute&&e.getAttribute(M)||""}function i(e,t){var n=o(e);n!==t&&delete D[n],e.setAttribute(M,t),D[t]=e}function a(e){return D.hasOwnProperty(e)&&s(D[e],e)||(D[e]=T.findReactNodeByID(e)),D[e]}function s(e,t){if(e){C(o(e)===t);var n=T.findReactContainerForID(t);if(n&&m(n,e))return!0}return!1}function u(e){delete D[e]}function c(e){var t=D[e];return t&&s(t,e)?void(_=t):!1}function l(e){_=null,h.traverseAncestors(e,c);var t=_;return _=null,t}var p=e("./DOMProperty"),d=e("./ReactBrowserEventEmitter"),f=(e("./ReactCurrentOwner"),e("./ReactDescriptor")),h=e("./ReactInstanceHandles"),v=e("./ReactPerf"),m=e("./containsNode"),g=e("./getReactRootElementInContainer"),y=e("./instantiateReactComponent"),C=e("./invariant"),E=e("./shouldUpdateReactComponent"),R=(e("./warning"),h.SEPARATOR),M=p.ID_ATTRIBUTE_NAME,D={},x=1,b=9,O={},P={},I=[],_=null,T={_instancesByReactRootID:O,scrollMonitor:function(e,t){t()},_updateRootComponent:function(e,t,n,r){var o=t.props;return T.scrollMonitor(n,function(){e.replaceProps(o,r)}),e},_registerComponent:function(e,t){C(t&&(t.nodeType===x||t.nodeType===b)),d.ensureScrollValueMonitoring();var n=T.registerContainer(t);return O[n]=e,n},_renderNewRootComponent:v.measure("ReactMount","_renderNewRootComponent",function(e,t,n){var r=y(e),o=T._registerComponent(r,t);return r.mountComponentIntoNode(o,t,n),r}),renderComponent:function(e,t,r){C(f.isValidDescriptor(e));var o=O[n(t)];if(o){var i=o._descriptor;if(E(i,e))return T._updateRootComponent(o,e,t,r);T.unmountComponentAtNode(t)}var a=g(t),s=a&&T.isRenderedByReact(a),u=s&&!o,c=T._renderNewRootComponent(e,t,u);return r&&r.call(c),c},constructAndRenderComponent:function(e,t,n){return T.renderComponent(e(t),n)},constructAndRenderComponentByID:function(e,t,n){var r=document.getElementById(n);return C(r),T.constructAndRenderComponent(e,t,r)},registerContainer:function(e){var t=n(e);return t&&(t=h.getReactRootIDFromNodeID(t)),t||(t=h.createReactRootID()),P[t]=e,t},unmountComponentAtNode:function(e){var t=n(e),r=O[t];return r?(T.unmountComponentFromNode(r,e),delete O[t],delete P[t],!0):!1},unmountComponentFromNode:function(e,t){for(e.unmountComponent(),t.nodeType===b&&(t=t.documentElement);t.lastChild;)t.removeChild(t.lastChild)},findReactContainerForID:function(e){var t=h.getReactRootIDFromNodeID(e),n=P[t];return n},findReactNodeByID:function(e){var t=T.findReactContainerForID(e);return T.findComponentRoot(t,e)},isRenderedByReact:function(e){if(1!==e.nodeType)return!1;var t=T.getID(e);return t?t.charAt(0)===R:!1},getFirstReactDOM:function(e){for(var t=e;t&&t.parentNode!==t;){if(T.isRenderedByReact(t))return t;t=t.parentNode}return null},findComponentRoot:function(e,t){var n=I,r=0,o=l(t)||e;for(n[0]=o.firstChild,n.length=1;r>",E={array:r("array"),bool:r("boolean"),func:r("function"),number:r("number"),object:r("object"),string:r("string"),any:o(),arrayOf:i,component:a(),instanceOf:s,objectOf:c,oneOf:u,oneOfType:l,renderable:p(),shape:d};t.exports=E},{"./ReactDescriptor":49,"./ReactPropTypeLocationNames":65,"./emptyFunction":100}],68:[function(e,t){"use strict";function n(){this.listenersToPut=[]}var r=e("./PooledClass"),o=e("./ReactBrowserEventEmitter"),i=e("./mixInto");i(n,{enqueuePutListener:function(e,t,n){this.listenersToPut.push({rootNodeID:e,propKey:t,propValue:n})},putListeners:function(){for(var e=0;e"+i+""},receiveComponent:function(e){var t=e.props;t!==this.props&&(this.props=t,o.BackendIDOperations.updateTextContentByID(this._rootNodeID,t))}}),t.exports=i.createFactory(u)},{"./DOMPropertyOperations":11,"./ReactBrowserComponentMixin":28,"./ReactComponent":31,"./ReactDescriptor":49,"./escapeTextForBrowser":102,"./mixInto":131}],74:[function(e,t){"use strict";function n(){d(R.ReactReconcileTransaction&&v)}function r(){this.reinitializeTransaction(),this.dirtyComponentsLength=null,this.callbackQueue=u.getPooled(null),this.reconcileTransaction=R.ReactReconcileTransaction.getPooled()}function o(e,t,r){n(),v.batchedUpdates(e,t,r)}function i(e,t){return e._mountDepth-t._mountDepth}function a(e){var t=e.dirtyComponentsLength;d(t===h.length),h.sort(i);for(var n=0;t>n;n++){var r=h[n];if(r.isMounted()){var o=r._pendingCallbacks;if(r._pendingCallbacks=null,r.performUpdateIfNecessary(e.reconcileTransaction),o)for(var a=0;a":">","<":"<",'"':""","'":"'"},i=/[&><"']/g;t.exports=r},{}],103:[function(e,t){"use strict";function n(e,t,n){var r=e,o=!r.hasOwnProperty(n);o&&null!=t&&(r[n]=t)}function r(e){if(null==e)return e;var t={};return o(e,n,t),t}{var o=e("./traverseAllChildren");e("./warning")}t.exports=r},{"./traverseAllChildren":138,"./warning":139}],104:[function(e,t){"use strict";function n(e){e.disabled||e.focus()}t.exports=n},{}],105:[function(e,t){"use strict";var n=function(e,t,n){Array.isArray(e)?e.forEach(t,n):e&&t.call(n,e)};t.exports=n},{}],106:[function(e,t){function n(){try{return document.activeElement||document.body}catch(e){return document.body}}t.exports=n},{}],107:[function(e,t){"use strict";function n(e){if(e.key){var t=o[e.key]||e.key;if("Unidentified"!==t)return t}if("keypress"===e.type){var n="charCode"in e?e.charCode:e.keyCode;return 13===n?"Enter":String.fromCharCode(n)}return"keydown"===e.type||"keyup"===e.type?i[e.keyCode]||"Unidentified":void r(!1)}var r=e("./invariant"),o={Esc:"Escape",Spacebar:" ",Left:"ArrowLeft",Up:"ArrowUp",Right:"ArrowRight",Down:"ArrowDown",Del:"Delete",Win:"OS",Menu:"ContextMenu",Apps:"ContextMenu",Scroll:"ScrollLock",MozPrintableKey:"Unidentified"},i={8:"Backspace",9:"Tab",12:"Clear",13:"Enter",16:"Shift",17:"Control",18:"Alt",19:"Pause",20:"CapsLock",27:"Escape",32:" ",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"ArrowLeft",38:"ArrowUp",39:"ArrowRight",40:"ArrowDown",45:"Insert",46:"Delete",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NumLock",145:"ScrollLock",224:"Meta"};t.exports=n},{"./invariant":118}],108:[function(e,t){"use strict";function n(e){var t=this,n=t.nativeEvent;if(n.getModifierState)return n.getModifierState(e);var r=o[e];return r?!!n[r]:!1}function r(){return n}var o={Alt:"altKey",Control:"ctrlKey",Meta:"metaKey",Shift:"shiftKey"};t.exports=r},{}],109:[function(e,t){"use strict";function n(e){var t=e.target||e.srcElement||window;return 3===t.nodeType?t.parentNode:t}t.exports=n},{}],110:[function(e,t){function n(e){return o(!!i),p.hasOwnProperty(e)||(e="*"),a.hasOwnProperty(e)||(i.innerHTML="*"===e?" ":"<"+e+">"+e+">",a[e]=!i.firstChild),a[e]?p[e]:null}var r=e("./ExecutionEnvironment"),o=e("./invariant"),i=r.canUseDOM?document.createElement("div"):null,a={circle:!0,defs:!0,ellipse:!0,g:!0,line:!0,linearGradient:!0,path:!0,polygon:!0,polyline:!0,radialGradient:!0,rect:!0,stop:!0,text:!0},s=[1,''," "],u=[1,""],c=[3,""],l=[1,""," "],p={"*":[1,"?","
"],area:[1,""," "],col:[2,""],legend:[1,""," "],param:[1,""," "],tr:[2,""],optgroup:s,option:s,caption:u,colgroup:u,tbody:u,tfoot:u,thead:u,td:c,th:c,circle:l,defs:l,ellipse:l,g:l,line:l,linearGradient:l,path:l,polygon:l,polyline:l,radialGradient:l,rect:l,stop:l,text:l};t.exports=n},{"./ExecutionEnvironment":21,"./invariant":118}],111:[function(e,t){"use strict";function n(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function r(e){for(;e;){if(e.nextSibling)return e.nextSibling;e=e.parentNode}}function o(e,t){for(var o=n(e),i=0,a=0;o;){if(3==o.nodeType){if(a=i+o.textContent.length,t>=i&&a>=t)return{node:o,offset:t-i};i=a}o=n(r(o))}}t.exports=o},{}],112:[function(e,t){"use strict";function n(e){return e?e.nodeType===r?e.documentElement:e.firstChild:null}var r=9;t.exports=n},{}],113:[function(e,t){"use strict";function n(){return!o&&r.canUseDOM&&(o="textContent"in document.documentElement?"textContent":"innerText"),o}var r=e("./ExecutionEnvironment"),o=null;t.exports=n},{"./ExecutionEnvironment":21}],114:[function(e,t){"use strict";function n(e){return e===window?{x:window.pageXOffset||document.documentElement.scrollLeft,y:window.pageYOffset||document.documentElement.scrollTop}:{x:e.scrollLeft,y:e.scrollTop}}t.exports=n},{}],115:[function(e,t){function n(e){return e.replace(r,"-$1").toLowerCase()}var r=/([A-Z])/g;t.exports=n},{}],116:[function(e,t){"use strict";function n(e){return r(e).replace(o,"-ms-")}var r=e("./hyphenate"),o=/^ms-/;t.exports=n},{"./hyphenate":115}],117:[function(e,t){"use strict";function n(e){return e&&"function"==typeof e.type&&"function"==typeof e.type.prototype.mountComponent&&"function"==typeof e.type.prototype.receiveComponent}function r(e){return o(n(e)),new e.type(e)}var o=e("./invariant");t.exports=r},{"./invariant":118}],118:[function(e,t){"use strict";var n=function(e,t,n,r,o,i,a,s){if(!e){var u;if(void 0===t)u=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,o,i,a,s],l=0;u=new Error("Invariant Violation: "+t.replace(/%s/g,function(){return c[l++]}))}throw u.framesToPop=1,u}};t.exports=n},{}],119:[function(e,t){"use strict";function n(e,t){if(!o.canUseDOM||t&&!("addEventListener"in document))return!1;var n="on"+e,i=n in document;if(!i){var a=document.createElement("div");a.setAttribute(n,"return;"),i="function"==typeof a[n]}return!i&&r&&"wheel"===e&&(i=document.implementation.hasFeature("Events.wheel","3.0")),i}var r,o=e("./ExecutionEnvironment");o.canUseDOM&&(r=document.implementation&&document.implementation.hasFeature&&document.implementation.hasFeature("","")!==!0),t.exports=n},{"./ExecutionEnvironment":21}],120:[function(e,t){function n(e){return!(!e||!("function"==typeof Node?e instanceof Node:"object"==typeof e&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName))}t.exports=n},{}],121:[function(e,t){"use strict";function n(e){return e&&("INPUT"===e.nodeName&&r[e.type]||"TEXTAREA"===e.nodeName)}var r={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};t.exports=n},{}],122:[function(e,t){function n(e){return r(e)&&3==e.nodeType}var r=e("./isNode");t.exports=n},{"./isNode":120}],123:[function(e,t){"use strict";function n(e){e||(e="");var t,n=arguments.length;if(n>1)for(var r=1;n>r;r++)t=arguments[r],t&&(e+=" "+t);return e}t.exports=n},{}],124:[function(e,t){"use strict";var n=e("./invariant"),r=function(e){var t,r={};n(e instanceof Object&&!Array.isArray(e));for(t in e)e.hasOwnProperty(t)&&(r[t]=t);return r};t.exports=r},{"./invariant":118}],125:[function(e,t){var n=function(e){var t;for(t in e)if(e.hasOwnProperty(t))return t;return null};t.exports=n},{}],126:[function(e,t){"use strict";function n(e,t,n){if(!e)return null;var r=0,o={};for(var i in e)e.hasOwnProperty(i)&&(o[i]=t.call(n,e[i],i,r++));return o}t.exports=n},{}],127:[function(e,t){"use strict";function n(e){var t={};return function(n){return t.hasOwnProperty(n)?t[n]:t[n]=e.call(this,n)}}t.exports=n},{}],128:[function(e,t){"use strict";var n=e("./mergeInto"),r=function(e,t){var r={};return n(r,e),n(r,t),r};t.exports=r},{"./mergeInto":130}],129:[function(e,t){"use strict";var n=e("./invariant"),r=e("./keyMirror"),o=36,i=function(e){return"object"!=typeof e||null===e},a={MAX_MERGE_DEPTH:o,isTerminal:i,normalizeMergeArg:function(e){return void 0===e||null===e?{}:e},checkMergeArrayArgs:function(e,t){n(Array.isArray(e)&&Array.isArray(t))},checkMergeObjectArgs:function(e,t){a.checkMergeObjectArg(e),a.checkMergeObjectArg(t)},checkMergeObjectArg:function(e){n(!i(e)&&!Array.isArray(e))},checkMergeIntoObjectArg:function(e){n(!(i(e)&&"function"!=typeof e||Array.isArray(e)))},checkMergeLevel:function(e){n(o>e)},checkArrayStrategy:function(e){n(void 0===e||e in a.ArrayStrategies)},ArrayStrategies:r({Clobber:!0,IndexByIndex:!0})};t.exports=a},{"./invariant":118,"./keyMirror":124}],130:[function(e,t){"use strict";function n(e,t){if(i(e),null!=t){o(t);for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])}}var r=e("./mergeHelpers"),o=r.checkMergeObjectArg,i=r.checkMergeIntoObjectArg;t.exports=n},{"./mergeHelpers":129}],131:[function(e,t){"use strict";var n=function(e,t){var n;for(n in t)t.hasOwnProperty(n)&&(e.prototype[n]=t[n])};t.exports=n},{}],132:[function(e,t){"use strict";function n(e){r(e&&!/[^a-z0-9_]/.test(e))}var r=e("./invariant");t.exports=n},{"./invariant":118}],133:[function(e,t){"use strict";function n(e){return o(r.isValidDescriptor(e)),e}var r=e("./ReactDescriptor"),o=e("./invariant");t.exports=n},{"./ReactDescriptor":49,"./invariant":118}],134:[function(e,t){"use strict";var n=e("./ExecutionEnvironment"),r=function(e,t){e.innerHTML=t};if(n.canUseDOM){var o=document.createElement("div");o.innerHTML=" ",""===o.innerHTML&&(r=function(e,t){if(e.parentNode&&e.parentNode.replaceChild(e,e),t.match(/^[ \r\n\t\f]/)||"<"===t[0]&&(-1!==t.indexOf("i;i++)o[i]=e[i];return o}var r=e("./invariant");t.exports=n},{"./invariant":118}],138:[function(e,t){"use strict";function n(e){return d[e]}function r(e,t){return e&&e.props&&null!=e.props.key?i(e.props.key):t.toString(36)}function o(e){return(""+e).replace(f,n)}function i(e){return"$"+o(e)}function a(e,t,n){return null==e?0:h(e,"",0,t,n)}var s=e("./ReactInstanceHandles"),u=e("./ReactTextComponent"),c=e("./invariant"),l=s.SEPARATOR,p=":",d={"=":"=0",".":"=1",":":"=2"},f=/[=.:]/g,h=function(e,t,n,o,a){var s=0;if(Array.isArray(e))for(var d=0;d